Memory Tagging Extension (MTE)

Impara l'hacking AWS da zero a eroe con htARTE (Esperto Red Team AWS di HackTricks)!

Altri modi per supportare HackTricks:

Informazioni di Base

Il Memory Tagging Extension (MTE) è progettato per migliorare l'affidabilità e la sicurezza del software rilevando e prevenendo errori legati alla memoria, come buffer overflow e vulnerabilità di uso dopo la liberazione. MTE, come parte dell'architettura ARM, fornisce un meccanismo per allegare un piccolo tag ad ogni allocazione di memoria e un tag corrispondente ad ogni puntatore che fa riferimento a quella memoria. Questo approccio consente di rilevare gli accessi illegali alla memoria durante l'esecuzione, riducendo significativamente il rischio di sfruttare tali vulnerabilità per eseguire codice arbitrario.

Come Funziona l'Estensione del Tagging della Memoria

MTE opera dividendo la memoria in blocchi di dimensioni fisse, con ciascun blocco assegnato un tag, tipicamente di pochi bit di dimensione.

Quando viene creato un puntatore per puntare a quella memoria, ottiene lo stesso tag. Questo tag è memorizzato nei bit non utilizzati di un puntatore di memoria, collegando efficacemente il puntatore al suo blocco di memoria corrispondente.

Quando un programma accede alla memoria attraverso un puntatore, l'hardware MTE controlla che il tag del puntatore corrisponda al tag del blocco di memoria. Se i tag non corrispondono, indica un accesso illegale alla memoria.

Tag dei Puntatori MTE

I tag all'interno di un puntatore sono memorizzati in 4 bit all'interno del byte superiore:

Pertanto, ciò consente fino a 16 diversi valori di tag.

Tag della Memoria MTE

Ogni 16B di memoria fisica ha un tag di memoria corrispondente.

I tag di memoria sono memorizzati in una regione RAM dedicata (non accessibile per un uso normale). Avendo tag di 4 bit per ogni 16B di tag di memoria fino al 3% di RAM.

ARM introduce le seguenti istruzioni per manipolare questi tag nella memoria RAM dedicata:

STG [<Xn/SP>], #<simm>    Store Allocation (memory) Tag
LDG <Xt>, [<Xn/SP>]       Load Allocatoin (memory) Tag
IRG <Xd/SP>, <Xn/SP>      Insert Random [pointer] Tag
...

Modalità di controllo

Sync

La CPU controlla i tag durante l'esecuzione dell'istruzione, se c'è una discrepanza, genera un'eccezione. Questa è la più lenta e sicura.

Async

La CPU controlla i tag in modo asincrono, e quando trova una discrepanza imposta un bit di eccezione in uno dei registri di sistema. È più veloce della precedente ma non è in grado di indicare l'istruzione esatta che ha causato la discrepanza e non genera immediatamente l'eccezione, dando del tempo all'attaccante per completare il suo attacco.

Misto

???

Esempi di Implementazione e Rilevamento

Chiamato KASAN basato su tag hardware, KASAN basato su MTE o MTE nel kernel. Gli allocatori del kernel (come kmalloc) chiameranno questo modulo che preparerà il tag da utilizzare (casualmente) lo attaccherà allo spazio kernel allocato e al puntatore restituito.

Si noti che verranno contrassegnati solo abbastanza granuli di memoria (16B ciascuno) per la dimensione richiesta. Quindi se la dimensione richiesta era 35 e veniva dato uno slab di 60B, verranno contrassegnati i primi 16*3 = 48B con questo tag e il resto verrà contrassegnato con un cosiddetto tag non valido (0xE).

Il tag 0xF è il puntatore di corrispondenza totale. Una memoria con questo puntatore consente l'uso di qualsiasi tag per accedere alla sua memoria (nessuna discrepanza). Questo potrebbe impedire a MET di rilevare un attacco se questo tag viene utilizzato nella memoria attaccata.

Pertanto ci sono solo 14 valori che possono essere utilizzati per generare tag poiché 0xE e 0xF sono riservati, dando una probabilità di riutilizzo dei tag pari a 1/17 -> circa 7%.

Se il kernel accede al granulo di tag non valido, la discrepanza verrà rilevata. Se accede a un'altra posizione di memoria, se la memoria ha un tag diverso (o il tag non valido) la discrepanza verrà rilevata. Se l'attaccante ha fortuna e la memoria utilizza lo stesso tag, non verrà rilevata. Le probabilità sono circa del 7%.

Un altro bug si verifica nell'ultimo granulo della memoria allocata. Se l'applicazione ha richiesto 35B, le è stato dato il granulo dal 32 al 48. Pertanto, i byte dal 36 al 47 utilizzano lo stesso tag ma non sono stati richiesti. Se l'attaccante accede a questi byte extra, ciò non viene rilevato.

Quando viene eseguito kfree(), la memoria viene contrassegnata nuovamente con il tag di memoria non valido, quindi in un uso dopo la liberazione, quando la memoria viene nuovamente accessa, la discrepanza viene rilevata.

Tuttavia, in un uso dopo la liberazione, se lo stesso blocco viene riallocato nuovamente con lo STESSO tag come precedentemente, un attaccante potrà utilizzare questo accesso e ciò non verrà rilevato (circa il 7% di probabilità).

Inoltre, solo slab e page_alloc utilizzano la memoria contrassegnata ma in futuro questo verrà utilizzato anche in vmalloc, stack e globals (al momento del video questi possono ancora essere abusati).

Quando viene rilevata una discrepanza, il kernel va in panico per impedire ulteriori sfruttamenti e tentativi dell'exploit (MTE non ha falsi positivi).

Riferimenti

Last updated