Donnerstag, 25. Juni 2009


Topthema

Donnerstag, 2. April 2009 | Topthema

About Security #198: Schwachstellen-Suche: Integer-Schwachstellen

(Link zum Artikel: http://www.entwickler.de/entwicklerde/kolumnen/048123)

Integer-Schwachstellen treten häufig dann auf, wenn ein Programm Rechenoperationen mit Längenwerten durchführt, ohne dabei die Behandlung von Integer-Werten durch Compiler und Prozessor zu berücksichtigen. Besonders häufig kommt es dann zu Integerüberläufen oder Vorzeichenfehlern.

Integerüberläufe (Integer Overflows)

Zu einem Integerüberlauf kommt es, wenn bei einer Rechenoperation mit Integerwerten das Ergebnis größer als der maximal mögliche Wert oder kleiner als der minimal mögliche Wert wird. Dabei wird aus einer sehr großen Zahl eine sehr kleine bzw. aus einer sehr kleinen Zahl eine sehr große.

Als Beispiel kann folgender Quelltext dienen:

void test1(char* Eingabe)
{
   unsigned short laenge = strlen(Eingabe) + 1;
   char* puffer = (char*) malloc(laenge);
   strcpy(puffer, Eingabe)
      
   ...
}

Die Anwendung berechnet die Länge des vom Benutzer eingegebenen Strings, addiert 1 zur Berücksichtigung des den String abschließenden Null-Bytes, reserviert einen Puffer der sich ergebenden Größe und kopiert die Eingabe hinein. Mit normal langen Eingaben verhält sich der Code wie vorgesehen, ein ohne Prüfung möglicher Pufferüberlauf wird verhindert.

Wird aber ein Wert eingegeben, der 65.535 Zeichen lang ist, kommt es zu einem Integerüberlauf: Ein short-Integer ist 16 Bit lang und kann damit Werte zwischen 0 und 65.535 aufnehmen. Wird ein String der Länge 65.535 eingegeben, addiert das Programm zu dieser Länge 1 dazu, und der Wert wird zu 0. Dadurch wird ein Puffer der Länge 0 reserviert und die Eingabe hinein kopiert: Es kommt zu einem Heapüberlauf. Der Code, der eigentlich einen Pufferüberlauf verhindern sollte, hat ihn erst ermöglicht.

Vorzeichenfehler (Signedness Errors)

Vorzeichenfehler treten auf, wenn ein Programm sowohl vorzeichenlose als auch vorzeichenbehaftete Integerwerte für die Berechnung von Pufferlängen verwendet und diese Werte falsch kombiniert. Das kann entweder in Form eines direkten Vergleichs zwischen vorzeichenlosen und vorzeichenbehafteten Wert passieren, oder bei der Übergabe eines vorzeichenbehafteten Werts an eine Funktion, die einen vorzeichenlosen Wert erwartet. In beiden Fällen wird der vorzeichenbehaftete Wert als sein vorzeichenloses Äquivalent aufgefasst, wodurch ein negativer Wert zu einer großen positiven Zahl wird.

Als Beispiel kann folgender Quelltext dienen:

void test2(char* Eingabe, int laenge)
{
   char puffer[32] = "";
   if (laenge < 32)
   strncpy(puffer, Eingabe, laenge);   
   
   ...
}

Die Funktion übernimmt den vom Benutzer eingegebenen String sowie dessen Länge als vorzeichenbehafteten Integer. Danach wird ein Puffer mit fester Länge auf dem Stack reserviert, geprüft, ob die Länge kleiner als die Pufferlänge ist, und nur wenn das zutrifft, wird der Parameter in den Puffer geschrieben. Ist der Parameter laenge eine positive Zahl, verhält sich der Code wie erwartet und verhindert einen Pufferüberlauf.

Gelingt es einem Angreifer aber, für den Parameter laenge einen negativen Wert zu übergeben, wird die Schutzfunktion unterlaufen, da beide Werte vom Compiler für den Vergleich als vorzeichenbehaftete Integer behandelt werden und ein negativer Wert immer kleiner als 32 ist. Da strncpy einen vorzeichenlosen Integerwert erwartet, casted der Compiler den übergebenen vorzeichenbehafteten Wert in einen solchen: Aus dem negativen Wert wird eine sehr große positive Zahl. Ist der vom Benutzer eingegebene Name länger als 32 Zeichen, kommt es zum Pufferüberlauf.

About Security: Alle Folgen

Ein solcher Angriff ist nur möglich, wenn der Angreifer den Parameter laenge manipulieren kann, z.B. weil er bereits auf dem Client über JavaScript ermittelt und danach auf dem Server nicht mehr überprüft wird. Ist die Größe der Integer-Variable klein genug, z.B. short, kann auch eine Längenberechnung auf dem Server ausgetrickst werden: Bei Eingabe eines überlangen Namens kommt es zu einem Integerüberlauf, der den gewünschten negativen Wert erzeugt.

Verhindert werden Integer-Schwachstellen, indem die Parameter vor ihrer Verwendung geprüft und immer auf den richtigen Type geachtet wird.

Integer-Schwachstellen finden

Interessant sind prinzipiell alle Parameter, in denen ein Integer-Wert an die Webanwendung übergeben wird. Dabei können die Werte auf zwei Arten übertragen werden: Zum einen als normale Zahlen in einem GET-, POST- oder Cookie-Parameter, zum anderen als Bestandteil eines größeren Objekts mit binären Daten, das z.B. von einer Clientseitigen Komponente wie einem ActiveX-Control oder einem Java-Applet übertragen wird.

Besonders interessant sind Parameter, die die Länge eines gleichzeitig übertragenen Strings enthalten. In GET-, POST- und Cookie-Parametern verrät meist der Kontext oder sogar schon der Parametername den Verwendungszweck, in binären Daten werden Längenangaben oft als Hexadezimalwert vor dem entsprechenden String gespeichert.

Testwerte

Für jeden in Frage kommenden Parameter müssen Werte eingegeben werden, die jeweils an den Grenzen der Wertbereiche für vorzeichenlose und vorzeichenbehaftete Integer-Werte liegen:

  • 127 und 128
  • 255 und 256
  • 32767 und 32768
  • 65535 und 65536
  • 2147483647 und 2147483648
  • 4294967295 und 4294967296

Werden die Daten hexadezimal übertragen, müssen sowohl Little-Endian- als auch Big-Endian-Werte eingegeben werden. Nach jeder Eingabe wird die Ausgabe der Webanwendung wie bei der Suche nach Pufferüberlauf-Schwachstellen auf ungewöhnliche Reaktionen überprüft, siehe About Security #197.

In der nächsten Folge wird die Suche nach Formatstring-Schwachstellen beschrieben.

Wenn Sie Fragen oder Themenvorschläge haben, können Sie diese gerne an die angegebene E-Mail-Adresse senden oder im Security-Forum einbringen!

Carsten Eilers

About Security - Übersicht zum aktuellen Thema:

Kommentare

Folgende Links könnten Sie auch interessieren

  • Parlez-vous Zend?  [11.07.2007]
    [http://entwickler.de/entwicklerde/artikel/Parlez-vous-Zend-1258.html]
  • Einfach m�glich  [02.12.2003]
    [http://entwickler.de/entwicklerde/artikel/Einfach-moeglich-0470.html]
  • Web-2.0-Anwendungen mit JSON und JSON-RPC  [28.09.2006]
    [http://entwickler.de/entwicklerde/artikel/Web-2.0-Anwendungen-mit-JSON-und-JSON-RPC-1175.html]
  • Gute Verbindung  [18.03.2005]
    [http://entwickler.de/entwicklerde/artikel/Gute-Verbindung-0672.html]
  • (Keine) Zeit f�r Herzrasen!  [18.12.2007]
    [http://entwickler.de/entwicklerde/artikel/%28Keine%29-Zeit-fuer-Herzrasen%21-1430.html]