Projet
Pour exécuter : ./script.sh
Dépôt GitHub - https://github.com/LaCinquette/practice-22-23
Déroulement
-
Pour trouver une vulnérabilité, j'ai choisi le projet FFmpeg. J'ai trouvé ce commit qui répondait aux exigences, à savoir :
- Correspondait au type CWE-476 - déréférencement de pointeur nul
-
J'ai créé un Dockerfile dans lequel :
- J'ai choisi Ubuntu 22.04 comme image de base
- J'ai défini
DEBIAN_FRONTEND=nointeractive pour éviter toute interaction avec la ligne de commande lors de l'installation des paquets et autres commandes
- J'ai installé les dépendances nécessaires indiquées dans le wiki officiel
- Je prépare l'espace de travail (dossier workdir)
- Je télécharge, décompresse et déplace le commit avec la vulnérabilité non corrigée dans l'espace de travail
- Je lance la construction du programme avec l'utilitaire make
- Je crée le script copy_out.sh qui recherche le fichier objet nécessaire contenant l'erreur et le copie dans le répertoire workspace/out
- Je laisse une instruction pour exécuter le script copy_out.sh, qui doit s'exécuter au démarrage du conteneur
-
Pour automatiser, je crée le script script.sh qui construit l'image et lance le conteneur, puis récupère le fichier et le déplace dans le répertoire courant :
- Je supprime le dossier courant out (s'il existe)
- Je construis l'image nommée ffmpeg_image
- Je lance un conteneur à partir de l'image construite, en lui passant les paramètres suivants :
--rm pour supprimer automatiquement le conteneur à la fin
-v $PWD/out:/workspace/out pour monter un répertoire temporaire par lequel le fichier objet est transféré vers l'hôte
- Je copie le fichier nécessaire depuis le dossier out
- Je supprime le dossier out
Analyse de la vulnérabilité
Sources :
- Commit avec l'erreur corrigée
- Page sur GitHub concernant la vulnérabilité
- Courrier d'un chercheur en sécurité sur la vulnérabilité
Analyse :
Problème :
- À l'aide de la commande
ffmpeg -c:v dnxhd -i poc.mov -y output.ts, un fichier .mov spécialement conçu est fourni en entrée au programme
- Pour analyser le format DNxHD, la fonction dnxhd_parse est appelée dans le fichier dnxhd_parser
- Celle-ci appelle à son tour la fonction dnxhd_find_frame_end (dans le même fichier), qui, dans certaines conditions, ne trouve pas la fin et renvoie un nombre négatif qui n'est pas un code d'erreur
- Ce nombre, ainsi que d'autres paramètres, est ensuite transmis à la fonction ff_combine_frame (située dans le fichier parser) pour assembler les trames
- Comme ce nombre n'est pas un code d'erreur, ff_combine_frame l'interprète comme un décalage et tente de relire ces octets dans le tampon. Mais comme le tampon est vide à ce moment-là, un déréférencement de pointeur nul se produit, ce qui provoque une erreur de segmentation (Segmentation fault)
En assembleur :
0x08000d4e - début de la section
-
movsxd rcx, dword [rbx + 0xc]
Dans le registre rcx, on obtient une référence à pc->buffer
-
add rcx, rdi
On ajoute next à pc->buffer
-
add rcx, qword [rbx]
On ajoute pc->last_index à next et à pc->buffer
-
movzx edi, byte [rcx]
On calcule l'octet à l'adresse rcx, mais comme pc->buffer est initialement null, on obtient une erreur de segmentation
Solution :
Empêcher l'accès à une zone mémoire non allouée en traitant correctement le cas exceptionnel. Lorsqu'un nombre négatif d'octets restants est détecté, continuer le traitement du fichier en sautant la boucle.