Zum Inhalt springen
Startseite » SQL-Injection 2 – Die UNION Attack

SQL-Injection 2 – Die UNION Attack

UNION Attack

Im zweiten Beitrag der SQL-Injection Reihe möchte ich euch eine Technik vorstellen, die sich UNION Attack nennt und mit der sich der Inhalt ganzer Datenbanken auslesen lässt.

Den ersten Beitrag mit den Grundlagen dieses Angriffs findet ihr hier.

Damit ihr die Technik direkt nachvollziehen könnt, verweise ich hier noch einmal auf die Trainingsumgebung, die ich mithilfe von Docker-Containern zusammengestellt habe und die Ihr bei Github findet:
git clone https://github.com/bugninja-de/SQL-injection-practice-course.git

Was ist die UNION Attack?

Der UNION-Befehl wird bei SQL-Abfragen dazu genutz, die Rückgaben mehrerer Statements in einem Ergebnis zusammenzufassen. Das machen wir uns bei der UNION Attack zu nutze. Als erstes müssen wir herausfinden, wie viele Felder das ursprüngliche SQL-Statement zurück gibt, da unser eingeschleustes Statement die gleiche anzahl an Feldern zurück geben muss, um es im selben Ergebnis zu speichern. Dies machen wir einfach dadurch, dass wir das Ergebnis des Statements nach der ersten, zweiten, … x-ten Spalte sortieren lassen. Wenn eine Fehlermeldung oder ein leeres Ergebnis zurück kommt, obwohl das Ergebnis eigentlich nicht leer sein sollte, haben wir nach einer Spalte sortiert, die es nicht gibt und wir wissen, wie viele Spalten das Statement liefert.

Wenn ihr euch die Trainingsumgebung von Github gecloned habt und ihr die Container per docker-compose up -d gestartet habt, könnt ihr einfach den Browser eurer Wahl öffnen und http://localhost/products.php aufrufen. Ihr solltet dann diese Seite sehen:

UNION Attack products page
http://localhost/products.php

Eine wunderschöne Seite, auf der euch einige Turnschuhe angezeigt werden. Oben über das Dropdown könnt ihr die Farbe der angezeigten Schuhe eingrenzen.

Schritt 1:

Der Parameter, welche Farbe angezeigt werden soll, wird hierbei als GET Parameter über die URL übergeben und hier ist auch unser Angriffspunkt. Wir fügen, wie im ersten Teil der SQL-Injection Reihe, ein ' gefolgt von unserer gewünschten Modifikation der Abfrage an die URL an. Eine Besonderheit müssen wir jedoch beachten: Da wir die Werte direkt über die Adresszeile des Browsers eingeben, müssen wir einige Sonderzeichen in ein kompatibles Format bringen, weil es sonst zu Fehlern kommen könnte. Bei der gewünschten Modifikation ist es das Kommentar-Zeichen # welches wir URL-kompatibel als %23 eingeben. Um jetzt herauszufinden, wie viele Spalten die Original-Abfrage zurück liefert, zählen wir erstmal die auf den ersten Blick ersichtlichen Elemente: Id, Image, Name, Description und Price macht zusammen 5. Also probieren wir erstmal zur Sicherheit, nach der 5. Spalte zu sortieren. Wir fügen also ' ORDER BY 5 %23 an die URL an. Diese sollte dann je nach ausgewählter Farbe etwa so aussehen:

UNION Attack URL field
http://localhost/products.php?color=blue‘ ORDER BY 5 %23

Die Seite wird wie erwartet angezeigt und da es sich um eine Testumgebung handelt, wird die komplette Query auch angezeigt und wir können sehen, dass das %23 wieder in ein # umgewandelt wurde:

first step

Natürlich können wir auch an der eingeblendeten Abfrage ablesen, wie fiele Felder das Ergebnis enthält, aber normalerweise sind Website-Entwickler nicht so freundlich, die Datenbank-Abfrage direkt auf die Seite zu stellen.

Also wissen wir jetzt schonmal sicher, dass die Abfrage mindestens 5 Felder hat. Nun zählen wir diesen Wert in der URL so weit hoch, bis wir eine Fehlermeldung oder ein leeres Ergebnis erhalten. Bei 6 ist noch alles gut, bei 7 kommt die Fehlermeldung:

UNION Attack error message

Deaktiviert im Live-Betrieb einer Website sollten solche Fehlermeldungen bitte auf jeden Fall, um Angreifern nicht zu viele Informationen über das System zu verraten.

