Eine SQL-Injection zählt zu den Sicherheitslücken die häufig vorgefunden und als sehr kritisch betrachtet werden. In den meisten Fällen sind öffentlich erreichbare Webanwendungen, auf denen Benutzer Eingaben tätigen können, das Ziel. Ein Log-In oder Suchfeld genügt den Angreifern. Doch wie funktioniert dieser Angriff und was genau passiert im Hintergrund, nachdem der Nutzer eine Eingabe getätigt hat.
Funktionsweise eines SQL-Statements
Der Großteil aller Websites, die dem Benutzer ein Eingabefeld, wie einen Login, zur Verfügung stellen, produzieren den Inhalt dynamisch. Das bedeutet, die Datenbank, die beispielsweise alle Blogbeiträge beinhaltet, wird erst durchsucht, nachdem der Benutzer seinen Suchbefehl in das Suchfenster eingegeben hat. Damit die Ergebnisse, die durch unseren Suchbefehl erzeugt werden, von der Datenbank auf unseren Bildschirm gelangen, benötigen die meisten Websites SQL.
Structured Query Language (SQL) stellt die Verbindung zwischen einer Webapplikation und dessen Datenbanken her. Die Kommunikation findet mit sogenannten SQL-Statements statt. Der Programmcode der im Hintergrund des Suchfensters abläuft nutzt SQL-Statements und sendet diese an die Datenbank. Die Datenbank verarbeitet diese Befehle und liefert die passenden Daten. Solch ein Befehl besteht meist aus drei verschiedenen Teilen, SELECT, WHERE und FROM:
SELECT blogtitle FROM blogs WHERE keyword = “Test”
Das SELECT entscheidet in welcher Spalte gesucht werden soll, in dem oben aufgeführten Beispiel wird die Spalte mit dem Namen blogtitle durchsucht. Das FROM entscheidet, in welcher Tabelle gesucht wird, hier wird in der Tabelle blogs gesucht. WHERE ist in den häufigsten Fällen der Parameter, der von dem User eingegeben werden kann. In unserem Beispiel gibt der Benutzer “Test” in das Suchfeld ein. Daraufhin wird das o.a. SQL-Statement erstellt, welches der Datenbank mitteilt, dass das Programm gerne alle blogtitle aus der Tabelle blogs hätte, in denen das keyword der Eingabe “Test” entspricht.
SQL-Injection – Die Sicherheitslücke in SQL-Statements
Innerhalb der oben dargestellten Methode kann es jedoch die Sicherheitslücke geben, die sich SQL-Injection nennt. Bei der SQL-Injection benutzt der Angreifer ein Eingabefeld, z.B. ein Suchfeld, um mit speziellen Eingaben Zugriff zu Daten zu erlangen, zu denen er nicht berechtigt ist. Dazu muss die Eingabe das SQL-Statement so verändern, dass die Datenbank Daten ausgibt, zu denen der Nutzer keinen Zugriff haben sollte. Ein einfaches Beispiel, wie eine Eingabe zu einer Fehlinterpretation der Datenbank führt ist z.B. “Tes’t”.
Befindet sich innerhalb des Eingabetextes ein Anführungszeichen entsteht folgendes SQL-Statement bei der Datenbank:
SELECT blogtitle FROM blogs WHERE keyword = “Tes’t”
Die Datenbank erkennt das erste Anführungszeichen und sucht nun nach dem folgenden Anführungszeichen, der die Eingabe beendet. Da der Suchbefehl jedoch selber auch ein Anführungszeichen (‘) stürzt das Programm ab, denn nun möchte die Datenbank nach dem Text: “Tes” suchen, allerdings führt das letzte Anführungszeichen zu einem Syntax-Fehler.
Die Fehlinterpretation kann der Angreifer nicht nur dafür ausnutzen verschiedene Fehlermeldungen zu generieren, sondern es besteht die Möglichkeit sich beispielsweise die gesamte Tabelle ausgeben zu lassen. Dies gelingt, indem der eingegebene Text nicht zu einem Syntax-Fehler führt, sondern eigenen Code enthält den die Datenbank ausführt. Die folgende Eingabe führt ebenso zu einer Code Ausführung: Test’ OR ‘a’=’a
Diesen Code kann ein Angreifer dazu nutzen sich auf Webseiten einzuloggen obwohl dieser weder einen Benutzernamen noch ein Passwort kennt. Bei einem Login geschieht ebenfalls eine Datenbankabfrage, welche aber nur Wahr oder Falsch zurückgibt. So wird mittels SQL bei einem Login gefragt: Gibt es in meiner Datenbank einen Benutzer mit dem Benutzernamen “Jan” und dem Passwort “schalke04”. Wenn es diese Anfrage wahr zurückgibt wird der Benutzer eingeloggt.
Nun aber zurück zu dem oben gezeigten Angriffscode. Die Datenbank erkennt den ersten Text und zwar Test. Doch nun ist die Eingabe noch nicht beendet und die Datenbank erkennt durch den Befehl OR eine weitere Bedingung. Die zweite Bedingung, die der Angreifer eingibt ist ‘a’ = ‘a’. Diese Operation ist immer wahr und durch das OR (oder) wird dieser mit der ersten Anfrage verbunden und die Anfrage an die Datenbank gibt immer Wahr zurück.
In dem folgenden Video haben wir auf einer Demo-Website die oben genannte Eingabe für ein Log-In-Fenster verwendet. Die Datenbank hinter der Website enthält keinen einzigen registrierten Benutzer, dementsprechend sollte ein Log-In nicht möglich sein. Sowohl der Benutzername, als auch das Passwort wurde auf Test’ OR ‘a’=’a’ gesetzt und folgendes Ergebnis haben wir erhalten:
Dadurch das unser Befehl immer korrekt ist, werden wir als Benutzer akzeptiert, obwohl kein Benutzerkonto hinterlegt ist.
Der Schutz vor einer SQL-Injection
Die Gefahr, die durch eine SQL-Injection ausgeht, kann sehr groß ein, da ein Angreifer durch die Ausführung eigener Befehle (innerhalb der Datenbank) auf Daten zugreifen kann die geschützt sein sollten. Durch das Erlangen von Informationen über Mitarbeiter, Gehaltslisten, Religionszugehörigkeit oder Behinderungen kann für ein Unternehmen ein sehr hoher Schaden entstehen. Daher wird eine SQL-Injection im Rahmen des Risk Ratings vom Open Web Application Security Projekt als MEDIUM oder HIGH gekennzeichnet
Es gibt eine einfache Methode sich gegen diesen Angriff zu schützen. Das funktioniert, indem das Programm, welches die Eingabe aus dem Suchfeld in ein SQL-Statement packt, nur PreparedStatements benutzt. Ein PreparedStatement ist ein vorgefertigtes SQL-Statement, welches dem Programm vorgibt, wann eine Variable kommt und wann nicht. So kann der Benutzer keinen Code mehr ausführen lassen, der von dem PreparedStatement nicht vorgesehen ist. (“Dieser Codierstil ermöglicht es der Datenbank, zwischen Code und Daten zu unterscheiden, unabhängig davon, welche Benutzereingaben geliefert werden.” CheatSheet OWASP).
Eine weitere Schutzmöglichkeit ist die Verwendung von stored procedure (gespeicherte Prozedur). Hinter einem stored procedure befinden sich mehrere Befehle die zu einer Prozedur gespeichert wurden. Befehle die häufig verwendet werden können so durch einen einzigen Aufruf verwendet werden. Die gespeicherte Prozedur kann zur Laufzeit keine neuen Befehle aufnehmen, dadurch ist es dem Nutzer nicht möglich eigene Befehle zur Ausführung zu bringen. Im Rahmen von Bug Bounty Programmen wird das Finden einer SQL-Injection oft monetär entlohnt.
Das Verwenden von PreparedStatements und stored procedure schützt gegen eine SQL-Injection, jedoch ist es sehr schwierig das gesamte interne Netzwerk und alle Schnittstellen nach draußen zu finden, die potentiell unsicher sind. Dementsprechend empfehlen wir neben den oben genannten Methoden einen Penetrationstest durchzuführen. In unseren Penetrationstest benutzen wir verschiedenste Software um unter anderem SQL-Injections zu finden. Wie genau ein Penetrationstest abläuft können Sie hier erfahren.