SQL Injection ohne Kommata durchführen

Letztens bin ich auf eine SQL Injection gestoßen, welche ich als sehr interessant empfand. Um die SQL Injection durchzuführen musste man einen Exploit entwickeln, welcher keine Kommata enthielt.

Die SQL Injection

Die folgend beschriebe SQL Injection Lücke klaffte bei einem großen Unternehmen. Man war in der Lage über einen numerischen Parameter das Query zu manipulieren. Die Daten des Querys wurden an ein Mail-Script übergeben, um Inhalte einer Datei an eine Email zu verschicken.

Hier war meine Neugier geweckt, denn vielleicht könnte man über die SQL Injection die Pfadangabe zur ausgelesenen Datei verändern und somit an andere Inhalte gelangen?

Nach ein paar Anfragen war die Spaltenanzahl des Querys bestimmt. Der Versuch das Query mit einem „union select“ zu erweitern scheiterte jedoch. Ernüchterung :(

index.php?fileid=1+and+1=2+union+select+1,2,3,4,5,6+--+

Als nächsten Ansatz wollte ich die MySQL-Version herausfinden, denn „union“ gibt es erst seit MySQL 5.0:

index.php?fileid=1+and+5=substr(version(),1,1)+--+

Dieses Query scheiterte jedoch auch. Eine normale bool’sche Anfrage wurde korrekt interpretiert. Das roch nach einem Blacklist-Filter.

Die Lösung – SQL Injection ohne Kommata

Die Überschrift verrät die Lösung eigentlich schon. Nach ein wenig rumspielen viel mir auf, dass der eingesetzte Filter nur auf das Komma-Zeichen ansprang und die Ausführung des Querys dadurch verhindert wurde. Die folgenden Anfragen bestätigten mir das:

index.php?fileid=1+and+1=1+/**Funktioniert**/
index.php?fileid=1+and+1=1+/** , Funktioniert nicht mehr **/

Mir war klar, dass ein Großteil aller SQL Anfragen Kommata enthält, sodass eine „union“-Injection nicht mehr möglich sein wird. Es gäbe keine Möglichkeit die selektierten Spalten ohne Kommata abzutrennen, ohne einen SQL Fehler zu erzeugen.

Somit war die mögliche File-Inclusion Attacke nicht mehr umsetzbar. Da Blacklists allgemein unsicher sind, wollte ich an dieser Stelle noch nicht aufgeben, und trotzdem eine funktionsfähige SQL Injection hinbekommen.

Die Lösung bestand darin, dass MySQL zu manchen Funktionen alternative Funktionsaufrufe akzeptiert. Statt

index.php?fileid=1+and+5=substr(version(),1,1)+--+

lässt MySQL auch folgendes zu:

index.php?fileid=1+and+5=substr(version() FROM 1 FOR 1)+--+ //ODER:
index.php?fileid=1+and+5=mid(version() FROM 1 FOR 1)+--+

In den letzten Exploits ist kein Komma mehr vorhanden, sodass der Filter umgangen wird und man die Lücke trotzdem ausnutzen konnte.

Fazit

Wie immer: Finger weg von Blacklist-Filtern!

Diese lassen sich nämlich fast immer mit irgendwelche Tricks umgehen. Man sollte lieber auf Prepared Statements nutzen. Das werde ich demnächst einen Artikel schreiben.

~Sebastian