Let’s Talk About Security – SQL Injection

In diesem Beitrag werde ich auf eine Angriffsmethode eingehen, die seit mehreren Jahren auf Platz 1 der OWASP Top 10 Sicherheitsrisiken für Webanwendungen steht: Die SQL-Injection. Viele Entwickler schütteln weiterhin noch die Köpfe, wie eine so simpel aufgebaute Angriffsmethode an der Spitze der Sicherheitslücken stehen kann. Einer der Gründe, warum SQL-Injections bei den Hackern so beliebt sind, ist die einfache und schnelle Nutzung dieser Sicherheitslücke. Dies folgt durch den hohen Zeitdruck in den Entwicklungsphasen von Applikationen, bei denen die Funktionalität an erster Stelle steht und die Sicherheitsvorkehrungen erst zum Schluss kommen.

Bei der SQL-Injection nutzt der Hacker die unzureichende Überprüfung der Eingabedaten ins System aus. Hierbei werden die Standard-Datenbank-Queries zu Gunsten des Angreifers umgeschrieben, um auf sensible Informationen des Servers zuzugreifen. In schlimmeren Fällen ist es einem Angreifer sogar möglich, Datenbanken umzuschreiben und eigene Inhalte hochzuladen. Der Zugangspunkt für solche Injections kann von externen sowie von registrierten Benutzern ausgenutzt werden. Daher kommt auch der Leitspruch „Never Trust The User!“.

Damit Ihre Systeme vor SQL-Injections geschützt werden können, werde ich versuchen, ein Grundverständnis über die Funktionsweise von Injections zu vermitteln. Wie der Name der Injections bereits verrät, handelt es sich hierbei um manipulierte SQL-Abfragen. Zu diesem Zweck müssen die Angriffsvektoren genauer betrachtet werden. Klassische Beispiele für SQL-Abfragen auf Websites sind:

  • Authentifikation (Login-Fenster)
  • Suchfelder (Extrahieren die relevanten Informationen aus der Datenbank)
  • URL (Weblink anpassen)

Im Bereich des Login-Fensters werden zwei Felder für die Eingabe der User-Informationen bereitgestellt. Die eingetragenen Informationen werden an den Server weitergeleitet, woraufhin die Datenbank nach einem passenden User durchsucht wird.

Saxonia-Systems-SQL-Injection-1
Abbildung 1: Login-Maske zur User-Abfrage

Wird kein passender User gefunden, schlägt der Login fehl. Auf Quellcode-Ebene wird der String von „Username“ und „Password“ dazu genutzt, eine SQL-Query aufzubauen, die wiederum dafür genutzt wird, auf die Datenbank zuzugreifen. Der Code würde in etwa so aussehen:

var User = getName("Tester");
var Password = getPass("Passwort1");

sql_cmd = 'SELECT * FROM Users WHERE Name ="' + User + '" AND Password ="' + + '"'

Resultierende SQL-Query:
              →  SELECT * FROM Users WHERE Name = “Tester” AND Password = “Passwort1”

In diesem Beispiel wird die Eingabe des Nutzers ohne Überprüfung angenommen und dazu verwendet, die Query zu bauen. Der Eingabe des Nutzers wird vertraut. Handelt es sich nun um einen Hacker, der diese Schwachstelle sieht, könnte er sie folgendermaßen ausnutzen.

Saxonia-Systems-SQL-Injection-2
Abbildung 2: Login ohne Überprüfung

Es werden Sonderzeichen und Befehle in die Login-Felder hinzugefügt, um die SQL-Query zu ergänzen. Mit den abgebildeten Eingaben würde solch eine Query entstehen:

Resultierende SQL-Query:
              →  SELECT * FROM Users WHERE Name =”” or “”=“” AND Password =”” or “”=””‘

Das ergänzende OR in der Query, welches in diesem Fall immer TRUE zurückgibt, führt dazu, dass jeder Eintrag aus der Tabelle angezeigt wird. Prüft das System beim Login nur, ob der User mit dem entsprechenden Passwort in der Datenbank vorhanden ist, würde er bei dieser Abfrage immer eine positive Antwort bekommen. Somit wäre die Eingabe für ein ungeschütztes System ein universaler Schlüssel für alle Angreifer.

Dies ist ein Beispiel, wie eine SQL-Injektion in Login-Felder durchgeführt werden kann. Die Injection kann aber auch über die URL einer Internetseite durchgeführt werden. Aufgebaut ist die URL aus der Adresse der Internetseite und einem Pfad, der das Verzeichnis des Servers darstellt. In diesem Dateipfad sind auch PHP- oder HTML-Parameter vorhanden, welche die Abfrage des Nutzers widerspiegeln.

Beispiel-URLs:

  • http://testmysql.com/report.php?id=23
  • http://www.testmysql.com/search.html?query=test&searchProfile=tester

Diese Parameter in den URL-Pfaden könnten für Injections verwendet werden. Ähnlich wie beim ersten Beispiel kann der String so ausgetauscht werden, dass eine SQL-Query für Zwecke des Angreifers manipuliert wird.

  • Veränderte URL: http://testmysql.com/report.php?id=105; DROP TABLE items; —
  • Resultierende Query:   →  SELECT * FROM items WHERE id = 105; DROP TABLE items; —

Durch das Hinzufügen des DROP TABLES wird der Query ein weiterer SQL-Befehl hinzugefügt und nach Aufbau der Verbindung zur Datenbank ausgeführt. Zuerst wird die erwünschte Standard-Abfrage ausgeführt. Es wird nach der ID 105 gesucht, aber direkt danach die komplette Tabelle mit allen darin befindlichen Daten gelöscht.

