SQL-Injection verstehen: 5 Schutz-Maßnahmen für deine Datenbank

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.

SQL Injection

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 oder 1=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ßnahmeErläuterung
1Prepared Statements / ParameterTrenne SQL-Code und Nutzereingaben, um Injection zu verhindern.
2Input Validation / WhitelistingErlaube nur erwartete Eingaben (z. B. E-Mail, Zahl, Liste) und blockiere alles andere.
3Minimale Rechte für Datenbank-UserJeder Datenbank-Account sollte nur die nötigsten Berechtigungen haben.
4Keine Admin-Accounts für WebanwendungRoot oder sa für Webanwendungen vermeiden – reduziert Schadenspotenzial.
5ORM korrekt nutzenNur sichere ORM-Funktionen verwenden, keine direkte String-Konkatenation.
6WAF / Firewall einsetzenWeb Application Firewalls erkennen und blockieren Angriffe automatisch.
7SQL-Fehler protokollierenFehler speichern, aber nicht an Nutzer ausgeben – sonst können Angreifer Details sehen.
8Verdächtige Requests überwachenAngriffe wie UNION SELECT, ‚ OR 1=1– etc. erkennen und blockieren.
9Tests in Testumgebung durchführenSQLi-Tests nur in sicheren Testumgebungen durchführen, nicht auf Live-Systemen.
10Sicherheitsscanner nutzenTools 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.