Außer den bisher beschriebenen SQL-Injection-Angriffen gibt es weitere Möglichkeiten, wie ein Angreifer seinen SQL-Code an die Datenbank schicken kann. Eine solche Möglichkeit ist die SQL-Injection 2. Ordnung, die in dieser Folge beschrieben wird.
To Escape or not to Escape
Wie bereits in den vorherigen Folgen zu sehen war, müssen einfache Anführungszeichen maskiert werden, wenn sie als Bestandteil der Eingabe benötigt werden. Es spricht also nichts dagegen, alle einfachen Anführungszeichen in der Eingabe zu verdoppeln. Das kann unter Umständen aber zu Problemen führen, wenn die gleichen Daten in mehreren SQL-Abfragen verwendet und dabei erst in die Datenbank geschrieben und danach draus gelesen werden. Das lässt sich am einfachsten an einem Beispiel verdeutlichen. Dazu soll die SQL-Anweisung zur Registrierung eines Benutzers dienen, die in About Security #169 beschrieben wurde:
INSERT INTO benutzer (name, passwort, ID, admin)
VALUES ('$name', '$pass', $id, $admin)
Meldet sich ein Benutzer mit dem Benutzernamen
test'sql
an, wird das Anführungszeichen verdoppelt, um es als solches zu
maskieren. Die sich ergebende SQL-Anweisung lautet also
INSERT INTO benutzer (name, passwort, ID, admin)
VALUES ('test''sql', 'g3he1m', 123, 'n')
Security aktuell
Täglich aktuelle Security-Infos!
Diese Anweisung ist korrekt und die Daten werden in der Datenbank gespeichert. Die Änderung des Passworts ist nur nach erfolgreicher Authentifizierung möglich, aus Sicherheitsgründen muss dabei aber auch das bisherige Passwort erneut eingegeben werden. Um eingegebenes und gespeichertes Passwort miteinander zu vergleichen, fragt die Webanwendung zuerst den Benutzernamen in der Datenbank ab:
SELECT name FROM benutzer WHERE ID = 123
liefert test'sql. Die doppelten Anführungszeichen werden nur für das Eintragen des Parameters in die Datenbank verwendet, gespeichert wird der eigentlich eingegebene String. Danach wird das Passwort für den so ermittelten Benutzernamen abgefragt:
SELECT passwort FROM benutzer WHERE name = 'test'sql'
Dadurch, das die Webanwendung den in der Datenbank gespeicherten String in einer weiteren SQL-Abfrage verwendet, wird SQL-Injection möglich: Gibt der Angreifer bei der Registrierung SQL-Code als Teil des Benutzernamens ein, wird er zwar nicht beim Eintragen in die Datenbank ausgeführt, dafür aber beim Ändern des Passworts. Zugegeben, dieses Beispiel ist sehr konstruiert, i.d.R. wird man die Abfrage von Benutzername und Passwort wie im Beispiel in About Security #169 beschrieben in einer SQL-Abfrage zusammenfassen, es zeigt aber das grundsätzliche Problem der SQL-Injection 2. Ordnung: Der Angreifer spielt sozusagen über Bande - der Schadcode wird nicht direkt nach der Eingabe ausgeführt, sondern erst später.
SQL-Injection für Fortgeschrittene
Bisher wurden Angriffe beschrieben, bei denen die Daten direkt ausgegeben wurden, z.B. indem sie über den UNION-Operator an eine vorhandene Abfrage und damit die zugehörige Ausgabe angehängt wurden. Wie in About Security #171 zu sehen war, reicht es dafür aus, das in der Ausgabe der Datentyp einer einzigen Spalte String ist. Aber auch wenn nur numerische Werte zurück geliefert werden, können darüber Daten ausgespäht werden. Sie müssen lediglich in numerische Daten umgewandelt werden. Dazu werden im wesentlichen zwei Funktionen verwendet:
-
SUBSTRING()liefert einen Teilstring der Eingabe -
ASCII()liefert den ASCII-Code eines eingegebenen Zeichens, also einen numerischen Wert
Beide Funktionen zusammen können verwendet werden, um ein einzelnes Zeichen aus einem String in einen numerischen Wert umzuwandeln:
SUBSTRING('abcde',1,1) liefert a
ASCII('a') liefert 97
und
ASCII(SUBSTRING('abcde',1,1)) liefert demnach ebenfalls
97.
Der Angreifer kann so einen String in einzelne Zeichen zerlegen und die wiederum als numerische Werte ausgeben. Das lässt sich auch über ein Skript automatisieren, was die Verarbeitungsgeschwindigkeit deutlich erhöht.
Indirekte Ausgabe
Werden die Zahlen nicht direkt ausgegeben, sondern als Identifier für
weitere Daten verwendet, kann der Angreifer zuerst für alle zu
erwartenden Werte die entsprechenden Daten abfragen und dann darüber
die später ausgegebenen Zahlen identifizieren. Werden die Zahlen z.B.
verwendet, um Profile einer Benutzerdatenbank auszugeben, könnte das
so aussehen: Die Ausgabe für die ID 97 ist das Profil von Max
Mustermann, dementsprechend bedeutet später im Rahmen des Angriffs die
Ausgabe des Profils von Max Mustermann, das ein a ausgegeben
wurde.
SQL-Injection ohne direkte Ausgabe
SQL-Injection ist auch dann möglich, wenn das Ergebnis des eingeschleusten SQL-Codes nicht ausgegeben wird Der einfachste Fall ist das Umgehen der Authentifizierung, wie es in About Security #167 beschrieben wurde: Das Ergebnis der SQL-Abfrage ist dem Angreifer egal, ihn interessiert nur, das er danach angemeldet ist. Weiter gehende Angriffe, die ohne Ausgabe des Ergebnisses auskommen, werden als Blind SQL-Injection bezeichnet. Was es damit auf sich hat, erfahren Sie in der nächsten Folge.
Wenn Sie Fragen oder Themenvorschläge haben, können Sie diese gerne an die angegebene E-Mail-Adresse senden oder im Security-Forum einbringen!
About Security - Übersicht zum aktuellen Thema:
- About Security #166: Schwachstellen-Suche: SQL-Injection Grundlagen
- About Security #167: Schwachstellen-Suche: SQL-Injection über Strings
- About Security #168: Schwachstellen-Suche: SQL-Injection statt Zahlen
- About Security #169: Schwachstellen-Suche: SQL-Injection Statements
- About Security #170: Schwachstellen-Suche: SQL-Injection mit UNION
- About Security #171: Schwachstellen-Suche: SQL-Injection mit UNION (2)
- About Security #172: Schwachstellen-Suche: SQL-Injection mit Filter
- About Security #173: Schwachstellen-Suche: SQL-Injection mit Escape
- About Security #174: Schwachstellen-Suche: SQL-Injection 2. Ordnung





