Informazioni su CVE-2024-0517
CVE-2024-0517 è una vulnerabilità di scrittura fuori dai limiti nel motore JavaScript V8 di Google Chrome precedente alla versione 120.0.6099.224, che consente agli aggressori remoti di sfruttare la corruzione dell'heap tramite una pagina HTML creata ad arte. La vulnerabilità è stata segnalata per la prima volta da Toan (Suto) Pham di Qrious Secure.
Questa vulnerabilità deriva dalla confusione di tipo, che si verifica quando un'applicazione alloca o inizializza una risorsa come un puntatore, un oggetto o una variabile utilizzando un tipo, ma successivamente accede a quella risorsa utilizzando un tipo incompatibile con quello originale (CWE-843). In questo CVE, la confusione dei tipi viene innescata durante un processo di allocazione della memoria chiamato folded allocation, utilizzato per l'ottimizzazione della memoria da Maglev, un compilatore ottimizzante per il motore JavaScript V8.
Sfruttando la confusione di tipo e scrivendo codici shell arbitrari tramite WebAssembly, un utente malintenzionato può eseguire comandi sul computer della vittima.
Fasi di attacco
Gli aggressori possono ospitare un sito web contenente una pagina HTML artigianale e indurre gli utenti ad accedervi tramite e-mail di phishing o social network. Quando gli utenti visitano il sito utilizzando una versione vulnerabile di Google Chrome, il codice dannoso incorporato esegue comandi arbitrari.
Motore JavaScript V8
Gli aggressori possono ospitare un sito web contenente una pagina HTML artigianale e indurre gli utenti ad accedervi tramite e-mail di phishing o social network. Quando gli utenti visitano il sito utilizzando una versione vulnerabile di Google Chrome, il codice dannoso incorporato esegue comandi arbitrari.
Maglev e allocazione ripiegata
Maglev, un compilatore ottimizzante in V8, migliora l'esecuzione del codice e l'allocazione della memoria. Maglev viene eseguito solo quando il codice viene eseguito frequentemente ed è contrassegnato come "caldo", indicando la necessità di un'esecuzione più rapida attraverso la compilazione piuttosto che la più lenta interpretazione riga per riga.
In genere, le allocazioni avvengono in regioni di memoria non contigue, con conseguente uso rado e inefficiente della memoria. Per risolvere questo problema, V8 impiega una tecnica chiamata folded allocation, che alloca più variabili in modo continuo e simultaneo. Anche Maglev ottimizza le allocazioni utilizzando l'allocazione ripiegata nel suo progresso.
Garbage Collection generazionale
Per ripulire le regioni di memoria inutilizzate, V8 impiega una tecnica di garbage collection (GC) generazionale, dividendo la memoria in due spazi: la generazione giovane e la generazione vecchia. Inoltre, ci sono due garbage collector: il minor garbage collector, responsabile della pulizia dello spazio giovane, e il major garbage collector, che gestisce la pulizia dello spazio vecchio. La generazione giovane è l'area di memoria in cui vengono inizialmente allocati gli oggetti di nuova creazione, mentre la generazione vecchia è una regione di memoria in cui vengono memorizzati gli oggetti a lunga vita. Gli oggetti che sono sopravvissuti a più cicli di GC minori nella generazione giovane vengono infine promossi alla generazione vecchia.
Analisi delle vulnerabilità
Panoramica
La vulnerabilità si verifica quando viene creato un oggetto da una classe ereditata da una classe base senza un costruttore esplicitamente definito (costruttore predefinito della base) e successivamente viene creato un altro oggetto. A causa dell'allocazione ripiegata, l'allocazione del primo oggetto può essere seguita da quella del secondo. Se tra queste due allocazioni si verifica un evento come la garbage collection, può verificarsi una vulnerabilità di confusione di tipo.
Analisi della causa principale
I borsisti OPSWAT hanno condotto un'analisi dettagliata del flusso di lavoro V8 durante il processo di assegnazione e hanno determinato che durante questo processo vengono invocate le seguenti funzioni:
In questo processo, è stato identificato un problema nella funzione TryBuildFindNonDefaultConstructorOrConstruct: La funzione BuildAllocateFastObject estende current_raw_allocation_ (un puntatore alla regione di memoria allocata per più variabili contemporaneamente) per costruire l'istanza della classe figlio, ma non riesce a cancellarla impostandola su null.
Di conseguenza, il prossimo oggetto creato viene sempre allocato subito dopo la memoria puntata da current_raw_allocation_, indipendentemente da qualsiasi evento precedente alla seconda allocazione.
Se viene invocato il GC, la regione di memoria adiacente a current_raw_allocation_ può essere assegnata ad altri oggetti. Questo può portare a una situazione in cui, dopo l'attivazione del GC e la creazione di un altro oggetto, due puntatori fanno riferimento alla stessa regione di memoria ma hanno tipi di dati diversi, causando una vulnerabilità di confusione di tipo.
Sfruttamento
Per sfruttare questa vulnerabilità, i borsisti dell OPSWAT hanno creato istanze WebAssembly contenenti shellcode e hanno tentato di innescare una confusione di tipo da parte del GC per controllare la memoria ed eseguire lo shellcode:
Confusione del tipo di innesco
Durante l'inizializzazione, si definisce innanzitutto un array (_arrayObject) contenente oggetti vuoti. Quindi, si costruisce un'istanza della classe figlio e un trigger garbage collector. Infine, si definisce un altro array con un numero in virgola mobile, chiamato _arrayDouble.
Questi costrutti devono essere ripetuti in modo che il codice venga eseguito più volte, facendo sì che V8 lo segnali come "caldo" e attivi il compilatore Maglev. Per ottenere questo risultato, invochiamo il costruttore della classe figlio all'interno di un ciclo, come segue:
La confusione dei tipi si innesca dopo aver inizializzato ripetutamente questi oggetti in un ciclo.
Creare primitive di lettura e scrittura
Dopo aver innescato con successo la confusione dei tipi, l'esecuzione dello shellcode richiede la lettura della memoria e la sovrascrittura della memoria a un indirizzo controllato. Per farlo, abbiamo creato primitive di lettura e scrittura. Le primitive di exploit sfrutteranno i metadati degli oggetti per fornire regioni di memoria in lettura/scrittura arbitrarie e utilizzarle per eseguire codice arbitrario.
Le primitive di lettura e scrittura di questo passo ci permetteranno di controllare il puntatore della tabella Jump dell'istanza WebAssembly nel passo successivo.
Creare istanze di WebAssembly
Successivamente, abbiamo creato due istanze WebAssembly: una per memorizzare lo shellcode e l'altra per attivarlo. Per evitare di scrivere direttamente lo shellcode nella memoria dell'istanza WebAssembly tramite primitive di lettura e scrittura, definiamo alcuni valori costanti in virgola mobile all'interno dell'istanza WebAssembly.
Puntatore alla tabella dei salti di controllo dell'istanza di WebAssembly
Utilizzando le primitive di lettura e scrittura, regoliamo il puntatore della tabella di salto della seconda istanza di WebAssembly per saltare alcuni byte del codice compilato delle costanti nella prima istanza di WebAssembly, in modo che le costanti in virgola mobile vengano interpretate come il nostro shellcode:
Eseguire l'istanza WebAssembly per eseguire lo Shellcode
Infine, dopo aver innescato la confusione dei tipi e aver utilizzato primitive di lettura/scrittura per controllare i puntatori della tabella di salto delle istanze WebAssembly, abbiamo invocato la funzione esportata della seconda istanza WebAssembly, che causa l'esecuzione dello shellcode nella prima istanza WebAssembly.
Il codice di shell che stiamo usando è progettato per terminare tutti i processi su una macchina Linux, come da comando seguente:
Il codice assembly per l'esecuzione di questo comando, convertito dai numeri in virgola mobile, sarà il seguente:
Simulare la vulnerabilità della sicurezza
Per simulare questo sfruttamento in uno scenario reale, i borsisti dell OPSWAT hanno creato una pagina HTML creata ad arte.
Alla vittima viene inviata un'e-mail di phishing con un link al dominio che ospita la pagina HTML creata ad arte.
Se la vittima accede al link utilizzando la versione vulnerabile di Google Chrome, lo shellcode viene eseguito, causando la terminazione di tutti i processi. Di conseguenza, l'utente viene disconnesso, come mostrato di seguito:
Bonifica
MetaDefender Endpoint™ è stato impiegato per mitigare proattivamente questo CVE sfruttando la sua funzionalità "Vulnerable Application". La soluzione individua e visualizza efficacemente tutte le CVE associate alle applicazioni di Google Chrome nell'ambiente endpoint. Per neutralizzare la minaccia, gli utenti possono disinstallare immediatamente Chrome o applicare la patch di sicurezza più recente. Implementando una delle due contromisure, la CVE viene completamente contenuta, riducendo in modo significativo il rischio di successo di un cyberattacco sull'endpoint.
Sicurezza Endpoint di livello superiore
Scoprite perché organizzazioni, istituzioni ed enti di tutto il mondo si affidano a MetaDefender Endpoint per proteggere gli endpoint critici. Parlate con un esperto oggi stesso per saperne di più e provate voi stessi con una demo gratuita.
Riferimenti
https://nvd.nist.gov/vuln/detail/CVE-2024-0517
https://cwe.mitre.org/data/definitions/843.html
https://blog.exodusintel.com/2024/01/19/google-chrome-v8-cve-2024-0517-out-of-bounds-write-code-execution/
https://jhalon.github.io/chrome-browser-exploitation-1/
https://whenderson.dev/blog/webgl-garbage-collection/
https://v8.dev/
https://github.com/Uniguri/CVE-nday/tree/master/Chrome/V8/CVE-2024-0517