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
freebsd-dirent-info-leak-bugs — CVE-2020-25578 e CVE-2020-25579: Alcuni bug di leak di informazioni in FreeBSD che ho trovato nel 2020. | Kitploit
Strumenti/GitHubGitHub/farazsth98/freebsd-dirent-info-leak-bugs
Memory ForensicsAnalisi delle VulnerabilitàExploitRaccolta InformazioniAnalisi di Binari
GitHubfarazsth98/freebsd-dirent-info-leak-bugs

freebsd-dirent-info-leak-bugs

CVE-2020-25578 e CVE-2020-25579: Alcuni bug di leak di informazioni in FreeBSD che ho trovato nel 2020.

Vedi Repository

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
725 anni faNon ancora revisionato

Come ho trovato i bug?

  1. Ho deciso a caso di fare l'audit dei filesystem in FreeBSD
  2. Ho fatto qualche ricerca e scoperto che il filesystem predefinito in uso è una combinazione di FFS e UFS
  3. Ho passato un po' di tempo a fare audit di ufs_create e trovato 0 bug
  4. Sono andato qui e ho esaminato la cronologia dei commit per le funzioni del filesystem UFS
  5. Ho notato questo commit relativo alla fuga di informazioni attraverso i byte di padding in oggetti struct dirent allocati sullo stack
  6. Ho analizzato la patch e scoperto che la patch a msdosfs_readdir è incompleta. Hanno corretto un'istanza del bug, ma non una seconda.
  7. Ho scritto un PoC per confermare che posso far fuoriuscire 3 byte dal padding. Poi ho iniziato a cercare varianti.
  8. Ho trovato le varianti in mqueuefs, autofs, smbfs e tmpfs che mi permettono di far fuoriuscire un puntatore completo di 8 byte. Ho scritto un PoC per confermare.

Bug originale

Come accennato in precedenza, il bug originale che ho trovato era in msdosfs_readdir mentre analizzavo la patch per il commit linkato sopra.

Il flusso di base per chiamare readdir su FreeBSD è il seguente:

root@kitploit:~
#include <dirent.h>

int main(void) {
    struct dirent *dp;
    DIR *dirp;

    dirp = opendir("./somedir");
    dp = readdir(dirp);
}

A seconda del filesystem in cui risiede somedir, potrebbe essere chiamata una qualsiasi delle numerose funzioni *_readdir nel kernel di FreeBSD.

La patch sopra aggiunge una funzione chiamata dirent_terminate che ha lo scopo di essere chiamata prima che un oggetto struct dirent venga restituito allo userspace (spesso tramite la funzione uiomove). Questa funzione azzera i byte di padding e tutti i byte rimanenti nel campo d_name della struct. La definizione di struct dirent è qui.

Guardando la patch, alla riga 1562, si può vedere dirent_terminate chiamata con la variabile dirbuf come argomento. Subito dopo, uiomove viene chiamata per copiare il contenuto di dirbuf di nuovo nello userspace. Tuttavia, nota che queste righe di codice sono all'interno del blocco di questo if. Il commento sopra questo if spiega che questo ramo viene seguito solo se readdir viene chiamato sulla radice del filesystem MSDOS, quindi possiamo semplicemente saltare questo if chiamando readdir in qualsiasi sottodirectory oltre la radice del filesystem.

Più avanti, vediamo un'altra chiamata a uiomove alla riga 1691. Tuttavia, leggendo attentamente il codice, vedrai che dirent_terminate non viene chiamata in questa occasione, il che significa che i byte di padding rimarranno non inizializzati. Purtroppo il campo d_name è stato azzerato all'inizio di questa funzione (qui), quindi non possiamo ottenere una fuga più grande.

PoC

Per prima cosa, non avevo una chiavetta USB, quindi ho dovuto trovare un modo per montare un filesystem MSDOS. Quanto segue funziona:

root@kitploit:~
$ dd if=/dev/zero of=test.img bs=512 count=256000
$ sudo mdconfig -a -t vnode -f test.img
$ sudo newfs_msdos -s 131072000 /dev/md1 # My mdconfig returned md1
$ mkdir ./temp
$ sudo mount -t msdosfs /dev/md1 ./temp
$ mkdir ./temp/test_dir

Il PoC si trova in original_poc.c. Basta compilare con clang ed eseguirlo dalla stessa directory dei comandi sopra, e vedrai i byte fuoriusciti stampati.

Varianti

Ho iniziato a cercare varianti di questo bug. Penso di aver semplicemente usato grep per uiomove\(&.*, che ha restituito circa 15-20 risultati, e li ho controllati tutti a mano. Purtroppo nessuna delle varianti è presente in FreeBSD di default (i filesystem devono essere abilitati / compilati manualmente nel kernel). Le funzioni con le varianti sono le seguenti:

  1. mqfs_readdir
  2. tmpfs_dir_getdotdent
  3. tmpfs_dir_getdotdotdent
  4. smbfs_readvdir
  5. autofs_readdir_one

Il bug è esattamente lo stesso in tutte queste funzioni, quindi tratterò solo mqfs_readdir.

  1. Per prima cosa, viene allocata una struct dirent entry sullo stack
  2. Successivamente, dirent_terminate viene chiamata per azzerare i campi padding + d_name della struct
  3. Infine, vfs_read_dirent viene chiamata. Questa funzione chiamerà uiomove per copiare la struct nello userspace

Tutto sembra a posto fin qui, vero? Non necessariamente. Dobbiamo assicurarci che tutti i campi della struct siano inizializzati. Se guardi attentamente il codice, vedrai che il campo d_off viene lasciato non inizializzato. Il tipo di questo campo è off_t, che è essenzialmente un int64_t. Quando la struct viene copiata nello userspace, otteniamo dati non inizializzati in questo campo.

PoC

Questo stesso PoC funzionerà per tutte le varianti, devi solo eseguirlo su un filesystem diverso. Per mqueuefs, fai quanto segue (richiede mqueuefs abilitato / compilato nel kernel prima):

root@kitploit:~
$ mkdir ./temp
$ sudo mount -t mqueuefs null ./temp

Il PoC stesso si trova in variants_poc.c. Basta compilare con clang ed eseguirlo dalla stessa directory dei comandi sopra. Vedrai dei puntatori del kernel stampati (presumibilmente un puntatore allo stack e un puntatore a sezione di codice / heap, non ho controllato).

Scarica lo strumento