Injection-Schwachstellen zählen neben Cross-Site-Scripting-Schwachstellen zu den häufigsten Schwachstellen in Web Applications. Sie gehören zu einer ganzen Klasse von Schwachstellen, die ihre Ursache in einer fehlerhaften Kodierung von Zeichen in einer SQL-Abfrage, in einem Shell-Kommando oder in einer Sprache haben, in die Eingabedaten eingebettet werden können. Diese Art von Schwachstelle kann sehr einfach ausgenutzt werden, da nur wenige Zeichen für einen erfolgreichen Angriff genügen. Am Häufigsten tritt diese Angriffsart in Kombination mit Datenbanksystemen auf. In diesem Fall spricht man von einer SQL-Injection bzw. MySQL-Injection.
Ein Denial-of-Service (DoS) Angriff ist ein Angriff auf eine oder mehrere Maschinen mit dem Ziel zu verhindern, dass der Opfer-Rechner weiterhin nützliche Arbeit leisten kann. Dies geschieht mit einer gezielten Überlastung durch eine große Anzahl von Anfragen, die möglichst viele Ressourcen für die Bearbeitung benötigen. Wird ein Angriff von einer größeren Anzahl von Systemen verursacht, so spricht man von einem Distributed Denial of Service (DDoS).
DDoS MySQL-Injection
Nehmen wir an, wir haben ein kleines Blog-System. Da hier auf Sicherheit geachtet worden ist, gibt es einen speziellen MySQL-Benutzer für das Frontend, der nur einen lesenden Zugriff auf die Datenbank „articles“ mit den Blog-Beiträgen hat. Grundsätzlich müsste man sich hier keine weiteren Gedanken machen, da der Benutzer keine Einträge in der Datenbank erstellen kann und auch nicht auf die Tabellen mit den Benutzern zugreifen darf.
Selbst wenn die übermittelten Parameter mit der Standardfunktion real_escape_string() auf unerwünschte Zeichen überprüft werden, die eigentlich eine MySQL-Injection verhindern sollen, ist noch ein Angriff möglich. Es werden die Zeichen (ASCII 0), \n, \r, \, ‚, „, und Control-Z gefiltert. Hier der Code mit Filterung:
$mysqli = new mysqli("localhost", "viewuser", "supperpassword", "blog"); $views = $mysqli->real_escape_string($_GET['views']); $result = $mysqli->query("SELECT headline,teaser FROM articles WHERE views > ".$views);
Die einfachste Variante um hier eine DoS MySQL-Injection einzuschleusen ist der Befehl sleep. Die präparierte URL und die MySQL-Anfrage lautet nun:
https://example.com/articles.php?views=100-SLEEP(15) SELECT headline,teaser FROM articles WHERE views > 100-SLEEP(15)
Damit hält der Prozess für 15 Sekunden an und gibt erst danach die Ressourcen frei. Noch stärker wird der Server belastet, wenn ein Benchmark Befehl eingeschleust wird:
https://example.com/articles.php?views=100- BENCHMARK(100000000, rand()) SELECT headline,teaser FROM articles WHERE views > 100-BENCHMARK(100000000, rand())
Damit führt die MySQL-Datenbank einen Benchmark 100 Millionen Mal mit einer Zufallszahl durch. Dies benötigt zusätzlich CPU- und Speicherressourcen. Diese Angriffe lassen sich noch beliebig mit COMPRESS() oder AES_ENCRYPT() weiter verschachteln.
Wird einer der oben vorgestellten MySQL-Injection Aufrufe durch ein Botnetz mehrfach ausgeführt, wird ein Distributed Denial of Service (DDoS) erreicht und als Folge der MySQL-Server stark ausgelastet.
Gegenmaßnahmen
Die obigen Beispiele zeigen, dass auch Standardfunktionen nicht in der Lage sind alle Angriffe abzublocken. Gerade die Funktion real_escape_string() wird in vielen Tutorials als die ultimative Lösung präsentiert. Jedoch sollten bei allen Usereingaben darüber hinaus noch eine maximale Länge und der Datentyp festgelegt werden. Würde beispielsweise im obigen Beispielfall geprüft werden, ob es sich um einen „integer-Wert“ handelt, würde der Angriff abgeblockt werden.
Hallo,
Ganz ehrlich, wer in der heutigen Zeit immer noch mysqli in Kombination mit direktem String Concat verwendet, hat es nicht anders verdient.
Man sollte hier auf jeden Fall auf Prepared Statements setzen, da hierdurch SQL Injections wesentlich besser abgefangen werden.