Zur Verhinderung von SQL-Injection gibt es außer dem in About Security #172 beschriebenen Ausfiltern unerwünschter Eingaben auch die Möglichkeit, Sonderzeichen wie z.B. das einfache Anführungszeichen ' zu escapen (maskieren). Danach werden sie von der Datenbank als Teil der Eingabe erkannt und können nicht zum Beenden eines vorhandenen Ausdrucks verwendet werden. Wieso das nicht zwingend zum gewünschten Erfolg führt, erfahren Sie in dieser Folge.
Security aktuell
Täglich aktuelle Security-Infos!
Escape statt Löschen
Wie bereits in About Security #167 beschrieben wurde, werden zwei einfache Anführungszeichen zusammen als Escape-Sequenz interpretiert: Sie ergeben ein einfaches Anführungszeichen, das als Bestandteil eines Strings und nicht als dessen Abschluss betrachtet wird. Möchte man z.B. O'Reilly in einer SQL-Abfrage verwenden, muss das ' escaped werden: O''Reilly. Viele Entwickler sind der Ansicht, durch das Verdoppeln jedes in einer Benutzereingabe enthaltenen einfachen Anführungszeichen könne SQL-Injection verhindert werden. Zum einen verhindert das aber nur SQL-Injection-Angriffe, die auf das Einschleusen von '-Zeichen angewiesen sind, z.B. um einen String zu beenden, um dann dahinter eigenen Code anzufügen. Zum anderen können beim Einsatz weiterer Filter diese unter Umständen so kombiniert werden, dass das Escapen aufgehoben wird.
Als Beispiel soll wieder die Authentifizierung aus About Security #167 dienen:
SELECT * FROM Benutzer WHERE Benutzername = '$name' AND Passwort = '$pass'
Als Schutzmaßnahmen gegen SQL-Injection werden alle einzelnen Anführungszeichen in der Eingabe verdoppelt, außerdem wird die Länge der Eingabe auf 10 Zeichen begrenzt - alles danach wird abgeschnitten.
Bei der Eingabe von
admin'--
als Benutzername und einem beliebigen Passwort ergibt das
SELECT * FROM Benutzer WHERE Benutzername = 'admin''--' AND Passwort = 'nix'
Diese Abfrage schlägt fehl, ein Umgehen der Authentifizierung ist also nicht möglich. Aber wie sieht es bei der Eingabe von z.B.
abcdefghi'
aus (bzw. allgemein bei der Eingabe von 9 Zeichen, gefolgt von einem Anführungszeichen)? Die Webanwendung verdoppelt das Anführungszeichen und erhält
abcdefghi''
Danach wird die Eingabe nach 10 Zeichen abgeschnitten - zurück bleibt die vorherige Eingabe, die zu folgender SQL-Abfrage führt:
SELECT * FROM Benutzer WHERE Benutzername = 'abcdefghi'' AND Passwort = 'nix'
Das doppelte Anführungszeichen hinter dem i wird als Teil des blau markierten Strings interpretiert. Das nutzt dem Angreifer auf den ersten Blick wenig, denn auch damit kann die Authentifizierung nicht umgangen werden. Wird aber zusätzlich als Wert für das Passwort
or 1=1--
eingegeben, ergibt das folgende Abfrage:
SELECT * FROM Benutzer WHERE Benutzername = 'abcdefghi'' AND Passwort = ' or 1=1--'
Gesucht wird nach Zeilen, in denen in der Spalte Benutzername
abcdefghi'' AND Passwort =
steht oder für die 1=1 gilt. Da 1=1 immer erfüllt ist, wird die Authentifizierung so umgangen.
Werden verschiedene Funktionen kombiniert, muss immer mit Nebenwirkungen gerechnet werden. Ganz besonders gilt das natürlich bei Schutzfunktionen, bei denen besonders darauf geachtet werden muss, das sie sich nicht gegenseitig aufheben.
SQL Column Truncation
Das oben beschriebene Problem kann leicht mit einer von Stefan Esser als 'SQL Column Truncation' bezeichneten Schwachstelle verwechselt werden. Deren Ursache ist eine fehlende Längenprüfung durch die Webanwendung: Überlange Eingaben werden beim Einfügen in die Datenbanktabelle von der Datenbank gekürzt, ohne das die Webanwendung das berücksichtigt. MySQL kürzt zu lange Eingaben, und gibt im Normalfall nur eine Warnung aus. Warnungen erreichen die Webanwendung aber i.A. nicht oder werden von ihr nicht berücksichtigt.
Als Beispiel nennt Stefan Esser ein Formular zur Anmeldung neuer Benutzer.
Der Benutzername des Administrators ist bekannt, z.B. 'admin'.
Es wird MySQL in der Default-Konfiguration verwendet, die Webanwendung
prüft die Länge der Eingaben nicht und die Spalte für die
Benutzernamen nimmt nur bis zu 16 Zeichen lang Namen auf.
Versucht ein Angreifer, sich als 'admin ' zu registrieren, schlägt das
fehl. Beim Vergleich des neuen Benutzernamens mit den vorhandenen
durch die Abfrage
SELECT * FROM user WHERE username='admin '
werden angehängte Leerzeichen ignoriert, so dass
'admin ' identisch mit 'admin' ist, die
Webanwendung verweigert daher die Registrierung. Meldet sich der Angreifer
aber mit dem Benutzernamen
'admin x'
an, wird dieser Benutzername nicht gefunden: Die Eingabe ist 17 Zeichen
lang, die Spalte für den Benutzernamen nimmt aber nur 16 Zeichen auf.
Die Webanwendung akzeptiert diesen Benutzernamen daher und trägt ihn
zusammen mit dem zugehörigen Passwort in die Datenbank ein. Da der
Name aber für die Spalte zu lang ist, wird er von MySQL gekürzt
und
'admin '
eingetragen. Die Benutzertabelle enthält nun zwei Benutzernamen, die
sich nur durch angehängte Leerzeichen unterscheiden. Je nachdem, wie
die Webanwendung die Benutzernamen verwendet, kann das zu Problemen
führen.
In der nächsten Folge werden einige weitere SQL-Injection-Angriffe 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!
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




