Schwache Typisierung und ihre Sicherheitsrisiken

Schwache Typisierung und ihre Sicherheitsrisiken

Marc Ruef
von Marc Ruef
Lesezeit: 11 Minuten

Die Typisierung (engl. typing) wird in der Informatik verwendet, um Objekte im Rahmen der Nutzung einer Programmiersprache korrekt anzuwenden. Diese Idee der Typsysteme stammt aus der Mathematik, die ihrerseits in Bezug auf die Mengenlehre ohne Typisierung zu Widersprüchen geführt hat.

Man unterscheidet in der Programmierung zwischen zwei grundlegenden Typsystemen. Eine starke Typisierung (engl. strong typing) verhindert, dass auf Objekte Operationen angewendet werden, für die sie nicht vorgesehen sind. Zum Beispiel kann eine Zeichenkette nicht ohne weiteres mit einem Zahlenwert multipliziert werden. Der Compiler oder Interpreter verweigert in diesem Fall die Arbeit und gibt eine Fehlermeldung aus:

$x = "string2" * 3 // bei strenger Typisierung nicht möglich

Eine strenge Typisierung führt dazu, dass sich Entwickler in jedem Detail bewusst sein müssen, welche Typen die von ihnen genutzten Objekte darstellen und welche Operationen sich darauf anwenden lassen. Dies ist nicht immer einfach und so greifen diverse Programmiersprachen auf die schwache Typisierung (engl. weak typing) zurück. Bei einer solchen wird eine automatische Typenumwandlung durchgeführt, um möglichst einfach Resultate generieren zu können.

Es gibt eine Reihe von Programmiersprachen, die mit einer schwachen Typisierung daherkommen. Da sie freizügiger im Umgang mit Datentypen sind, gelten sie als leichter handzuhaben und deshalb eher einsteigerfreundlich. Zu den populären Sprachen mit einem schwachen Typensystem zählen Javascript, Objective-C, Perl und PHP.

Im zuvor genannten Fall der Multiplikation eines Strings mit einem Integer ist es sodann nicht untypisch, dass das Resultat $x den Wert 3 oder 6 annehmen wird. Die Sprache wird Integer als primitiven Datentyp vorziehen und den String in einen solchen umwandeln wollen. Da der String definiert ist, kann er entweder den Wert 1 (ein leerer String würde 0 lauten) oder den Wert 2 (das Eliminieren sämtlicher Teile, die nicht direkt als Integer verwendet werden können) annehmen. Wie das Resultat genau lautet, ist von der Definition und Implementierung der zugrundeliegenden Programmiersprache abhängig.

Dieser Effekt kann in Angriffen eine wichtige Rolle spielen. Gehen wir davon aus, dass eine Funktion eine Berechnung vornehmen soll. Der Anwender kann einen spezifischen Wert durch eine legitime Eingabe definieren. Durch eine Eingabeüberprüfung wird aber verhindert, dass der Wert 0 lauten kann. Dabei wird der Vergleichsoperator in folgender Form eingesetzt:

if($_GET['input'] == 0){
   echo 'Die Eingabe ist nicht zugelassen.';
}else{
   setPermissions($_GET['input']);
}

Da die Eingabe 0 nicht übergeben werden kann, kann versucht werden einen leeren String zu übergeben. Dieser wird eventuell aufgrund der schwachen Typisierung angenommen und im Rahmen der Funktion irgendwann doch noch als 0 verarbeitet.

Dieses Phänomen tritt ebenso bei der Nutzung von Vergleichsoperatoren bei unterschiedlichen Datentypen auf. Die folgende Tabelle illustriert das Verhalten von PHP, wenn die Werte mit dem typenneutralen Operator == verglichen werden:

  TRUE FALSE 1 0 -1 “1” “0” “-1” NULL arr() “php” . “”
TRUE TRUE FALSE TRUE FALSE TRUE TRUE FALSE TRUE FALSE FALSE TRUE FALSE
FALSE FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE TRUE TRUE FALSE TRUE
1 TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
0 FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE TRUE FALSE TRUE TRUE
-1 TRUE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
“1” TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
“0” FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
“-1” TRUE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
NULL FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE TRUE TRUE FALSE TRUE
arr() FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE
“php” TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE
. “” FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE TRUE

Auch hier sieht man, dass PHP den Vergleich "" == 0 mit TRUE beantworten würde. Dies ist ein Effekt, der bei Rückgabewerten von bestimmten Funktionen zu Problemen führen kann. Und zwar dann, wenn sie sowohl den Rückgabewert 0 als auch FALSE liefern können, diese Werte aber unterschiedliche Status ausweisen.

Ein klassisches Beispiel ist die Funktion strpos(), welche zum Auffinden eines Strings in einem anderen String genutzt wird:

$a = substr('abcd', 'a');  // liefert 0
$b = substr('abcd', 'b');  // liefert 1    
$c = substr('abcd', 'cd'); // liefert 2
$d = substr('abcd', 'x');  // liefert FALSE

Der erste Aufruf wird in $a den Rückgabewert 0 liefern, da das Zeichen a in der Zeichenkette abcd an Position 0 auftritt (es wird nicht bei 1 zu zählen begonnen). Diese Zählweise wird weitergezogen. Doch beim letzten Beispiel wird in $d der Wert FALSE gespeichert, da das Zeichen x nicht in der Zeichenkette abcd vorkommt. So mancher Programmierer benutzt irrtümlicherweise folgende Struktur, um das Vorkommen einer Zeichenkette zu determinieren:

$pos = substr('abcd', 'x');
if($pos != 0){
   return 'gefunden';
}else{
   return 'nicht gefunden';
}

Doch genau dieser fehlerhafte Vergleich kann nun herangezogen werden, um Eingabeüberprüfungen zu umgehen. Um dies zu verhindern, muss der typensensitive Vergleichsoperator === herangezogen werden. Denn dieser kann sehr wohl zwischen 0 (gefunden an erster Stelle) und FALSE (nicht gefunden) unterscheiden. Mittlerweile wird in der Online-Dokumentation von PHP explizit auf die Risiken dieser Art bei bestimmten Funktionen hingewiesen. Dennoch sieht man immerwieder Applikationen, die dieses Prinzip übersehen und sich so gegen geschickte Angriffe verwundbar machen.

Über den Autor

Marc Ruef

Marc Ruef ist seit Ende der 1990er Jahre im Cybersecurity-Bereich aktiv. Er hat vor allem im deutschsprachigen Raum aufgrund der Vielzahl durch ihn veröffentlichten Fachpublikationen und Bücher – dazu gehört besonders Die Kunst des Penetration Testing – Bekanntheit erlangt. Er ist Dozent an verschiedenen Fakultäten, darunter ETH, HWZ, HSLU und IKF. (ORCID 0000-0002-1328-6357)

Links

Sie brauchen Unterstützung bei einem solchen Projekt?

Unsere Spezialisten kontaktieren Sie gern!

×
Konkrete Kritik an CVSS4

Konkrete Kritik an CVSS4

Marc Ruef

scip Cybersecurity Forecast

scip Cybersecurity Forecast

Marc Ruef

Voice Authentisierung

Voice Authentisierung

Marc Ruef

Bug-Bounty

Bug-Bounty

Marc Ruef

Sie wollen mehr?

Weitere Artikel im Archiv

Sie brauchen Unterstützung bei einem solchen Projekt?

Unsere Spezialisten kontaktieren Sie gern!

Sie wollen mehr?

Weitere Artikel im Archiv