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
cve-2023-5217-poc — Un PoC para desencadenar CVE-2023-5217 desde la interfaz WebCodecs o MediaRecorder del navegador. | Kitploit
Herramientas/GitHubGitHub/ut-security/cve-2023-5217-poc
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebFuzzingAprendizaje y EducaciónExplotación de Binarios
GitHubut-security/cve-2023-5217-poc

cve-2023-5217-poc

Un PoC para desencadenar CVE-2023-5217 desde la interfaz WebCodecs o MediaRecorder del navegador.

Ver Repositorio
1631hace 2 añosAú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 →
Compartir

CVE-2023-5217: Desbordamiento de Montón en Codificación VP8 de libvpx PoC

CVE-2023-5217 es una vulnerabilidad de libvpx explotada in-the-wild que fue encontrada por Clément Lecigne del Grupo de Análisis de Amenazas de Google para estar atacando Chrome.

Este repositorio muestra cómo desencadenar CVE-2023-5217 en el navegador utilizando las API WebCodecs y MediaRecorder. CVE-2023-5217 permite un desbordamiento de búfer de montón con una longitud de desbordamiento controlada y una sobrescritura de un valor pequeño repetido de 4 bytes. Actualmente no se sabe cómo fue explotado CVE-2023-5217 en la naturaleza.

Alrededor del momento de la divulgación pública, hubo dos parches en libvpx y uno en Chromium que corrigieron CVE-2023-5217. Los parches de libvpx incluyeron deshabilitar los cambios en el número de hilos de VP8 y una prueba para la codificación multihilo. El parche de Chromium deshabilitó el ajuste del número de hilos en WebCodecs.

Problema Subyacente en libvpx v1.13.0 Ugly Duckling

Resumen

libvpx es una biblioteca que maneja la codificación y decodificación de VP8/VP9.

El problema clave en CVE-2023-5217 es que reducir el número de hilos mientras se aumenta la altura del cuadro en una sesión de codificación VP8 de libvpx provoca un desbordamiento lineal de montón de una longitud controlada y una sobrescritura controlada de un valor pequeño repetido de 4 bytes. La diferencia en la altura del cuadro controla la longitud de la sobrescritura, y el nuevo ancho del cuadro controla el valor de 4 bytes que se escribe repetidamente. Esta vulnerabilidad se puede explotar múltiples veces para escribir continuamente diferentes valores pequeños de 4 bytes reduciendo la altura en cada configuración subsiguiente.

Detalles

El codificador VP8 de libvpx mantiene un array llamado mt_current_mb_col que almacena la columna actual en la que está trabajando un hilo del codificador. Este array solo se asigna si hay más de un hilo, y su tamaño es una función de mb_rows, donde mb_rows = frame_height >> 4 y frame_height se redondea al múltiplo de 16 más cercano.

root@kitploit:~
// https://github.com/webmproject/libvpx/blob/6512f994da13e2f27e6a7bd449efee0a374b55b7/vp8/common/alloccommon.c#L85
// The width and height are rounded up to a multiple of 16 and then assigned to `mb_rows` and `mb_cols`
int vp8_alloc_frame_buffers(VP8_COMMON *oci, int width, int height) {
    ...
    // Round up the width/height up to the nearest multiple of 16
    if ((width & 0xf) != 0) width += 16 - (width & 0xf);
    if ((height & 0xf) != 0) height += 16 - (height & 0xf);
    ...
    oci->mb_rows = height >> 4;
    oci->mb_cols = width >> 4;
    ...
}
// https://github.com/webmproject/libvpx/blob/6512f994da13e2f27e6a7bd449efee0a374b55b7/vp8/encoder/onyx_if.c#L1232
// This snippet shows the allocation of `mt_current_mb_col`
void vp8_alloc_compressor_data(VP8_COMP *cpi) {
  ...
  // Only allocate if we have more than 1 thread
  if (cpi->oxcf.multi_threaded > 1) {
    int i;

    vpx_free(cpi->mt_current_mb_col);
    // sizeof(*cpi->mt_current_mb_col) is 4
    CHECK_MEM_ERROR(&cpi->common.error, cpi->mt_current_mb_col,
                    vpx_malloc(sizeof(*cpi->mt_current_mb_col) * cm->mb_rows));
    for (i = 0; i < cm->mb_rows; ++i)
      vpx_atomic_init(&cpi->mt_current_mb_col[i], 0);
  }
  ...
}