Ich hoffe, ich konnte mit diesen beiden Beispielen zeigen, wie kritisch sich Injections auf eine Datenbank auswirken können. Hier muss natürlich auch dazugesagt werden, dass es sich bei diesen Injections um sehr einfache Beispiele handelt. Solche Injections können nicht auf jeder Seite direkt aufgerufen werden. In der Praxis müssen sich potenzielle Angreifer mehr anstrengen. Es sind zwar via Google Internetseiten zu finden, die einen solchen URL-Pfad besitzen – wie z.B.:

  • inurl:”product.php?id=” site:.de

Diese sind aber in vielen Fällen gesichert. Des Weiteren muss sich ein Angreifer zuerst einmal einen Überblick über das System verschaffen. Jede Datenbank ist mit anderen Strukturen aufgebaut und besitzt andere Namen für die Tabellen, beispielsweise für die Benutzerinformationen. Aktiv kann man sein System durch die Verwendung von Standard-Frameworks schützen. Diese haben sich bewährt und werden ständig weiterentwickelt. Sofern man solch ein Framework für das eigene System zusätzlich anpasst, erhöht sich der Aufwand für einen Angreifer weiter. Der Angreifer muss mehrere Versuche starten, um herauszufinden inwiefern die Queries überprüft und was für Input-Formate genutzt werden. Entsprechend der Fehlermeldungen, die bei diesen Test-Injections angezeigt werden, bekommt der Angreifer mitunter leider Informationen, die er für seinen Angriff benötigt. Darum ist es sehr wichtig, Fehlermeldungen, die dem Benutzer angezeigt werden, auf ihren Inhalt zu überprüfen. In einem schlechten Fall sagt die Fehlermeldung aus, in welcher Datenbank-Tabelle mit welchen Spalten sich bestimmte Informationen befinden. Mit diesen Informationen ist es dann sehr einfach, eine passende Injection aufzubauen. Eine weitere wichtige Schutzmaßnahme ist es, für den Zugriff auf die Datenbank einen User zu nutzen, dessen Rechte beschränkt sind. Damit verhindert man Befehle wie das Löschen oder Ändern von Daten in den Tabellen. Weiterhin sollten „Stored Procedures“ verwendet werden, damit die Möglichkeiten zum Zugriff auf die Datenbank zusätzlich eingeschränkt werden.

Im Zuge einer umfassenden Qualitätssicherung kann man potenziell gefährliche Schwachstellen natürlich auch durch Tests erkennen und anschließend beseitigen.

Zum Testen solcher Sicherheitslücken gibt es mehrere Tools, welche die üblichen Schwachstellen ausnutzen, um die Systeme auf Schwachstellen zu testen. Diese Tools werden fortlaufend weiterentwickelt und können nicht nur von Entwicklern, sondern auch von Testern verwendet werden. Dies betrifft z.B. folgende Tools:

  • BSQL Hacker
  • SQLmap
  • SQLNinja
  • Safe3 SQL Injector

Nachdem die Grundlagen erklärt wurden, werde ich jetzt ein praktisches Beispiel unter Verwendung eines der genannten Tools vorführen. Das SQLmap-Tool ermöglicht es sowohl einem Angreifer als auch einem Tester, mit wenigen Kommandozeilen die Datenbank einer Internetseite zu durchforsten. Handelt es sich z.B. um eine PHP-Anwendung, welche den “php?id”-String im URL-Pfad besitzt, kann dieser als Schnittstelle für die Injection genutzt werden.

Abbildung 3: Abfrage verbundener Datenbanken

Das Tool überprüft mit Hilfe seiner Standard-Abfragen, mit welchen Datenbanken die Internetseite verbunden ist. Für dieses Beispiel überprüfen wir die selbsterstellte Website „testing-site.com“. Durch die Injection lässt sich einfach in Erfahrung bringen, dass die Datenbanken INFORMATION, WALLET und TESTING-DATABASE mögliche Ziele für einen Angriff sind. Nachdem man erfahren hat, welche Datenbanken zu Auswahl stehen, ist es möglich, die nächste Ebene zu analysieren.

Abbildung 4: Tabellen der TESTING Database

In der TESTING-Database sind neun Tabellen implementiert. Als nächstes wird die Tabelle USERS genauer betrachtet, um die Informationen herauszulesen.

Abbildung 5: Analyse der USERS-Tabelle

Mit der genaueren Analyse der USERS-Tabelle weiß der Angreifer nun, welche Spalten ausgelesen werden müssen, um an die gewünschten Daten zu kommen. Mit den gesammelten Informationen ist man nun in der Lage, eine spezifische Injection zu schreiben, um der Datenbank Informationen über die Benutzer zu entziehen.

Abbildung 6: Nutzer-Informationen im Klartext

Der USERNAME und die EMAIL sind innerhalb der Datenbank im Klartext gespeichert. Das PASSWORT wurde verschlüsselt. Nun wäre der nächste Schritt z.B. anhand von Rainbow-Tabellen die Passwörter zu entschlüsseln, um daraufhin einen User verwenden zu können.

Ich hoffe, ich konnte mit diesem Blogbeitrag einen kleinen Einblick in SQL-Injections geben und auf die entsprechenden Sicherheitslücken aufmerksam machen. Denn leider werden diese viel zu oft ausgenutzt, um auf fremde Systeme zuzugreifen und dagegen sollte man entsprechende Schutzmaßnahmen ergreifen.

Neco Giedrojc

Neco Giedrojc schloss sich kurz nach seinem Studienabschluss im Bereich „Computer Engineering“ dem Testbereich der Saxonia Systems AG an und arbeitet dort als Tester. Dabei befasst er sich in seinem Hauptprojekt aktuell mit dem Integrationstest komplexer Systeme.