Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
cve-2023-5217-poc — Una PoC per innescare CVE-2023-5217 dall'interfaccia WebCodecs o MediaRecorder del browser. | Kitploit
Strumenti/GitHubGitHub/ut-security/cve-2023-5217-poc
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebFuzzingApprendimento e FormazioneBinary Exploitation
GitHubut-security/cve-2023-5217-poc

cve-2023-5217-poc

Una PoC per innescare CVE-2023-5217 dall'interfaccia WebCodecs o MediaRecorder del browser.

Vedi Repository
1632 anni faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2023-5217: PoC dell'heap overflow nella codifica VP8 di libvpx

CVE-2023-5217 è una vulnerabilità di libvpx sfruttata in the wild che è stata trovata da Clément Lecigne del Threat Analysis Group di Google mentre prendeva di mira Chrome.

Questo repository mostra come innescare CVE-2023-5217 nel browser usando le API WebCodecs e MediaRecorder. CVE-2023-5217 consente un heap buffer overflow con una lunghezza dell'overflow controllata e la sovrascrittura di un piccolo valore ripetuto di 4 byte. Al momento non è noto come CVE-2023-5217 sia stata sfruttata in the wild.

Al momento della divulgazione pubblica, c'erano due patch in libvpx e una in Chromium che hanno corretto CVE-2023-5217. Le patch di libvpx includevano la disabilitazione delle modifiche al numero di thread VP8 e un test per la codifica multithread. La patch di Chromium ha disabilitato la regolazione del numero di thread in WebCodecs.

Il problema alla base di libvpx v1.13.0 Ugly Duckling

Riepilogo

libvpx è una libreria che gestisce la codifica e la decodifica VP8/VP9.

Il problema chiave in CVE-2023-5217 è che ridurre il numero di thread mentre si aumenta l'altezza del frame in una sessione di codifica VP8 di libvpx causa un heap overflow lineare di lunghezza controllata e la sovrascrittura controllata di un piccolo valore ripetuto di 4 byte. La differenza nell'altezza del frame controlla la lunghezza della sovrascrittura, e la nuova larghezza del frame controlla il valore a 4 byte che viene scritto ripetutamente. Questa vulnerabilità può essere sfruttata più volte per scrivere continuamente diversi piccoli valori a 4 byte riducendo l'altezza in ogni configurazione successiva.

Dettagli

L'encoder VP8 di libvpx mantiene un array chiamato mt_current_mb_col che memorizza la colonna corrente su cui sta lavorando un thread dell'encoder. Questo array viene allocato solo se c'è più di un thread, e la sua dimensione è una funzione di mb_rows, dove mb_rows = frame_height >> 4 e frame_height viene arrotondato per eccesso al multiplo di 16 più vicino.

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);
  }
  ...
}

Quando libvpx termina la codifica di un frame, memorizza il numero di colonne codificate più mt_sync_range in 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));
  }
  ...
}

Per far overflow di mt_current_mb_col, servono tre configurazioni di codifica:

  1. configinit: Durante l'inizializzazione, libvpx imposta initial_width e initial_height. Questi sono i limiti massimi possibili delle configurazioni successive. Il numero di thread qui non ha importanza. La configurazione intermedia serve perché nessuna combinazione successiva di larghezza/altezza può essere più grande di quella iniziale.
  2. configvuln: Durante la riconfigurazione, se viene usato più di un thread, libvpx crea l'allocazione vulnerabile di mt_current_mb_col basandosi su configvuln.height. Questa nuova altezza deve essere minore di configinit.initial_height, altrimenti si ottiene un errore.
  3. configattack: Durante la riconfigurazione, se viene usato un solo thread, libvpx non rialloca mt_current_mb_col, lasciandolo in uno stato vulnerabile. libvpx scriverà ripetutamente il valore (configattack.width >> 4) + 1 (dove 1 è la variabile mt_sync_range e la larghezza è arrotondata per eccesso al multiplo di 16 più vicino) oltre i limiti precedentemente allocati, quando vale la seguente condizione:
root@kitploit:~
\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

Più concretamente, supponiamo di inizializzare una configurazione di codifica VP8 con configinit con larghezza = 1200, altezza = 1200, thread = 4. L'attacco è il seguente:

  1. configvuln riconfigura l'encoder con larghezza = 500 (512 arrotondato per eccesso), altezza = 700 (704 arrotondato per eccesso) e thread = 2. La variabile mb_rows viene impostata a 704/16=44, e l'array mt_current_mb_col viene allocato a (44)*4 = 176 byte. Il valore scritto e memorizzato in mt_current_mb_col è 512/16 + 1 = 33.
  2. configattack riconfigura l'encoder con larghezza = 18 (32 arrotondato per eccesso), altezza = 1000 (1008 arrotondato per eccesso) e thread = 1. Poiché mt_current_mb_col viene riallocato solo quando c'è più di un thread, la sua dimensione rimane la stessa, ma mb_rows ora è impostato a 1008/16 = 63. Quando libvpx chiama encode_mb_row, sovrascriverà (63-44)*4 = 68 byte oltre l'allocazione di mt_current_mb_col, scrivendo ripetutamente il valore 32/16 + 1 = 3, dove 32 è la larghezza arrotondata per eccesso e 1 è il valore di mt_sync_range.
  3. Un attaccante potrebbe riesfruttare questa vulnerabilità con un'altezza minore di quella in configattack ma comunque maggiore di configvuln per scrivere un altro valore. Ad esempio, un attaccante potrebbe creare configattack' con larghezza = 34 e altezza = 990, impostando mb_rows = 992/16 = 62 e mb_cols = 48/16 = 3, scrivendo solo (62-44)*4 = 64 byte oltre l'allocazione originale il valore 4.

