TL; DR
- Die Anwendung übernimmt Eingang, in diesem Fall ‚Nancy‘, ohne zu versuchen - sterilisieren Sie die Eingabe, wie durch die Flucht Sonderzeichen
Schule => INSERT INTO Studenten VALUES ( ‚Nancy‘ ); INSERT 0 1
- SQL - Injektion auftritt , wenn die Eingabe in eine Datenbank Befehl manipuliert wird - Ursache des Datenbankserver beliebigen SQL auszuführen
Schule => INSERT INTO Studenten VALUES ( ‚Robert‘ ); DROP TABLE Studenten ; - '); INSERT 0 1 DROP TABLE
- Die Studentenakten sind jetzt weg - es hätte noch schlimmer kommen können!
Schule => SELECT * FROM Schüler ;
ERROR : Beziehung „Schüler“ ist nicht vorhanden
Zeile 1 : SELECT * FROM Studenten ; ^
Dadurch wird die Schülertabelle gelöscht (gelöscht).
( Alle Codebeispiele in dieser Antwort wurden auf einem PostgreSQL 9.1.2-Datenbankserver ausgeführt. )
Um zu verdeutlichen, was passiert, versuchen wir dies mit einer einfachen Tabelle, die nur das Namensfeld enthält, und fügen eine einzelne Zeile hinzu:
Schule => CREATE TABLE Schüler ( Name TEXT PRIMARY KEY );
HINWEIS : CREATE TABLE / PRIMARY KEY wird schaffen impliziten Index "students_pkey" für Tabelle "Studenten" CREATE TABLE
Schule => INSERT INTO Studenten VALUES ( 'John' ); INSERT 0 1
Angenommen, die Anwendung verwendet das folgende SQL, um Daten in die Tabelle einzufügen:
INSERT INTO Studenten VALUES ( 'Foobar' );
Ersetzen Sie foobar
durch den tatsächlichen Namen des Schülers. Ein normaler Einfügevorgang würde folgendermaßen aussehen:
- Eingabe: Nancy
Schule => EINFÜGEN IN DIE WERTE DER Schüler ( 'Nancy' ); INSERT 0 1
Wenn wir die Tabelle abfragen, erhalten wir Folgendes:
Schule => SELECT * FROM Schüler ;
Name
-------
John
Nancy
( 2 Reihen )
Was passiert, wenn wir den Namen von Little Bobby Tables in die Tabelle einfügen?
- Eingabe: Robert '); DROP TABLE Studenten; -
Schule => INSERT INTO Studenten VALUES ( 'Robert' ); DROP TABLE Studenten ; - '); INSERT 0 1 DROP TABLE
Die SQL-Injection ist hier das Ergebnis des Namens des Schülers, der die Anweisung beendet und einen separaten DROP TABLE
Befehl enthält. Die beiden Striche am Ende der Eingabe sollen alle verbleibenden Codes auskommentieren, die sonst einen Fehler verursachen würden. Die letzte Zeile der Ausgabe bestätigt, dass der Datenbankserver die Tabelle gelöscht hat.
Es ist wichtig zu beachten, dass INSERT
die Anwendung während des Vorgangs die Eingabe nicht auf Sonderzeichen überprüft und daher die Eingabe beliebiger Eingaben in den SQL-Befehl ermöglicht. Dies bedeutet, dass ein böswilliger Benutzer in ein Feld, das normalerweise für Benutzereingaben vorgesehen ist, spezielle Symbole wie Anführungszeichen und beliebigen SQL-Code einfügen kann, um das Datenbanksystem zur Ausführung zu veranlassen, daher SQL- Injection .
Das Ergebnis?
Schule => SELECT * FROM Schüler ;
ERROR : Beziehung „Schüler“ ist nicht vorhanden
Zeile 1 : SELECT * FROM Studenten ; ^
SQL Injection ist das Datenbankäquivalent einer Sicherheitsanfälligkeit bezüglich der Ausführung von beliebigem Remotecode in einem Betriebssystem oder einer Anwendung. Die möglichen Auswirkungen eines erfolgreichen SQL-Injection-Angriffs sind nicht zu unterschätzen. Je nach Datenbanksystem und Anwendungskonfiguration kann ein Angreifer Datenverluste verursachen (wie in diesem Fall), unbefugten Zugriff auf Daten erhalten oder sogar ausführen beliebiger Code auf dem Host-Computer selbst.
Wie im XKCD-Comic erwähnt, besteht eine Möglichkeit zum Schutz vor SQL-Injection-Angriffen darin, Datenbankeingaben zu bereinigen, z. B. indem Escapezeichen maskiert werden, damit sie den zugrunde liegenden SQL-Befehl nicht ändern und daher keinen beliebigen SQL-Code ausführen können. Wenn Sie parametrisierte Abfragen verwenden, z. B. SqlParameter
in ADO.NET, wird die Eingabe mindestens automatisch bereinigt, um eine SQL-Injektion zu verhindern.
Das Bereinigen von Eingaben auf Anwendungsebene kann jedoch fortgeschrittenere SQL-Injektionstechniken nicht stoppen. Beispielsweise gibt es Möglichkeiten, die mysql_real_escape_string
PHP-Funktion zu umgehen . Für zusätzlichen Schutz unterstützen viele Datenbanksysteme vorbereitete Anweisungen . Bei ordnungsgemäßer Implementierung im Backend können vorbereitete Anweisungen die SQL-Injection unmöglich machen, indem Dateneingaben als semantisch vom Rest des Befehls getrennt behandelt werden.