SQL Injection ist eine Art von Datenbankangriff, bei dem ein Angreifer bösartigen SQL-Code in Abfrageparameter einschleust und so unbefugten Zugriff auf Daten oder die Möglichkeit erhält, diese zu ändern. Laut OWASP (2025) bleibt SQL Injection eine der kritischen Schwachstellen, die zu einer vollständigen Kompromittierung der Datenbank führen kann. SQL-Code-Injektion ermöglicht es dem Angreifer, Datensätze zu lesen, zu ändern und zu löschen sowie in einigen Fällen Zugriff auf das Betriebssystem des Servers zu erhalten.
Wichtige Punkte
SQL Injection ist eine Schwachstelle, die auftritt, wenn eine Anwendung SQL-Abfragen durch Zeichenkettenverkettung mit Benutzerdaten erstellt. Ein Angreifer übergibt eine speziell konstruierte Zeichenkette in einem Abfrageparameter, die die Struktur des SQL-Befehls ändert. Anstatt Daten zu sein, wird die injizierte Zeichenkette Teil des SQL-Codes, wodurch der Angreifer beliebige Abfragen gegen die Datenbank ausführen kann. Laut dem Verizon Data Breach Report (2025) ist SQL Injection in 8% aller untersuchten Datenlecks vorhanden.
Trotz einer bekannten Schwachstelle (erste Erwähnung Ende der 1990er Jahre) wird SQL Injection immer noch in modernen Anwendungen gefunden. Der Grund ist menschliches Versagen: Entwickler schreiben Code mit Zeichenkettenverkettung, Legacy-Code wird nicht refaktoriert und ORM-Frameworks werden falsch verwendet (z. B. Raw-Queries mit Zeichenketteninterpolation). Laut Veracode (2026) enthalten etwa 14% aller gescannten Anwendungen mindestens eine SQLi-Schwachstelle.
Eine erfolgreiche SQL Injection gibt dem Angreifer eine breite Palette von Fähigkeiten: Lesen beliebiger Datenbanktabellen, einschließlich Passwort-Hashes und persönlicher Benutzerdaten; Ändern und Löschen von Datensätzen; Ausführen von Verwaltungsoperationen (DROP TABLE, TRUNCATE); und in einigen Konfigurationen die ferngesteuerte Ausführung von Befehlen über xp_cmdshell (MSSQL) oder INTO OUTFILE (MySQL). Die Folgen reichen von der Offenlegung von Benutzerdaten bis zum vollständigen Verlust der Systemkontrolle.
SQL-Injektionen werden nach der Methode der Datenextraktion aus der Datenbank klassifiziert. Die Wahl der Methode hängt davon ab, wie die Anwendung Abfrageergebnisse und Fehlermeldungen verarbeitet. Die OWASP-Klassifizierung identifiziert drei Haupttypen: In-band (Datenextraktion über denselben Kanal), Inferential/Blind (logische Schlussfolgerungen) und Out-of-band (Datenübertragung über einen anderen Kanal).
| Typ | Extraktionsmethode | Komplexität | Häufigkeit |
|---|---|---|---|
| In-band (klassisch) | Direkt über das Abfrageergebnis | Niedrig | Hoch |
| Blind SQLi | Logische Schlussfolgerungen aus Serverantworten | Hoch | Mittel |
| Out-of-band | Über einen externen Kanal (DNS, HTTP) | Mittel | Niedrig |
Der häufigste Typ. Ein Angreifer injiziert SQL-Code in einen Abfrageparameter, und das Ergebnis der Injektion ist direkt in der Serverantwort sichtbar. Zwei Untertypen: Error-based (über DB-Fehlermeldungen) und UNION-based (über den UNION SELECT-Operator). Error-based nutzt Informationen aus Fehlermeldungen, wie einen MySQL-Syntaxfehler, der den Tabellennamen oder die Abfragestruktur preisgeben kann. UNION-based ermöglicht es, Ergebnisse legitimer Abfragen mit Daten aus anderen Datenbanktabellen zu kombinieren.
Wird verwendet, wenn die Anwendung keine Abfrageergebnisse oder Fehlermeldungen anzeigt. Ein Angreifer stellt Ja/Nein-Fragen, indem er Abfragen mit logischen Bedingungen sendet und die Unterschiede in den Serverantworten (z. B. Antwortzeit oder Seiteninhalt) analysiert. Time-based Blind SQLi verwendet Verzögerungsfunktionen (SLEEP, WAITFOR DELAY), um Bedingungen zu bestätigen — wenn die Seite länger lädt, ist die Bedingung wahr. Diese Methode ist sehr langsam — das Extrahieren eines einzelnen Datensatzes kann Stunden dauern.
# Beispiel für Blind SQL Injection (zeitbasiert)
# Wenn SQLi anfällig ist, wird SLEEP(2) ausgeführt, wenn die Bedingung erfüllt ist
import requests
import time
payload = "' OR IF(SUBSTRING((SELECT password FROM users LIMIT 1),1,1)='a',SLEEP(2),0) -- "
url = "http://example.com/user?id=1" + payload
start = time.time()
response = requests.get(url)
elapsed = time.time() - start
# Wenn die Antwort nach >2 Sekunden eintrifft — der erste Buchstabe des Passworts ist 'a'
print(f"Time: {elapsed:.2f}s - First letter is 'a'" if elapsed > 2 else "First letter is not 'a'")
Daten werden nicht über die HTTP-Antwort, sondern über alternative Kanäle übertragen: DNS-Abfragen, HTTP-Anfragen an einen externen Server, SMTP. Wird verwendet, wenn die Anwendung keine Abfrageergebnisse zurückgibt oder Fehler anzeigt. MySQL unterstützt die Funktion LOAD_FILE(), die eine DNS-Abfrage auslösen kann, und MSSQL hat xp_dirtree zum Senden von Daten an einen entfernten SMB-Server. Out-of-band SQL Injection ist effektiv, erfordert aber zusätzliche Angreiferserver-Einrichtung und spezifische DB-Funktionen.
Der Mechanismus der SQL Injection basiert darauf, dass SQL Anführungszeichen für Zeichenkettenliterale verwendet. Wenn eine Anwendung Benutzereingaben direkt ohne Escape in eine SQL-Abfrage einfügt, kann ein Angreifer die Zeichenkette „schließen“ und beliebigen SQL-Code hinzufügen. Zum Beispiel verwandelt in der Abfrage SELECT * FROM users WHERE name = '$input' das Einfügen von ' OR '1'='1 sie in SELECT * FROM users WHERE name = '' OR '1'='1', was alle Benutzer zurückgibt.
Betrachten Sie ein Anmeldeformular mit der Abfrage SELECT * FROM users WHERE username = '$user' AND password = '$pass'. Wenn ein Angreifer admin' -- in das Benutzernamenfeld eingibt und das Passwort leer lässt, wird die resultierende Abfrage zu SELECT * FROM users WHERE username = 'admin' -- ' AND password = ''. Die -- Zeichen kommentieren den Rest der Abfrage aus und deaktivieren die Passwortprüfung. Der Server gibt den Admin-Benutzerdatensatz zurück, und der Angreifer meldet sich an, ohne das Passwort zu kennen.
# Beispiel für SQL Injection — Authentifizierungsumgehung
# ANFÄLLIGER CODE: direkte Zeichenkettenverkettung
def login_vulnerable(username, password):
query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
cursor.execute(query)
return cursor.fetchone() is not None
# username = "admin' --" macht die Passwortprüfung zunichte
# SICHERE VERSION: parametrisierte Abfrage
def login_secure(username, password):
query = "SELECT * FROM users WHERE username = %s AND password = %s"
cursor.execute(query, (username, password))
return cursor.fetchone() is not None
Der UNION SELECT-Operator ermöglicht es, Ergebnisse von zwei SELECT-Abfragen zu kombinieren. Wenn ein Angreifer einen anfälligen Parameter findet, fügt er UNION SELECT mit einer Abfrage aus einer anderen Tabelle hinzu. Beispiel: ' UNION SELECT username, password FROM admins --. Die Erfolgsbedingung ist, dass die Anzahl der Spalten in beiden Abfragen übereinstimmen muss. Die Spaltenanzahl wird durch ORDER BY bestimmt (Einfügen von ' ORDER BY 1--, dann 2, 3... bis ein Fehler auftritt). Kennt der Angreifer die Spaltenanzahl, fügt er UNION SELECT mit derselben Anzahl von Feldern ein.
Mobile Anwendungen sind sowohl auf der Serverseite (API) als auch auf der Clientseite — in lokalen Datenbanken (SQLite, Realm) — von SQL Injection betroffen. Während die serverseitige SQLi in mobilen APIs Webanwendungen ähnelt, schaffen lokale Datenbanken einen zusätzlichen Vektor. Wenn eine Anwendung Daten in SQLite speichert und Abfragen mit Zeichenkettenverkettung ausführt, können bösartige Daten, die über die API in die lokale Datenbank gelangen, bei der späteren Verarbeitung SQLi auslösen.
Die lokale SQLite-Datenbank auf einem Gerät ist ebenfalls anfällig für SQL Injection, wenn die Anwendung Abfragen durch Zeichenkettenverkettung erstellt. Content Providers auf Android und Core Data auf iOS verwenden standardmäßig Parametrisierung, aber Raw-Queries erfordern die Aufmerksamkeit des Entwicklers. SQLite unterstützt keine mehrfachen durch Semikolon getrennten Abfragen, was die Möglichkeiten des Angreifers einschränkt, aber nicht vor dem Lesen von Daten durch WHERE-Bedingungen schützt. Verwenden Sie immer selectionArgs in Android und NSPredicate mit Parametern in iOS.
Die API, mit der eine mobile Anwendung kommuniziert, ist genauso anfällig wie jeder Webserver. Mobile Entwickler gehen oft davon aus, dass SQLi nur ein Backend-Problem ist, aber die Schwachstelle tritt am API-Endpunkt auf, der Parameter vom Client akzeptiert. Die Trennung der Verantwortlichkeiten schützt nicht: Wenn der Backend-Entwickler vergessen hat, die Abfrage zu parametrisieren, wird die mobile App des Benutzers zum Angriffsvektor. Fordern Sie vom Backend die Verwendung von ORM oder Prepared Statements.
// Beispiel für SQL Injection in lokaler SQLite auf Android
// ANFÄLLIGER CODE: direkte Verkettung
fun getUserVulnerable(db: SQLiteDatabase, userId: String): Cursor {
return db.rawQuery(
"SELECT * FROM users WHERE id = $userId", null
)
}
// SICHERE VERSION: Parametrisierung über selectionArgs
fun getUserSecure(db: SQLiteDatabase, userId: String): Cursor {
return db.rawQuery(
"SELECT * FROM users WHERE id = ?",
arrayOf(userId)
)
}
Der Schutz vor SQL Injection basiert auf einem einfachen Prinzip: Vertrauen Sie niemals Benutzereingaben in SQL-Abfragen. Die einzige zuverlässige Methode ist die Abfrageparametrisierung (Prepared Statements), bei der SQL-Code und Daten getrennt übergeben werden. Alle anderen Methoden — Escaping, Validierung, WAF — sind zusätzliche Sicherheitsschichten, ersetzen aber nicht die Parametrisierung. Laut OWASP (2025) verhindert Parametrisierung 100% der SQL Injection-Angriffe.
Bei Verwendung von Prepared Statements wird die SQL-Abfrage zuerst vom DB-Server ohne Daten kompiliert, und dann werden die Parameterwerte getrennt übergeben. Die Datenbank behandelt Parameter als Daten, nicht als ausführbaren Code. Selbst wenn ein Angreifer ' OR '1'='1 übergibt, interpretiert die Datenbank dies als Zeichenkettenwert, nicht als SQL-Code. Prepared Statements werden von allen modernen Sprachen und Frameworks unterstützt: PDO in PHP, PreparedStatement in Java, cursor.execute in Python.
Moderne ORMs (Hibernate, Entity Framework, SQLAlchemy, Room) verwenden bei der Ausführung von Abfragen automatisch Parametrisierung, es sei denn, der Entwickler wechselt zu Raw-Queries. Allerdings schützen ORMs nicht vollständig: Konstrukte wie @Query(value = "SELECT * FROM users WHERE name = :name", nativeQuery = true) in JPA erfordern die Übergabe von Parametern über benannte Parameter, nicht durch Verkettung. Query Builder (Knex, jOOQ) parametrisieren Abfragen standardmäßig ebenfalls, wenn keine Raw-Methoden verwendet werden.
Das Escaping von Sonderzeichen (mysql_real_escape_string) ist eine veraltete Methode, die nicht vor allen Arten von SQL Injection schützt. Das Problem: Das Escaping hängt von der Kodierung ab und kann bei Verwendung von Multibyte-Kodierungen (z. B. GBK in asiatischen Systemen) umgangen werden. Verwenden Sie Escaping nur in Legacy-Code, wo Parametrisierung nicht möglich ist, und immer in Kombination mit strenger Eingabetyp-Validierung.
| Methode | Wirksamkeit | Empfehlung |
|---|---|---|
| Prepared Statements | 100% | Für alle Abfragen obligatorisch |
| ORM (korrekte Verwendung) | 99% | Empfohlen |
| Zeichenketten-Escaping | 70% (abhängig von Kodierung) | Nur Legacy |
| Eingabevalidierung (White-List) | 50% (nur Zahlen) | Zusätzlich |
| WAF (Web Application Firewall) | 60% | Zusätzlich |
Das Anwendungskonto sollte minimal notwendige Berechtigungen haben: SELECT, INSERT, UPDATE, DELETE — nur auf Tabellen, die die Anwendung tatsächlich benötigt. Untersagen Sie die Verwendung von DROP, TRUNCATE, CREATE für das Anwendungskonto. Dies begrenzt den Schaden selbst bei einer erfolgreichen SQL Injection: Der Angreifer kann keine Tabellen löschen oder administrative Operationen ausführen.
Regelmäßige SQL Injection-Tests sollten Teil der sicheren Entwicklungspipeline sein. Eine Kombination aus statischer Analyse, dynamischem Scannen und manuellen Penetrationstests liefert die besten Ergebnisse. Laut dem Synopsys Cybersecurity Report (2025) finden automatisierte Scanner bis zu 70% der SQLi-Schwachstellen, aber komplexe Blind-Angriffe erfordern manuelle Tests.
Für mobile Anwendungen ist auch die Analyse der lokalen SQLite wichtig: Überprüfen Sie alle rawQuery-Aufrufe, ContentProvider-Abfragen und Room-Abfragen mit rawQuery. Tools: Android Studio Lint (erkennt SQLi in SQLite), MobSF (Mobile Security Framework) für die automatische statische und dynamische Analyse von APK/IPA. Es wird auch empfohlen, API-Endpunkte über sqlmap mit Proxy-Abfang des Datenverkehrs der mobilen Anwendung zu testen.
Häufig gestellte Fragen
SQL Injection greift relationale Datenbanken über SQL-Abfragen an. NoSQL Injection wirkt sich auf nicht-relationale Datenbanken (MongoDB, Couchbase) über deren Abfrageoperatoren ($gte, $ne, $where) aus. In MongoDB ist eine Injektion möglich, wenn die Anwendung ein BSON-Dokument aus einer JSON-Zeichenkette erstellt. Die Schutzmechanismen sind ähnlich: Parametrisierung und Typvalidierung.
Finden Sie alle Stellen, an denen SQL-Abfragen durch Zeichenkettenverkettung mit Benutzerdaten gebildet werden. Suchen Sie nach Mustern wie "SELECT ... WHERE id = " + userId oder f"UPDATE ... SET name = '{name}'". Jede solche Zeile ist eine potenzielle SQL-Injektion. Ersetzen Sie alle durch parametrisierte Abfragen oder Prepared Statements.
ORM-Frameworks schützen nur dann automatisch, wenn Sie deren Query Builder-Methoden und benannte Parameter verwenden. Wenn Sie Raw-Queries (nativeQuery in JPA, rawQuery in Room) verwenden, funktioniert der Schutz nicht — Sie müssen Parameter über vorbereitete Ausdrücke übergeben, nicht durch Zeichenkettenverkettung.
Second-Order SQL Injection ist ein Angriff, bei dem bösartige Daten sicher in der Datenbank gespeichert werden, aber später in einer anderen Abfrage ohne Escaping verwendet werden. Beispielsweise registriert sich ein Angreifer mit einem Benutzernamen wie ' OR '1'='1. Die Daten werden als Zeichenkette gespeichert — bei der Registrierung gibt es keinen Angriff. Wenn jedoch eine andere Abfrage den Benutzernamen ohne Parametrisierung in SQL verwendet, wird die Injektion ausgelöst.
NoSQL Injection kann aufgrund des geringeren Bewusstseins der Entwickler potenziell gefährlicher sein. Entwickler kennen SQL Injection und die meisten verwenden ORM, aber nur wenige kennen NoSQL Injection. In MongoDB kann eine falsch geformte Abfrage alle Dokumente einer Sammlung zurückgeben. Der Schutz ist derselbe — Prepared Statements (BSON-Parametrisierung) und strenge Eingabevalidierung.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch