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

Einige Schwachstellen in Webressourcen, die SQL verwenden


In diesem Hinweis wird die SQL-Sicherheitsanfälligkeit erläutert, die mit dem Eindringen in den Hauptteil der Abfrage verbunden ist.

Das Wesen der Verwundbarkeit

Betrachten Sie die Arbeit eines einfachen Systems mit einer WEB-Oberfläche, mit der Benutzer auch Informationen über sich selbst speichern können. Solche Systeme sind eines der häufigsten im Netzwerk. Es kann auch ein Gästebuch, einen Chat, eine Fotogalerie und einen E-Mail-Service geben.

Die generierte Abfrage an die Datenbank muss sich mit dem vom Benutzer eingegebenen Passwort anmelden. Basierend auf diesen Feldern sollte die Datenbank den entsprechenden Datensatz in der Tabelle finden. Nach Abschluss der Anforderung gibt die Datenbank die über den Benutzer gefundenen Informationen zurück, die das PHP-Skript erkennt, da HTML auch dem Benutzer zur Verfügung stellt.

Stellen Sie sich ein ziemlich typisches Fragment eines PHP-Skripts vor, das eine SQL-Abfrage verwendet, um auf eine Datenbank zuzugreifen:

<? php
$ result = mysql_db_query ("database", "select * from userTable wobei login = '$ userLogin' und password = '$ userPassword'");
while ($ row = mysql_fetch_array ($ result)) {
echo $ row ["vollständiger Name"];
echo $ row ["email"];
echo $ row ["Passwort"];
}}
mysql_free_result ($ result);
?>

Wie wir beobachten, sind das Login und das vom Benutzer eingegebene Passwort in den Variablen $ userLogin und $ userPassword enthalten . Der Inhalt dieser Variablen wird in die Anforderung eingefügt, Informationen über diesen Benutzer herauszufiltern. Der Filter wird mit der Option where des Befehls select SQL angegeben. In diesem Fall sieht die Abfrage folgendermaßen aus: Wählen Sie * aus userTable aus, wobei login = '$ userLogin' und password = '$ userPassword', wobei userTable der Name der Tabelle ist, die die erforderlichen Informationen enthält. Wenn die Anmelde- und Kennwortvariablen auch Vanya- bzw. Vasya- Werte enthalten, sieht die an die Datenbank gesendete Anforderung folgendermaßen aus: Wählen Sie * aus der Benutzertabelle aus, wobei login = 'vanya' und password = 'vasya' . Es ist klar, dass wenn es einen Eintrag in der Datenbank gibt, in dem das Login vanya ist, das Passwort jedoch vasya ist , bis zur Anfrage keine einzige Zeile aus der Datenbank gesendet wird und das Skript nichts erzeugt. Somit bietet das obige System nur einem Benutzer Zugriff auf Informationen, der über ein fehlerfreies Kennwort und eine fehlerfreie Anmeldung verfügt.

Es scheint, dass ein solches System keine Mängel enthält. In der Lektion selbst ist dies nicht der Fall. Die Logik der Programmierer, die das obige Beispiel erstellt haben, impliziert, dass der vom Benutzer eingegebene Benutzername und das Kennwort in einfachen Anführungszeichen enthalten sind, die im Anforderungshauptteil fest codiert sind. Mal sehen, was passiert, wenn das vom Benutzer selbst eingegebene Passwort ein Anführungszeichen enthält. Lassen Sie es den Wert vas'ya besitzen , während die Anfrage die Form annehmen wird: Wählen Sie * aus der Benutzertabelle aus, wobei login = 'vanya' und password = 'vas'ya' . Bei der Ausführung einer solchen Anforderung tritt mit Sicherheit ein Fehler auf, da das Anführungszeichen aus dem Kennwort das öffnende Anführungszeichen aus der Anforderung geschlossen hat und auch das Ende des Kennworts außerhalb des bedingten Ausdrucks "hängen geblieben" ist.

Wenn Sie die folgende Zeile als Kennwort einfügen: 'oder 1 = 1' , lautet die Anforderung wie folgt : Wählen Sie * aus der Benutzertabelle aus, wobei login = 'vanya' und password = '' oder 1 = 1 '' ebenfalls keine Syntaxfehler aufweisen . Der logische Ausdruck wird jedoch identisch wahr, auch im Gegensatz zu dieser Abfrage gibt SQL die gesamte Benutzerdatenbank zurück 8-).

