EMZETT.
Login

SQLi (SQL-Injection)

Kurz: Eine Angriffstechnik, bei der Angreifer über ungesicherte Eingabefelder eigenen SQL-Code in eine Datenbankabfrage einschleusen — kann Daten auslesen, verändern oder löschen.

Genauer: Entsteht, wenn Nutzereingaben ungeprüft direkt in eine SQL-Abfrage eingebaut werden (String-Verkettung statt parametrisierter Queries). Ein klassisches Beispiel: ein Login-Feld, in das ' OR '1'='1 eingegeben wird, kann die Passwortprüfung aushebeln. Die Standard-Verteidigung sind parametrisierte Queries/Prepared Statements, bei denen Nutzereingaben nie als ausführbarer SQL-Code interpretiert werden können.

Im Detail

Eine verwundbare Login-Abfrage könnte naiv so aussehen (String-Verkettung, Nutzereingabe direkt eingebaut):

-- Verwundbarer Code (NIEMALS so schreiben):
query = "SELECT * FROM users WHERE username = '" + input + "' AND password = '" + pw + "'"
 
-- Eingabe: username = admin' --
-- Ergebnis-Query:
SELECT * FROM users WHERE username = 'admin' --' AND password = '...'
-- Der Passwort-Check wird durch "--" (SQL-Kommentar) einfach auskommentiert!

Über solche Manipulationen kann ein Angreifer nicht nur die Login-Prüfung umgehen, sondern je nach Rechten der Datenbankverbindung auch komplette Tabellen auslesen (UNION SELECT um Daten aus anderen Tabellen mit in die Ausgabe zu schmuggeln), Daten verändern oder löschen, oder in schlimmen Fällen sogar Befehle auf dem Datenbankserver selbst ausführen.

Die zuverlässige Verteidigung ist strukturell, nicht durch “Filtern gefährlicher Zeichen”:

// Sicher: parametrisierte Query - Eingabe wird NIE als SQL-Code interpretiert
db.query("SELECT * FROM users WHERE username = $1", [input])

Bei parametrisierten Queries (auch “Prepared Statements”) sendet die Anwendung die Struktur der Abfrage und die Nutzereingabe getrennt an die Datenbank — die Datenbank selbst weiß dadurch immer, welcher Teil “Code” (die Abfragestruktur) und welcher Teil reine “Daten” (die Eingabe) ist, egal was der Nutzer eintippt. Moderne ORMs (siehe Drizzle ORM) nutzen intern standardmäßig parametrisierte Queries, weshalb SQL-Injection bei korrektem Einsatz eines ORMs praktisch ausgeschlossen ist — Rohdaten-SQL mit String-Verkettung bleibt trotzdem in jeder Sprache/jedem Framework möglich und gefährlich.

Blind SQL Injection

Nicht immer gibt eine verwundbare Anwendung Datenbankfehler oder Abfrageergebnisse direkt aus — bei “Blind SQL Injection” sieht der Angreifer keine direkte Rückmeldung, kann aber trotzdem Informationen extrahieren, indem er Bedingungen formuliert, die das Verhalten der Anwendung sichtbar beeinflussen (z. B. eine andere Antwortzeit oder eine andere Seite je nachdem ob eine Bedingung wahr oder falsch ist). Ein Beispiel: ' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin')='a — liefert die Anwendung dieselbe Antwort wie ohne die Bedingung, war die Vermutung richtig, sonst nicht. Zeichen für Zeichen lässt sich so theoretisch ein komplettes Passwort extrahieren, auch ganz ohne sichtbare Fehlermeldungen — deutlich langsamer als klassische SQLi, aber genauso gefährlich.

Weitere Schutzebenen

Parametrisierte Queries sind die wichtigste, aber nicht die einzige Verteidigungslinie. Das Prinzip der minimalen Rechte (“Principle of Least Privilege”) begrenzt den Schaden selbst bei einer erfolgreichen Injection: Der Datenbank-User, mit dem sich eine Webanwendung verbindet, sollte nur die tatsächlich benötigten Rechte haben (z. B. kein DROP TABLE-Recht für einen reinen Lese-Endpunkt). Eine Web Application Firewall (WAF) kann zusätzlich bekannte Injection-Muster im eingehenden Traffic erkennen und blockieren, bevor sie die Anwendung überhaupt erreichen — als zusätzliche Absicherung, nicht als Ersatz für sichere Datenbankzugriffe im Code selbst. Regelmäßige automatisierte Sicherheitsscans (z. B. mit Tools wie sqlmap im Rahmen eigener Tests) helfen, versehentlich eingeführte Injection-Lücken frühzeitig vor einem echten Angriff zu finden.

Siehe auch: SQL, Forged Cookies