SQL-Injection unter Umgehung von mysql_real_escape_string(): Analyse von Schwachstellen

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

„Hilfe! Meine mysql_real_escape_string() funktioniert nicht!“



Wenn Sie jemals nach „SQL injection that gets around mysql_real_escape_string()“ gegoogelt haben, sind Sie nicht allein. Diese Frage auf Stack Overflow hat Zehntausende von Aufrufen gesammelt und ist ein Klassiker der Websicherheit geworden. Man würde meinen, man nimmt mysql_real_escape_string() – und ist geschützt. Aber nein. Hacker finden Schlupflöcher und Entwickler bekommen graue Haare.



In diesem Artikel analysieren wir, wie genau SQL-Injection die Maskierung von mysql_real_escape_string() in PHP umgehen kann. Sie sehen echte Codebeispiele, verstehen, warum der „gute alte“ Ansatz nicht mehr funktioniert, und erfahren, wie Sie sich wirklich schützen. Los geht‘s!



Warum ist mysql_real_escape_string() kein Allheilmittel?



Zunächst ein wenig Geschichte: Die Funktion mysql_real_escape_string() erschien in der Ära von PHP 4 und 5, als alle auf der Erweiterung mysql_* saßen. Sie maskiert Sonderzeichen wie Anführungszeichen, Backslashes und Steuerzeichen. Das Problem ist jedoch, dass sie nur im Kontext einer Kodierung funktioniert.



Wenn die Kodierung von Client und Server nicht übereinstimmt – beginnt das Chaos. Und wenn Sie Multi-Byte-Kodierungen (z. B. GBK oder SJIS) verwenden – kann die Funktion zu Ihrem schlimmsten Feind werden.



Klassisches Beispiel: Multi-Byte-Angriff



Stellen Sie sich vor, Ihre Website verwendet die Kodierung GBK (Chinesisch) und Sie übergeben die Zeichenfolge:



$_POST['name'] = "0xbf27"; // Maskiertes ' oder einfach '?


In GBK ist das Zeichen 0xbf27 ein gültiges chinesisches Schriftzeichen. Aber wenn mysql_real_escape_string() 0x27 (Apostroph) „sieht“, maskiert es ihn mit einem Backslash: 0xbf5c27. Das Problem ist, dass 0xbf5c ebenfalls ein gültiges Zeichen in GBK ist! Das bedeutet, dass der Apostroph 0x27 unmaskiert bleibt und der Hacker seinen eigenen SQL-Code einfügen kann.



// Anfälliger Code$name = mysql_real_escape_string($_POST['name']);$query = "SELECT * FROM users WHERE name = '$name'";

// Wenn eingegeben: 0xbf27// Die Funktion gibt zurück: 0xbf5c27// In GBK ist das: chinesisches Zeichen + Apostroph// Die Abfrage wird zu: SELECT * FROM users WHERE name = 'chin_zeichen' OR 1=1 -- '


Voilà! Die Injection ist gelungen. Und das ist keine Theorie – solche Schwachstellen wurden in echten Projekten gefunden.



Typische Schwachstellen bei der Verwendung von mysql_real_escape_string()



Lassen Sie uns die häufigsten Fehler auflisten, die eine Umgehung der Maskierung ermöglichen:



  • Falsche Kodierung – wie im obigen Beispiel. Wenn der Server denkt, die Daten seien in UTF-8, der Client aber GBK sendet, bricht die Maskierung zusammen.
  • Verwendung von numerischen Feldern ohne Anführungszeichen – wenn Sie eine Zahl direkt einsetzen, funktioniert die Maskierung nicht. Zum Beispiel: SELECT * FROM users WHERE id = $id – und der Hacker schreibt 1 OR 1=1.
  • LIKE-Abfragen – die Maskierung behandelt die Zeichen % und _ nicht. Eine Blind SQL-Injection über Muster ist möglich.
  • Mehrfache Maskierung – wenn Sie die Funktion zweimal aufrufen, wird der Backslash verdoppelt und der Schutz verschwindet.


Beispiel: Angriff auf ein numerisches Feld



// Anfälliger Code$id = mysql_real_escape_string($_GET['id']);$query = "SELECT * FROM products WHERE id = $id"; // Anführungszeichen nicht nötig!

// Der Hacker gibt ein: 1 UNION SELECT username, password FROM users// Die Abfrage wird zu: SELECT * FROM products WHERE id = 1 UNION SELECT username, password FROM users


Die Maskierung ist hier nutzlos – es gibt keine Anführungszeichen, die maskiert werden müssten. Der Hacker fügt einfach sein eigenes SQL direkt ein.



Moderne Schutzmethoden (die funktionieren)



Genug der Schreckensgeschichten – kommen wir zu den Lösungen. Wenn Sie in PHP schreiben und SQL-Injection vergessen möchten, hier ist Ihre Checkliste:



1. Verwenden Sie PDO oder MySQLi mit prepared statements



Das ist

Blogs

Buchempfehlungen