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

Einige Sicherheitslücken in Webressourcen mit SQL


Der Hinweis beschreibt die SQL-Sicherheitsanfälligkeit, die mit dem Eindringen in den Hauptteil der Abfrage verbunden ist.

Das Wesen der Verwundbarkeit

Betrachten Sie die Arbeit des einfachsten Systems mit einer WEB-Schnittstelle, über die Benutzer auch Informationen über sich selbst speichern können. Solche Systeme gehören zu den am weitesten verbreiteten im Netzwerk. Es kann auch ein Gästebuch, ein Chat, eine Fotogalerie und ein E-Mail-Dienst vorhanden sein.

Bei der generierten Abfrage der Datenbank muss sich auch das vom Benutzer eingegebene Passwort anmelden. Basierend auf diesen Feldern sollte die Datenbank den entsprechenden Datensatz in der Tabelle finden. Nach Abschluss der Anforderung gibt die Datenbank die gefundenen Informationen über den Benutzer zurück, die das PHP-Skript als HTML-Code ausgibt.

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

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

Wie wir beobachten, ist das Login auch das Passwort, das der Benutzer in den Variablen $ userLogin und $ userPassword eingegeben hat . Der Inhalt dieser Variablen wird in die Anforderung zum Filtern von Informationen über diesen Benutzer eingefügt. 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 Variablen login und password auch Werte für vanya und vasya enthalten, sieht die an die Datenbank gesendete Anforderung folgendermaßen aus: Wählen Sie * aus userTable aus, wobei login = 'vanya' und password = 'vasya' . Es ist klar, dass, wenn es einen Eintrag in der Datenbank gibt, in dem der Benutzername vanya lautet, das Kennwort jedoch vasya lautet , bis zur Anforderung keine einzelne Zeile aus der Datenbank gesendet wird und das Skript nichts zurückgibt . Somit ermöglicht das obige System den Zugriff auf Informationen nur einem Benutzer, der ein fehlerfreies Passwort und eine fehlerfreie Anmeldung hat.

Es scheint, dass ein solches System keine Mängel aufweist. 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 stehen, die im Anforderungshauptteil fest codiert sind. Sehen wir uns jedoch an, was passiert, wenn das vom Benutzer selbst eingegebene Kennwort ein Anführungszeichen enthält. Lassen Sie es den Wert vas'ya besitzen , während die Anfrage die Form annimmt : Wählen Sie * aus userTable, 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 schloss und auch das Ende des Kennworts außerhalb des bedingten Ausdrucks "hängen" blieb.

Und wenn Sie die folgende Zeile als Passwort eingeben: 'oder 1 = 1' , wird die Anfrage folgendermaßen aussehen: select * from userTable wobei login = 'vanya' und password = '' oder 1 = 1 '' ebenfalls keine Syntaxfehler aufweisen . Der logische Ausdruck wird jedoch identisch wahr, und 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 Text der SQL-Abfrage eindringen, um die zu überprüfende Bedingung als wahr zu kennzeichnen. Wenn wir an einem bestimmten Benutzer vanya interessiert sind, ist es zulässig, die folgende Kennwortzeile zu verwenden, um Informationen über ihn zu erhalten: 'oder login =' vanya . Die Anfrage wird wie folgt lauten : Wählen Sie * aus der Benutzertabelle aus, wobei login = 'vanya' und password = '' oder login = 'vanya' . Wie Sie wissen, erhalten wir dadurch Informationen über vanya .

Die beschriebene Sicherheitslücke 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 nicht nur möglich, den Bedingungsausdruck im Befehl select zu ändern, sondern auch über diesen Befehl hinauszugehen und einen anderen Datenbankbefehl auszuführen. Da MySQL mehrere Befehle in einer einzelnen Abfrage erlaubt, 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 ein beliebiger gültiger Befehl angegeben werden darf. Also zum Beispiel ein solcher Code: '; drop table 'userTable zerstört einfach die userTable- Tabelle aus der Datenbank.

