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 TABLE fü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.