SQL Injection

In diesem Beitrag soll es kurz um meine Erfahrungen mit SQL Injection gehen. Es hat also mal gar nichts mit Elektronik zu tun.

Ich bin eher durch Zufall über dieses Thema gestolpert und habe es bei einigen Seiten im „Vorbeisurfen“ mal angetestet. Es ist schon erschreckend wie viele Seiten davon betroffen sind. Hatte ich eine Seite gefunden, wollte ich natürlich wissen ob und wie weit offen das Fenster nun steht.

Ist das schon „Hacken“?

Ich bin immer technisch interessiert und gebe Informationen gern kostenfrei (hier) weiter, um die Welt vielleicht ein Stück besser zu machen. Als Hacker würde ich mich wohl nicht bezeichnen wollen. Es ist aber sehr interessant bei der Injection herauszufinden, wie die hinterlagerte Datenbank tickt und wie sie aufgebaut ist. Es ist spannender als jedes Sudoku und Kreuzworträtsel zu gleich und trotzdem ähnlich kniffelig. Dabei ist es mir auch völlig egal welche Daten dort gehalten werden, da ich kein Interesse an den Daten selbst habe. Die meisten Daten sind über die Webseite eh schon frei zugänglich, dann geht es eher darum auf einen anderen Weg diese wieder abrufen zu können.

Für nicht technisch versierte (und für sich selbst?) sollte man vielleicht ein Vergleich heranziehen: Man schaut durch die Nachbarschaft und entdeckt gegen 22 Uhr abends ein offenes Fenster. Steht das Fenster wirklich offen? Sollte ich den Nachbarn lieber warnen? Man schaut also genauer hin. Vielleicht muss man ein fremdes Grundstück betreten oder benutzt ein Tool, wie z.B. ein Fernglas, um ganz sicher zu gehen. Hat man zweifelsfrei die Sicherheitslücke erkannt schaut man durch das Fenster, um hineinzurufen „Entschuldigung! Ihr Fenster steht für alle zugänglich offen. Sie sollten es lieber schließen!“. Wahrscheinlich wird sich der Nachbar auch etwas über ihren Besuch wundern…

So in etwa stell ich mir den Sachverhalt vor. Vielleicht sieht es der Staatsanwalt aber auch ganz anders? Aber das ist ein anderes Thema…

Damit es Sicherheitslücken bei der Datenübergabe geben kann, muss es eine Webseite sein die mit Datenbankzugriffen arbeitet. Eine statische HTML-Seite läuft also nicht Gefahr ein Datenleck zu besitzen. Meist sind es mittelgroße Seiten, die nicht auf einem gut bekannten Framework beruhen, sondern der Betreiber viel eigene bzw. externe IT-Leistung hineinsteckt hat. Ist die Seite wiederum zu groß und hat viele Benutzer, könnt ihr euch den Versuch sparen. Bei Facebook haben sicher schon Andere etwas gefunden und es wurde gefixt. Außerdem können sich solche Seiten Sicherheit etwas kosten lassen, aber wir kommen vom Thema ab.

Beim Besuch einer Webseite versuche ich immer mal gelegentlich ein „‚“ oder auch ein „““ in eine Textfeld oder Textbox einzugeben. Hat der Ersteller der Webseite aus Unwissenheit oder einfach nur aus Versehen die Daten dieses Textfelds unverändert an den Datenbankaufruf weitergereicht, dann wird sich die Webseite merkwürdig verhalten. Es kommt zu Fehlern oder leeren Seiten, aber nicht zu einem geordneten „Ihr Suchbegriff wurde nicht gefunden“ oder „Ihre Benutzer oder Kennwort ist falsch“.  Im schlechtesten Fall bekommt man eine ausführliche Fehlermeldung aus der Datenbank. Ich sage schlechtesten Fall, da wir nicht hacken wollen sondern ehe entrüstet über diese grobe Sicherheitslücken sind!

Beispiel:

Microsoft OLE DB Provider for ODBC Drivers Fehler "80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Fehler beim Konvertieren einer Zeichenfolge in ein Datum und/oder eine Uhrzeit.

Das Rätzel welcher Datenbankserver auf der Internetseite verwendet wird ist nun schon gelöst. Interessant, was bietet denn die Seite sonst noch? Da ist doch sicher noch mehr schlechte Programmierung. Ah, ein Benutzername- und Passwortfeld… Wir befreien uns aus dem String des Benutzernamens mit „“ und fügen ein „“ hinzu. Im Benutzer steht nun „‚““ und im Passwort ein nettes „hallo„. Dies führt zu Fehlermeldung:

