SQL-Injection ist seit über 20 Jahren eine der größten Bedrohungen für Webanwendungen – und sie taucht immer wieder ganz oben in der OWASP Top 10 auf. Der Grund: Der Angriffsvektor ist simpel, weit verbreitet und oft erschreckend effektiv. Selbst moderne Anwendungen sind nicht automatisch davor geschützt, wenn grundlegende Sicherheitsprinzipien missachtet werden.
Ein erfolgreich ausgeführter Angriff kann dramatische Folgen haben. Angreifer können sensible Kundendaten stehlen, interne Systeme kompromittieren oder sogar vollständige Kontrolle über den Server erlangen. Die Schadenshöhe reicht von Imageschäden über Bußgelder bis hin zu langfristigen wirtschaftlichen Verlusten.
In diesem Artikel gehen wir einen praxisorientierten Weg: Du lernst die Funktionsweise von SQL-Injection kennen und bekommst fünf konkrete Schutzmaßnahmen, die du direkt umsetzen kannst – inklusive Code-Beispielen in mehreren Programmiersprachen. Das Ziel: Mehr Sicherheit für deine Datenbank in fünf klaren Schichten.

Teil 1: SQL-Injection-Grundlagen
1.1 Wie funktioniert SQL-Injection?
Eine SQL-Injection ist eine Angriffstechnik, bei der ein Angreifer eigenen SQL-Code in eine Datenbankabfrage einschleust. Das gelingt nur, wenn die Anwendung Benutzereingaben ungeprüft in eine SQL-Abfrage einfügt.
Warum ist das gefährlich?
Stell dir vor, ein Login-Formular hat die Felder „Benutzername“ und „Passwort“. Im Code der Anwendung steht so etwas wie:
SELECT * FROM users WHERE user = 'EINGABE_USERNAME' AND password = 'EINGABE_PASSWORT';
Wenn EINGABE_USERNAME
direkt vom Benutzer kommt und der Code keine Prüfung oder Absicherung vornimmt, kann
der Benutzer dort nicht nur Text, sondern auch eigenen SQL-Code einfügen.
Beispiel: Login umgehen
Ein Angreifer könnte in das Feld „Benutzername“ Folgendes eingeben:
admin'--
Die Abfrage würde dann so aussehen:
SELECT * FROM users WHERE user = 'admin'--' AND password = '';
--
ist ein SQL-Kommentar. Alles dahinter wird ignoriert.- Die Passwort-Bedingung wird komplett übersprungen.
- Ergebnis: Der Angreifer meldet sich als
admin
an – ohne das Passwort zu kennen.
Visueller Ablauf
Benutzereingabe ("admin'--")
↓
Unsichere SQL-Abfrage wird gebaut
↓
Datenbank führt den eingeschleusten Code aus
1.2 Die wichtigsten Angriffsarten
Klassische SQL-Injection
Dies ist die einfachste und älteste Form der SQL-Injection. Der Angreifer gibt gezielt Zeichen oder Befehle in ein Eingabefeld ein, um die Datenbank zu einer Fehlermeldung zu bringen. Diese Fehlermeldung verrät oft Details über die Struktur der Datenbank – zum Beispiel, welche Tabellen und Spalten existieren.
Beispiel: Ein Login-Feld fragt den Benutzernamen ab.
Gibt der Angreifer ' OR '1'='1
ein, könnte die Abfrage so aussehen:
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '';
Da '1'='1'
immer wahr ist, liefert die Datenbank alle Benutzer zurück und der Angreifer könnte sich einloggen.
Blind SQL-Injection
Hier gibt die Website keine Fehlermeldungen aus. Der Angreifer muss durch Beobachten herausfinden, ob seine Eingabe etwas bewirkt. Er achtet auf Veränderungen auf der Seite oder auf ungewöhnlich lange Ladezeiten.
Beispiel: Der Angreifer fügt in ein Eingabefeld ' AND SLEEP(5)--
ein.
Wenn die Seite nun 5 Sekunden länger lädt, weiß er, dass seine Eingabe ausgeführt wurde und kann so Schritt für Schritt Daten herausfinden.
UNION-basierte Angriffe
Bei einem UNION-basierten Angriff hängt der Angreifer eine zweite Abfrage an die ursprüngliche Abfrage der Website an.
Mit dem Schlüsselwort UNION
werden beide Ergebnisse kombiniert.
So können Daten aus anderen Tabellen angezeigt werden, die eigentlich verborgen bleiben sollten.
Beispiel: Angenommen, die Seite zeigt eine Produktliste mit
SELECT name, price FROM products;
Gibt der Angreifer in ein Suchfeld folgendes ein:
' UNION SELECT credit_card_number, name FROM payments--
Dann könnten im Produktbereich plötzlich Kreditkartendaten erscheinen – wenn die Anwendung unsicher ist.
Teil 2: Die 5 Schutz-Maßnahmen
Maßnahme 1: Prepared Statements & Parameterisierte Queries
SQL-Injection passiert, wenn Benutzereingaben direkt in eine Datenbankabfrage eingefügt werden. Ein Angreifer kann so die Abfrage manipulieren und Zugriff auf Daten erlangen, die er eigentlich nicht sehen sollte.
Beispiel für eine unsichere Abfrage
SELECT * FROM users WHERE username = 'Eingabe' AND password = 'Eingabe';
Gibt ein Angreifer als Benutzername admin'--
ein, wird die Abfrage so interpretiert:
SELECT * FROM users WHERE username = 'admin'--' AND password = '';
Das --
kommentiert den Rest der Abfrage aus. Der Angreifer kann sich ohne Passwort einloggen.
Was Prepared Statements machen
Prepared Statements trennen SQL-Code von Benutzerdaten. Die Datenbank behandelt Eingaben niemals als Code, nur als Text.
Beispiel in PHP (PDO)
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username");
$stmt->bindParam(':username', $userInput);
$stmt->execute();
Beispiel in Python (SQLite)
cursor.execute("SELECT * FROM users WHERE email = ?", (user_input,))
rows = cursor.fetchall()
Tipps für Anfänger
- Niemals SQL-Strings direkt mit Benutzereingaben zusammenfügen.
- Immer Platzhalter verwenden und Werte sicher binden.
- Auch Zahlen oder Datumswerte sollten parametrisiert werden.
Vorher-Nachher zum Merken
Unsicher:
"SELECT * FROM users WHERE username = '" + userInput + "'"
Sicher:
"SELECT * FROM users WHERE username = ?"
Selbst wenn ein Angreifer versucht, SQL-Code einzuschleusen, wird die Eingabe nur als Text behandelt, die Abfrage bleibt sicher.
Maßnahme 2: Input Validation & Whitelisting
Selbst sichere Prepared Statements sind nur ein Teil des Schutzes. Es ist wichtig, dass nur erlaubte Eingaben in die Anwendung gelangen. Das schützt vor unerwarteten oder gefährlichen Daten.
Was Input Validation bedeutet
Input Validation prüft die Eingaben der Benutzer und akzeptiert nur gültige Werte.
Alles andere wird abgelehnt oder korrigiert.
Beispiel für E-Mail-Validierung in PHP
$email = $_POST['email'];
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo "Ungültige E-Mail-Adresse!";
}
Hier wird überprüft, ob die Eingabe tatsächlich wie eine E-Mail aussieht.
Alles andere wird abgelehnt.
Beispiel für Postleitzahlen-Validierung mit Regex
$plz = $_POST['plz'];
if (!preg_match("/^\d{5}$/", $plz)) {
echo "Ungültige Postleitzahl!";
}
Nur fünfstellige Zahlen werden akzeptiert, andere Eingaben blockiert.
Was Whitelisting bedeutet
Beim Whitelisting legst du genau fest, welche Werte erlaubt sind. Alles andere wird automatisch abgelehnt.
Beispiel für Sortier-Parameter
$allowed_columns = ['name', 'date', 'price'];
$order_by = in_array($_GET['sort'], $allowed_columns) ? $_GET['sort'] : 'id';
Nur die Spalten name
, date
oder price
können für die Sortierung verwendet werden.
Jeder andere Wert wird auf id
zurückgesetzt.
Tipps für Anfänger
- Akzeptiere nur Werte, die du wirklich erwartest.
- Nutze Whitelists statt Blacklists – Blacklists lassen oft gefährliche Eingaben durch.
- Validiere nicht nur Text, sondern auch Zahlen, Datumswerte oder IDs.
- Kombiniere Input Validation immer mit Prepared Statements für maximale Sicherheit.
Vorher-Nachher-Beispiel
Unsicher:
$query = "SELECT * FROM products ORDER BY " . $_GET['sort'];
Sicher:
$allowed_columns = ['name','date','price'];
$order_by = in_array($_GET['sort'], $allowed_columns) ? $_GET['sort'] : 'id';
$query = "SELECT * FROM products ORDER BY " . $order_by;
Maßnahme 3: Principle of Least Privilege
Das Prinzip „Least Privilege“ bedeutet: Jeder Benutzer oder jede Anwendung bekommt nur die Rechte, die wirklich nötig sind. Wenn ein Angreifer eine Schwachstelle findet, kann er so weniger Schaden anrichten.
Problem, wenn man zu viele Rechte vergibt
Viele Entwickler nutzen oft den Datenbank-Administrator (root
oder sa
) für ihre Webanwendung.
Fällt die Anwendung einem Angriff zum Opfer, hat der Angreifer sofort volle Kontrolle über die gesamte Datenbank.
Wie man es richtig macht
Stattdessen erstellt man für jede Anwendung einen eigenen Benutzer mit nur den nötigen Rechten.
Beispiel in MySQL
-- NIE 'root' oder 'sa' für die App nutzen!
CREATE USER 'webapp'@'localhost' IDENTIFIED BY 's1ch3resP4ss!';
GRANT SELECT, INSERT ON shop.products TO 'webapp'@'localhost';
REVOKE DELETE, DROP ON *.* FROM 'webapp'@'localhost';
In diesem Beispiel darf der Benutzer webapp
nur Daten abfragen (SELECT
) oder neue Daten einfügen (INSERT
) in der Tabelle shop.products
.
Löschen oder Tabellen löschen (DELETE
, DROP
) ist nicht erlaubt.
Tipps für Anfänger
- Erstelle für jede Anwendung oder jeden Service einen eigenen Datenbank-Benutzer.
- Vergib nur die Rechte, die unbedingt nötig sind.
- Überprüfe regelmäßig, ob Benutzerrechte noch aktuell und korrekt sind.
- Vermeide Administrator-Konten in der Produktion, soweit es möglich ist.
Vorher-Nachher-Beispiel
Unsicher:
-- Anwendung nutzt root
mysql -u root -p
Sicher:
-- Anwendung nutzt eigenen Benutzer
mysql -u webapp -p
Mit der „Least Privilege“-Strategie wird der Schaden eines erfolgreichen Angriffs stark begrenzt.
Maßnahme 4: ORMs richtig nutzen
ORM steht für Object-Relational Mapping. Ein ORM ist ein Werkzeug oder eine Bibliothek, das deine Programmiersprache mit der Datenbank verbindet. Anstatt selbst SQL-Abfragen zu schreiben, arbeitest du mit Objekten oder Klassen, und das ORM übersetzt deine Befehle automatisch in SQL.
Beispiel: Du hast in C# eine Klasse User
. Mit einem ORM kannst du einfach sagen „Hole alle User“,
und das ORM erstellt die passende SELECT
-Abfrage für die Datenbank.
Du musst dich also nicht um die genauen SQL-Befehle kümmern.
Warum ORMs helfen
Ein ORM (Object-Relational Mapping) wie Hibernate, Entity Framework oder Sequelize übersetzt Datenbankabfragen in Programmlogik. Vorteil: ORMs übernehmen oft das Escaping von Daten automatisch und schützen so vor vielen SQL-Injections.
Aber Achtung!
Ein ORM macht deine Anwendung nicht automatisch sicher. Wenn du Daten in Abfragen direkt zusammenfügst, kann SQL-Injection trotzdem passieren.
Unsicheres Beispiel in C# mit Entity Framework
// Gefährlich, weil user_input direkt in die Query kommt
var users = context.Users.FromSqlRaw("SELECT * FROM Users WHERE Name = '" + name + "'");
Sichere Alternative mit Parametern
// Sicher, weil Parameter automatisch escaped werden
var users = context.Users.FromSqlInterpolated($"SELECT * FROM Users WHERE Name = {name}");
Tipps für Anfänger
- Verwende immer die Parameter-Funktionen deines ORMs, nicht das einfache Zusammenfügen von Strings.
- Kontrolliere auch, ob ORMs in deiner Sprache weitere Sicherheitsfeatures haben.
- Denke daran: ORM schützt nur die Datenbankabfragen, nicht die gesamte Anwendung.
Vorher-Nachher-Beispiel
Unsicher:
var sql = "SELECT * FROM Users WHERE Name = '" + userInput + "'";
var users = context.Users.FromSqlRaw(sql);
Sicher:
var users = context.Users.FromSqlInterpolated($"SELECT * FROM Users WHERE Name = {userInput}");
Richtig genutzt, reduzieren ORMs das Risiko von SQL-Injections erheblich.
Maßnahme 5: Defense-in-Depth (WAFs & Logging)
Defense-in-Depth heißt, dass du nicht nur auf eine Schutzmaßnahme vertraust, sondern mehrere Sicherheitslagen aufbaust. So ist deine Anwendung besser geschützt, selbst wenn ein Mechanismus versagt.
1. Web Application Firewalls (WAFs)
Eine WAF überwacht den Datenverkehr zu deiner Webanwendung und blockiert verdächtige Anfragen. Sie kann typische SQL-Injection-Muster erkennen und Angriffe abwehren, bevor sie die Datenbank erreichen.
Beispiele für WAFs:
- ModSecurity (Open-Source, auf dem Server installiert)
- Cloud-Lösungen wie AWS WAF oder Cloudflare WAF
Eine WAF ist besonders nützlich, weil sie auch gegen neue Angriffsmuster helfen kann, die du noch nicht in deinem Code bedacht hast.
2. Logging & Monitoring
Du solltest verdächtige Aktivitäten in deiner Anwendung protokollieren. So kannst du Angriffe erkennen und reagieren, bevor Schaden entsteht.
Beispiele für Logging:
# Verdächtiger SQLi-Versuch wird protokolliert
[Alert] Blocked SQLi attempt: 1=1 in query param 'id'
Monitoring bedeutet, dass du diese Logs regelmäßig überprüfst oder automatisierte Alerts einrichtest. So siehst du sofort, wenn jemand versucht, SQL-Injection auszuführen, und kannst reagieren.
Tipps für Anfänger
- Nutze WAF-Regeln, die speziell für SQL-Injection geschrieben wurden.
- Protokolliere SQL-Fehler, aber zeige sie niemals direkt dem Benutzer.
- Überprüfe regelmäßig deine Logs auf verdächtige Muster wie
UNION SELECT
oder1=1
.
Praxisbeispiel
Angreifer versucht: https://example.com/product?id=1 OR 1=1
Die WAF erkennt das Muster OR 1=1
und blockiert die Anfrage. Gleichzeitig wird ein Log-Eintrag erstellt, den du überprüfen kannst.
Durch die Kombination aus WAF und Logging erhöhst du die Sicherheit deiner Anwendung deutlich – selbst wenn andere Maßnahmen versagen.
Teil 3: Praxistest & Tools
Um die Sicherheit deiner Anwendung zu überprüfen, gibt es mehrere Methoden. Zwei gängige Ansätze sind:
1. Selbst testen
Du kannst SQL-Injection selbst in einer sicheren Testumgebung ausprobieren, um zu verstehen, wie Angriffe funktionieren und wie deine Schutzmaßnahmen wirken.
Einfacher Test
Versuche in einem Login-Feld oder Eingabefeld folgende Eingabe: ' OR 1=1--
.
Wenn die Anwendung daraufhin ungewollt Zugang gewährt oder Daten zeigt, ist sie anfällig.
Tool: sqlmap
sqlmap ist ein automatisches Test-Tool für SQL-Injection. Du kannst damit eine URL analysieren und prüfen, ob die Datenbank anfällig ist.
# Beispielaufruf
sqlmap -u "https://example.com?id=1" --dbs
Dieses Kommando prüft, welche Datenbanken auf der Seite erreichbar sind. Führe solche Tests nur auf **eigene Systeme oder mit ausdrücklicher Erlaubnis** durch.
2. Sicherheitsscanner
Professionelle Sicherheitsscanner helfen, Schwachstellen zu erkennen und zu dokumentieren. Sie sind vor allem nützlich, um regelmäßige Sicherheitsüberprüfungen durchzuführen.
Beliebte Tools:
- OWASP ZAP – Open-Source und ideal für Anfänger und Profis
- Burp Suite – Umfassendes Tool für manuelle und automatische Tests
- Acunetix – Kommerziell, sehr benutzerfreundlich
Tipps für Anfänger
- Teste immer in einer sicheren Umgebung, nicht auf Live-Systemen ohne Erlaubnis.
- Beginne mit kleinen Testfällen wie
' OR 1=1--
, bevor du komplexe Tools einsetzt. - Dokumentiere Ergebnisse, damit du Schwachstellen systematisch beheben kannst.
Praxistests sind wichtig: Nur wer weiß, wie Angriffe funktionieren, kann seine Anwendung wirklich effektiv schützen.
SQL-Injection-Checkliste
Nutze diese Checkliste, um systematisch zu prüfen, ob deine Anwendung gegen SQL-Injection geschützt ist.
Jede Maßnahme ist ein wichtiger Baustein für die Sicherheit deiner Daten.
# | Maßnahme | Erläuterung |
---|---|---|
1 | Prepared Statements / Parameter | Trenne SQL-Code und Nutzereingaben, um Injection zu verhindern. |
2 | Input Validation / Whitelisting | Erlaube nur erwartete Eingaben (z. B. E-Mail, Zahl, Liste) und blockiere alles andere. |
3 | Minimale Rechte für Datenbank-User | Jeder Datenbank-Account sollte nur die nötigsten Berechtigungen haben. |
4 | Keine Admin-Accounts für Webanwendung | Root oder sa für Webanwendungen vermeiden – reduziert Schadenspotenzial. |
5 | ORM korrekt nutzen | Nur sichere ORM-Funktionen verwenden, keine direkte String-Konkatenation. |
6 | WAF / Firewall einsetzen | Web Application Firewalls erkennen und blockieren Angriffe automatisch. |
7 | SQL-Fehler protokollieren | Fehler speichern, aber nicht an Nutzer ausgeben – sonst können Angreifer Details sehen. |
8 | Verdächtige Requests überwachen | Angriffe wie UNION SELECT, ‚ OR 1=1– etc. erkennen und blockieren. |
9 | Tests in Testumgebung durchführen | SQLi-Tests nur in sicheren Testumgebungen durchführen, nicht auf Live-Systemen. |
10 | Sicherheitsscanner nutzen | Tools wie OWASP ZAP oder Burp Suite helfen, Schwachstellen systematisch aufzudecken. |
Download: Lade die SQL-Injection-Checkliste hier runter: SQL Injection Checkliste (PDF)
Fazit
SQL-Injection bleibt eine der größten Bedrohungen für Webanwendungen. Mit den fünf Schutzmaßnahmen, die wir in diesem Artikel vorgestellt haben, kannst du deine Anwendung deutlich sicherer machen. Sicherheit ist kein einmaliges Feature, sondern eine Grundhaltung, die du konsequent umsetzen und regelmäßig überprüfen solltest.
Wer Prepared Statements, Input Validation, minimale Datenbankrechte, sichere ORM-Nutzung und Defense-in-Depth kombiniert, reduziert das Risiko eines erfolgreichen Angriffs erheblich.
Dynamic SQL: Wann es sich lohnt – und wann es gefährlich wird
Dynamic SQL ist ein mächtiges Werkzeug in der Datenbankwelt –...
Artikel lesenWas ist SQL? Einfach erklärt!
Stell dir vor, du könntest mit ein paar einfachen Befehlen...
Artikel lesenTimeouts, Deadlocks & Co – was tun bei Problemen?
In datenbankgestützten Anwendungen gehören Timeouts und Deadlocks zu den häufigsten...
Artikel lesenCTEs verstehen: Dein Einstieg in die SQL-WITH-Klausel
SQL-Abfragen können schnell unübersichtlich werden, besonders wenn du mehrere Verschachtelungen...
Artikel lesen