Eine Kundenanwendung mit URL-Processing in PHP
Ein Kunde betreibt eine PHP-Webanwendung, bei der Anfragen via .htaccess und mod_rewrite auf ein zentrales PHP-Skript umgeleitet werden. Die URL-Parameter werden dabei intern als GET-Parameter übergeben:
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
Im PHP-Code wird dieser Parameter url anschließend verarbeitet, u.a. durch Zuweisung in eine SQL-Abfrage. Unser Penetrationstest offenbarte hier eine potenzielle SQL Injection-Schwachstelle, da der Input unzureichend gefiltert wurde.
Problem durch Leerzeichen in Payloads
Versuche, SQL Payloads wie ' OR 1=1 --
zu übermitteln, scheiterten jedoch wiederholt, da Leerzeichen zu Fehlern führten. Der Webserver, genauer mod_rewrite, blockierte diese Anfragen. Dies deutete darauf hin, dass Leerzeichen in der URL – vermutlich durch %20
– vom Webserver nicht korrekt behandelt wurden.
Erster Lösungsansatz: SQL Injection Payloads ohne Spaces?
Als initialer Workaround wurde versucht, Payloads ohne Spaces zu verwenden. Dies ist begrenzt möglich, erfordert aber kreatives Encoding oder spezielle SQL-Syntax. Eine typische Technik, die in SQL-Injection Cheat Sheets zu finden ist, ist das Nutzen von inline Kommentaren, um Leerzeichen zu umgehen:
SELECT/*avoid-spaces*/password/**/FROM/**/Members
Neuer Bypass
Ein bislang unbekannter Ansatz, den wir eigens für den zuvor genannten Kunden-Pentest entwickelt haben, besteht darin, sämtliche Expressions in Klammern zu umschließen:
index'AND'1'=(extractvalue(rand(),concat(0x3a,(select(substr(group_concat(user),1,10))from(mysql.user)))))AND'1'='1
Dieser Trick wird von der Rewrite-Logik nicht blockiert. Dies haben wir auf einer lokalen Demo-Instanz mit einer deckungsgleichen Webserverkonfiguration nachgestellt:
Ein klarer Vorteil in bestimmten SQL-Injection-Kontexten und eine interessante Neuentdeckung, da dieser Ansatz bisher nicht in öffentlich bekannten Exploit-Datenbanken dokumentiert war.
Recherche: Wie kann man doch Spaces verwenden?
Die Frage, warum Spaces problematisch sind und welche Alternativen erfolgreich eingeschleust werden können, führte zu spannenden Erkenntnissen:
SQLmap nutzt %20
Automatisierte Tests mit sqlmap waren nicht in der Lage die SQL-Injection Schwachstelle auszunutzen. Der Grund: SQLmap nutzt standardmäßig %20 zur URL-Kodierung von Leerzeichen. Mit der Nutzung von diesen Leerzeichen zur Payload-Generierung trat beim Kundenserver durch die Rewrite-Logik ein 403-Fehler auf.
sqlmap -u http://localhost:8080/index --level 3 --risk 3 --dbms=mysql
Hackvertor nutzt + statt %20
Bei einer manuellen Analyse der zuvor von SQLmap verwendeten Payloads mittels BurpSuite Repeater und URL-Encoding mittels Hackvertor-Plugin, funktionierten diese auf einmal. Hierbei konnten wir feststellen, dass der reguläre URL-Encoder des Hackvertor-Plugins standardmäßig Leerzeichen via ‚+‘ Zeichen enkodiert. Mit diesem Zeichen war es also möglich die Injection in mod_rewrite auszunutzen.
Nutzung von + gezielt durch SQLmap forcieren
In einem nächsten Schritt erforschten wir demnach, wie wir SQLmap so konfigurieren können, dass ebenfalls das + Zeichen als Leerzeichen kodiert wird. Dies gelang über das Tamper-Script spacetoplus.py:
sqlmap -u "http://example.com/index.php?url=..." --tamper=spacetoplus
Die sqlmap Payloads mit + wurden vom Webserver akzeptiert, intern korrekt als Leerzeichen interpretiert und ermöglichten eine erfolgreiche Ausnutzung der SQL-Injection.
Warum funktioniert das? Das Verhalten von + im mod-rewrite-Kontext
Nachdem wir diesen entscheidenden Unterschied zwischen %20 und + Zeichen feststellen konnten, interessierte uns die genaue Ursache hinter diesem Verhalten. Aus diesem Grund haben wir uns auf eine tiefere Analyse von mod_rewrite begeben:
Verhalten von Apache mod_rewrite bei %20 und +
Laut diesem StackOverflow-Thread interpretiert Apache %20 nicht als %20 weiter, sondern dekodiert es zu einem echten Leerzeichen, bevor die Rewrite-Regel greift. Dies kann zu folgender Fehlermeldung führen:
AH10411: Request rejected: space in rewritten query string
Entscheidend ist dabei der Einsatz bestimmter Flags in der RewriteRule:
- Diese Regel führt zu Fehlern:
RewriteRule ^(.*)$ /index.php?url=$1 [QSA,L]
- Diese Regel hingegen umgeht das Problem:
RewriteRule ^(.*)$ /index.php?url=$1 [B,QSA,L]
Das B-Flag sorgt für eine korrekte URL-Neukodierung („escape backreferences“), wodurch %20 als %2520 übertragen wird – dies verhindert die problematische Interpretation als Space. Ohne [B] kann $1 Sonderzeichen enthalten (z. B. &, ?), die die Ziel-URL zerbrechen. Mit [B] wird $1 korrekt escaped (& → %26, etc.).
Sicherheitsimplikationen von serverseitiger URL-Enkodierung
Während in unserem Kundenszenario das fehlende „B“ Flag ausschließlich dazu führte, dass wir als Angreifer keine Leerzeichen in unseren Payloads verwenden konnten, gibt es weitere Artikel im Internet, die aufzeigen, dass durch eine fehlerhafte oder unvollständige Konfigurationen in Bezug auf URL-Encodings nicht nur unerwünschtes Verhalten auftreten kann, sondern weitere Sicherheitsrisiken entstehen können:
Hierbei wollen wir die folgenden Varianten als Beispiele zeigen:
- Confusion Attacks durch RewriteFlags (Orange Tsai)
- Während Orange Tsai eine ganze Reihe an Fehlkonfigurationen gefunden hat, ist folgendes Beispiel in unserem Kontext besonders interessant:
RewriteRule ^(.+\.php)$ $1 [H=application/x-httpd-php]
- Angriff:
http://server/upload/1.gif%3fooo.php
- In diesem Beispiel geht es um einen mod_rewrite-Trick, bei dem Apache eine Datei mit .php-Handler behandelt, obwohl sie keine .php-Datei ist. Die Rewrite-Regel prüft, ob eine URL mit .php endet, und weist dann einen PHP-Handler zu. Apache matcht dabei nur den sichtbaren Pfad vor dem ?, während der Rewrite-Handler sich nach dem vollständigen String richtet. Der Angreifer hängt also ?foo.php an eine .gif-Datei an — Apache behandelt sie dadurch als PHP.
- Während Orange Tsai eine ganze Reihe an Fehlkonfigurationen gefunden hat, ist folgendes Beispiel in unserem Kontext besonders interessant:
- Auth-Bypass durch NGINX-Apache-Pfadverwechslung
- In PAN-OS, dem Betriebssystem von Palo Alto Networks, wurde eine Schwachstelle entdeckt, bei der durch eine Kombination von Nginx und Apache eine Pfadverwirrung ausgenutzt wurde, um die Authentifizierung zu umgehen. Ein speziell gestalteter URL-Pfad wie
/unauth/%252e%252e/php/ztp_gate.php/PAN_help/x.css
wurde von Nginx und Apache unterschiedlich interpretiert. Nginx dekodierte den Pfad einmal und setzte aufgrund des /unauth/-Segments einen Header, der die Authentifizierung deaktivierte. Apache hingegen dekodierte den Pfad erneut und erkannte eine Pfad-Traversierung, die zu einer internen Weiterleitung führte. Dadurch wurde ein PHP-Skript ohne Authentifizierung ausgeführt.
- In PAN-OS, dem Betriebssystem von Palo Alto Networks, wurde eine Schwachstelle entdeckt, bei der durch eine Kombination von Nginx und Apache eine Pfadverwirrung ausgenutzt wurde, um die Authentifizierung zu umgehen. Ein speziell gestalteter URL-Pfad wie
- CVE-2021-41773 (Apache Path Traversal)
- In Apache HTTP Server 2.4.49 wurde eine Änderung in der Pfadnormalisierung eingeführt, um RFC 1808 zu entsprechen. Dabei trat ein Fehler auf, bei dem die Funktion ap_normalize_path URL-encoded Zeichen nicht vollständig dekodierte, bevor sie auf Pfad-Traversierungssequenzen prüfte. Die Funktion dekodierte nur das erste Punkt-Zeichen (.) in einem Pfadsegment. Dadurch konnten Angreifer Sequenzen wie .%2e/ verwenden, die nach der unvollständigen Dekodierung nicht als ../ erkannt wurden, um auf Dateien außerhalb des vorgesehenen Verzeichnisses zuzugreifen.
Diese Fälle verdeutlichen, dass Logik zum Umschreiben oder Interpretieren von URLs nicht nur funktionale, sondern auch sicherheitsrelevante Auswirkungen haben kann – insbesondere, wenn Input-Validierung fehlt oder Encoding/Decoding-Prozesse unzureichend dokumentiert sind.
Fazit
Unsere Recherche zeigt, wie tiefgreifend Webserver-Verhalten und Encoding-Logik in die Sicherheit von Webanwendungen eingreifen können. Gerade die Interaktion zwischen mod_rewrite, URL-Encoding, Pfadnormalisierung und Parameterverarbeitung kann in Missverständnissen und Zweideutigkeiten resultieren, die ultimativ eine Schwachstelle ergeben.
Um sich gegen Angriffe auf Pfad- oder Parameternormalisierung zu schützen (Path Traversal, Double Decode, Confusion Attacks), sollten folgende Maßnahmen beachtet werden:
- Pfadnormalisierung früh und konsistent durchführen – idealerweise zentral im Code oder durch Reverse Proxies.
- Keine sicherheitsrelevanten Entscheidungen auf Basis von URLs oder dekodierten Werten treffen.
- Eingaben mehrfach dekodieren, prüfen und verwerfen, wenn sie nach Dekodierung Traversal- oder Escape-Muster enthalten (../, %2e, %252e usw.).
- Reverse Proxies und Webserver wie NGINX und Apache auf konsistentes Dekodierungsverhalten prüfen.
- Nur whitelisting-basierte Routen und Dateizugriffe erlauben.