
Exploit del kernel Android 14 per Pixel7/8 Pro
Questo articolo fornisce un'analisi approfondita di due vulnerabilità del kernel nella GPU Mali, raggiungibili dalla sandbox applicativa predefinita, che ho identificato e segnalato autonomamente a Google. Include un exploit del kernel che raggiunge capacità arbitrarie di lettura/scrittura del kernel. Di conseguenza, disabilita SELinux ed eleva i privilegi a root sui modelli Google Pixel 7 e 8 Pro con le seguenti versioni di Android 14:
google/husky/husky:14/UD1A.231105.004/11010374:user/release-keysgoogle/cheetah/cheetah:14/UP1A.231105.003/11010452:user/release-keysgoogle/cheetah/cheetah:14/UP1A.231005.007/10754064:user/release-keysgoogle/panther/panther:14/UP1A.231105.003/11010452:user/release-keys (di m4b4 (Marcel))Questo exploit sfrutta due vulnerabilità: un overflow di interi derivante da una patch incompleta nel comando ioctl gpu_pixel_handle_buffer_liveness_update_ioctl, e una fuga di informazioni nei buffer dei messaggi del timeline stream.
Google ha risolto un overflow di interi nel comando ioctl gpu_pixel_handle_buffer_liveness_update_ioctl in questo commit. All'inizio, quando ho segnalato il problema, pensavo che il bug fosse causato da un difetto nella patch descritta in precedenza. Dopo aver riesaminato il report, mi sono reso conto che la mia analisi della vulnerabilità era imprecisa. Nonostante la mia iniziale ipotesi che la patch fosse incompleta, essa risolve e previene effettivamente un underflow nel calcolo. Questo mi ha portato a sospettare che la modifica non fosse stata applicata nelle build di produzione. Tuttavia, sebbene io possa causare un underflow nel calcolo, non è possibile causare un overflow. Ciò suggerisce che il comando ioctl sia stato parzialmente corretto, anche se non con la patch mostrata sopra. L'analisi con IDA ha rivelato che un'altra patch incompleta è stata distribuita nelle release di produzione, e questa patch non è presente in alcun ramo git del modulo kernel della GPU Mali.
Questa vulnerabilità è stata scoperta per la prima volta nell'ultima versione di Android e segnalata il 19 novembre 2023. In seguito, Google mi ha informato che l'aveva già identificata internamente e le aveva assegnato CVE-2023-48409 nel bollettino sulla sicurezza Android di dicembre, etichettandola come problema duplicato. Sebbene sia riuscito a verificare che il bug era stato identificato internamente mesi prima della mia segnalazione (in base alla data del commit intorno al 30 agosto), permangono dei dubbi. In particolare, è strano che i livelli di patch di sicurezza (SPL) di ottobre e novembre dei dispositivi più recenti fossero ancora affetti da questa vulnerabilità — non ho indagato sulle versioni precedenti. Pertanto, non sono in grado di determinare in modo conclusivo se si trattasse davvero di un problema duplicato e se la patch appropriata fosse effettivamente prevista per dicembre prima della mia segnalazione, o se ci sia stata una svista nella gestione di questa vulnerabilità.
Ad ogni modo, ciò che rende potente questo bug è il seguente:
info.live_ranges è completamente controllato dall'utente.info.live_ranges possa trovarsi a un offset arbitrario prima dell'inizio dell'indirizzo di kernel di buff.Questa vulnerabilità condivide somiglianze con la vulnerabilità di buffer underflow DeCxt::RasterizeScaleBiasData() che ho trovato e sfruttato nel kernel di iOS 15 nel 2022.
La GPU Mali implementa un timeline stream personalizzato progettato per raccogliere informazioni, serializzarle e successivamente scriverle in un ring buffer seguendo un formato specifico. Gli utenti possono invocare il comando ioctl kbase_api_tlstream_acquire per ottenere un file descriptor che consente loro di leggere da questo ring buffer. Il formato dei messaggi è il seguente:
Un buffer di messaggi serializzato, il cui contenuto specifico dipende dall'ID del messaggio.
Ad esempio, la funzione __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_fence_wait serializza i puntatori del kernel kbase_kcpu_command_queue e dma_fence nel buffer dei messaggi, causando la fuga di puntatori del kernel verso un processo dello spazio utente.```c
void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_fence_wait(
struct kbase_tlstream *stream,
const void *kcpu_queue,
const void *fence
)
{
const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_WAIT;
const size_t msg_size = sizeof(msg_id) + sizeof(u64)
+ sizeof(kcpu_queue)
+ sizeof(fence)
;
char *buffer;
unsigned long acq_flags;
size_t pos = 0;
buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags);
pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_serialize_timestamp(buffer, pos); pos = kbasep_serialize_bytes(buffer, pos, &kcpu_queue, sizeof(kcpu_queue)); pos = kbasep_serialize_bytes(buffer, pos, &fence, sizeof(fence));
kbase_tlstream_msgbuf_release(stream, acq_flags); }
L'exploit proof of concept fa trapelare l'indirizzo dell'oggetto `kbase_kcpu_command_queue` monitorando l'ID del messaggio `KBASE_TL_KBASE_NEW_KCPUQUEUE`, che viene inviato dalla funzione `kbasep_kcpu_queue_new` ogni volta che viene allocato un nuovo oggetto kcpu queue.
Google mi ha informato che la vulnerabilità è stata segnalata a marzo 2023 ed è stata assegnata la [CVE-2023-26083](https://source.android.com/docs/security/bulletin/2023-07-01) nel loro bollettino di sicurezza. Ciononostante, sono riuscito a riprodurre il problema sugli ultimi dispositivi Pixel forniti con i livelli di patch di sicurezza (SPL) di ottobre e novembre, il che indica che la correzione non era stata applicata correttamente o non era stata applicata affatto. Successivamente, Google ha risolto rapidamente il problema nel bollettino degli aggiornamenti di sicurezza di dicembre senza riconoscere il merito, e in seguito mi ha informato che il problema era stato considerato un duplicato. La logica alla base della classificazione di questo problema come duplicato, tuttavia, rimane discutibile.
## Sfruttamento
---
Quindi ho due vulnerabilità interessanti. La prima offre una potente capacità: modificare il contenuto di qualsiasi indirizzo di kernel allineato a 16 byte che si trovi prima dell'indirizzo dell'oggetto ~buff~ allocato. La seconda vulnerabilità fornisce indizi sulle potenziali posizioni degli oggetti all'interno della memoria del kernel.