„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 schreibt1 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 usersDie 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