flawopen.com/SQL Injection/Reicht Escaping?
Verhindert Escaping von Anführungszeichen SQL Injection?
Meistens nicht. Eine Escaping-Funktion hängt von Datenbank, Verbindungszeichensatz, SQL-Modus und dem genauen Anführungs-Kontext ab. Parametrisierte Abfragen halten Werte über die Treiber-API aus der SQL-Syntax heraus. Werte werden gebunden; dynamische Bezeichner, die nicht gebunden werden können, müssen aus einer anwendungseigenen Allowlist stammen.
Warum Escaping in der Praxis fragil ist
Escaping ist kein kontextfreies Ersetzen von Text. MySQL dokumentiert, dass mysql_real_escape_string() den Verbindungszeichensatz nutzt und SET NAMES den Zustand der Clientbibliothek, den diese Funktion verwendet, nicht aktualisiert. Eine Abweichung kann Annahmen über escapten Text ungültig machen. Bevorzugen Sie parametrisierte APIs. Falls Altcode noch Escaping benötigt, verwenden Sie die unterstützte Treiberfunktion mit korrekt konfiguriertem Zeichensatz und behandeln Sie Fehler.
Escaping muss an jeder Interpolationsstelle mit passendem Treiber, Zeichensatz, SQL-Modus und Literal-Kontext korrekt angewendet werden. Parametrisierte APIs machen die Trennung zwischen Wert und Daten an der Abfrage sichtbar und vermeiden manuell zusammengesetzte Literale.
Escaping von Anführungszeichen betrifft nur Zeichen in einem bestimmten Stringliteral. Es erstellt keine sicheren Tabellen- oder Spaltennamen, Schlüsselwörter oder Sortierrichtungen und schützt keine Eingabe in ungequoteten numerischen Ausdrücken. Binden Sie Werte und wählen Sie dynamische SQL-Struktur aus festen Anwendungsoptionen.
// Benutzereingabe wird in SQL-Syntax eingefügt
query = f"SELECT id FROM users WHERE name = '{name}'"
cursor.execute(query)
// Der Treiber bindet name als Datenwert
cursor.execute(
"SELECT id FROM users WHERE name = ?",
(name,),
)
Was Parameterbindung anders macht
Eine parametrisierte Abfrage übergibt SQL-Struktur und Werte über die Datenbank-API als getrennte Eingaben. Treiber können native Prepared Statements oder eine andere sichere Implementierung nutzen; nehmen Sie keinen bestimmten Ablauf auf Protokollebene an. Entscheidend ist, dass der Wert als Daten und nicht erneut als SQL-Syntax behandelt wird. Verwenden Sie bei Python DB-API den Platzhalter des Treibers und übergeben Sie Werte separat; formatieren Sie die Abfrage nicht als String.
Engineering-Checkliste
- ✓Binden Sie jeden benutzergesteuerten Wert über die Treiber-API; formatieren Sie ihn nie in SQL-Text.
- ✓Ordnen Sie dynamische Tabellen-, Spalten- und Sortiernamen festen anwendungseigenen Allowlists zu.
- ✓Falls Legacy-Escaping vorerst bleibt, verwenden Sie die kontextgerechte Treiber-API und prüfen Sie Zeichensatz sowie SQL-Modus der Verbindung.
- ✓Testen Sie Abfragen mit Anführungszeichen, Nicht-ASCII-Text und ungültigen Bezeichnern, ohne destruktive Anweisungen auszuführen.
Häufige Fragen
Für Bezeichner oder SQL-Fragmente, die nicht gebunden werden können, nutzen Sie nur eine vom Treiber unterstützte Quote-API zusammen mit einer festen Allowlist der Anwendung. Escapen Sie keine beliebigen Werte mit einer allgemeinen Funktion.
Sie kann im dokumentierten Kontext helfen, hängt aber weiterhin von Datenbank, Verbindungseinstellungen, Quote-Kontext und korrekter Anwendung an jeder Stelle ab. Parametrisierte Abfragen sind für Werte die sicherere Standardeinstellung.
Referenzen
- OWASP — Leitfaden zur Vermeidung von SQL Injection
- CWE-89 — SQL Injection
- PHP-Handbuch — mysqli::real_escape_string
- MySQL C API — mysql_real_escape_string
- flawopen.com — SQL Injection (alle Sprachen)