Datenbanken härten durch Vermeidung von SQL-Injektionen

SQL-Injektionen sind eine Sicherheitslücke in Datenbankanwendungen, die es Angreifern ermöglicht, bösartige SQL
Befehle in eine Datenbank einzuschleusen. Dies kann durch fehlerhaften Code entstehen, der Benutzereingaben
nicht korrekt validiert. Angreifer können dadurch sensible Daten auslesen, ändern, löschen oder sogar die Kontrolle
über den gesamten Datenbankserver erlangen.

In diesem Artikel möchte ich vorstellen, wie Injektionen funktionieren und was man dagegen tun kann.

Betrachten wir folgendes Beispiel. Die Datenbank führt die Abfrage:

SELECT * FROM users WHERE passwort = 'passwort123' AND benutzername = 'admin';

aus, wobei ‘passwort123’ die Benutzereingabe ist. Wenn ein Angreifer statt eines normalen Passworts die
Zeichenfolge

' OR 1=1 --

eingibt, ändert sich die Abfrage zu:

SELECT * FROM users WHERE passwort = '' OR 1=1 -- AND benutzername = 'admin';

Das — markiert in SQL den Beginn eines Kommentars, sodass alles danach ignoriert wird; die effektive Abfrage
lautet deshalb:

SELECT * FROM users WHERE passwort = '' OR 1=1;

Diese Bedingung ist immer wahr. Auf diese Weise kann der Angreifer alle Benutzerzeilen einsehen oder sich
unberechtigt Zugang verschaffen.

Ein weiteres Beispiel zeigt, wie ein Angreifer sich direkt Administratorrechte verschaffen kann. Auf einer Website,
auf der man sich mit Benutzername und Passwort anmeldet, wird die SQL-Abfrage zur Überprüfung der
Anmeldedaten unsicher per String-Konkatenation zusammengesetzt, zum Beispiel:

SELECT id, benutzername, passwort, info FROM users WHERE benutzername = '…';

Trägt ein Angreifer im Feld für den Benutzernamen die Zeichenfolge

' UNION SELECT 1, 'Angreifer', 'superPasswort', '{}' --

ein, liefert die Datenbank eine zusätzliche, vom Angreifer kontrollierte Zeile zurück. Das — markiert den Rest der
ursprünglichen Abfrage als Kommentar, sodass nur die eingefügte Zeile aktiv wird. Die neue Zeile erzeugt einen
„Fake“-Benutzer, der über die id eindeutig identifiziert wird. Da viele Anwendungen Benutzerrechte über die id
prüfen, würde ein Angreifer, dessen eingefügte Zeile id = 1 enthält — und id = 1 einem Administratorkonto
entspricht — direkt als Administrator eingeloggt werden, ohne dass Benutzername oder Passwort des echten Kontos
bekannt sein müssen. Auf diese Weise kann eine manipulierte Rückgabe die Authentifizierungslogik umgehen, wenn
keine parametrisierten Queries oder weitere Sicherheitsmaßnahmen eingesetzt werden.

SQL-Injektionen lassen sich vor allem durch sorgfältige Handhabung von Benutzereingaben verhindern. Anstatt
Eingaben direkt in SQL-Abfragen einzubauen, sollten parametrisierte Queries oder Prepared Statements
verwendet werden; sie sorgen dafür, dass Benutzerdaten niemals die Logik der Abfrage verändern können. Auch
Object-Relational Mapping (ORMs) oder sichere Abfrage-APIs bieten diesen Schutz oft automatisch.

Ein besonders wichtiger Punkt ist die sichere Speicherung von Passwörtern. Sie dürfen niemals im Klartextgespeichert werden, sondern sollten gehasht und gesalzen werden:

  • Hashen bedeutet, dass das Passwort mit einem Einweg-Algorithmus in eine andere Zeichenfolge umgewandelt wird. Selbst wenn ein Angreifer Zugriff auf die Datenbank erhält, kann er das ursprüngliche Passwort nicht direkt ablesen.
  • Salzen bedeutet, dass jedem Passwort ein zufälliger Wert (Salz) hinzugefügt wird, bevor es gehasht wird. Dadurch entsteht für jedes Passwort selbst bei gleichem Inhalt ein einzigartiger Hash. Das macht es extrem schwer, Passwörter durch vorberechnete Vergleichswerte oder automatisierte Abgleichmethoden zu erraten.

Eingaben sollten überprüft und nur in zulässigen Grenzen erlaubt werden, zum Beispiel durch Whitelists oder
maximale Längen. Das Datenbankkonto der Anwendung sollte nur die Rechte haben, die unbedingt nötig sind.
Ergänzend helfen regelmäßige Prüfungen des Codes, Logging und Monitoring, um Sicherheitslücken früh zu
erkennen und SQL‐Injektionen zu verhindern