SQL-Injections: Gefährliche Lücken in Webanwendungen

SQL-Injections: Gefährliche Lücken in Webanwendungen

ZurückSeite 1 von 4

Was sind SQL-Injections?

Nahezu alle Internetseiten verwenden heutzutage Datenbanken zum Speichern von Inhalten, Nutzerinformationen, Einstellungen und anderen Daten. Sie bilden die Grundlage für komplexe Webanwendungen. U-Labs hat Beispielsweise ebenfalls eine Datenbank, in der die Daten von allen Benutzern sowie sämtliche Threads und Beiträge gespeichert sind. Das Forensystem generiert zum Abruf dieser Daten Abfragen an die Datenbank mit Werten von außen – Meist sind dies GET oder POST-Parameter. Der Link https://u-labs.de/member.php?u=18 beispielsweise erhält den Parameter u für die Id des Benutzers. Im dahintersteckenden PHP-Script gibt es also eine Abfrage nach dem Schema Lade die Informationen des Benutzers mit der Id 18, wobei 18 variabel mit dem Wert des u-Parameters ersetzt wird.

Genau hier besteht potenzielle Manipulationsgefahr: Bei einer SQL-Injection werden fremde Daten ungewollt in eine SQL-Datenbankabfrage eingeschleust (injected). Dadurch ist es möglich, die Abfrage nahezu beliebig zu manipulieren. Manchmal ist auch von der Abkürzung SQLI die Rede – nicht zu verwechseln mit der PHP-Erweiterung MySQLi, einer verbesserten (improved) Version der MySQL-Schnittstelle.

Ein typisches Beispiel

Wir haben ein einfaches Login-System das auf PHP basiert. Unser Script bekommt per GET die Logindaten bestehend aus Nutzer und Passwort übermittelt. Es soll prüfen, ob diese Kombination in der Datenbank existiert, wenn ja ist der Nutzer eingeloggt. Wir erzeugen also eine dynamische SQL-Query, und prüfen mit mysqli_num_rows() ob mindestens 1 Zeile mit den Nutzerdaten in der Datenbank vorhanden ist – dann ist der User eingeloggt.

Der relevante Teil dieses Scripts – nennen wir es login.php – sieht dann also wie folgt aus:

$res = mysql_query("SELECT username FROM users WHERE username='" . $_GET['username'] . "' AND password='" . $_GET['password'] . "'");
$rows = mysql_num_rows($res);
if($rows > 0) {
    echo 'Erfolgreich Eingeloggt!';
}else {
    echo 'Fehler: Benutzername oder Passwort ist nicht korrekt!';
}

Das dazu passende HTML-Formular ist ebenfalls sehr überschaubar:

<form action="login.php" method="GET">
    <input type="text" name="username" value="Benutzername"/>
    <input type="password" name="password" value="Passwort"/>
    <input type="submit" />
</form>

Ein Login mit dem Benutzer Max und dem Passwort 123 würde somit unser Login-Script mit folgenden Parametern aufrufen: login.php?username=Max&password=123. Natürlich könnten wir genau so gut HTTP-POST verwenden und die Daten im Body der Anfrage übertragen. GET ist zur Demonstration allerdings besser geeignet, da die Injection so ohne zusätzliche Software direkt über die Adresszeile des Browsers ausgenutzt werden kann.

Wo ist nun die Gefahr?

Die GET-Variablen $_GET[‚username‘] sowie $_GET[‚password‘] werden ungefiltert in die SQL-Abfrage eingefügt. Schauen wir uns mal an wie die obige SQL-Abfrage aussieht, wenn sich unser Nutzer Max ganz normal anmeldet:

SELECT username FROM users WHERE username='Max' AND password='123'

Der Benutzer Max wird gefunden, eingeloggt und erhält Zugriff auf den Mitgliedsbereich der jeweiligen Seite (etwa ein Forum) – Soweit alles in Ordnung.
Da aber nichts gefiltert wird kann man die SQL-Abfrage ganz einfach nach belieben manipulieren und den Login selbst mit ungültigen Daten bestehen: Nehmen wir mal einen unbefugten Dritten, der sich als Max anmelden möchte, aber das korrekte Passwort nicht kennt. Obige Abfrage könnte spielend einfach ausgehebelt werden, in dem neben einem Fantasie-Passwort eine weitere Bedingung in die Abfrage eingefügt wird.

Dazu genügt es, als Passwort bla‘ OR ‚1‘=’1 zu übergeben. Da wir ein HTTP-GET Script haben, kann der Aufruf direkt in der Adresszeile des Browser über die URL http://example.com/login.php?username=Max&password=bla‘ OR ‚1‘=’1 stattfinden. Die SQL-Abfrage sieht dadurch wie folgt aus:

SELECT username FROM users WHERE username='Max' AND password='bla' OR '1'='1'

Der Benutzer Max wird also eingeloggt, wenn sein Passwort bla lautet oder ‚1‘ das gleiche ist wie ‚1‘. Das Passwort von Max lautet zwar nicht bla. Aber da ‚1‘ und ‚1‘ bekanntlich gleich sind und durch das OR nur eine der zwei Bedingungen erfüllt sein muss, wird der Nutzer Max trotzdem eingeloggt – obwohl das Passwort völlig falsch ist!

Da keine Filterung stattfindet können wir beliebig weitere Bedingungen in der SQL-Abfrage einfügen, und damit dessen Verhalten vollkommen auf den Kopf stellen. Wir erinnern uns, ursprünglich sollte diese Abfrage feststellen, ob Benutzer und Passwort gültig sind. Das kann die Abfrage zwar nach wie vor. Aber dass sich durch Manipulation unbefugte zu jedem beliebigen Account Zugang verschaffen können ist ein Nebeneffekt, den ein Login eigentlich verhindern sollte.

ZurückSeite 1 von 4

Was sind SQL-Injections?

One thought on “SQL-Injections: Gefährliche Lücken in Webanwendungen

  1. CDLF

    Toller Artikel.

    Allerdings: Dass die Hochkomma, die im Prinzip „öffnende“ Anführungszeichen sind, tiefgestellt werden, erschwert hier leider das Lesen enorm.

Leave a Reply