
Шаблон Nuclei для обнаружения серверов Apache, уязвимых к CVE-2024-38473

Шаблон Nuclei, предназначенный для обнаружения уязвимых серверов Apache к CVE-2024-38473. Сначала он определяет серверы, работающие на Apache < 2.4.60 с настройками PHP-FPM по умолчанию. Затем он фаззит потенциальные PHP-файлы, защищённые ACL, которые можно обойти из-за этой уязвимости.
Для использования этого шаблона Nuclei необходимо клонировать репозиторий. Вы можете сделать это, выполнив следующую команду:
git clone https://github.com/juanschallibaum/CVE-2024-38473-Nuclei-Template
Перейдите в каталог клонированного репозитория:
cd CVE-2024-38473-Nuclei-Template
Запуск шаблона nuclei для одного хоста:
nuclei -t CVE-2024-38473.yaml -u http://example.com
Запуск шаблона nuclei для списка хостов:
nuclei -t CVE-2024-38473.yaml -l hosts.txt
Запуск шаблона nuclei для одного хоста с указанием валидного .html или .php файла:
nuclei -t CVE-2024-38473.yaml -u http://example.com/valid.php
Запуск Nuclei таким образом может повысить уровень обнаружения. Вы также можете включить URL-адреса в этом формате в файл hosts, чтобы запустить шаблон против этого списка.
Чтобы легко протестировать уязвимость CVE-2024-38473, вы можете поднять уязвимое окружение с помощью Docker. Выполните следующие шаги для быстрой проверки эффективности шаблона Nuclei:
Убедитесь, что Docker Daemon запущен: Убедитесь, что демон Docker запущен на вашей системе. Вы можете запустить его следующей командой, если он ещё не запущен:
sudo systemctl start docker
Запустите Docker-контейнер: В каталоге репозитория используйте следующую команду Docker для запуска контейнера с уязвимой конфигурацией Apache и PHP-FPM:
docker run -p 8787:80 -v "$(pwd)/test-env-webroot:/app" webdevops/php-apache:7.1
Проверьте уязвимость:
Вручную: Откройте веб-браузер и перейдите по адресу http://localhost:8787, чтобы взаимодействовать с сервером Apache, работающим в контейнере Docker. Перейдите по адресу http://localhost:8787/info.php для тестирования уязвимости. Этот файл защищён ACL, и если обход ACL успешен, вы увидите вывод phpinfo():

