Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
Outils/GitHubGitHub/farazsth98/freebsd-dirent-info-leak-bugs
Criminalistique MémoireAnalyse des VulnérabilitésExploitationCollecte d'InformationsAnalyse de Binaires
GitHubfarazsth98/freebsd-dirent-info-leak-bugs

freebsd-dirent-info-leak-bugs

CVE-2020-25578 et CVE-2020-25579: Des bugs de fuite d'informations FreeBSD que j'ai trouvés en 2020.

Voir le dépôt

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager
722il y a 5 ansPas encore vérifié

Comment ai-je trouvé les bugs ?

  1. Décider aléatoirement d'auditer les systèmes de fichiers de FreeBSD
  2. Faire quelques recherches et découvrir que le système de fichiers par défaut est une combinaison de FFS et UFS
  3. Passer du temps à auditer ufs_create et trouver 0 bugs
  4. Aller ici et examiner l'historique des commits pour les fonctions du système de fichiers UFS
  5. Repérer ce commit à propos de fuites d'informations via les octets de bourrage dans les objets struct dirent alloués sur la pile
  6. Analyser le correctif et constater que le correctif pour msdosfs_readdir est incomplet. Ils ont corrigé une instance du bug, mais pas une deuxième.
  7. Écrire un PoC pour confirmer que je peux faire fuiter 3 octets du bourrage. Puis commencer à chercher des variantes.
  8. Trouver les variantes dans mqueuefs, autofs, smbfs et tmpfs qui me permettent de faire fuiter un pointeur complet de 8 octets. Écrire un PoC pour confirmer.

Bug original

Comme mentionné ci-dessus, le bug original que j'ai trouvé était dans msdosfs_readdir pendant que j'analysais le correctif pour le commit lié ci-dessus.

Le flux de base pour appeler readdir sur FreeBSD est le suivant :

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

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

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

Selon le système de fichiers dans lequel somedir réside, l'une des nombreuses fonctions *_readdir du noyau FreeBSD peut être appelée.

Le correctif ci-dessus ajoute une fonction appelée dirent_terminate qui est destinée à être appelée avant qu'un objet struct dirent soit renvoyé à l'espace utilisateur (souvent fait en utilisant la fonction uiomove). Cette fonction va mettre à zéro les octets de bourrage ainsi que tous les octets restants dans le champ d_name de la structure. La définition de struct dirent se trouve ici.

En regardant le correctif, à la ligne 1562, vous pouvez voir dirent_terminate appelé avec la variable dirbuf comme argument. Ensuite, uiomove est appelé pour copier le contenu de dirbuf vers l'espace utilisateur. Cependant, remarquez que ces lignes de code se trouvent dans le bloc de cette instruction if. Le commentaire au-dessus de cette instruction if explique que cette branche n'est prise que si readdir est appelé sur la racine du système de fichiers MSDOS, donc nous pouvons simplement ignorer cette instruction if en appelant readdir dans n'importe quel sous-répertoire au-delà de la racine du système de fichiers.

Plus loin, nous voyons un autre appel à uiomove à la ligne 1691. Cependant, en lisant attentivement le code, vous verrez que dirent_terminate n'est pas appelé dans cette instance, ce qui signifie que les octets de bourrage resteront non initialisés. Malheureusement, le champ d_name a été mis à zéro au début de cette fonction (ici), donc nous ne pouvons pas obtenir une fuite plus importante.

PoC

D'abord, je n'avais pas de clé USB, donc j'ai dû trouver un moyen de monter un système de fichiers MSDOS. Ce qui suit fonctionne :

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

Le PoC se trouve dans original_poc.c. Il suffit de compiler avec clang et de l'exécuter depuis le même répertoire que les commandes ci-dessus, et vous verrez les octets fuités être affichés.

Variantes

J'ai commencé à chercher des variantes de ceci. Je pense avoir simplement grepé uiomove\(&.*, qui a renvoyé environ 15-20 résultats, et j'ai tous vérifiés manuellement. Malheureusement, aucune des variantes n'existe dans FreeBSD par défaut (les systèmes de fichiers doivent être activés / compilés manuellement dans le noyau). Les fonctions comportant les variantes sont les suivantes :

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

Le bug est exactement le même dans toutes ces fonctions, donc je vais juste couvrir mqfs_readdir.

  1. D'abord, une struct dirent entry est allouée sur la pile
  2. Ensuite, dirent_terminate est appelé pour mettre à zéro les champs de bourrage + d_name de la structure
  3. Enfin, vfs_read_dirent est appelé. Cette fonction appellera uiomove pour copier la structure vers l'espace utilisateur

Tout a l'air bon jusqu'à présent, n'est-ce pas ? Pas nécessairement. Nous devons nous assurer que tous les champs de la structure sont initialisés. Si vous regardez attentivement le code, vous verrez que le champ d_off est laissé non initialisé. Le type de ce champ est off_t, qui est essentiellement un int64_t. Lorsque la structure est copiée vers l'espace utilisateur, nous obtenons des données non initialisées dans ce champ.

PoC

Ce même PoC fonctionnera pour toutes les variantes, il suffit de l'exécuter sur un système de fichiers différent. Pour mqueuefs, faites ce qui suit (nécessite mqueuefs activé / compilé dans le noyau d'abord) :

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

Le PoC lui-même se trouve dans variants_poc.c. Il suffit de compiler avec clang et de l'exécuter depuis le même répertoire que les commandes ci-dessus. Vous verrez des pointeurs noyau être affichés (probablement un pointeur de pile et un pointeur de section de code / tas, je n'ai pas vérifié).

Télécharger l’outil