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

Einige Sicherheitslücken in Webressourcen mit SQL


Dieser Beitrag behandelt eine SQL-Sicherheitsanfälligkeit im Zusammenhang mit dem Eindringen in den Text einer Abfrage.

Das Wesen der Verwundbarkeit

Betrachten Sie die Arbeit des einfachsten Systems mit einer WEB-Schnittstelle, mit der Benutzer auch Änderungsinformationen über sich selbst speichern können. Solche Systeme gehören zu den gebräuchlichsten im Netzwerk. Dies kann auch ein Gästebuch, einen Chat, eine Fotogalerie und einen Postdienst beinhalten.

Bei der generierten Abfrage der Datenbank muss der Benutzer den Benutzernamen und das Kennwort eingeben. Für diese Felder sollte die Datenbank den entsprechenden Eintrag in der Tabelle finden. Nach Abschluss der Anfrage liefert die Datenbank die gefundenen Informationen über den Benutzer, die das PHP-Skript in Form von HTML auch dem Benutzer zur Verfügung stellt.

Analysieren wir ein ziemlich typisches Fragment eines PHP-Skripts, 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 sehen, sind der vom Benutzer eingegebene Benutzername und das Kennwort in den Variablen $ userLogin und $ userPassword enthalten . Der Inhalt dieser Variablen ist in der Anforderung enthalten, Informationen über diesen bestimmten Benutzer zu filtern. Der Filter wird mit der Option where des Befehls select SQL festgelegt. 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 Anmeldevariablen des Passworts auch die Werte von vanya und vasya enthalten, sieht die an die Datenbank gesendete Abfrage folgendermaßen aus: Wählen Sie * aus der Benutzertabelle, wobei login = 'vanya' und password = 'vasya' . Es ist klar, dass, wenn in der Datenbank kein Datensatz vorhanden ist, in dem der Anmeldename gleich vanya ist, das Kennwort jedoch vasya lautet , bis zur Anforderung weder eine einzelne Zeile aus der Datenbank gesendet noch vom Skript etwas erzeugt wird. Somit bietet das gegebene System nur Zugang zu den Informationen des Benutzers, der ein fehlerfreies Passwort und eine fehlerfreie Anmeldung hat.

Es scheint, dass ein solches System keine Mängel aufweist. In der Praxis 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 Kennwort persönlich ist und der eingegebene Benutzer ein Anführungszeichen enthält. Lassen Sie ihn den Wert von vas'ya besitzen , während die Anfrage so aussieht: Wählen Sie * aus userTable, wobei login = 'vanya' und password = 'vas'ya' . Wenn eine solche Anfrage ausgeführt wird, tritt mit Sicherheit ein Fehler auf, da das Anführungszeichen aus dem Passwort das Eröffnungszitat aus der Anfrage schloss und auch das Ende des Passworts außerhalb des bedingten Ausdrucks "hängen" blieb.

Und wenn Sie eine solche Zeile als Passwort einfügen: 'oder 1 = 1' , wird die Abfrage folgendermaßen aussehen: select * from userTable, wobei login = 'vanya' und password = '' oder 1 = 1 '' ebenfalls keine Syntaxfehler aufweisen . Aber der logische Ausdruck wird identisch korrekt, auch wenn diese Abfrage beanstandet wird, gibt SQL die gesamte Datenbank der Benutzer zurück 8-).

Mit dem Apostroph können wir daher auch den Text der SQL-Abfrage einfügen, sodass die zu überprüfende Bedingung wahr ist. Wenn wir an einem bestimmten Benutzer vanya interessiert sind, ist es zulässig, die folgende Kennwortzeichenfolge zu verwenden, um Informationen über ihn zu erhalten: 'oder login =' vanya . Dies macht die Anfrage: Wählen Sie * aus userTable, wobei login = 'vanya' und password = '' oder login = 'vanya' . Wie Sie verstehen, werden wir als Ergebnis Informationen über Vanya erhalten .

Die beschriebene Sicherheitslücke von SQL-basierten Diensten beschränkt sich in keiner Weise auf den unbefugten Empfang von Informationen. Da in solchen Systemen in der Regel MySQL verwendet wird, ist es in keiner Weise möglich, den Bedingungsausdruck im Befehl select zu ändern, aber auch über diesen Befehl hinauszugehen und einen anderen DB-Befehl 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 darf ein gültiger Befehl als <SQL-Befehl> angegeben werden . Also zum Beispiel den folgenden Code: '; drop table 'userTable zerstört einfach die userTable aus der Datenbank.

Praktische Anwendung von Sicherheitslücken