Praktische Nutzung der Sicherheitsanfälligkeit

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

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

    Die betrachtete Sicherheitsanfälligkeit ist allen SQL-Abfragen eigen, 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 PHP-Fehlerstrom als Position (Standard) an den Endbenutzer gerichtet ist. Gleichzeitig informieren Perl- oder Exe-Anwendungen den Benutzer normalerweise nicht über die Art der Fehler.

    Feststellen, ob SQL im System verwendet wird.

    Wenn Sie ein bestimmtes System untersuchen, müssen Sie zuerst herausfinden, ob es SQL verwendet.
    Diese Tatsache kann entweder indirekt festgestellt werden (indem man sich die Namen der verwendeten Dateien ansieht, Links zu den verwendeten Tools usw.) oder direkt SQL zwingt, sich zu beweisen. Wenn wir mit PHP arbeiten, gibt es nur eine Möglichkeit, die Verwendung von SQL eindeutig zu bestimmen - dies führt zu einem Fehler bei der Ausführung. Wenn beim Ausführen der Anforderung ein Fehler auftritt, das PHP-Skript jedoch offensichtlich keine Fehler behandelt, wird die PHP-Fehlermeldung direkt an die Seite des Benutzers 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 Ermitteln der Reaktion des Skripts auf Fehler.

    Die einfachste Möglichkeit, das Vorhandensein einer Sicherheitsanfälligkeit, aber gleichzeitig auch die Verwendung von SQL zu erkennen, ist die folgende: Geben Sie in ein beliebiges Feld, das an der Erstellung der SQL-Abfrage beteiligt sein soll (z. B. das Feld " Anmelden" oder " Kennwort" ), ein einfaches Anführungszeichen ein. Die übrigen Felder werden mit gültigen Daten gefüllt (oder leer gelassen, wenn das System dies zulässt). Nach dem Absenden dieser Formulare betrachten wir die Reaktion des Systems. Wenn uns das PHP-Skript einen SQL-Fehler liefert, können wir uns gratulieren: Das System verwendet SQL und das Skript filtert in keiner Weise ein einzelnes Anführungszeichen. Das Essen System 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 Sicherheitslücke, 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, zu welchem ​​Zeitpunkt die SQL-Syntax korrekt ist, sondern zu welchem ​​Zeitpunkt.
    2) Das Skript filtert das Anführungszeichen, daher treten keine Fehler auf. In diesem Fall enthält das System keine Schwachstellen.
    3) Das allgemeine System verwendet in keiner Weise SQL.
    In den letzten paar 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 Sie die Werte einiger Felder in der Anforderung ermitteln (z. B. die Benutzeranmeldung festlegen). Hierzu müssen Sie jedoch die Namen der entsprechenden Felder kennen. Es gibt keine direkte Möglichkeit, diese Namen herauszufinden. Daher müssen Sie diese Namen mit brachialer Gewalt suchen. Die Datennamen können mit den Namen der Felder in dem an den Server gesendeten Formular übereinstimmen, oder sie stimmen auch in keiner Weise überein. 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 Login- Benutzer oder zum Nick . Ähnliches gilt für password: password ist entweder pwd oder pass .
    Um die Existenz eines bestimmten Feldes zu bestimmen, wird eine ausgeklügelte Methode vorgeschlagen: Überprüfen Sie, ob das Feld pwd in der Tabelle vorhanden ist. Geben Sie die Zeichenfolge 'pwd =' in ein beliebiges Formularfeld ein. Wenn das Feld pwd in der Tabelle vorhanden ist, verarbeitet SQL die Abfrage ordnungsgemäß, und wenn es kein solches Feld gibt, tritt erneut der SQL-Ausführungsfehler auf. Wenn Sie also verschiedene Werte der Feldnamen einsetzen und gleichzeitig das Ergebnis der Abfrage prüfen, können Sie feststellen, welche Felder in der Tabelle vorhanden sind, welche jedoch nicht.

    Definieren der Namen vorhandener Tabellen.

    Ähnlich wie bei der Suche nach Feldnamen in Tabellen können Sie auch nach den Namen vorhandener Tabellen in der Datenbank suchen. Angenommen, wir möchten herausfinden, ob die Tabelle adminList in der Datenbank vorhanden ist. Geben Sie dazu die folgende Zeile in das Formularfeld ein “; wählen Sie * aus adminList . Wenn SQL aufgrund des Fehlers überhaupt nicht startet, 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, um Syntaxfehler aufgrund des verbleibenden Endes der ursprünglichen Anforderung zu vermeiden, die später vorhanden sein wird . Wählen Sie in der Administratorliste * aus . Beachten Sie, dass, wenn ein Paar von Login- und Passwortfeldern auch die Ansicht für die Anfrage besitzt, das Passwortfeld höchstwahrscheinlich das letzte ist, das in der Anfrage erscheint.

    PS

    Mit 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 Inhabern der Website gemeldet. Das Loch wurde behoben. Aber jetzt haben wir noch einmal das Chat-Registrierungsformular überprüft. Plus fand ich alle diese bla bla Verwundbarkeit 8-).