Schritt 2:

Wir wissen nun, dass Unser Ergebnis 6 Felder enthält. Als nächstes wäre es sinnvoll zu sehen, an welcher stelle welches Feld auf der Seite angezeigt wird. Hier kommt UNION ALL zum tragen. Warum UNION ALL und nicht UNION ? Ein UNION ohne ALL zeigt keine doppelten Datenbankeinträge. Ich persönlich finde es besser, alle Zeilen einer Tabelle zu erhalten. Doppelte Einträge kann ich auch hinterher noch ausfiltern. Außerdem ist UNION ALL im Vergleich zu UNION schneller, da es eben nicht filtert, aber das fällt normalerweise nicht wirklich ins Gewicht. Es ist wie bei so vielem Geschmackssache, ob man sich für UNION mit oder ohne ALL entscheidet.
Wir modifizieren unsere URL wie folgt, um zu sehen, welches Feld an welcher Stelle auf der Seite erscheint:
http://localhost/products.php?color=blue' UNION ALL SELECT 1,2,3,4,5,6 %23

second step

Was haben wir gemacht? Wir haben einen Datensatz mit den Werten 1, 2, 3, 4, 5 und 6 an das Ergebnis angefügt. Auf der Seite sieh man nun, an welcher Stelle welches Feld auftaucht. Besonders geeignet für Textausgaben sind hier die Felder 2 und 3. Wenn wir also die nächsten Statements erzeugen, werden wir uns auf diese Felder konzentrieren.

Schritt 3:

Jetzt wäre es ganz interessant zu wissen, was es für Tabellen gibt, um zu schauen, wo sich zum Beispiel Login-Daten befinden, die wir auslesen können. Dafür bietet MySQL die Datenbank INFORMATION_SCHEMA an, in der Informationen zu den Datenbanken und Tabellen gespeichert werden. Besonders die Tabelle TABLES ist hier interessant, da diese sämtliche Tabellennamen enthält. Wir modifizieren unsere URL, um uns die Tabellennamen auszugeben:

http://localhost/products.php?color=blue' UNION ALL SELECT 1,TABLE_NAME,3,4,5,6 FROM INFORMATION_SCHEMA.TABLES %23

Als erstes werden uns die ganzen Standard-Tabellen angezeigt, die bei jeder MySQL-Datenbank vorhanden sind. Wenn wir aber ganz nach unten scrollen, kommmen wir zu den interessanten Einträgen:

UNION Attach INFORMATION_SCHEMA.TABLES
Die Tabellen ‚products‘ und ‚users‘

Die Tabellen ‚products‘ und ‚users‘ fallen hier ins Auge. Schauen wir mal, wie die Spalten der Tabelle ‚users‘ heißen. Dafür grifen wir auf die Daten der Tabelle COLUMNS in der Datenbank INFORMATION_SCHEMA zu:

http://localhost/products.php?color=blue' UNION ALL SELECT 1,COLUMN_NAME,3,4,5,6 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'users' %23

UNION Attack INFORMATION_SCHEMA.COLUMNS
Spalten id, username und password

Treffer: es gibt die Spalten id, username und passwort. Dann schauen wir uns den Inhalt der Tabelle ‚users‘ mal an:

Schritt 4:

http://localhost/products.php?color=blue' UNION ALL SELECT id,username,password,4,5,6 FROM users #

UNION Attack final exploit

Sieht so aus, als hätten wir hier die Zugangsdaten der Benutzer. Wir könnten jetzt diese Daten nehmen und versuchen, uns auf der Seite http://localhost damit anzumelden.

Wenn ihr mit euren Tests zur UNION Attack fertig seid, denkt daran, die Trainingsumgebung mittels docker-compose down zu beenden.

Fazit:

Dieses Beispiel zeigt, warum es keine gute Idee ist, Passwörter im Klartext in einer Datenbank zu speichern. Wenn Benutzerdaten einer Website aus welchen Gründen auch immer abhanden kommen, kann der Angreifer diese so direkt nutzen. Deshalb sollten Passwörter immer mit einem geeigneten Algorithmus gehashed werden – sinvollerweise mit Salt und Pepper um Rainbowtables unbrauchbar zu machen. Was Salt, Pepper und Rainbowtables sind und wie dieses Salz und Pfeffer dazu genutzt werden kann, um Passwörter sicher zu speichern, werde ich in einem späteren Beitrag erläutern.

Den dritten Blogpost zur SQL Injection findet ihr hier.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.