Una vez que libvpx termina de codificar un cuadro, almacena el número de columnas codificadas más mt_sync_range en mt_current_mb_col.

root@kitploit:~
// https://github.com/webmproject/libvpx/blob/6512f994da13e2f27e6a7bd449efee0a374b55b7/vp8/encoder/onyx_if.c#L1212
// Snippet where the mt_sync_range value is set, based on the width.
void vp8_alloc_compressor_data(VP8_COMP *cpi) {
    ...
#if CONFIG_MULTITHREAD
  if (width < 640) {
    cpi->mt_sync_range = 1;
  } else if (width <= 1280) {
    cpi->mt_sync_range = 4;
  } else if (width <= 2560) {
    cpi->mt_sync_range = 8;
  } else {
    cpi->mt_sync_range = 16;
  }
#endif
  ...
}
// https://github.com/webmproject/libvpx/blob/6512f994da13e2f27e6a7bd449efee0a374b55b7/vp8/encoder/encodeframe.c#L560
// Function where the attacker chosen value is written
static void encode_mb_row(...) {
  ...
  const int nsync = cpi->mt_sync_range; // This value is set in vp8_alloc_compressor_data
  vpx_atomic_int rightmost_col = VPX_ATOMIC_INIT(cm->mb_cols + nsync);
  ...
  if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0) {
    current_mb_col = &cpi->mt_current_mb_col[mb_row];
  }
  ...
  if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0) {
    // current_mb_col is a reference to mt_current_mb_col
    vpx_atomic_store_release(current_mb_col,
                             vpx_atomic_load_acquire(&rightmost_col));
  }
  ...
}

Para desbordar mt_current_mb_col, necesitamos tres configuraciones de codificación:

  1. configinit: Durante la inicialización, libvpx establece initial_width y initial_height. Estos son los límites máximos posibles de configuraciones posteriores. El número de hilos aquí no importa. Necesitamos la configuración intermedia porque ninguna combinación posterior de ancho/alto puede ser mayor que con la que comenzamos.
  2. configvuln: Durante la reconfiguración, si se usa más de un hilo, libvpx crea la asignación vulnerable de mt_current_mb_col basada en configvuln.height. Esta nueva altura debe ser menor que configinit.initial_height o de lo contrario obtendremos un error.
  3. configattack: Durante la reconfiguración, si solo se usa un hilo, libvpx no reasignará mt_current_mb_col, dejándolo en un estado vulnerable. libvpx escribirá repetidamente el valor (configattack.width >> 4) + 1 (donde 1 es la variable mt_sync_range y el ancho se redondea al múltiplo de 16 más cercano) fuera de los límites previamente asignados cuando se cumpla la siguiente condición: $$\text{ceil}(\text{config}{\text{init}}.\text{height}/16) \geq \text{ceil}(\text{config}{\text{attack}}.\text{height}/16) \gt \text{ceil}(\text{config}_{\text{vuln}}.\text{height}/16)$$

mt_current_mb_col overflow

