Eine SQL-Injection können Ihre Datenbank zu zerstören.
SQL in Web-Seiten
In den vorangegangenen Kapiteln haben Sie gelernt (und Aktualisierung) Datenbank zum Abrufen von Daten unter Verwendung von SQL.
Wenn SQL verwendet wird, um Daten auf einer Webseite angezeigt werden, ist es üblich, Web-Nutzer geben ihre eigenen Suchwerte zu lassen.
Da SQL-Anweisungen nur Text sind, ist es mit einem kleinen Stück von Computer-Code, leicht, dynamisch SQL-Anweisungen ändern, um die Benutzer mit ausgewählten Daten zur Verfügung zu stellen:
Server-Code
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
Das obige Beispiel erzeugt eine select-Anweisung durch eine Variable (txtUserId) auf eine ausgewählte Zeichenfolge hinzufügen. Die Variable abgerufen wird vom Benutzereingabe (Request) an die Seite.
Der Rest dieses Kapitels beschreibt die möglichen Gefahren von Benutzereingaben in SQL-Anweisungen.
SQL-Injektion
SQL-Injection ist eine Technik, wo böswillige Benutzer injizieren können SQL-Befehle in einer SQL-Anweisung, über Web-Seite-Eingang.
Eingespritzte SQL-Befehle können SQL-Anweisung und gefährden die Sicherheit einer Web-Anwendung ändern.
SQL Injection Basierend auf 1 = 1 ist immer wahr
Schauen Sie sich das Beispiel oben, ein weiteres Mal.
Nehmen wir an, dass der ursprüngliche Zweck des Codes eine SQL-Anweisung zu erstellen war ein Benutzer mit einer bestimmten Benutzer-ID zu wählen.
Wenn es nichts gibt , einen Benutzer von der Eingabe zu verhindern "wrong" Eingang kann der Benutzer etwas eingeben "smart" Eingabe wie folgt aus :
Benutzeridentifikation:
Server Ergebnis
SELECT * FROM Users WHERE UserId = 105 or 1=1
Die SQL-oben ist gültig. Es werden alle Zeilen aus der Tabelle Benutzer zurückgeben, da WHERE 1 = 1 immer wahr ist.
Hat das Beispiel scheinen über gefährlich? Was, wenn der Benutzer Tabellennamen und Passwörter enthält?
Die SQL-Anweisung oben ist sehr ähnlich wie folgt aus:
SELECT UserId, Name, Password
FROM Users WHERE UserId = 105 or 1=1
Ein Smart-Hacker könnte durch einfaches Einsetzen 105 oder 1 = 1 in das Eingabefeld den Zugriff auf alle Benutzernamen und Passwörter in einer Datenbank erhalten.
SQL Injection Basierend auf ""="" ist immer wahr
Hier ist eine gemeinsame Konstruktion verwendet, um Benutzer-Login auf einer Website zu überprüfen:
Benutzername:
Passwort:
Server-Code
uName = getRequestString("UserName");
uPass = getRequestString("UserPass");
sql = "SELECT * FROM Users WHERE Name ='" + uName + "' AND Pass ='" + uPass + "'"
Ein Smart - Hacker könnte durch einfaches Einfügen "oder den Zugriff auf Benutzernamen und Passwörter in einer Datenbank zu bekommen ""=" in der Benutzername oder das Passwort Textfeld ein .
Der Code auf dem Server wird eine gültige SQL-Anweisung wie folgt zu erstellen:
Ergebnis
SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""
Das Ergebnis SQL gültig ist. Es werden alle Zeilen aus der Tabelle Benutzer zurückgeben, da WHERE "" = "" immer wahr ist.
SQL Injection Basierend auf Batched SQL-Anweisungen
Die meisten Datenbanken unterstützen batched SQL-Anweisung durch ein Semikolon getrennt.
Beispiel
SELECT * FROM Users; DROP TABLE Suppliers
Die SQL oben kehren alle Zeilen in der Tabelle Benutzer, und löschen Sie die Tabelle mit dem Namen Lieferanten.
Wenn wir den folgenden Server-Code hatte:
Server-Code
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
Und die folgende Eingabe:
Benutzeridentifikation:
Der Code auf dem Server würde eine gültige SQL-Anweisung wie folgt zu erstellen:
Ergebnis
SELECT * FROM Users WHERE
UserId = 105; DROP TABLE Suppliers
Parameter für den Schutz
Einige Web - Entwickler verwenden , um eine "blacklist" von Wörtern oder Zeichen in SQL - Eingabe zu suchen, SQL - Injection - Angriffe zu verhindern.
Dies ist keine sehr gute Idee. Viele dieser Wörter (wie zu löschen oder zu fallen) und Zeichen (wie Semikolons und Anführungszeichen) werden in gemeinsame Sprache verwendet, und sollte in vielen Arten von Eingangs zugelassen werden.
(In der Tat sollte es vollkommen legal sein zur Eingabe einer SQL-Anweisung in einem Datenbankfeld.)
Die einzige bewährte Methode, eine Website von SQL-Injection-Angriffe zu schützen, ist SQL-Parameter zu verwenden.
SQL Parameter sind Werte, die eine SQL-Abfrage zur Ausführungszeit hinzugefügt werden, in einer kontrollierten Weise.
ASP.NET Razor Beispiel
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);
Beachten Sie, dass Parameter von einem @ Marker in der SQL-Anweisung dargestellt werden.
Die SQL-Engine prüft jeden Parameter, um sicherzustellen, dass es für seine Spalte korrekt ist, und buchstäblich behandelt und nicht als Teil der SQL ausgeführt werden.
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);
Sie haben gerade gelernt, SQL-Injection zu vermeiden. Eines der Top-Website-Schwachstellen.
Beispiele
Die folgenden Beispiele zeigt, wie parametrisierte Abfragen in einigen gemeinsamen Web-Sprachen zu bauen.
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-Anweisung 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-Anweisung 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();