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.

Spritze für SQL Injection

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.

User-Informationen SQL-Injection
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.

User-Informationen SQL-Injection
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 Injection 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.

Code SQL-Injection
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.

Code SQL-Injection
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.

Code SQL-Injection
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.

Code SQL-Injection
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.

QA Navigation Board – Wie wir müssen das noch testen?

Meist stehen bei Entwicklungsprojekten die Überlegungen zur Funktionalität und der Mehrwert für den Kunden im Vordergrund. QA und Testbarkeit kommen dadurch bei der Planung zu kurz. So treten während der Testphase Hürden für das Team auf, welche sich durch eine gewisse Voraussicht bei der Planung der QA-Aufgaben umgehen lassen. Tester haben für die Planung der höheren Teststufen bereits ein geeignetes Vorgehen: ein detailliertes Testkonzept, welches die Testziele dokumentiert sowie entsprechende Maßnahmen und eine Zeitplanung festlegt (Abb. 1).

Aspekte der Teststrategie / Inhalte eines Testkonzepts
Abbildung 1: Aspekte der Teststrategie / Inhalte eines Testkonzepts

Diese Detailtiefe eignet sich aber nicht für agile Projekte und Entwicklungsteams. Trotzdem sollte sich das Team vor dem Start eines Projektes über die meisten Aspekte, die im Testkonzept genannt werden, Gedanken machen. Darum haben wir ein Hilfsmittel entwickelt, welches es den Teams ermöglicht, alle Maßnahmen für eine optimale Testbarkeit in Softwareprojekten mit einzubeziehen. Das Hilfsmittel berücksichtigt sowohl die Fragen „Was ist zu testen?“ als auch „Wie und wo wollen wir testen?“.

Um die erste Frage „Was ist zu testen?“ im Hinblick auf Softwareprodukte zu beantworten, ist die Ausprägung der Qualitätskriterien der umzusetzenden Anforderungen ausschlaggebend. Die unterschiedlichen Qualitätskriterien sind in der ISO 25010 „Qualitätskriterien und Bewertung von System und Softwareprodukten (SQuaRE)“ enthalten (Abb. 2).

Qualitätskriterien nach ISO 25010
Abbildung 2: Qualitätskriterien nach ISO 25010

Je nachdem wie stark die umgesetzten Anforderungen auf die Qualitätskriterien einzahlen, ergibt sich die Notwendigkeit, diese Qualitätskriterien mit einer entsprechenden Testart zu prüfen. So verlangen Apps mit hohem Datendurchsatz nach Effizienztests und Webshops sollten auf Kompatibilität in verschiedenen Browsern geprüft werden.

Um den Teams den Einstieg in das Thema zu erleichtern, nutzen wir den QA-Oktant. Folgend der ISO 25010 beinhaltet der QA-Oktant die Qualitätskriterien für Softwaresysteme. Sie geben aber auch einen Hinweis auf die notwendigen Testarten, welche sich aus der gesetzten Gewichtung der unterschiedlichen funktionalen und nichtfunktionalen Kriterien ergeben (Abb. 3).

QA Oktant
Abbildung 3: Der QA-Oktant mit gewichteten Qualitätskriterien

Durch die einfache Visualisierung und Gewichtung der unterschiedlichen Qualitätskriterien kann der QA-Oktant für die Planung genutzt werden. Product Owner können damit die Übersicht über relevante Anforderungen behalten und das Team kann gemeinsam mit dem Product Owner die Anforderungen anhand der Qualitätskriterien einordnen. Durch die Gewichtung im Team können unterschiedliche Meinungen besser wahrgenommen und eine gemeinsame Einordnung anschaulich dokumentiert werden. Aus dem Ergebnis lassen sich die notwendigen Testarten ableiten.

Um die zweite Frage „Wie und wo wollen wir testen?“ zu beantworten, müsste das Team den gesamten Entwicklungsprozess nach Test- und QA-Aspekten durchforsten und diese dokumentieren. Je nach Projekt kann der Entwicklungsprozess unterschiedlich ausgeprägt sein und damit die Fragestellung schnell recht komplex werden lassen (Abb. 4).

Entwicklungs- und QA-Prozess
Abbildung 4: Entwicklungs- und QA-Prozess

Um auch hier den Teams einen mühelosen Einstieg in das Thema zu geben, haben wir die QA-Karte entwickelt. Die QA-Karte bietet dem Team eine praktische Möglichkeit, die Maßnahmen für eine optimale Testbarkeit der Projekte zu planen und zu dokumentieren. Ziel ist es, bereits zu einem frühen Zeitpunkt alle QA-relevanten Fragen für die Teams und Entwicklungsprojekte durch einen spielerischen Ansatz zu ermitteln. In Planungsrunden können gemeinsam alle Aspekte der Teststrategie wie Testarten und Werkzeuge visualisiert, diskutiert und priorisiert werden. Neben der Planung dient die QA-Karte mit ihrer plakativen Darstellung auch als Erinnerung oder schneller Einstieg in die Teststrategie des Teams.

Zusammengesetzt ergeben der Oktant und die Karte das QA Navigation Board, welches sich als Wandbild platzieren lässt (Abb. 5).

Das QA Navigation Board mit Oktant und Karte als Wandbild
Abbildung 5: Das QA Navigation Board (mit Oktant und Karte) als Wandbild

Mit dem QA Navigation Board haben die Entwicklungsteams ein visuelles Hilfsmittel, mit dem sie frühzeitig die planerischen Aspekte der Qualitätssicherung beurteilen können. Dabei kann das QA Navigation Board innerhalb der Projektlaufzeit auch als Referenz des aktuellen Vorgehens und als Ansatz für potenzielle Verbesserung genutzt werden.

Viel Erfolg beim Testen!