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-2022-0185-Case-Study | Kitploit
Strumenti/GitHubGitHub/dcheng69/cve-2022-0185-case-study
Escalation di PrivilegiAnalisi delle VulnerabilitàExploitCTFApprendimento e FormazioneBinary ExploitationLab e Pratica
GitHubdcheng69/cve-2022-0185-case-study

CVE-2022-0185-Case-Study

Vedi Repository
312 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-2022-0185-Case-Study

Questo case study è il risultato di un compito del corso ECE 9069: Introduction to Hacking : https://whisperlab.org/introduction-to-hacking/

Panoramica di CVE-2022-0185

CVE-2022-0185 è un difetto di overflow del buffer basato su heap trovato nel modo in cui la funzione legacy_parse_param nella funzionalità Filesystem Context del kernel Linux verificava la lunghezza dei parametri forniti. Un utente locale non privilegiato (nel caso in cui gli user namespaces non privilegiati siano abilitati, altrimenti è necessario il privilegio CAP_SYS_ADMIN all'interno del namespace) in grado di aprire un filesystem che non supporta l'API Filesystem Context (e che quindi ripiega sulla gestione legacy) potrebbe usare questo difetto per aumentare i propri privilegi sul sistema. [1]

Dopo che questa vulnerabilità è stata segnalata, è stata rilasciata una patch per correggere il bug:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=722d94847de2

https://ubuntu.com/security/CVE-2022-0185#impact-score

C'è un writeup dettagliato dell'esploratore: https://www.hackthebox.com/blog/CVE-2022-0185:_A_case_study

In questo repository spiegherò i passaggi di base e le informazioni di contesto correlate per riprodurre questa vulnerabilità. Inoltre, se c'è qualcosa che non ti è chiaro, puoi inviarmi una email: [email protected]. Sarò molto felice di rispondere alle domande.

1. Introduzione

La vulnerabilità CVE-2022-0185 è stata pubblicata il 02/11/2022, con un punteggio base CVSS 3.x di 8.4 (Alto).[1] Questa vulnerabilità è un overflow del buffer basato su heap, causato da un underflow di un intero senza segno.

La vulnerabilità è stata introdotta nel kernel Linux v5.1, interessando tutte le distribuzioni Linux con versioni del kernel superiori alla 5.1. Per esempio, Ubuntu 20.04 LTS (focal) era vulnerabile a questo bug. Tuttavia, una patch è stata rilasciata ed è disponibile dalla versione 5.4.0-96.109 .[3]

Lo sfruttamento di questa vulnerabilità consente a un utente locale non privilegiato di aumentare i propri privilegi sul sistema, compromettendo potenzialmente l'intero sistema.[1] [2] Ecco un'analisi dettagliata del punteggio CVSS: Punteggio Base: 8.4, che indica un rischio di sicurezza significativo che richiede attenzione immediata. Punteggio di Impatto: 5.9, che suggerisce un potenziale danno sostanziale se sfruttata. I valori elevati di riservatezza, integrità e disponibilità contribuiscono a questo punteggio. Punteggio di Sfruttabilità: 2.5, che suggerisce una sfruttabilità relativamente alta. Il vettore di attacco locale, l'elevata integrità e l'elevata disponibilità contribuiscono a questo punteggio.

La Tabella 1.1 e la Tabella 1.2 forniscono maggiori informazioni su questi punteggi e sui loro componenti.

Gravità CVSS v3.1Valore
Punteggio Base8.4 ALTO
Punteggio di Impatto5.9
Punteggio di Sfruttabilità2.5

Tabella 1.1 Punteggi di gravità CVSS[1]

Tabella 1.2 Vettore CVSS[1]

2. Background e concetti correlati

2.1 Underflow dei numeri senza segno

2.1.1 Complemento a due

Nei computer moderni esistono due tipi di interi: con segno e senza segno. La rappresentazione dei numeri con segno coinvolge generalmente un'operazione chiamata complemento a due.[4] “Il complemento a due usa la cifra binaria con il maggior valore posizionale come segno per indicare se il numero binario è positivo o negativo”[4]

L'introduzione del complemento a due converte il calcolo della sottrazione in addizione, semplificando quindi la progettazione e l'implementazione della CPU. La generazione del complemento a due di un intero coinvolge tre passaggi:[4]

  • Passo 1: “Partendo dalla rappresentazione binaria del numero, con il bit iniziale che funge da bit di segno”;
  • Passo 2: “Invertire tutti i bit”;
  • Passo 3: “Aggiungere 1 all'intero numero invertito, ignorando eventuali overflow”

La Fig 2.1.1.1 mostra il processo di conversione in un diagramma con un esempio reale di conversione di “-6” nel suo formato in complemento a due.

twos_complement.drawio

Fig 2.1.1.2 Addizione usando il complemento a due

La Figura 2.1.1.2 mostra il processo di addizione del complemento a due di '-6' a '+6'. Questo dimostra come l'uso del complemento a due consenta di utilizzare l'addizione come sostituto della sottrazione.

twos_complement-Page-2.drawio

Fig 2.1.1.2 Addizione usando il complemento a due

2.1.2 Rappresentazione dei numeri nella RAM

Dalla Sezione 2.1.1, abbiamo già capito cos'è il complemento a due. Ora diamo un'occhiata allo scenario dell'underflow dei numeri senza segno nei computer. Nei computer moderni, quando si usano numeri senza segno, il bit più significativo non viene trattato come bit di segno; invece, fa parte del numero senza segno stesso. Questa situazione significa che quando si esegue una sottrazione con un numero senza segno, bisogna essere cauti, poiché può portare a una condizione nota come underflow dei numeri senza segno.[5]

La Fig 2.1.2.1 illustra la situazione della sottrazione di 6 da 5 per un numero senza segno a 8 bit. Il risultato finale è 255 a causa dell'avvolgimento del numero senza segno. Quando questo underflow si verifica in un'istruzione condizionale, ha il potenziale di interrompere la funzionalità dell'istruzione stessa.

twos_complement-Page-3.drawio

Fig 2.1.2.1 Underflow di un numero senza segno

2.2 Memoria del kernel Linux

2.2.1 Slab nella memoria heap

Nel kernel Linux, l'allocatore Slab è un meccanismo di gestione della memoria utilizzato per l'allocazione e la deallocazione efficiente di piccoli blocchi di memoria. Offre prestazioni mantenendo diverse cache di Slab, ciascuna contenente blocchi di memoria di dimensione fissa. Tipicamente, kmalloc-32 alloca 32 byte di memoria ed è uno slab kmalloc-32, mentre kmalloc-4k alloca 4096 byte di memoria ed è uno slab kmalloc-4k.[6]

Inoltre, l'allocazione a slab nel kernel Linux comporta tipicamente l'allocazione di memoria da uno spazio di indirizzi contiguo all'interno della regione di memoria heap del kernel. Questo indirizzo contiguo è gestito dal kernel e viene utilizzato per allocare memoria per vari oggetti e strutture dati del kernel. La Fig 2.2.1.1 mostra la disposizione degli slab nella memoria del kernel Linux.

img

Fig 2.2.1.1 Allocatore Slab in Linux [7] (L'autore di questa figura è https://leviathan.vip/)

3 Analisi tecnica della vulnerabilità

3.1 Proof of Concept

Se vuoi riprodurre il processo con un kernel Linux compilato da te, leggi i seguenti file markdown per ottenere le informazioni di contesto:

  1. Prima leggi il markdown su come compilare un kernel Linux: https://github.com/dcheng69/CVE-2022-0185-Case-Study/blob/main/compile_linux/compile.md
  2. Poi leggi il markdown su come preparare un file system RAM per eseguire il POC: https://github.com/dcheng69/CVE-2022-0185-Case-Study/blob/main/ramfs/ramfs.md
  3. Infine segui il markdown del poc: https://github.com/dcheng69/CVE-2022-0185-Case-Study/blob/main/Poc/poc.md

Nota:

Tutti i file markdown, così come il codice e gli script, si trovano in diverse cartelle di questo repository; ogni cartella ha il proprio file markdown, leggilo prima di provare a fare qualsiasi cosa!

3.1.1 Underflow senza segno nel kernel

Nella sezione 2.1 abbiamo spiegato come funziona l'underflow senza segno. Ora esamineremo la funzione del kernel che contiene questa vulnerabilità.

L'utente “clubby789” ha scoperto una vulnerabilità nella funzione del kernel legacy_parse_param . Questa funzione è principalmente responsabile dell'analisi dei parametri passati al kernel. In CVE-2022-0185, veniva invocata dopo l'uso di fsopen per aprire un file descriptor, seguito dall'uso della funzione fsconfig per passare le coppie chiave-valore di configurazione al kernel. Una versione semplificata di legacy_parse_param è mostrata nel codice seguente. [2]```c static int legacy_parse_param(struct fs_context *fc, struct fs_parameter *param) { struct legacy_fs_context *ctx = fc->fs_private; // [1] unsigned int size = ctx->data_size; // [2] size_t len = 0; int ret; [ ... ] switch (param->type) { case fs_value_is_string: len = 1 + param->size; // [3] case fs_value_is_flag: len += strlen(param->key); break; default: return invalf(fc, "VFS: Legacy: Parameter type for '%s' not supported", param->key); } if (len > PAGE_SIZE-2-size) return invalf(fc, "VFS: Legacy: Cumulative options too large"); // [4] [ ... ] if (!ctx->legacy_data) { ctx->legacy_data = kmalloc(PAGE_SIZE, GFP_KERNEL); // [5] if (!ctx->legacy_data) return -ENOMEM; } ctx->legacy_data[size++] = ','; // [6] len = strlen(param->key); memcpy(ctx->legacy_data + size, param->key, len); size += len; if (param->type == fs_value_is_string) { ctx->legacy_data[size++] = '='; memcpy(ctx->legacy_data + size, param->string, param->size); size += param->size; } ctx->legacy_data[size] = '\0'; ctx->data_size = size; ctx->param_type = LEGACY_FS_INDIVIDUAL_PARAMS; return 0; }

root@kitploit:~
Dal frammento di codice sopra, possiamo vedere che le righe [1] e [2] impostano il contesto del codice, mentre la riga [4] contiene l'istruzione in cui si verifica l'underflow senza segno. La riga [5] gestisce l'allocazione dello slab nell'heap, e le righe [6] e [7] sono responsabili del popolamento dei dati nello slab allocato. In particolare, la riga [6] aggiunge una virgola (',') come delimitatore separato, e viene aggiunto anche un segno di uguale ('='), risultando in due byte extra rispetto alla dimensione effettiva dei dati.

Nella riga [4], le variabili all'interno dell'istruzione if contengono PAGE_SIZE (una macro impostata a 4096) e size (un numero senza segno a 64 bit). Quando un numero senza segno si accumula fino a 4095, si verifica un underflow, facendo sì che l'istruzione if venga sempre valutata come falsa. Ciò consente una scrittura fuori dai limiti nello slab adiacente. L'underflow è causato dalla sottrazione di un numero senza segno, risultando in 4096 - 4095, che produce un numero senza segno pari a 18446744073709551615.[2]

Il risultato di `18446744073709551615` è spiegato nel testo seguente:```c
if (len > PAGE_SIZE-2-size) return invalf(fc, "VFS: Legacy: Cumulative options too large");

Si noti che qui PAGE_SIZE è uguale a 4096 byte, e il 2 corrisponde ai caratteri , e = aggiunti per separare ogni coppia chiave-valore. Il problema è che size è un valore unsigned, quindi quando size raggiunge 4095, l'istruzione PAGE_SIZE-2-size sarà uguale a singned value: -1, ma per unsigned value: 18446744073709551615 a causa del complemento a 2, come mostrato nel diagramma seguente! [3]

poc.drawio

Pertanto l'istruzione if sopra sarà sempre falsa, il che significa che il resto dei dati verrà copiato nell'heap oltre lo slab che abbiamo allocato!

3.1.2 Analisi del codice POC

Dopo aver compreso come può verificarsi questo underflow di numeri unsigned, possiamo procedere a creare un codice proof of concept (POC) per dimostrare la vulnerabilità.

L'utente “clubby789” ci fornisce un codice POC dettagliato, mostrato nel seguente frammento di codice. Il codice è conciso: apre prima un descrittore di file chiamato ext4, poi usa più volte fsconfig per popolare i dati nel kernel.

Due cose da notare qui:

  • Invocare fsopen per aprire ext4 richiede privilegi CAP_SYS_ADMIN. Pertanto, in un exploit successivo, useremmo unshare per ottenere questi privilegi. Tuttavia, per questo proof of concept (POC), eseguiremo semplicemente il programma con privilegi di root.
  • Ogni coppia chiave-valore che popoliamo nel kernel ha una lunghezza di 33. Tuttavia, la funzione legacy_parse_param inserisce una virgola (',') all'inizio e un segno di uguale ('=') tra la chiave e il valore. Di conseguenza, la dimensione effettiva occupata per ogni ciclo è 35.```c #define _GNU_SOURCE #include <sys/syscall.h> #include <stdio.h> #include <stdlib.h> #ifndef __NR_fsconfig #define __NR_fsconfig 431 #endif #ifndef __NR_fsopen #define __NR_fsopen 430 #endif #define FSCONFIG_SET_STRING 1 #define fsopen(name, flags) syscall(__NR_fsopen, name, flags) #define fsconfig(fd, cmd, key, value, aux) syscall(__NR_fsconfig, fd, cmd, key, value, aux) int main(void) { char* key = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; // 33 characters [1] int fd = 0; fd = fsopen("ext4", 0); // [2] if (fd < 0) { puts("Open failed!\n"); exit(-1); } for (int i = 0; i < 130; i++) { fsconfig(fd, FSCONFIG_SET_STRING, "\x00", key, 0); //[3] } return 0; }
root@kitploit:~
In section 3.1.1, we mentioned that 4095 bytes of data must be populated before observing the out-of-bounds write. Given that each cycle only populates 35 bytes, we must perform the operation 117 times (4095 / 35) before observing the heap memory to complete the proof of concept.

### 3.1.3 POC con QEMU

In questo repository: GitHub - dcheng69/CVE-2022-0185-Case-Study, abbiamo fornito uno script shell chiamato poc.sh per facilitare il processo di debug. Prima di iniziare la configurazione, leggete il file markdown nella cartella Poc.

Poiché legacy_parse_param è una funzione del kernel, dovrai eseguire il debug di una funzione del kernel. Per farlo, devi compilare il sorgente del kernel per ottenere i simboli e il codice sorgente necessari. Abbiamo anche fornito un file markdown dettagliato che ti guida nel processo. Per maggiori dettagli, fai riferimento alla cartella Compile_linux.

Nella Fig. 3.1.3.1, abbiamo dimostrato che dopo aver popolato 4095 byte di dati nell'heap del kernel, abbiamo attivato con successo una scrittura fuori dai limiti sfruttando l'underflow senza segno. Inoltre, abbiamo popolato un totale di 4130 byte di dati in uno slab kmalloc-4k, corrompendo con successo lo slab adiacente. Sebbene in questo esempio lo slab adiacente non contenga informazioni (tutti zeri), possiamo costruire attentamente il nostro codice per sfruttare questa funzionalità per scrivere dati dannosi. Dimostreremo come raggiungere questo obiettivo nella sezione 3.2 Exploit.

![image-20240417133914423](https://assets.kitploit.com/production/public/readmes/24547/2a679fe489b44c6f1f46040bf6c74c7481d6bd4eaf70a594830cc4c0afc2ffc4.png)

**Fig 3.1.3.1 POC con QEMU**

Per maggiori dettagli, fare riferimento a https://github.com/dcheng69/CVE-2022-0185-Case-Study/blob/main/Poc/poc.md nella cartella `Poc` di questo repository!

## 3.2 Exploit

Dopo aver conosciuto questa vulnerabilità, possiamo passare a sfruttarla; i dettagli sono documentati nella cartella `exploit-ubuntu` e anche in questo file markdown: https://github.com/dcheng69/CVE-2022-0185-Case-Study/blob/main/explot-ubuntu/exploit.md

In breve, abbiamo compilato il codice sorgente di Ubuntu, ottenuto il file deb, quindi lo abbiamo testato su una macchina virtuale per ottenere una versione specifica del kernel. Poi abbiamo modificato l'offset del codice di exploit per indirizzare quella versione del kernel usando le informazioni trovate nel file `System.map`. Infine, aggiorniamo grub e riavviamo per eseguire l'exploit!

### 3.2.1 Panoramica dell'exploit

L'utente 'clubby789' ci fornisce un codice di exploit dettagliato. Inizieremo con una panoramica, seguita dalla spiegazione di diversi concetti chiave tramite diagrammi. Infine, presenteremo i risultati dell'exploit utilizzando Ubuntu in esecuzione su una macchina virtuale (VirtualBox).

Dopo aver dimostrato la prova di concetto per questa vulnerabilità, possiamo ora procedere allo sfruttamento. Nella Fig. 3.2.1.1 è illustrata una panoramica di come sfruttare questa vulnerabilità:

- La sezione sinistra si concentra sull'ottenimento dell'indirizzo di base del kernel Linux. Ciò si ottiene sfruttando l'underflow senza segno per sovrascrivere il campo m_ts della struttura msg_msg, consentendoci di leggere fuori dai limiti e di accedere a strutture del kernel precedentemente allocate tramite heap spray.
- La sezione destra mira a ottenere i privilegi di root. Ciò si ottiene utilizzando l'underflow senza segno per sovrascrivere il puntatore next della struttura msg_msg, indirizzandolo a modprobe_path. Successivamente, attiviamo un page fault che invoca il nostro codice FUSE, consentendo scritture arbitrarie nello spazio del kernel.

![Exploit.drawio](https://assets.kitploit.com/production/public/readmes/24547/a8f37de0aa45a0f1bc442bc2bb485402558656b76f3dab668d878132e67c0656.png)

**Fig 3.2.1.1 Panoramica dell'exploit**

### 3.2.2 Ottenere l'indirizzo di base del kernel Linux

Come analizzato in precedenza, in questa parte sfrutteremo l'underflow senza segno per sovrascrivere il campo m_ts della struttura msg_msg, abilitando una lettura fuori dai limiti. Eseguendo lo spray dell'heap con strutture contenenti puntatori del kernel, possiamo sperare di ottenere una perdita di memoria (memory leak).

La struct msg_msg è una struttura dati nel kernel Linux utilizzata per implementare le code di messaggi System V . In questa sezione, ci concentriamo sulla struttura interna di struct msg_msg e sulla logica delle funzioni relative all'invio, alla ricezione e all'allocazione dei messaggi. Come mostrato nella Fig. 3.2.2.1, queste sono le funzioni che dobbiamo comprendere.

La struct msg_msg è una struttura dati nel kernel Linux utilizzata per implementare le code di messaggi System V.[8] In questa discussione, ci concentriamo sulla struttura interna di struct msg_msg, insieme alla logica delle funzioni relative all'invio, alla ricezione e all'allocazione dei messaggi. Come mostrato nella Fig. 3.2.2.1, queste sono le funzioni che dobbiamo comprendere.

L'implementazione dell'invio dei messaggi si trova nel file msg.c, che definisce la lunghezza massima di un messaggio come 8192 byte. Nella funzione alloc_msg, i messaggi vengono divisi in segmenti in base alla loro lunghezza. Se la lunghezza del messaggio, insieme all'intestazione del messaggio, supera una pagina (4096 byte), il messaggio verrà memorizzato in più segmenti collegati tra loro da puntatori.

![img](https://assets.kitploit.com/production/public/readmes/24547/f8e7cad3bbc5f2de8854df978f329a67645fb1e36e824e81785a15fee4f24221.png)

**Fig 3.2.2.1 struct msg_msg: invio e ricezione**

Nella Fig. 3.2.2.2, possiamo vedere che la struct msg_msg funge da intestazione del messaggio, occupando 0x30 byte di memoria. Se nel messaggio sono presenti dati residui, questi verranno memorizzati in segmenti di messaggio e collegati alla struct msg_msgseg. Pertanto, se il kernel consente messaggi fino a un massimo di 8192 byte, i dati verranno memorizzati in un massimo di tre segmenti di messaggio.

![img](https://assets.kitploit.com/production/public/readmes/24547/d5d17b09317a77e03559d587bde7c9a5eb8e9a446f3833d47ce6f57219c9c37b.png)

**Fig 3.2.2.2 struct msg_msg**

Nella Fig. 3.2.2.3, illustriamo la struttura di struct msg_msg. Dal codice, sappiamo che il campo m_ts è quello che dobbiamo sovrascrivere per leggere fuori dai limiti. (Se ti serve, puoi trovare il file sorgente draw.io nella cartella `res`!)

![img](https://assets.kitploit.com/production/public/readmes/24547/8b1a61a5a135f83757eb965ea221a92026f913ec590756f6fde7ce970e1a2f34.png)

**Fig 3.2.2.2 struttura di struct msg_msg**

Ora che comprendiamo la struttura di struct msg_msg, dobbiamo imparare come ottenere un leak dal kernel. Il kernel Linux ha una funzionalità di Kernel Address Space Layout Randomization (KASLR), il che significa che il codice del kernel viene caricato a un indirizzo casuale deciso durante la fase di avvio. Tuttavia, l'offset dal punto di partenza del kernel a qualsiasi indirizzo di funzione rimane costante, consentendoci di eseguire operazioni specifiche per riempire lo spazio heap con strutture contenenti particolari funzioni del kernel. Sottraendo l'offset, possiamo trovare l'indirizzo di partenza del kernel.

Fortunatamente, possiamo facilmente eseguire lo spray dell'heap con strutture seq_operations aprendo /proc/self/stat, che risiede negli slab kmalloc-32. La definizione di seq_operations è mostrata nella Fig. 3.2.2.3.

![img](https://assets.kitploit.com/production/public/readmes/24547/8612e158d1534e21c1f56210aeaad89b83f4663bea3838b5874dcb613cec3f7a.png)

**Fig 3.2.2.3 Strutture per il leak del kernel**

Infine, il processo complessivo è rappresentato nella Fig. 3.2.2.4. Iniziamo popolando legacy_data con 4095 byte di dati per preparare la sovrascrittura. Poi costruiamo messaggi usando struct msg_msg. Poiché la memoria heap viene allocata in modo continuo, i messaggi costruiti saranno probabilmente adiacenti allo slab kmalloc-4k vicino. Sovrascriviamo il campo m_ts controllando i dati che scriviamo in legacy_data.

Successivamente, eseguiamo lo spray dell'heap con più strutture seq_operations kmalloc-32. Poi riceviamo i dati dalla coda dei messaggi, il che attiva una lettura fuori dai limiti. Regolando l'offset dalla funzione del kernel, possiamo ottenere l'indirizzo di base del kernel.

![img](https://assets.kitploit.com/production/public/readmes/24547/c4e1e439085cb22305cae68e7b2edff599a51211c159f3682f4f3085d85198c1.png)

**Fig 3.2.2.3 Panoramica della lettura fuori dai limiti**

### 3.2.3 Ottenere i privilegi di root

Similmente alla nostra analisi precedente, in questa parte dobbiamo impostare un file system FUSE, che consente al nostro codice in spazio utente di gestire i page fault dallo spazio del kernel. Allo stesso tempo, sovrascriveremo il puntatore msg_msgseg *next per puntare a modprobe_path, abilitando scritture arbitrarie nello spazio del kernel.

Esaminiamo prima la call stack FUSE mostrata nella Fig. 3.2.3.1. In generale, FUSE ci consente di implementare un file system nello spazio utente. Quando c'è una nuova operazione, il sistema invocherà il codice che abbiamo definito per FUSE!

![img](https://assets.kitploit.com/production/public/readmes/24547/304bbdfc643bea5b104119270549179c725ef45c12a166527a06e7097c748ccb.png)

**Fig 3.2.3.1 Panoramica di FUSE**

Analizziamo come usare FUSE per ottenere scritture arbitrarie nello spazio del kernel. Per prima cosa, consideriamo l'operazione di invio del messaggio per struct msg_msg. Questa operazione comporta la scrittura di dati nello spazio del kernel. Se costruiamo il messaggio con due segmenti, possiamo sovrascrivere il puntatore e scrivere in qualsiasi indirizzo del kernel. Questo concetto è illustrato nella Fig. 3.2.3.2.

Inoltre, dopo aver esaminato la logica dell'invio dei messaggi alla coda, sappiamo che il processo comporta la copia di un buffer dallo spazio utente allo spazio del kernel. Se i messaggi sono abbastanza lunghi, verranno copiati segmento per segmento. Se riusciamo ad attivare un page fault durante questo processo, possiamo ottenere lo scenario mostrato nella Fig. 3.2.3.2.

Fortunatamente, FUSE fornisce la funzionalità necessaria. Possiamo mappare una pagina su FUSE e, quando viene attivato un page fault, il sistema chiamerà la nostra funzione di lettura FUSE per gestire il page fault. Mettendo in pausa il processo di lettura finché l'underflow senza segno non sovrascrive il puntatore msg_msg_seg *next e poi riprendendo il processo di invio del messaggio, possiamo ottenere scritture arbitrarie. L'intero processo è dimostrato nella Fig. 3.2.3.3.

![img](https://assets.kitploit.com/production/public/readmes/24547/8880a54e3e6935fe02652f53e91d8135878cf10b0d45f83aeae10b9777e8d11e.png)

**Fig 3.2.3.2 Utilizzo dell'invio dei messaggi**

![img](https://assets.kitploit.com/production/public/readmes/24547/84c63673478a7d9646c8cdcf0c6e4efbdfab431d36d825f28822208c2df08f7e.png)

**Fig 3.2.3.3 FUSE e invio dei messaggi**

### 3.2.4 Exploit con VirtualBox

Seguendo il file markdown: https://github.com/dcheng69/CVE-2022-0185-Case-Study/blob/main/explot-ubuntu/exploit.md

Una volta completata la compilazione, puoi osservare i risultati dell'exploit nella Fig. 3.2.4.1.

![img](https://assets.kitploit.com/production/public/readmes/24547/16e9a8827c11c7f44d7e37cf5e97a9b47a8b5c14e408c2fe3c1622da7d8ecb30.png)

**Fig 3.2.4.1 Exploit con VirtualBox**

# 4. Mitigazione della vulnerabilità

## 4.1 Patch ufficiali

Dopo la segnalazione di questa vulnerabilità, Linux e le sue numerose distribuzioni hanno integrato patch per correggere questo bug.[9] [10] [11]

Nello screenshot seguente, mostriamo la patch integrata da Linus Torvalds. La mitigazione di questo problema di underflow consiste semplicemente nel convertire l'operazione di sottrazione in addizione.

![img](https://assets.kitploit.com/production/public/readmes/24547/f3303a9112d28a5ef779f3e248e2bef28f9793355d55e59ad8509c7d1b72141e.png)

# 5. Impatto nel mondo reale

In questo report, dimostriamo come questa vulnerabilità possa essere sfruttata per compromettere un sistema Ubuntu. Inoltre, può potenzialmente colpire sistemi meno recenti che non ricevono aggiornamenti di sicurezza regolari.

Per quanto riguarda Kubernetes, questa vulnerabilità potrebbe causare escalation dei privilegi, fuga dal container o attacchi denial of service.

Sebbene non ci siano state perdite segnalate causate da questa vulnerabilità nelle notizie, ciò sottolinea l'importanza di applicare costantemente aggiornamenti di sicurezza critici. Il ricercatore che ha segnalato questa vulnerabilità esemplifica le pratiche di hacking etico che tutti dovremmo sforzarci di sostenere.[12]

# Riferimenti

[1] https://nvd.nist.gov/vuln/detail/CVE-2022-0185

[2] https://www.hackthebox.com/blog/CVE-2022-0185:_A_case_study

[3] https://ubuntu.com/security/CVE-2022-0185#impact-score

[4] [https://en.wikipedia.org/wiki/Two%27s_complement](https://en.wikipedia.org/wiki/Two's_complement)

[5]https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Unsigned-Overflow.html

[6] https://www.kernel.org/doc/gorman/html/understand/understand011.html

[7] https://leviathan.vip/

[8] https://www.willsroot.io/2021/08/corctf-2021-fire-of-salvation-writeup.html

[9] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=722d94847de2

[10] https://ubuntu.com/security/CVE-2022-0185

[11] https://access.redhat.com/security/cve/CVE-2022-0185

[12]https://jfrog.com/blog/the-impact-of-cve-2022-0185-linux-kernel-vulnerability-on-popular-kubernetes-engines/

[14] https://github.com/chenaotian/CVE-2022-0185?tab=readme-ov-file

[15] https://www.tutorialspoint.com/two-s-complement
Scarica lo strumento
Metriche CVSS v3.1Valore
Vettore di attacco (AV)Locale
Privilegi richiesti (PR)Nessuno
Interazione utente (UI)Nessuna
Riservatezza (C)Alta
Integrità (I)Alta
Disponibilità (A)Alta