
Анализирует CVE-2026-42945 — переполнение кучи в rewrite-модуле NGINX, предоставляя дифференциальный детектор, детерминированный PoC для DoS и подтверждённый порт RCE с верификацией.
Исследование безопасности CVE-2026-42945 (CVSS 4.0 9.2 CRITICAL): переполнение
буфера в куче в скриптовом движке NGINX, где rewrite с аргументами в
замене (например, rewrite ^(.*) /new?c=1;) оставляет флаг is_args
движка установленным и никогда не сбрасывает его — поэтому любое захваченное
значение ($1), вычисленное после этого в set/if, копируется с URI-экранированием
в буфер, который был выделен под неэкранированную длину. Доступно до аутентификации
любому клиенту, чей URI запроса содержит %XX-экранирования или +.
Результат (фаза 1): безопасный дифференциальный детектор (уязвимая
1.30.0 против исправленной 1.30.1, ноль сбоев) плюс детерминированный DoS воркера
(SIGSEGV, core dumped — ответ полностью отдаётся сначала). Оба
воспроизведены на сборках из исходников на коммите 71d62c6.
Результат (фаза 2): порт RCE репортёра с указанием авторства —
выполнение system() от имени пользователя воркера (nobody), воспроизведено 3/3
чистых прогонов против зафиксированной сборки репортёра, воспроизведённой в lab/rce/.
Техника эксплуатации принадлежит Leo Lin (DepthFirst); см.
Что здесь оригинально, а что — предыдущая работа и раздел Предыдущая работа в отчёте.
| Утверждение | Доказательство |
|---|---|
| Первопричина выведена из фикс-коммита (не из блогов) | finding-sheet |
Фикс — одна строка — e->is_args = 0; в ngx_http_script_regex_end_code() | коммит 524977e (цитируется в отчёте) |
| Безопасный детектор: уязвимый против исправленного оракула, ноль сбоев | poc/diagnose.py — отпечаток усечения (/foo%25b против /foo%bar) |
| Матрица триггеров: кавычки/плюс в URI и экранируемые символы в захвате — обязательны оба | батарея проб poc/diagnose.py, включая контроль /a%41b |
| Детерминированный DoS воркера (SIGSEGV, core dumped, ответ отдаётся первым) | poc/crash.py — изменение X-Worker-PID доказывает смерть воркера |
| Исправленная 1.30.1 переживает идентичную атаку | poc/crash.py --host 127.0.0.1:29544 — 3/3 раундов выжило |
| RCE (фаза 2, техника репортёра, порт с указанием авторства) | exploit/rce.py — 3/3 прогона, файл-доказательство + uid=65534(nobody), воркеры exited on signal 11 после выполнения |
# дифференциальная пара: nginx 1.30.0 (:29543) + 1.30.1 (:29544), собранные из исходников
cd lab && docker compose up -d --build && cd ..
python3 poc/diagnose.py # безопасный оракул — никогда не роняет ни одного воркера
python3 poc/crash.py --host 127.0.0.1:29543 # 1.30.0: воркер умирает на сигнале 11, core dumped
python3 poc/crash.py --host 127.0.0.1:29544 # 1.30.1: переживает каждый раунд
docker logs cve-42945-vuln 2>&1 | grep 'exited on signal' | tail -3
Фаза 2 — RCE против зафиксированной сборки репортёра (dev-ревизия nginx
98fc3bb7 = release-1.29.8-14, ASLR отключена зафиксированной точкой входа):
docker compose -f lab/rce/docker-compose.yml up -d --build # :29545, сборка занимает минуты
python3 exploit/rce.py \
--cmd 'echo pwned-by-cve-2026-42945 > /tmp/proof' --verify --expect pwned
docker compose -f lab/rce/docker-compose.yml exec nginx cat /tmp/proof
| Документ | Что это |
|---|---|
| docs/finding-sheet.md | Одностраничный даташит: версии, CVSS, паттерн конфигурации, условия триггера, сигнатуры обнаружения |
| docs/report-ptes.md | Отчёт по структуре PTES (7 фаз), ограниченный фактически выполненным |
| docs/research-writeup.md | Повествование об исследовании — археология фикс-коммита, сюрприз с усечением, переносимые уроки, будущая работа |
Цепочка исследования фазы 1 — оригинальная работа: безсбойный дифференциальный
оракул и его отпечаток усечения (отданное тело — это повторно экранированный
захват, усечённый до сырой длины — видимая сигнатура несоответствия двух проходов
длина/значение), матрица триггеров, доказывающая необходимость обоих предусловий,
объяснение на уровне исходников, почему проход длины не видит is_args, и
детерминированное убийство воркера после ответа. Сама ошибка, уязвимый паттерн
конфигурации и анализ фикс-коммита — предыдущая работа репортёра и апстрима —
Leo Lin (DepthFirst) раскрыл проблему, а Roman Arutyunyan её исправил; см.
раздел Предыдущая работа в отчёте и
DepthFirst Disclosures — Nginx-Rift,
дерево CVE-2026-42945.
Фаза 2 (RCE) — это порт опубликованного эксплойта репортёра, а не
независимая цепочка: межзапросный heap feng shui, который наводит переполнение
на указатель cleanup соседнего пула запроса, спрей фейковых
ngx_pool_cleanup_t через удерживаемые тела POST, перенаправление cleanup-диспетчера
на libc system(), геометрия переполнения (349 A + 969 + +
6 целевых байт), константы базы/смещения без ASLR и зафиксированная сборка
в lab/rce/ (их env/) — всё это дизайн Leo Lin, воспроизведённый
с указанием авторства в exploit/rce.py. Наше в фазе 2: сам порт — соглашения
CLI/логирования/верификации этого репозитория, живое обнаружение кандидатов
сканированием кучи и автоопределение базы (их статические константы
зависят от ядра; см. docstring эксплойта), слушатель reverse-shell на stdlib
и доказательства верификации.
Этот репозиторий разделяет методологию с CVE-2026-42533 — NGINX Pre-Auth Heap Overflow: Analysis & RCE (родственный репозиторий): тот же класс ошибки двух проходов длина/значение в скриптовом движке nginx, доведённый там до полной цепочки RCE до аутентификации. Эта цепочка очертила правдоподобный потолок для данной ошибки; фаза 2 этого репозитория достигает того же потолка здесь — как порт с указанием авторства техники репортёра, а не независимая цепочка.
docs/ finding sheet · отчёт PTES · исследовательский отчёт
poc/ diagnose.py (безопасный дифференциальный оракул) · crash.py (детерминированный DoS)
exploit/ rce.py — порт цепочки system() репортёра с указанием авторства
lab/ Dockerfile (nginx из исходников, -g -O0) + дифференциальная compose-пара
lab/nginx/ vulnerable.conf — PoC-конфигурация из фикс-коммита
lab/rce/ зафиксированная RCE-среда репортёра (их env/, наше отображение порта)
524977e7c534
"Rewrite: fixed escaping and possible buffer overrun" (Roman Arutyunyan) — выпущен в nginx 1.30.1CVE-2026-42945 (предыдущая работа репортёра; Leo Lin)Образовательный исследовательский артефакт. Запускайте только против систем, которые принадлежат вам или на тестирование которых у вас есть явное разрешение. Уязвимость исправлена — обновите nginx до ≥ 1.30.1.