Mit dem Apostroph-Symbol können wir also auch in den Hauptteil der SQL-Abfrage eindringen, um die zu prüfende Bedingung wahr zu machen. Wenn wir an einem bestimmten Benutzer vanya interessiert sind, kann zum Abrufen von Informationen über ihn die folgende Kennwortzeichenfolge verwendet werden: 'oder login =' vanya . Gleichzeitig lautet die Anforderung: Wählen Sie * aus der Benutzertabelle aus, wobei login = 'vanya' und password = '' oder login = 'vanya' . Wie Sie wissen, erhalten wir dadurch Informationen über Wanja .

Die beschriebene Sicherheitsanfälligkeit von Diensten, die auf SQL basieren, ist nicht auf den unbefugten Empfang von Informationen beschränkt. Da MySQL in solchen Systemen in der Regel verwendet wird, ist es möglich, nicht nur den bedingten Ausdruck im Befehl select zu ändern, sondern auch über diesen Befehl hinauszugehen und einen anderen Datenbankbefehl auszuführen. Da MySQL mehrere Befehle in einer einzigen Abfrage zulässt, getrennt ; Dann können wir jeden dieser Befehle ausführen, indem wir den folgenden Code in das Passwortfeld eingeben: '; <SQL-Befehl> An welcher Stelle als <sql> -Befehl dürfen Sie einen gültigen Befehl angeben. So zum Beispiel ein solcher Code: '; drop table 'userTable zerstört einfach einfach die userTable- Tabelle aus der Datenbank.

Praktische Nutzung der Sicherheitslücke

Trotz seiner Einfachheit ist die praktische Verwendung von SQL-Abfragefehlern sehr schwierig.

