SQL -Injection
SQL-Injektion
SQL-Injection ist eine Code-Injection-Technik, die Ihre Datenbank zerstören kann.
SQL-Injection ist eine der häufigsten Web-Hacking-Techniken.
SQL-Injection ist das Platzieren von bösartigem Code in SQL-Anweisungen über Webseiteneingaben.
SQL in Webseiten
Eine SQL-Einschleusung tritt normalerweise auf, wenn Sie einen Benutzer um eine Eingabe bitten, z. B. seinen Benutzernamen/Benutzer-ID, und der Benutzer Ihnen anstelle eines Namens/einer ID eine SQL-Anweisung gibt, die Sie unwissentlich in Ihrer Datenbank ausführen.
Sehen Sie sich das folgende Beispiel an, das eine
SELECT
Anweisung erstellt, indem eine Variable (txtUserId) zu einer ausgewählten Zeichenfolge hinzugefügt wird. Die Variable wird aus der Benutzereingabe abgerufen (getRequestString):
Beispiel
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
Der Rest dieses Kapitels beschreibt die potenziellen Gefahren der Verwendung von Benutzereingaben in SQL-Anweisungen.
SQL-Injection basierend auf 1 = 1 ist immer wahr
Sehen Sie sich das obige Beispiel noch einmal an. Der ursprüngliche Zweck des Codes bestand darin, eine SQL-Anweisung zu erstellen, um einen Benutzer mit einer bestimmten Benutzer-ID auszuwählen.
Wenn es nichts gibt, was einen Benutzer daran hindert, "falsche" Eingaben einzugeben, kann der Benutzer einige "intelligente" Eingaben wie die folgende eingeben:
Benutzeridentifikation:
Dann sieht die SQL-Anweisung so aus:
SELECT * FROM Users WHERE UserId = 105 OR 1=1;
Die obige SQL ist gültig und gibt ALLE Zeilen aus der Tabelle „Benutzer“ zurück, da OR 1=1 immer TRUE ist.
Sieht das obige Beispiel gefährlich aus? Was ist, wenn die Tabelle „Benutzer“ Namen und Passwörter enthält?
Die obige SQL-Anweisung ist ähnlich wie diese:
SELECT UserId, Name, Password
FROM Users WHERE UserId = 105 or 1=1;
Ein Hacker könnte Zugriff auf alle Benutzernamen und Passwörter in einer Datenbank erhalten, indem er einfach 105 ODER 1=1 in das Eingabefeld eingibt.
SQL-Injection basierend auf ""="" ist immer wahr
Hier ist ein Beispiel für eine Benutzeranmeldung auf einer Website:
Nutzername:
Passwort:
Beispiel
uName = getRequestString("username");
uPass = getRequestString("userpassword");
sql = 'SELECT * FROM Users WHERE Name ="' + uName + '" AND Pass ="' + uPass +
'"'
Ergebnis
SELECT * FROM Users WHERE Name ="John Doe" AND Pass ="myPass"
Ein Hacker könnte Zugriff auf Benutzernamen und Passwörter in einer Datenbank erhalten, indem er einfach „OR“ „=“ in das Textfeld „Benutzername“ oder „Passwort“ einfügt:
Nutzername:
Passwort:
Der Code auf dem Server erstellt eine gültige SQL-Anweisung wie diese:
Ergebnis
SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""
Die obige SQL ist gültig und gibt alle Zeilen aus der Tabelle "Benutzer" zurück, da OR ""="" immer TRUE ist.
SQL-Injection basierend auf Batch-SQL-Anweisungen
Die meisten Datenbanken unterstützen Batch-SQL-Anweisungen.
Ein Stapel von SQL-Anweisungen ist eine Gruppe von zwei oder mehr SQL-Anweisungen, die durch Semikolons getrennt sind.
Die folgende SQL-Anweisung gibt alle Zeilen aus der Tabelle „Benutzer“ zurück und löscht dann die Tabelle „Lieferanten“.
Beispiel
SELECT * FROM Users; DROP TABLE Suppliers
Sehen Sie sich das folgende Beispiel an:
Beispiel
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
Und folgende Eingabe:
Benutzeridentifikation:
Die gültige SQL-Anweisung würde wie folgt aussehen:
Ergebnis
SELECT * FROM Users WHERE
UserId = 105; DROP TABLE Suppliers;
Verwenden Sie SQL-Parameter für den Schutz
Um eine Website vor SQL-Injection zu schützen, können Sie SQL-Parameter verwenden.
SQL-Parameter sind Werte, die einer SQL-Abfrage zur Ausführungszeit auf kontrollierte Weise hinzugefügt werden.
ASP.NET Razor-Beispiel
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);
Beachten Sie, dass Parameter in der SQL-Anweisung durch eine @-Markierung dargestellt werden.
Die SQL-Engine überprüft jeden Parameter, um sicherzustellen, dass er für seine Spalte korrekt ist und wörtlich und nicht als Teil der auszuführenden SQL behandelt wird.
Ein anderes Beispiel
txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
db.Execute(txtSQL,txtNam,txtAdd,txtCit);
Beispiele
Die folgenden Beispiele zeigen, wie parametrisierte Abfragen in einigen gängigen Websprachen erstellt werden.
SELECT-Anweisung in ASP.NET:
txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserId);
command.ExecuteReader();
INSERT INTO STATEMENT IN ASP.NET:
txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
command = new SqlCommand(txtSQL);
command.Parameters.AddWithValue("@0",txtNam);
command.Parameters.AddWithValue("@1",txtAdd);
command.Parameters.AddWithValue("@2",txtCit);
command.ExecuteNonQuery();
INSERT INTO STATEMENT IN PHP:
$stmt = $dbh->prepare("INSERT INTO Customers (CustomerName,Address,City)
VALUES (:nam, :add, :cit)");
$stmt->bindParam(':nam', $txtNam);
$stmt->bindParam(':add', $txtAdd);
$stmt->bindParam(':cit', $txtCit);
$stmt->execute();