Sfruttamento

Per sfruttare questa vulnerabilità, un attaccante deve essere in grado di controllare l'altezza, la larghezza e il numero di thread della codifica. Le prime due sono semplici, mentre l'ultimo richiede di trovare punti in cui il numero di thread di codifica viene riconfigurato.

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

In Firefox, possiamo controllare il numero di thread regolando l'area del frame che stiamo codificando in VP8TrackEncoder. Se l'area del frame è maggiore di 307.200 (un frame 640x480) e la macchina ha più di 2 core, verrà usato più di un thread.

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
  }
  ...

Abbiamo scoperto che l'API MediaRecorder si basa su VP8TrackEncoder, e possiamo regolare larghezza e altezza cambiando la dimensione della canvas registrata. Vedi la sezione MediaRecorder qui sotto per come chiamare questa funzionalità.

Chrome

Chrome, analogamente, regola il numero di thread in base all'area del frame da codificare, adattandolo al numero di core.

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;
}

Questo percorso viene esercitato dall'API WebCodecs VideoEncoding, dove possiamo modificare direttamente larghezza/altezza di codifica. Vedi la sezione WebCodecs per vedere come funziona.

MediaRecorder

Il file mediarecorder.html mostra come creare una sessione MediaRecorder da una canvas e regolare larghezza/altezza per attivare una riconfigurazione della codifica VP8 e innescare CVE-2023-5217 in un browser vulnerabile. Quando modifichiamo i parametri di larghezza e altezza della canvas, usiamo un setTimeout per garantire che la sessione di codifica VP8 abbia abbastanza tempo per riconfigurarsi. Il parametro del timeout può essere regolato per affidabilità.

Stato

  • ✅ Firefox: Provoca un crash nel renderer di Firefox.
  • ❌ Browser Chromium: I browser basati su Chromium non cambiano il numero di thread quando riconfigurano l'encoder in una sessione MediaRecorder [codice].
  • ❌ Safari: WebKit non supporta VP8 per le sessioni MediaRecorder [codice].

Demo di Firefox

Per testare su Firefox, puoi usare fuzzfetch per ottenere una build ASAN precedente alla patch per questa CVE con il comando fuzzfetch --build 2023-09-27 -a, quindi aprire direttamente mediarecorder.html.

Firefox demo

WebCodecs

I file webcodecs.html e webcodecs.js mostrano come usare l'API WebCodecs in un Worker per innescare CVE-2023-5217 in un browser vulnerabile. Abbiamo più controllo sulle chiamate per codificare un frame in WebCodecs rispetto a MediaRecorder, ma facciamo comunque affidamento su un timeout per eseguire ciascuno dei tre passaggi.

Stato

  • ✅ Browser Chromium: Provoca il crash della scheda. Questa patch di Chromium per WebCodecs è stata inclusa nel triage iniziale.
  • ❌ Firefox: Firefox non supporta la codifica WebCodecs (la decodifica è abilitata dietro un flag di configurazione).
  • 🚧 Safari: Safari supporta la codifica WebCodecs, ma non sono riuscito a ottenere alcun crash.

Demo di Chromium

Per testare su Chromium, puoi usare get_asan_chrome.py per ottenere una versione vulnerabile di Chrome con il comando python get_asan_chrome.py --version 117.0.5938.131. Dovrai quindi avviare un server HTTP locale con SSL. Vedi gen_server_key.sh e server.py per generare una chiave del server e avviare un server. Poi puoi semplicemente aprire la pagina nel Chromium vulnerabile per vedere il risultato.

Chromium demo

WebCodecs + MediaRecorder combinati

Vedi combined.html, che usa MediaRecorder come fallback quando WebCodecs non è disponibile. Questo file combinato può essere usato per colpire sia Chrome che Firefox con la stessa pagina.

Conclusione

Questa vulnerabilità dimostra le sfide e i pericoli dell'esporre complesse librerie multimediali a un attaccante remoto. Usando strumenti come RLBox, i browser possono isolare potenziali vulnerabilità nelle librerie multimediali. Firefox include già questo in alcune librerie.

Grazie per la lettura! I contributi sono benvenuti. Sentiti libero di aprire una Issue o una PR con qualsiasi altra idea. Ciò che resta da esplorare è capire come questa piccola sovrascrittura di 4 byte possa portare all'esecuzione di codice.

Grazie a Anand Balaji per il feedback su una bozza precedente.

Scarica lo strumento