SQL-Injection – Angriff verstehen und Daten schützen
SQL-Injection ist eine der gefährlichsten Angriffsmethoden auf Webanwendungen. Ein Angreifer schleust über Eingabefelder (Login, Suche, Formulare) eigenen SQL-Code in eine Datenbankabfrage ein. Gelingt das, kann er Daten auslesen, verändern oder löschen – im schlimmsten Fall die Kontrolle über den Server übernehmen. Die OWASP-Liste führt Injection seit Jahren unter den Top-Risiken.
Wie der Angriff funktioniert
Wer eine Query direkt aus Nutzereingaben zusammenbaut, öffnet die Tür:
SELECT * FROM user WHERE email = '$email' AND passwort = '$pw'
Gibt der Angreifer als Passwort ' OR '1'='1 ein, wird daraus:
SELECT * FROM user WHERE email = 'x' AND passwort = '' OR '1'='1'
Die Bedingung ist immer wahr – der Login ist ohne gültiges Passwort möglich. Mit UNION SELECT lassen sich weitere Tabellen auslesen, mit -- oder # Restbedingungen auskommentieren. Automatisierte Tools scannen das Web nach solchen Lücken.
Die wichtigste Gegenmaßnahme: Prepared Statements
Die Datenbank bekommt den SQL-Befehl und die Daten getrennt. Nutzereingaben werden nie als Code interpretiert, sondern immer als reine Werte behandelt.
// PHP mit PDO
$stmt = $pdo->prepare('SELECT * FROM user WHERE email = ? AND passwort = ?');
$stmt->execute([$email, $pw]);
# Python mit sqlite3
cur.execute('SELECT * FROM user WHERE email = ? AND passwort = ?', (email, pw))
Fast alle Datenbank-Treiber unterstützen Platzhalter (? oder benannte Parameter). Auch ORM-Bibliotheken (z. B. Doctrine, SQLAlchemy) erzeugen parametrisierte Queries, wenn man ihre Query-Builder nutzt statt roher SQL-Strings.
Weitere Schutzschichten
- Eingabevalidierung: Erwartete Formate prüfen (Whitelist statt Blacklist), z. B. E-Mail-Format, Zahlenbereiche.
- Least Privilege: Der DB-Benutzer der Anwendung darf nur das, was die Anwendung braucht – kein
DROP TABLEfür eine Login-Seite. Siehe auch Passwort-Hashing. - Keine Fehlerdetails nach außen: SQL-Fehlermeldungen verraten Angreifern Tabellennamen.
- WAF/Filter: Eine Web Application Firewall kann bekannte Angriffsmuster blocken – ersetzt aber nie Prepared Statements.
- Updates: Framework und Datenbank-Treiber aktuell halten; Lücken werden laufend geschlossen.
Fazit
Die Regel ist einfach: Niemals Nutzereingaben direkt in SQL-Strings einbauen. Wer konsequent Prepared Statements und ORM-Parameter nutzt, schließt die Angriffsklasse praktisch komplett. Details zu den SQL-Befehlen selbst findest du in der SQL-Schnellreferenz und SQL-Grundlagen.