Más concretamente, supongamos que inicializamos una configuración de codificación VP8 con configinit con ancho = 1200, alto = 1200, hilos = 4. El ataque es el siguiente:

  1. configvuln reconfigura el codificador con ancho = 500 (512 redondeado), alto = 700 (704 redondeado) y hilos = 2. La variable mb_rows se establece en 704/16 = 44, y el array mt_current_mb_col se asigna a (44)*4 = 176 bytes. El valor escrito almacenado en mt_current_mb_col es 512/16 + 1 = 33.
  2. configattack reconfigura el codificador con ancho = 18 (32 redondeado), alto = 1000 (1008 redondeado) y hilos = 1. Debido a que mt_current_mb_col solo se reasigna cuando hay más de un hilo, permanece del mismo tamaño, pero mb_rows ahora se establece en 1008/16 = 63. Cuando libvpx llama a encode_mb_row, sobrescribirá (63-44)*4 = 68 bytes más allá de la asignación de mt_current_mb_col, escribiendo repetidamente el valor 32/16 + 1 = 3, donde 32 es el ancho redondeado y 1 es el valor de mt_sync_range.
  3. Un atacante podría reexplotar esta vulnerabilidad con una altura menor que la de configattack pero aún mayor que configvuln para escribir otro valor. Por ejemplo, un atacante podría crear configattack' con ancho = 34 y alto = 990, estableciendo mb_rows = 992/16 = 62 y mb_cols = 48/16 = 3, escribiendo solo (62-44)*4 = 64 bytes más allá de la asignación original el valor 4.

Explotación

Para explotar esta vulnerabilidad, un atacante necesita poder controlar la altura, anchura y número de hilos de codificación. Las dos primeras son sencillas, pero la última requiere encontrar lugares donde se reconfigura el número de hilos de codificación.

root@kitploit:~
// https://github.com/webmproject/libvpx/blob/67bfb41ed8598edfb25bd6f245f9c39a68808548/vp8/vp8_cx_iface.c#L301
static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
 ...
  oxcf->multi_threaded = cfg.g_threads;

Firefox

En Firefox, podemos controlar el número de hilos ajustando el área del cuadro que estamos codificando en el VP8TrackEncoder. Si el área del cuadro es mayor que 307,200 (un cuadro de 640x480) y la máquina tiene más de 2 núcleos, entonces se usará más de un hilo.