Trotz der 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:
  • Bestimmen, ob SQL im System verwendet wird.
  • Identifizieren Sie das Vorhandensein einer Sicherheitsanfälligkeit. Klarstellung der Reaktion des Skripts auf Fehler.
  • Definition der Feldnamen in der Tabelle.
  • Identifizieren Sie die 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 an der Tatsache, dass der PHP-Fehlerstrom als Position (standardmäßig) an den Endbenutzer gesendet wird. Perl- oder Exe-Anwendungen informieren den Benutzer normalerweise nicht über die Art der Fehler.

    Bestimmen, 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 (durch Betrachten der Namen der verwendeten Dateien, Verweise auf die verwendeten Tools usw.) oder direkt aufgedeckt werden, indem die SQL sich manifestiert. Wenn wir mit PHP arbeiten, gibt es nur einen Weg, die Verwendung von SQL eindeutig zu bestimmen - um einen Fehler in seiner Ausführung zu verursachen. Wenn während der Ausführung der Anforderung ein Fehler auftritt, das PHP-Skript jedoch die Fehler bei der Ausführung nicht explizit behandelt, wird die PHP-Fehlermeldung direkt an die Seite des Benutzers gesendet.
    Wie ein Fehler bei der Ausführung einer SQL-Abfrage verursacht wird, hängt vom jeweiligen Gerät des betreffenden Systems ab. In den meisten Fällen darf der Fehler die Eingabe falscher Daten in das System aufrufen.

    Identifizieren Sie das Vorhandensein einer Sicherheitsanfälligkeit. Klarstellung der Reaktion des Skripts auf Fehler.

    Das einfachste Mittel, um das Vorhandensein einer Sicherheitsanfälligkeit, aber gleichzeitig auch die Verwendung von SQL zu erkennen, ist das Folgende: Geben Sie in ein beliebiges Feld, das an der Generierung einer 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 lassen, wenn das System dies zulässt). Nachdem wir die gegebenen Formulare gesendet haben, 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 das einfache Anführungszeichen in keiner Weise. Dann frisst das System eine Schwachstelle auf.
    Der SQL-Abfragefehler sieht dann auf der Seite folgendermaßen aus:

    Dateneingabeformular:


    Das Ergebnis ist 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 "durch Berührung" handeln, da wir zu keinem Zeitpunkt wissen, zu welchem ​​Zeitpunkt die SQL-Syntax korrekt ist, aber zu welchem ​​Zeitpunkt nicht.
    2) Das Skript filtert das Angebot auch, weil keine Fehler auftreten. In diesem Fall enthält das System keine Schwachstellen.
    3) Das allgemeine System verwendet kein SQL.
    In den letzten paar Fällen ist klar, dass die weitere Erforschung von SQL überhaupt keine Bedeutung hat.

    Definition der Feldnamen in der Tabelle.

    Um Informationen mit bestimmten Daten aus der Datenbank abzurufen, müssen Sie die Werte einiger Felder in der Anforderung ermitteln (z. B. die Benutzeranmeldung festlegen). Dazu müssen Sie jedoch den Namen der entsprechenden Felder kennen. Das direkte Herausfinden dieser Namen ist nicht möglich. Daher ist es notwendig, diese Namen mit der Suchmethode zu suchen. Diese Namen stimmen möglicherweise mit den Namen der Felder in dem an den Server gesendeten Formular überein, sie stimmen jedoch möglicherweise auch nicht überein. Das Gute ist, dass die Namen der Felder als Position auch Standardvarianten sind, um sie in keiner Weise so sehr zu schreiben. Der Name des Felds für den Benutzernamen ist beispielsweise wahrscheinlich " Anmeldename" oder " Benutzer" oder " Nickname" . Ähnlich wie das Passwort: Passwort entweder pwd oder pass .
    Um die Existenz eines bestimmten Feldes zu bestimmen, schlagen wir eine unkomplizierte Methode vor: Angenommen, Sie möchten überprüfen, ob das Feld pwd in der Tabelle vorhanden ist. Geben Sie in ein beliebiges Formularfeld die folgende Zeichenfolge "pwd =" ein . Wenn das Feld pwd in der Tabelle vorhanden ist, verarbeitet SQL die Anforderung ordnungsgemäß. Wenn es kein solches Feld gibt, tritt der Ausführungsfehler von SQL erneut auf. Wenn Sie also verschiedene Werte der Feldnamen einsetzen und auch das Ergebnis des Abschlusses der Abfrage prüfen, können Sie feststellen, welche Felder in der Tabelle vorhanden sind, welche jedoch nicht.

    Identifizieren Sie die Namen vorhandener Tabellen.

    Ähnlich wie beim Ermitteln der Namen von Feldern in Tabellen kann auch nach den Namen vorhandener Tabellen in der Datenbank gesucht werden. Angenommen, wir möchten herausfinden, ob die Tabelle adminList in der Datenbank vorhanden ist. Geben Sie dazu die folgende Zeichenfolge in das Formularfeld mit dem Sprecher ein '; wählen Sie * aus adminList . Wenn der SQL-Fehler daher überhaupt nicht startet, ist die Tabelle adminList vorhanden. Für die Richtigkeit dieses Tests müssen Sie diese Zeichenfolge in das Feld eingeben, das in der SQL-Abfrage als endgültig angezeigt wird. Dies ist erforderlich, um sicherzustellen, dass der Syntaxfehler nicht auf den verbleibenden "Schwanz" der ursprünglichen Anforderung zurückzuführen ist, der später angezeigt wird . Beachten Sie, dass, wenn die Ansicht für die Anforderung einem Paar des Anmeldefelds und des Kennworts gehört , das Kennwortfeld höchstwahrscheinlich als letztes in der Anforderung angezeigt wird.

    PS

    Mit dieser Sicherheitsanfälligkeit wurde die Website http://www.bigmir.net gehackt (genauer gesagt, die Fotogalerie ist auch ein Chat). Wir haben eine Sicherheitsanfälligkeit für Websitebesitzer veröffentlicht. Das Loch wurde behoben. Aber jetzt haben wir das Chat-Formular noch einmal überprüft. Plus fand alle diese bla bla Verwundbarkeit 8-).