Используя шаблон Nuclei: Выполните следующую команду Nuclei для тестирования сервера с помощью шаблона:
nuclei -t CVE-2024-38473.yaml -u http://localhost:8787
8 августа 2024 года исследователь безопасности Orange Tsai выступил с докладом на Black Hat USA 2024 под названием: Confusion Attacks: Exploiting Hidden Semantic Ambiguity in Apache HTTP Server!. В этом докладе он сообщил о множестве уязвимостей, затрагивающих Apache HTTP Server. Он объяснил, что Apache имеет высокомодульную архитектуру, состоящую из сотен модулей, каждый из которых выполняет свою функцию, читая и записывая данные в общую структуру request_rec, содержащую почти 100 полей.
Коренная причина уязвимостей, о которых сообщил исследователь, заключается в несогласованности обработки различных полей этой общей структуры разными модулями Apache. Например, mod_authz_core интерпретирует поле r->filename как файл, тогда как mod_proxy интерпретирует его как URL-адрес, что приводит к расхождениям и множеству уязвимостей.
В своём докладе Orange Tsai определяет тип атаки под названием "Filename Confusion". Хотя поверхность этой атаки разнообразна, CVE-2024-38473, которую мы рассматриваем в этом шаблоне, относится к тому, как применить атаку "Filename Confusion" для обхода ACL Apache и получения доступа к ограниченным файлам.
Проблема возникает, когда модуль аутентификации Apache mod_authz_core интерпретирует атрибут r->filename как файл, в то время как mod_proxy интерпретирует его как URL-адрес. Из-за этого установки Apache с PHP-FPM в конфигурации по умолчанию подвержены этой уязвимости. Представьте, что сервер, работающий на Apache и PHP-FPM, имеет настроенный ACL, подобный следующему, для защиты доступа к файлу admin.php с учётными данными:
<Files "admin.php">
AuthType Basic
AuthName "Admin Panel"
AuthUserFile "/etc/apache2/.htpasswd"
Require valid-user
</Files>
Из-за уязвимости можно обойти ACL, подобный приведённому выше, который защищает отдельный файл. Фактически, это можно сделать, просто отправив такой запрос: http://server/admin.php%3fooo.php.
Чтобы понять это в деталях, важно учесть, что когда Apache обрабатывает подобный запрос, модуль mod_authz_core читает значение admin.php?fooo.php из поля r->filename общей структуры. Он интерпретирует это значение как имя запрашиваемого файла, и при сравнении с ACL оно не совпадает, потому что admin.php?fooo.php отличается от admin.php.
Затем, поскольку admin.php?fooo.php заканчивается на .php, запрос передаётся в PHP-FPM. PHP-FPM удаляет всё после ? в имени файла, полученном от Apache, перед обработкой, интерпретируя его как URL-адрес, а не как файл. В результате PHP-FPM обработает непосредственно admin.php. Поскольку проверка ACL была пройдена ранее, злоумышленник может получить доступ к admin.php без аутентификации.
Текущий шаблон Nuclei направлен не только на обнаружение защищённых файлов методом перебора, но и включает логику для определения, когда сервер имеет уязвимую конфигурацию Apache < 2.4.60 с PHP-FPM, даже если случаи файлов, защищённых ACL, не обнаружены. В базовом потоке он сначала пытается определить, имеет ли сервер уязвимую конфигурацию, а затем, если это так, пытается выявить общие файлы, которые могут быть защищены ACL.
Идея обнаружения уязвимых конфигураций с Apache < 2.4.60 и PHP-FPM основана на двух основных предпосылках:
В уязвимой конфигурации, если file.php существует на сервере, то запрос к http://server/file.php%3fooo.php вернёт тот же статус 200 и ту же длину тела, что и запрос к http://server/file.php (поскольку после удаления %3fooo.php PHP-FPM запрашиваемый файл будет тем же самым).
В уязвимой конфигурации, если file.html существует на сервере, то запрос к http://server/file.html%3fooo.php вернёт 403 Access Denied. Это происходит потому, что PHP-FPM попытается загрузить файл с расширением .html вместо .php, что по умолчанию не разрешено.
Поток шаблона состоит из 7 групп запросов. Они должны выполняться последовательно и должны соответствовать соответствующим условиям для перехода к следующей группе запросов. Это помогает минимизировать количество запросов, отправляемых впустую, если условия уже не выполняются.
Шаблон отправляет запрос к index.phpooo.php%3fooo.php, который является несуществующим файлом. Идея — отсеять ложные срабатывания в случаях, когда index.php%3fooo.php возвращает статус 200 и то же тело, что и index.php, даже если PHP-FPM не настроен. Это может произойти, например, при наличии правил, которые переписывают любой запрошенный файл или файлы, начинающиеся с "index", на index.php, как:
RewriteRule . /index.php [L]
RewriteRule ^index\.php(.*)$ index.php [L]
RewriteRule ^index(.*)$ index.php [L]
Этот запрос должен вернуть статус 200, если на сервере есть такие правила, или статус 404 в обычных случаях, когда PHP-FPM может быть настроен. Если этот запрос не возвращает статус 404, шаблон прекратит обработку этого хоста.
Шаблон отправляет запрос к foo.phpooo.php%3fooo.php, который является несуществующим файлом. Идея — отсеять ложные срабатывания в случаях, когда index.html%3fooo.php возвращает статус 403, даже если PHP-FPM не настроен. Это может произойти, например, при наличии правил, запрещающих символ %3f где-либо в URL-адресе или ограничивающих доступ к файлам, заканчивающимся на .php. Примеры таких правил:
<FilesMatch "\.php$">
Require all denied
</FilesMatch>
RewriteCond %{REQUEST_URI} (%3f)
RewriteRule ^(.*)$ - [F]
Этот запрос должен вернуть статус 403, если на сервере есть такие правила, или статус 404 в обычных случаях, когда PHP-FPM может быть настроен. Если этот запрос не возвращает статус 404, шаблон прекратит обработку этого хоста.
Шаблон отправляет запросы для определения некоторых доступных файлов на сервере. Сначала он пытается определить, доступен ли index.php. Затем проверяет index.html и index.htm. Наконец, он проверяет файл, указанный в URL-адресе, предоставленном пользователем, если он существует. Если Nuclei запущен с указанием валидного файла в URL-адресе, это может повысить эффективность обнаружения в случаях, когда классические индексные файлы отсутствуют.
Шаблон отправляет запрос к несуществующему файлу для отсеивания последних ложных срабатываний в случаях, когда index.php%3fooo.php возвращает статус 200 и то же тело, что и index.php, даже если PHP-FPM не настроен. Некоторые веб-серверы, особенно не Apache, игнорируют всё, что следует за %3f. Поэтому, если мы отправим index.php%3fooo.php, сервер обработает его как index.php. Чтобы отсеять такие случаи, шаблон отправляет запрос к index.php%3fooo.html (если index.php найден на сервере) или index.html%3fooo.html (если index.html найден на сервере). Поскольку он заканчивается на .html, в обычных случаях, когда PHP-FPM может быть настроен, он не будет обработан PHP-FPM и будет рассматриваться как статический файл, который логически не существует, что приведёт к статусу 404. Однако он вернёт статус 200 в тех случаях, которые мы хотим отсеять, где всё, что следует за %3f, игнорируется. Если этот запрос не возвращает статус 404, шаблон прекратит обработку этого хоста.
Шаблон отправляет запрос для определения уязвимой конфигурации. Есть 2 случая, из которых должно быть выполнено хотя бы одно из условий совпадения:
Случай 1: В Запросе #3 был найден index.php. В этом случае, если Apache < 2.4.60 и PHP-FPM включён с конфигурацией по умолчанию, он должен отбросить часть %3fooo.php и загрузить index.php, что приведёт к ответу 200 с той же длиной, что и в Запросе #3. Если используется mod_php или другой обработчик, он воспримет index.php%3fooo.php как полное имя файла и вернёт 404. Чтобы этот случай совпал, запрос должен вернуть 200 и тело той же длины, что и ответ от Запроса #3.
Случай 2: В Запросе #3 был найден index.html. В этом случае, если Apache < 2.4.60 и PHP-FPM включён с конфигурацией по умолчанию, он должен отбросить часть %3fooo.php и попытаться загрузить index.html, что вернёт 403 Access Denied, так как PHP-FPM пытается загрузить файл с недопустимым расширением. Если используется mod_php или другой обработчик, он воспримет index.html%3fooo.php как полное имя файла и вернёт 404. Чтобы этот случай совпал, запрос должен вернуть 404.
Если шаблон дошёл до этого момента, это означает, что сервер имеет уязвимую конфигурацию. Следовательно, шаблон отправляет запросы для фаззинга потенциально защищённых файлов, которые возвращают статус 403 или требуют аутентификации и возвращают статус 401. По умолчанию он пытается определить лишь несколько наиболее распространённых и потенциально защищённых имён файлов. Однако вы можете раскомментировать строку, чтобы использовать собственный wordlist с 350 возможными именами PHP-файлов.
Шаблон отправляет запрос для проверки того, что защищённый файл, определённый в Запросе #6, возвращает статус 200 при обходе.
Если какое-либо условие из Запроса #5 выполнено, это указывает на то, что сервер работает под управлением Apache < 2.4.60 с настройками PHP-FPM по умолчанию. Это означает, что если ACL защищает отдельный файл, его можно обойти. Однако часто такие уязвимые конфигурации можно обнаружить без идентификации каких-либо защищённых файлов. По умолчанию шаблон использует wordlist wordlists/potential_protected_php_files_10.php для фаззинга защищённых файлов. Этот список включает 10 наиболее вероятных имён PHP-файлов, которые могут быть защищены ACL. Альтернативно, доступен более крупный wordlist из 350 записей: wordlists/potential_protected_php_files_350.php. Чтобы переключиться на более крупный список, закомментируйте wordlist из 10 записей и раскомментируйте список из 350 в разделе YAML Запроса #6 в шаблоне следующим образом:
#fuzz: wordlists/potential_protected_php_files_10.txt
fuzz: wordlists/potential_protected_php_files_350.txt
Использование более крупного wordlist может увеличить шансы нахождения защищённых PHP-файлов. Однако wordlist potential_protected_php_files_350.txt может содержать редко встречающиеся имена PHP-файлов и может не включать более распространённые имена PHP-файлов, которые могут быть защищены ACL. Поэтому любые улучшения или дополнения к wordlist приветствуются. Кроме того, для дальнейшего исследования можно использовать и большие собственные wordlist.
Обратите внимание, что обходимые ACL могут быть настроены для разных виртуальных хостов, в файлах .htaccess в любом каталоге приложения, а не только в корневом каталоге. Поэтому для максимизации шансов выявления файлов, защищённых ACL, рекомендуется провести тщательную разведку каталогов и поддоменов и запустить шаблон против всех идентифицированных URL-адресов с разными поддоменами и каталогами.
В настоящее время поток Запроса #6 останавливается после обнаружения первого файла, защищённого ACL. Однако их может быть больше. Это происходит потому, что я не нашёл способа фаззить несколько файлов с помощью Nuclei, сохранять результаты, а затем использовать их в последующем запросе для проверки, предоставляет ли обход фактический доступ к защищённым файлам. Поэтому любые предложения по изменению шаблона для идентификации нескольких защищённых файлов и проверки, что они действительно обходимы, также приветствуются.
Все заслуги за сообщение об уязвимостях и проведение выдающегося исследования принадлежат Orange Tsai. Его обширная работа над уязвимостями Apache HTTP Server, включая CVE-2024-38473, значительно способствовала повышению осведомлённости в области безопасности. Я, Juan Schallibaum, несу ответственность исключительно за создание этого шаблона Nuclei для облегчения тестирования и обнаружения CVE-2024-38473.
Использование этого шаблона Nuclei для атак на цели без предварительного взаимного согласия является незаконным. Конечный пользователь обязан соблюдать все применимые местные, государственные и федеральные законы. Разработчики не несут ответственности за любое неправомерное использование, ущерб или юридические последствия, возникшие в результате использования этого шаблона. Всегда убедитесь, что у вас есть явное разрешение перед проведением любого тестирования безопасности.