Konkrete Kritik an CVSS4
Marc Ruef
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.
Unsere Spezialisten kontaktieren Sie gern!
Marc Ruef
Marc Ruef
Marc Ruef
Marc Ruef
Unsere Spezialisten kontaktieren Sie gern!