Mittwoch, 23. November 2011


Topthema

Donnerstag, 14. August 2008 | Topthema

About Security #168: Schwachstellensuche: SQL Injection statt Zahlen

(Link zum Artikel: http://www.entwickler.de/entwicklerde/kolumnen/044661)
  • Teilen
  • kommentieren
  • empfehlen
  • Bookmark and Share

SQL-Injection ist auch über numerische Parameter möglich. Denn nur, weil ein Feld für z.B. eine Kundennummer vorgesehen ist, heißt das noch lange nicht, dass ein Angreifer dort nicht einen SQL-Befehl eingeben kann. Und auch eine Beschränkung der Länge des Eingabefelds auf z.B. fünf Zeichen ist keine Garantie dafür, dass ein Angreifer nicht einen längeren Parameter an den Server sendet. Dazu kann er (wie in About Security #149 bei der Manipulation von Zustandsinformationen beschrieben) z.B. das Formular lokal speichern und ändern, den Parameter in einem Proxy 'on the fly' manipulieren oder seine Daten unter Umgehung des Clients direkt an die Webanwendung senden.

Numerische Parameter werden manchmal als Strings, d.h. eingeschlossen in '-Zeichen, an die Datenbank übergeben. Daher müssen auch die in About Security #167 für Strings beschriebenen Tests durchgeführt werden. Meistens werden sie aber direkt als numerische Werte an die Datenbank übergeben und daher nicht in '-Zeichen eingeschlossen. Ergibt sich bei den Tests aus About Security #167 kein Hinweis auf eine Schwachstelle, sind weitere Tests notwendig.

Tests für numerische Parameter

Die folgende SQL-Abfrage könnte verwendet werden, um einen Nachrichtentext anhand einer numerischen ID auszuwählen:

SELECT Text FROM Nachrichten WHERE ID = $id

Als erster Test wird ein mathematischer Ausdruck übergeben, der äquivalent zu einem gültigen numerischen Wert ist. Ist ein Originalwert z.B. 5, könnte z.B. 2+3 oder 6-1 als Wert für $id eingegeben werden:

SELECT Text FROM Nachrichten WHERE ID = 2+3

Liefert die Webanwendung für den Ausdruck dasselbe Ergebnis wie bei Eingabe des Originalwerts, kann sie für SQL-Injection anfällig sein.

N E U ! Security aktuell
Täglich aktuelle Security-Infos!

Dieser Test ist immer dann zuverlässig, wenn eine Änderung des betroffenen Parameters eine sichtbare Auswirkung auf die Ausgabe der Webanwendung hat. Ist der getestete Parameter wie im obigen Beispiel eine numerische ID, die den auszugebenden Text bestimmt, ist eine identische Ausgabe für 5 und 2+3 ein ziemlich sicheres Zeichen dafür, dass SQL-Injection möglich ist. Kann für den betroffenen Parameter aber ein beliebiger Wert eingegeben werden, ohne dass sich die Ausgabe ändert, liefert der Test keine zuverlässige Aussage.

Ist der erste Test erfolgreich, kann als nächstes ein Test mit einem komplizierteren SQL-Ausdruck durchgeführt werden. Gut geeignet ist dafür der Befehl ASCII(), der den numerischen ASCII-Wert des übergebenen Zeichens zurückliefert. Der ASCII-Wert von A ist 65, der folgende Ausdruck ist also in SQL äquivalent zu 5:

70-ASCII('A')

Dieser Test funktioniert nicht, wenn '-Zeichen von der Webanwendung ausgefiltert werden. In diesem Fall kann ausgenutzt werden, dass die Datenbank bei Bedarf numerische Daten automatisch in Strings umwandelt. Der ASCII-Wert des Zeichens 1 ist 49, der folgende Ausdruck ist also in der SQL-Abfrage äquivalent zu 5:

54-ASCII(1)

Ist einer der letzten beiden Tests erfolgreich, kann beliebiger SQL-Code eingeschleust werden, evtl. eingeschränkt durch Filterfunktionen der Webanwendung, die bestimmte Zeichen wie z.B. das '-Zeichen ausfiltern oder maskieren.

Die in About Security #167 und dieser Folge beschriebenen Tests reichen aus, um einen Großteil aller SQL-Injection-Schwachstellen zu finden. Machmal sind weiterführende Test wie z.B. Wartezeiten (time delays) notwendig, um eine Schwachstelle nachzuweisen. Auf diese Fälle wird später noch eingegangen.

Sonderzeichen kodieren
About Security: Die komplette Serie

Einige Zeichen haben in HTTP-Requests eine besondere Bedeutung und können nicht direkt als Teil der Eingabe für Parameter verwendet werden. Sollen sie Bestandteil einer SQL-Injection sein, müssen sie URL-kodiert werden. Das betrifft die folgenden Zeichen:

  • & und = verbinden Parameternamen und -werte in URL und POST-Daten. Sie können als %26 und %3d kodiert werden.
  • Leerzeichen sind in Query-Strings verboten und beenden den gesamten String. Sie können wahlweise als + oder %20 kodiert werden.
  • Da + ein Leerzeichen kodiert, kann es nicht als eigentliches + verwendet werden. Soll das Zeichen + übergeben werden, muss es als %2b kodiert werden. Das obige 2+3 muss also als 2%2b3 eingegeben werden.
  • Das ; dient als Trennzeichen für Cookie-Felder und kann als %3b kodiert werden.

Werden die Zeichen nicht korrekt kodiert, ist die sich ergebende SQL-Abfrage nicht gültig oder erfüllt zumindest nicht die geplante Funktion.

SQL-Injection in verschiedene Statements

Für SQL-Injection-Beispiele wird meistens das SELECT-Statement verwendet, aber entsprechende Schwachstellen können auch in Verbindung mit anderen Statements existieren - und natürlich auch ausgenutzt werden. Mit was für einem Statement ein anfälliger Parameter verwendet wird, kann ein Angreifer ohne Zugriff auf den Quelltext der Webanwendung nicht mit Sicherheit wissen, aber meist aus den jeweiligen Umständen (z.B. Anzeigen/Eintragen/Ändern von Daten) sehr gut raten.

Wie SQL-Injection in Verbindung mit verschiedenen Statements ausgenutzt werden kann, wird in der nächsten Folge 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

Kommentare

Folgende Links könnten Sie auch interessieren