root@kitploit:~
// https://searchfox.org/mozilla-central/source/dom/media/encoder/VP8TrackEncoder.cpp#97
nsresult CreateEncoderConfig(...) {
  ...
  int32_t number_of_cores = PR_GetNumberOfProcessors();
  if (aWidth * aHeight > 1920 * 1080 && number_of_cores >= 8) {
    config->g_threads = 4;  // 4 threads for > 1080p.
  } else if (aWidth * aHeight > 1280 * 960 && number_of_cores >= 6) {
    config->g_threads = 3;  // 3 threads for 1080p.
  } else if (aWidth * aHeight > 640 * 480 && number_of_cores >= 3) {
    config->g_threads = 2;  // 2 threads for qHD/HD.
  } else {
    config->g_threads = 1;  // 1 thread for VGA or less
  }
  ...

Descubrimos que la API MediaRecorder depende del VP8TrackEncoder, y podemos ajustar la anchura y altura cambiando el tamaño del lienzo que se está grabando. Consulte la sección MediaRecorder a continuación para ver cómo llamar a esto.

Chrome

Chrome ajusta de manera similar el número de hilos según el área del cuadro que se está codificando, ajustado por el número de núcleos.

root@kitploit:~
// https://source.chromium.org/chromium/chromium/src/+/main:media/video/vpx_video_encoder.cc;l=84
EncoderStatus SetUpVpxConfig(...) {
  ...
  // Set the number of threads based on the image width and num of cores.
  config->g_threads = GetNumberOfThreadsForSoftwareEncoding(opts.frame_size);
}

// https://source.chromium.org/chromium/chromium/src/+/main:media/base/video_encoder.cc;drc=f5bdc89c7395ed24f1b8d196a3bdd6232d5bf771;l=33
int GetNumberOfThreadsForSoftwareEncoding(gfx::Size frame_size) {
  int area = frame_size.GetCheckedArea().ValueOrDefault(1);
  // Default to 1 thread for less than VGA.
  int desired_threads = 1;

  if (area >= 3840 * 2160) {
    desired_threads = 16;
  } else if (area >= 2560 * 1080) {
    desired_threads = 8;
  } else if (area >= 1280 * 720) {
    desired_threads = 4;
  } else if (area >= 640 * 480) {
    desired_threads = 2;
  }

  // Clamp to the number of available logical processors/cores.
  desired_threads =
      std::min(desired_threads, base::SysInfo::NumberOfProcessors());

  return desired_threads;
}

Esta ruta es ejercida por la API WebCodecs VideoEncoding, donde podemos modificar directamente la anchura/altura de codificación. Consulte la sección WebCodecs para ver cómo funciona.

MediaRecorder

El archivo mediarecorder.html muestra cómo crear una sesión de MediaRecorder desde un lienzo y ajustar la anchura/altura para desencadenar una reconfiguración de codificación VP8 que active CVE-2023-5217 en un navegador vulnerable. Al ajustar los parámetros de anchura y altura del lienzo, usamos un setTimeout para asegurarnos de que la sesión de codificación VP8 tenga tiempo suficiente para reconfigurarse. El parámetro de tiempo de espera se puede ajustar para mayor fiabilidad.

Estado

  • ✅ Firefox: Provoca un bloqueo en el renderizador de Firefox.
  • ❌ Navegadores Chromium: Los navegadores basados en Chromium no cambian el número de hilos al reconfigurar el codificador en una sesión de MediaRecorder [código].
  • ❌ Safari: WebKit no admite VP8 para sesiones de MediaRecorder [código].

Demostración en Firefox

Para probar en Firefox, puedes usar fuzzfetch para obtener una compilación ASAN anterior a que este CVE fuera parcheado con el comando fuzzfetch --build 2023-09-27 -a y luego abrir mediarecorder.html directamente.

Firefox demo

WebCodecs

Los archivos webcodecs.html y webcodecs.js muestran cómo usar la API WebCodecs en un Worker para desencadenar CVE-2023-5217 en un navegador vulnerable. Tenemos más control sobre las llamadas para codificar un cuadro en WebCodecs que en MediaRecorder, pero aún así dependemos de un tiempo de espera para realizar cada uno de los tres pasos.

Estado

  • ✅ Navegadores Chromium: Provoca un bloqueo de pestaña. Este parche de Chromium para WebCodecs fue incluido en el triaje inicial.
  • ❌ Firefox: Firefox no admite la codificación WebCodecs (la decodificación está habilitada detrás de una bandera de configuración).
  • 🚧 Safari: Safari admite la codificación WebCodecs, pero no pude obtener ningún bloqueo.

Demostración en Chromium

Para probar en Chromium, puedes usar get_asan_chrome.py para obtener una versión vulnerable de Chrome con el comando python get_asan_chrome.py --version 117.0.5938.131. Luego necesitarás iniciar un servidor HTTP local con SSL. Consulta gen_server_key.sh y server.py para generar una clave de servidor e iniciar un servidor. Luego solo abre la página en el Chromium vulnerable para ver el resultado.

Chromium demo

WebCodecs + MediaRecorder Combinados

Consulta combined.html que usa MediaRecorder como respaldo cuando WebCodecs no está disponible. Este archivo combinado se usaría para atacar tanto Chrome como Firefox con la misma página.

Conclusión

Esta vulnerabilidad demuestra los desafíos y peligros de exponer bibliotecas multimedia complejas a un atacante remoto. Usando herramientas como RLBox, los navegadores pueden aislar vulnerabilidades potenciales en bibliotecas multimedia. Firefox ya incluye esto en bibliotecas seleccionadas.

¡Gracias por leer! Las contribuciones son bienvenidas. No dudes en crear un Issue o abrir un PR con cualquier otro conocimiento. Lo que queda por explorar es ver cómo esta pequeña sobrescritura de 4 bytes puede conducir a la ejecución de código.

Gracias a Anand Balaji por sus comentarios en un borrador anterior.

Descargar herramienta