In diesem Abschnitt betrachten wir die folgenden Probleme, die bei der Verwendung der beschriebenen Sicherheitsanfälligkeit auftreten:
  • Bestimmen der Tatsache, dass SQL im System verwendet wird.
  • Identifizierung des Vorhandenseins einer Sicherheitsanfälligkeit. Klärung der Reaktion des Skripts auf Fehler.
  • Feldnamen in einer Tabelle definieren.
  • Definieren der Namen vorhandener Tabellen.

    Die betrachtete Sicherheitsanfälligkeit ist allen SQL-Abfragen inhärent, unabhängig davon, von welchem ​​Skript oder Programm sie aufgerufen werden. Trotzdem werden wir Systeme betrachten, die auf PHP basieren. Dies liegt daran, dass der Fluss von PHP-Fehlern als Position (Standard) an den Endbenutzer gerichtet ist. Gleichzeitig informieren Perl- oder Exe-Anwendungen den Benutzer normalerweise nicht über die Art der Fehler.

    Bestimmen der Tatsache, dass SQL im System verwendet wird.

    Wenn Sie ein bestimmtes System untersuchen, müssen Sie zunächst herausfinden, ob es SQL verwendet.
    Diese Tatsache kann entweder indirekt (anhand der Namen der verwendeten Dateien, Links zu den verwendeten Tools usw.) oder direkt erkannt werden, indem SQL gezwungen wird, sich zu beweisen. Wenn wir mit PHP arbeiten, gibt es nur einen Weg, die Verwendung von SQL eindeutig zu bestimmen - dies führt zu einem Fehler bei der Ausführung. Wenn während der Ausführung der Anforderung ein Fehler auftritt, das PHP-Skript jedoch eindeutig keine Fehler verarbeitet, wird die PHP-Fehlermeldung direkt an die Benutzerseite gesendet.
    Wie ein Fehler beim Ausführen einer SQL-Abfrage verursacht wird, hängt vom jeweiligen Gerät des betreffenden Systems ab. In den meisten Fällen kann ein Fehler durch die Eingabe falscher Daten in das System verursacht werden.

    Identifizierung des Vorhandenseins einer Sicherheitsanfälligkeit. Klärung der Reaktion des Skripts auf Fehler.

    Das genialste Mittel zum Erkennen des Vorhandenseins einer Sicherheitsanfälligkeit, aber gleichzeitig auch der Verwendung von SQL, ist das Folgende: Geben Sie in jedem Feld, das angeblich an der Bildung der SQL-Abfrage beteiligt ist (z. B. das Feld Anmelden oder Kennwort ), ein einfaches Anführungszeichen ein. Wir füllen die verbleibenden Felder mit gültigen Daten aus (oder lassen sie leer, wenn das System dies zulässt). Nach dem Senden dieser Formulare betrachten wir die Reaktion des Systems. Wenn uns das PHP-Skript als Ergebnis einen SQL-Fehler gibt, können wir uns selbst gratulieren: Das System verwendet SQL und das Skript filtert in keiner Weise ein einzelnes Anführungszeichen. Dieses Esssystem enthält Verwundbarkeit.
    Der SQL-Abfragefehler sieht dann auf der Seite folgendermaßen aus:

    Dateneingabeformular:


    Als Ergebnis ein SQL-Abfragefehler:


    Wenn auf der Seite kein SQL-Fehlercode vorhanden ist, kann dies Folgendes bedeuten:
    1) Das System enthält eine Sicherheitsanfälligkeit, aber das PHP-Skript behandelt Fehler. In diesem Fall darf das System gehackt werden, aber Sie müssen "per Berührung" handeln, da wir nicht wissen, wann die SQL-Syntax korrekt ist, aber zu welcher Zeit.
    2) Das Skript filtert auch das Anführungszeichen, daher treten keine Fehler auf. In diesem Fall enthält das System keine Schwachstellen.
    3) Das allgemeine System verwendet SQL in keiner Weise.
    In den letzten Fällen ist klar, dass weitere SQL-Untersuchungen keinen Sinn ergeben.

    Feldnamen in einer Tabelle definieren.

    Um Informationen aus einer Datenbank mit bestimmten Daten abzurufen, müssen wir die Werte einiger Felder in der Anforderung ermitteln (z. B. die Benutzeranmeldung festlegen). Dazu müssen Sie jedoch den Namen der entsprechenden Felder kennen. Es gibt keine direkte Möglichkeit, diese Namen herauszufinden. Daher müssen Sie diese Namen mit brutaler Gewalt suchen. Die Datennamen können mit den Namen der Felder in dem an den Server gesendeten Formular übereinstimmen, oder sie können auch in keiner Weise übereinstimmen. Es ist gut, dass die Namen der Felder als Position Standard sind und es nicht so viele Möglichkeiten gibt, sie zu schreiben. So wird beispielsweise der Feldname für den Benutzernamen höchstwahrscheinlich entweder zum Benutzer oder zum Nick . Ähnliches gilt für das Passwort: Das Passwort ist entweder pwd oder pass .
    Um die Existenz eines bestimmten Feldes festzustellen, wird eine ausgeklügelte Methode vorgeschlagen: Lassen Sie uns überprüfen, ob das pwd- Feld in der Tabelle vorhanden ist. Geben Sie die Zeichenfolge 'pwd =' in ein beliebiges Formularfeld ein. Wenn das pwd- Feld in der Tabelle vorhanden ist, verarbeitet SQL die Abfrage korrekt. Wenn kein solches Feld vorhanden ist, tritt erneut ein SQL-Ausführungsfehler auf. Wenn Sie also verschiedene Werte der Feldnamen ersetzen und gleichzeitig das Ergebnis der Abfrage untersuchen, können Sie herausfinden, welche Felder in der Tabelle vorhanden sind, welche jedoch nicht.

    Definieren der Namen vorhandener Tabellen.

    Ähnlich wie beim Suchen von Feldnamen in Tabellen ist es auch möglich, nach den Namen vorhandener Tabellen in der Datenbank zu suchen. Angenommen, wir möchten herausfinden, ob die Tabelle adminList in der Datenbank vorhanden ist. Geben Sie dazu die folgende Zeile in ein bestimmtes Formularfeld ein '; wählen Sie * aus der adminList . Wenn SQL aufgrund des Fehlers überhaupt nicht gestartet wird, ist die Tabelle adminList vorhanden. Für die Richtigkeit dieses Tests müssen Sie diese Zeile in das Feld eingeben, das in der SQL-Abfrage als endgültig angezeigt wird. Dies ist erforderlich, damit der Syntaxfehler nicht durch das verbleibende Ende der ursprünglichen Anforderung verursacht wird, die später vorhanden sein wird . Wählen Sie * aus adminList . Beachten Sie, dass, wenn das Paar für das Anmeldefeld auch das Kennwort für die Anforderungsansicht enthält, das Kennwortfeld höchstwahrscheinlich das letzte ist, das in der Anforderung angezeigt wird.

    PS

    Aufgrund dieser Sicherheitsanfälligkeit wurde die Website http://www.bigmir.net gehackt (genauer gesagt, die Fotogalerie ist auch ein Chat). Wir haben die Sicherheitslücke den Eigentümern der Website gemeldet. Das Loch wurde repariert. Aber jetzt haben wir noch einmal das Chat-Registrierungsformular überprüft. Außerdem habe ich all diese blah blah Verwundbarkeit gefunden 8-).