Kein schließendes Anführungszeichen nach der Zeichenfolge '' and Pwd='hallo''.

Jetzt sind es schon drei gravierende Verstöße: Die Seite lässt SQL Injection zu, der Datenbankserver informiert sauber über seinen Zustand und die Passwörter werden im Klartext gespeichert. Der Webseiten-Admin kann also regulär alle Passwörter der Benutzer sehen. Zur Speicherung von Passwörtern sollte immer nur gehashte Werte verwenden!

Aufgrund der gewonnen Informationen kann sich nun einfach ohne gültiges Passwort eingeloggt werden, da wir annehmen können das das SQL Query wie folgt aussieht:

SELECT * FROM table_name WHERE user='Basti' and Pwd='hallo'

Derzeit nicht bekannt ist der Tabellenname oder ob wirklich „user“ verwendet wird. Ob alle Spalten der Tabelle mit „*“ gewählt wurden ist auch noch nicht klar.

Da wo nun Basti steht ist der Einstiegspunkt der Injection. Damit dieser Aufruf Zeilen der Datenbank zurück gib, muss er nur wahr werden. Dazu können wir erst einmal das nervige Passwort (Pwd) mit „“ auskommentieren. Mit der immer wahren Operation user=“ or 1=1 werden alle Zeilen gültig.

Letztendlich geben wir beim Benutzernamen nur ein „‚ or 1=1–“ und erhalten den Zugang eines Benutzers. Dies funktioniert da es die Seite zulässt, wenn gleich mehrere Benutzer mit einen mal gültig sind. Es wird einfach der Erste genommen. Das SQL Query sieht nun so aus:

SELECT * FROM table_name WHERE user='' or 1=1--

Wenn nun ein Benutzer geht, dann gehen sicher auf noch Andere, vielleicht mit mehr Rechten?! In einer Tabelle gibt es immer/oft eine ID-Spalte. Wenn alle Spalten mit „*“ selektiert wurden und wir den Namen der Spalte herausbekommen, dann ist es ganz einfach. Der Versuch zeigt: die Spalte heißt „id„. Damit kann man sich nun als beliebiger Benutzer des Systems anmelden: „gfdgdfgdf‘ or id=5–“ -> wird zu:

SELECT * FROM table_name WHERE user='gfdgdfgdf' or id=5--

Damit habe ich es bei weiteren Versuchen gelassen. Ich habe den Webseitenbetreiber über die Sicherheitslücke informiert, ohne dabei konkret zu werden. Leider habe ich bisher keine Rückmeldung erhalten. Es wäre möglich alle Passwörter mit Email-Adressen aus dem System zu bekommen. Was eine ziemliche Sauerei für die Betroffenen wäre. Da mich aber so etwas nicht interessiert, blieb es bei dieser kleinen Knobelei. Wobei es einem schon zu einfach gemacht wurde!

Weiterhin habe ich sqlmap angetestet. Ein Python-basierendes Tool, um die SQL-Eingabe zu automatisieren. Das führte jedoch bei meinen Tests zu wenigen neuen Erkenntnissen. Außerdem war es nicht mehr nötig seinen Kopf zu benutzten. Vielleicht für schnelle Tests für Admins geeignet, aber nicht für echte Knobler. Jedoch soll es Helfen, wenn Tabellennamen und -spalten aus der Datenbank extrahiert werden sollen. Dazu ist es evtl. nötig jeden Buchstaben einzeln einer Ja/Nein-Abfrage zu unterziehen, also einer ganz schöne Arbeit, die man niemals per Hand eingeben würde.

sqlmap erzeugt riesige lange Datenbankeingaben. Wenn die in den Logs der Datenbankserver landen, fallen diese definitiv auf. Wahrscheinlich wurde auch deshalb eine Woche später die SQL-Sicherheitslücke von einer anderen Webseite entfernt. Auch nicht schlecht!

Meist stellt man die Injection selbst nur fest und kommt dann nicht weiter, entweder weil die Ideen fehlen oder weil es einfach nicht viel weiter geht. Das wichtigste Hilfsmittel ist die offizielle Befehlsdokumentation der einzelnen Datenbank-Systeme und Geduld. Der Vollständigkeit halber sollte ich erwähnen, dass natürlich nicht nur angebotene Textfelder untersucht werden können, auch Dinge die per GET und POST versandt werden sind gerade anfällig. Hierfür gibt es nicht immer ein Eingabefeld.

Dieser Beitrag wurde unter Allgemein veröffentlicht. Setze ein Lesezeichen auf den Permalink.

Hinterlasse einen Kommentar