
Ce dépôt documente six vulnérabilités de sécurité confirmées dans FatFs ainsi qu'un harnais de test, un fuzzer et un générateur autonome d'images disque d'exploitation.
Le code source original de FatFs se trouve dans le répertoire FatFs-R0.16.
Ce projet marque un retour sur une évaluation de sécurité de 2017, lorsqu'un audit manuel et un effort de fuzzing de plusieurs jours avaient identifié quelques bugs basiques mais sans intérêt dans le driver FatFs. Neuf ans plus tard, en mars 2026, nous avons réexaminé ce projet avec Visual Studio Code, GitHub Copilot en mode "auto", et quelques invites simples, sans boucles, harnais ou compétences spécifiques. Les résultats ont été surprenants - des bugs négligés lors de l'audit manuel sont devenus triviaux à trouver, en utilisant le LLM pour construire automatiquement un fuzzer avec des entrées inédites. Non seulement cet effort a trouvé des bugs intéressants, mais il a aussi automatisé le processus de validation de l'exploitabilité dans différents scénarios de développement embarqué.
Veuillez consulter les fichiers suivants pour des notes détaillées :
FatFs est une bibliothèque de système de fichiers FAT/exFAT portable et libre de droits, écrite en C par ChaN (elm-chan.org). Elle est conçue pour les systèmes embarqués à ressources limitées, sans dépendance à un OS, et est généralement compilée directement dans le firmware. Elle prend en charge FAT12, FAT16, FAT32 et exFAT, ainsi que le support optionnel des LFN (Long File Name) et des partitions GPT.
Parce que FatFs est petite, autonome et sous licence permissive, elle est devenue l'implémentation FAT de facto pour les firmwares de microcontrôleurs. La bibliothèque est intégrée telle quelle dans les SDK officiels, les RTOS, les bootloaders et les frameworks applicatifs - ce qui signifie qu'une seule vulnérabilité en amont se propage à chaque projet en aval qui a copié ff.c.
Les projets suivants ont été confirmés comme intégrant une version vulnérable de FatFs. Voir 02_CRITICAL.md pour l'analyse complète, les chemins de propagation par projet et les coordonnées de contact pour la sécurité.
FatFs n'a aucun historique de CVE, aucune liste de diffusion sécurité, ni mécanisme de notification de correctifs. Chaque projet en aval qui intègre ff.c doit découvrir, trier et corriger ces vulnérabilités indépendamment, généralement sans savoir qu'il est concerné. Cela signifie que la fenêtre entre la divulgation publique et la correction généralisée se mesurera en années, pas en jours. La surface d'attaque pratique n'est donc pas une application ou un service logiciel, mais des dizaines de millions d'appareils répartis dans des dizaines de bases de code indépendantes, dont beaucoup ne recevront jamais de correctif.
Le scénario d'exploitation archétypal est la carte SD malveillante : un attaquant disposant de quelques secondes d'accès physique remplace le support de stockage d'un appareil, des caméras grand public aux drones, en passant par les imprimantes 3D et des milliers d'autres familles de produits. Chaque vulnérabilité de cet ensemble est déclenchable en montant une image FAT spécialement conçue, ce qui se produit presque toujours automatiquement à l'insertion, sans aucune interaction de l'utilisateur. Cela dit, l'accès physique n'est pas la seule voie.
Les appareils qui ingèrent des paquets de mise à jour au format FAT depuis une source réseau, tels que les frameworks de mise à jour OTA et les mises à jour de bootloader par glisser-déposer, sont exploitables par tout attaquant capable de fournir une image malveillante au pipeline de mise à jour. Compromission de la chaîne d'approvisionnement, injection AitM dans un flux de mise à jour HTTP en clair, ou image malveillante publiée sur un portail de distribution de firmware amateur. La voie OTA est entièrement distante sur tout appareil qui ne dispose pas d'une vérification d'intégrité authentifiée de bout en bout de son conteneur de mise à jour avant de le monter avec FatFs.
CVE-2026-6682 - Débordement d'entier conduisant à une longueur de lecture contrôlée par l'attaquant
En concevant un volume FAT32 avec un champ spécifique configuré pour déborder, un attaquant peut amener un appareil victime à lire un nombre d'octets choisi par l'attaquant dans un tampon fixe - une voie directe vers l'exécution de code. Sur les cibles embarquées bare-metal, l'exploit est déterministe et ne nécessite ni heap spray, ni force brute, ni fuite d'information préalable.
L'attaquant doit contrôler le volume FAT que la cible va monter. Pour la plupart des appareils, cela signifie un accès physique pour remplacer une carte SD. Les appareils qui acceptent des mises à jour de firmware via un réseau, ou qui ne font confiance à l'intégrité d'un paquet de mise à jour qu'après que FatFs l'a déjà analysé, sont exploitables à distance.
CVE-2026-6683 - Division par zéro dans la synchronisation exFAT
Un attaquant capable de fournir un volume exFAT spécialement conçu à un appareil exécutant une version de FatFs antérieure à R0.16 peut garantir un crash lors de toute écriture ultérieure. FatFs R0.16 a ajouté une protection partielle au moment du montage qui peut rejeter le volume malveillant avant qu'une écriture ne se produise, mais le défaut arithmétique sous-jacent n'est pas entièrement corrigé. Contre les appareils qui appliquent des mises à jour OTA en écrivant sur un support formaté en FAT, un déclenchement réussi devient une brique à distance en un coup : le processus de mise à jour plante en pleine écriture et l'appareil peut être irrécupérable sans accès physique à un débogueur matériel.
L'attaquant doit amener la cible à monter un volume exFAT qu'il contrôle, puis à effectuer une opération d'écriture ou de synchronisation. Le scénario de la carte SD malveillante couvre la plupart des appareils embarqués ; pour une exploitation à distance, le pipeline OTA de la cible doit accepter et monter une image fournie par l'attaquant sans d'abord vérifier son intégrité.
CVE-2026-6684 - Boucle infinie dans l'analyse des partitions GPT
La fourniture d'une image disque GPT avec un seul champ réglé à sa valeur maximale amène la cible à boucler sur la lecture des secteurs du disque jusqu'à la coupure de l'alimentation. Contre les bootloaders et les firmwares bare-metal qui fonctionnent sans watchdog, c'est une brique permanente : l'appareil ne termine plus jamais son démarrage. Cette vulnérabilité est corrigée dans FatFs R0.16, elle n'affecte donc que les appareils qui intègrent une version plus ancienne.
L'attaquant doit amener la cible à monter un disque formaté en GPT qu'il contrôle, et la cible doit exécuter une version pré-R0.16 de FatFs avec le support LBA 64 bits activé. Notons que les bootloaders sont les cibles les plus attrayantes ici précisément parce qu'ils n'ont généralement ni watchdog ni voie de récupération.
CVE-2026-6686 - Données de clusters obsolètes lisibles après un seek au-delà de l'EOF
Lorsqu'un fichier est étendu en cherchant au-delà de sa fin (seek), FatFs ne met pas à zéro le stockage nouvellement alloué. Toute donnée écrite précédemment sur ces secteurs par un fichier supprimé est lisible par le processus suivant qui ouvre le fichier étendu. Sur les appareils qui font tourner des images de firmware dans une zone de staging OTA, ou qui partagent une carte SD entre un bootloader et une application, cela peut exposer d'anciens blobs de firmware, des clés ou d'autres contenus sensibles à un lecteur moins privilégié.
L'attaquant a besoin d'un accès en lecture à un fichier sur le volume FAT de la cible qui a été étendu via une opération de seek. C'est principalement un scénario d'accès local ou physique.
CVE-2026-6687 - Débordement de pile via le libellé du volume exFAT
La fourniture d'un volume exFAT avec un libellé surdimensionné amène FatFs à déborder le tampon de libellé de l'appelant lorsque l'application appelle f_getlabel(). Le générateur de code STM32CubeMX de ST émet la taille de tampon vulnérable dans chaque projet compatible FatFs qu'il produit, ce qui signifie que cette vulnérabilité existe dans une population énorme et en grande partie non répertoriée de firmwares STM32 commerciaux. Sur les appareils bare-metal Cortex-M sans cookies de pile ni ASLR (le cas courant), c'est une primitive d'exécution de code en un seul coup.
L'attaquant doit amener la cible à monter un volume exFAT qu'il contrôle, puis à appeler f_getlabel(). La bibliothèque FatFs ne l'appelle pas en interne - l'application doit l'appeler explicitement. La plupart des projets le font dans le cadre de leur propre initialisation au moment du montage, ne nécessitant en pratique aucune autre interaction de l'attaquant pour ces projets.
CVE-2026-6688 - Débordement de tampon via un nom de fichier LFN long dans le listage de répertoire
En plaçant un fichier avec un nom long dans un répertoire FAT, un attaquant peut déborder du tampon qu'une application appelante utilise pour stocker ce nom lors de l'itération du répertoire. Le débordement est proportionnel à la longueur du nom de fichier, jusqu'à 255 octets. Cette vulnérabilité se trouve dans le code appelant, pas dans FatFs lui-même, donc l'impact varie selon la cible - mais toute application qui itère un répertoire et copie les noms de fichiers dans un tampon de taille fixe sans vérifier la longueur est concernée.
L'attaquant doit amener la cible à parcourir un répertoire sur un volume FAT qu'il contrôle. Aucun exFAT n'est requis ; cela fonctionne sur FAT12, FAT16 et FAT32. Le support des noms de fichiers longs doit être activé dans la configuration de FatFs, ce qui est le réglage par défaut et recommandé dans toutes les distributions majeures.
Six bugs distincts ont été identifiés dans FatFs R0.16 et les versions antérieures.
mount_volume() → finfo.fsize contrôlé par l'attaquantEmplacement : ff.c mount_volume() - fasize *= fs->n_fats
Un dépassement d'entier par multiplication DWORD se produit lorsque BPB_FATSz32 est conçu pour produire une valeur importante. Avec BPB_FATSz32 = 0x80000001 et NumFATs = 2 :```c
fasize = 0x80000001;
fasize *= 2; // DWORD overflow → 0x00000002
La valeur `fasize` tronquée fait que `fs->database` (le début de la zone de données) se retrouve à l'intérieur de la région FAT. Un attaquant qui contrôle l'image disque peut placer une fausse entrée de répertoire au niveau du secteur chevauchant, ce qui amène `f_stat()` à retourner un `finfo.fsize` contrôlé par l'attaquant. Toute application qui appelle ensuite `f_read(fp, buf, finfo.fsize, &br)` sans borner la longueur par rapport à `sizeof(buf)` fait déborder le tampon de destination avec des octets entièrement contrôlés par l'attaquant — une voie directe vers l'exécution de code arbitraire (RCE).
**Impact maximal :** Exécution de code à distance (débordement de tas ou de pile) sur tout appareil embarqué qui lit une taille de fichier depuis FatFs et l'utilise comme longueur de lecture.
---
### CVE-2026-6683 - Division par zéro dans `sync_fs()` (exFAT)
**Emplacement :** `ff.c` `sync_fs()` - `(n_fatent - 2 - free_clst) * 100 / (n_fatent - 2)`
Lorsque `BPB_NumClusEx = 0`, `n_fatent = 2`, ce qui rend le diviseur `(n_fatent - 2) = 0`. Ce cas est atteint lors de toute opération d'écriture ou de synchronisation sur un volume exFAT contrefait, produisant un SIGFPE / défaut matériel et faisant planter la cible.
FatFs R0.16 protège partiellement contre cela au moment du montage (la validation du cluster de bitmap échoue lorsque `NumClusEx = 0`). Les versions plus anciennes - R0.14b (ArduPilot, Mbed OS), R0.15 (RIOT OS, STM32), R0.13c (MicroPython) - ne disposent pas d'une telle protection et plantent inconditionnellement.
**Impact maximal :** Déni de service / crash système lors de toute écriture sur un volume exFAT contrefait. Pendant une mise à jour OTA, cela peut rendre l'appareil inutilisable.
---
### CVE-2026-6684 - Boucle de scan de partitions GPT sans limite dans `find_volume()` (pre-R0.16)
**Emplacement :** `ff.c` `find_volume()` - `for (i = 0; i < n_ent; i++) disk_read()`
Lorsque `FF_LBA64 = 1`, `find_volume()` itère sur chaque entrée de partition GPT pour rechercher une partition FAT. Dans les versions antérieures à R0.16, le nombre d'itérations est pris directement depuis le champ `GPTH_PtNum` sur disque (0–0xFFFFFFFF) sans limite supérieure. Une image GPT contrefaite avec `GPTH_PtNum = 0xFFFFFFFF` provoque environ un milliard de lectures disque avant que la fonction ne retourne « introuvable », gelant le système définitivement.
R0.16 a introduit `test_gpt_header()` qui valide le CRC32 et impose `PtNum ≤ 128` avant d'entrer dans la boucle.
**Impact maximal :** Déni de service permanent au moment du montage. Sur les appareils sans chien de garde (bootloaders, bootrom FPGA bare-metal), cela rend le système définitivement inutilisable.
### CVE-2026-6686 - Données de cluster non initialisées via `f_lseek()` au-delà de la fin du fichier
**Emplacement :** `ff.c` `f_lseek()` :```c
if (!FF_FS_READONLY && fp->fptr > fp->obj.objsize) {
fp->obj.objsize = fp->fptr; // extend, but never zero-fill
fp->flag |= FA_MODIFIED;
}
La recherche au-delà de l'EOF appelle create_chain() pour allouer de nouveaux clusters, mais ne remet jamais leurs secteurs à zéro. Toute lecture ultérieure de la région étendue renvoie des données brutes obsolètes - contenu de fichiers précédemment supprimés subsistant dans le cluster recyclé.
Impact dans le pire des cas : Divulgation d'informations sur le contenu de fichiers supprimés (anciennes images de firmware, clés privées, données de capteurs) à un lecteur moins privilégié ou via une interface connectée.
f_getlabel() via exFAT XDIR_NumLabelEmplacement : ff.c f_getlabel() :```c
for (si = di = hs = 0; si < dj.dir[XDIR_NumLabel]; si++) {
wc = ld_16(dj.dir + XDIR_Label + si * 2);
nw = put_utf((DWORD)hs << 16 | wc, &label[di], 4);
di += nw;
}
La spécification exFAT limite `XDIR_NumLabel` à 11 caractères. FatFs lit
ce champ comme un `BYTE` brut (0–255) sans validation. Un volume malveillant avec
`XDIR_NumLabel = 128` amène `f_getlabel` à écrire 128 caractères dans le
tampon de l'appelant - généralement `char label[12]` ou `char label[24]` tel que généré
par STM32CubeMX - débordant la pile de jusqu'à 244 octets.
**Impact dans le pire cas :** Débordement de tampon de pile dans tout appelant de `f_getlabel()` sur
un volume exFAT. Le motif vulnérable canonique (`char label[12]`) apparaît
dans tous les projets générés par STM32CubeMX, AN3224 et UM1721.
---
### CVE-2026-6688 - Débordement de la pile/tas de l'appelant via un nom de fichier LFN long
**Cause racine :** Avec `FF_USE_LFN` activé, `f_readdir()` remplit `fno.fname` avec
le nom de fichier long complet - jusqu'à `FF_LFN_BUF` (255) caractères. Les appelants
conçus pour un fonctionnement SFN uniquement utilisent des tampons de chemin ou de nom à taille fixe (par ex.,
`char path[16]`, `char name[14]`) et copient `fno.fname` sans vérification
des limites.
Motifs vulnérables courants trouvés dans plusieurs projets :```c
strcpy(entry->name, fno.fname); // Zephyr: entry->name[14]
sprintf(path, "0:/%s", fno.fname); // NodeMCU, ChibiOS demo, StarryPilot
sprintf(&cur_path[n], "/%s", fn); // Samsung TizenRT
Impact dans le pire des cas : Débordement de pile ou de tas proportionnel à la longueur du LFN
(jusqu'à 255 octets) lors de tout parcours de répertoire sur un volume FAT conçu à cet effet. Une
carte SD malveillante qui fait déborder entry->name[14] de 241 octets corrompt de manière fiable
la frame de pile du planificateur Zephyr.
├── harness/ Security test harness and exploit tools
│ ├── Makefile Build system (see targets below)
│ ├── test_ffconf.h FatFs config for the harness (LFN+exFAT+LBA64)
│ ├── diskio_ramdisk.c/h In-memory block device (2 MiB RAM disk)
│ ├── ffunicode_stub.c Minimal Unicode stub (CP437 pass-through)
│ ├── test_harness.c Deterministic per-bug test suite (CVE-2026-6682 through CVE-2026-6688)
│ ├── rce_demo.c Standalone CVE-2026-6682 RCE demo: OTA struct-pointer overwrite
│ ├── libfuzzer_harness.c libFuzzer / AFL++ entry point
│ ├── exploit_disks.c Standalone disk-image generator (see below)
│ ├── build/ Compiled binaries
│ └── img/ Generated exploit disk images (*.img)
│
├── fuzzer/ Go corpus generator and structural fuzzer
│ ├── main.go Corpus builder + Go native fuzz targets
│ ├── fat_image.go FAT12/16/32/exFAT/GPT image construction helpers
│ └── corpus/ Seed corpus written by make corpus
---
## Cibles de construction du harnais
Toutes les cibles sont exécutées depuis le répertoire `harness/`. Nécessite `clang` (ou définir `CC=gcc`).
Pour compiler la cible `afl` sur macOS, utilisez `brew install afl++` puis `sudo afl-system-config` pour préparer votre système.
| Cible | Description |
|--------|-------------|
| `make` / `make test` | Construire et exécuter la suite de tests déterministe avec ASan + UBSan |
| `make rce_demo` | Construire et exécuter la démo RCE CVE-2026-6682 (sans sanitizers, sans stack-protector) |
| `make exploit_disks` | Construire et générer les 14 images de disque d'exploitation dans `harness/img/` |
| `make fuzz_asan` | Construire le binaire libFuzzer (`build/fuzz_fatfs`) |
| `make afl` | Construire la cible AFL++ (nécessite `afl-clang-fast` dans `PATH`) |
| `make corpus` | Générer le corpus de départ via le générateur Go dans `harness/corpus/` |
| `make clean` | Supprimer `build/` et `img/` |
### Démarrage rapide```sh
# Run the full deterministic test suite
cd harness && make
# Run the CVE-2026-6682 RCE demo
make rce_demo
# Generate all exploit disk images
make exploit_disks
# Fuzz with libFuzzer (requires clang)
make fuzz_asan
build/fuzz_fatfs -max_len=2097152 corpus/
# Fuzz with AFL++
make corpus afl
afl-fuzz -i corpus/ -o findings/ -- build/afl_fatfs @@
make exploit_disks produit 14 images de disque brutes dans harness/img/, une pour chaque combinaison projet/vulnérabilité. Chaque image est auto-testée au moment de la génération en la montant avec le FatFs fourni. Les images peuvent être écrites sur une carte SD physique :```sh
dd if=harness/img/exploit_bug1_espidf.img of=/dev/sdX bs=512
| Image | Bug | Projet(s) cible(s) | Effet |
|-------|-----|------------------|--------|
| `exploit_bug1_fat32.img` | CVE-2026-6682 | Générique | Fournit une charge utile de la taille d'un pointeur via `f_read` |
| `exploit_bug1_espidf.img` | CVE-2026-6682 | espressif/esp-idf | `finfo.fsize=16 MB` → débordement de tas `malloc`/`fread` |
| `exploit_bug1_stm32.img` | CVE-2026-6682 | STMicro stm32-mw-fatfs | `finfo.fsize=1 MB` → débordement du tampon firmware de 1 Ko |
| `exploit_bug1_keystone3.img` | CVE-2026-6682 | KeystoneHQ wallet | `finfo.fsize=512 KB` → débordement du tampon OTA |
| `exploit_bug1_ardupilot.img` | CVE-2026-6682 | ArduPilot / Mbed OS / RIOT / MicroPython | `finfo.fsize=2 MB` → débordement du tampon de lecture de journal |
| `exploit_bug2_exfat.img` | CVE-2026-6683 | ArduPilot / Mbed OS / MicroPython / RIOT | `BPB_NumClusEx=0` → division par zéro `sync_fs` (SIGFPE sur les versions pré-R0.16) |
| `exploit_bug3_gpt.img` | CVE-2026-6684 | vivado-risc-v / tinyuf2 / circle | `GPTH_PtNum=0xFFFFFFFF` → boucle infinie au démarrage (pré-R0.16) |
| `exploit_bug5_stale.img` | CVE-2026-6686 | RT-Thread / tinyuf2 / ArduPilot / RIOT | L'extension `f_lseek` expose des données de clusters supprimés initialisées à `0xAA` |
| `exploit_bug6_stm32.img` | CVE-2026-6687 | STMicro stm32-mw-fatfs | `XDIR_NumLabel=128` → débordement de 117 octets de `label[12]` de CubeMX |
| `exploit_bug6_zephyr.img` | CVE-2026-6687 | Zephyr / ArduPilot / RIOT / MicroPython | `XDIR_NumLabel=255` → débordement de 216 octets de `label[24]` |
| `exploit_bug7_max255.img` | CVE-2026-6688 | NodeMCU / ChibiOS / StarryPilot / TizenRT | Un LFN de 255 caractères déborde tout tampon fixe < 255 octets |
| `exploit_bug7_zephyr.img` | CVE-2026-6688 | Zephyr | Un LFN de 14 caractères → débordement d'un octet NUL de `entry->name[14]` |
| `exploit_bug7_grblhal.img` | CVE-2026-6688 | grblHAL | Off-by-one : la garde vérifie l'entrée précédente ; un LFN de 11 caractères fait déborder `dirent.name[12]` d'un octet NUL |
---
## Suite de tests déterministe (`test_harness.c`)
Le harnais de test exerce six bogues avec des images disque fabriquées à la main et construites en mémoire, puis confirme que le chemin de code vulnérable a été atteint :
- **CVE-2026-6682** - construit une image FAT32 `BPB_FATSz32=0x80000001`, la monte, et confirme que `fs.database` se situe à l'intérieur de la région FAT ; puis exécute la chaîne RCE complète (fausse entrée de répertoire → `f_read` d'un pointeur de fonction planté → `rce_proof_of_execution()` appelé).
- **CVE-2026-6683** - documente le diviseur `(n_fatent-2)` et confirme le chemin arithmétique ; vérifie que R0.16 rejette l'image au moment du montage.
- **CVE-2026-6684** - construit une image GPT `GPTH_PtNum=0xFFFFFFFF` et confirme que R0.16 la rejette en ≤ 3 lectures disque via `test_gpt_header()`.
- **CVE-2026-6686** - pré-remplit tous les clusters de données avec `0xAA`, écrit un fichier court, l'étend via `f_lseek`, puis relit pour confirmer que les octets obsolètes sont visibles.
- **CVE-2026-6687** - construit une image exFAT avec `XDIR_NumLabel=128`, appelle `f_getlabel` dans un tampon sonde, et compte le dépassement au-delà de l'octet 24.
- **CVE-2026-6688** - construit un répertoire FAT16 avec un LFN de 50 caractères, le lit via `f_readdir`, et confirme que la longueur de `fno.fname` dépasse les tampons d'appelant typiques.
---
## Démo RCE CVE-2026-6682 (`rce_demo.c`)
Une démonstration autonome et réaliste de la chaîne d'exploitation de CVE-2026-6682, modelée sur du code embarqué de mise à jour de firmware OTA. Une structure est déclarée avec un tampon d'en-tête de taille fixe, immédiatement suivi d'un rappel de pointeur de fonction :```c
typedef struct {
uint8_t fw_header[128]; // buffer the developer reads into
uint32_t crc32;
uint32_t version;
void (*on_apply)(void); // callback - attacker target
} ota_ctx_t;
La démo construit une image disque spécialement conçue où DIR_FileSize = sizeof(ota_ctx_t),
place l'adresse de rce_win() au bon décalage d'octet dans le secteur de charge utile,
puis exécute le vérificateur OTA. f_read écrit au-delà de fw_header dans
on_apply, et l'appel ultérieur ctx.on_apply() invoque rce_win(),
définissant rce_canary = 0xDEAD.
Compiler et exécuter: cd harness && make rce_demo
fuzzer/)Le fuzzer Go a deux modes:
Générateur de corpus (go run . -out ./corpus ou make corpus): écrit 18
images de départ structurées couvrant six classes de bugs, les trois variantes FAT
GPT normal et malformé, et 50 mutations aléatoires d'un octet d'une
image FAT32 valide.
Fuzzer natif Go (go test -fuzz=FuzzFAT32BPB): fuzzing structurel des
valeurs des champs BPB avec le fuzzer intégré de Go; vérifie que les relations
entre les champs restent valides sans appeler le C.
Le corpus de départ alimente à la fois le binaire libFuzzer (build/fuzz_fatfs) et la
cible AFL++ (build/afl_fatfs).
Ce dépôt inclut un cas de test Docker autonome qui démontre un schéma de débordement côté appelant de type CVE-2026-6688, pertinent pour l'ESP32, en utilisant la traversée de répertoires FatFs sur le firmware ESP-IDF dans l'émulateur QEMU ESP32 d'Espressif.
L'image PoC actuelle est intentionnellement hybride:
readdir().strcpy / strcat
assemblage de chemin) et copie le long nom de fichier dans un tampon fixe de 32 octets.Cette copie finale est la condition de type CVE-2026-6688: débordement côté appelant par utilisation illimitée de noms de fichiers longs.``` cd esp32-qemu-test ./run.sh
Ou alternativement :```
docker build -t fatfs-esp32-vuln-test esp32-qemu-test/
docker run --rm fatfs-esp32-vuln-test
f_readdir() peut renvoyer des noms longs (LFN) jusqu'à 255 caractères. De nombreux appelants embarqués réels copient encore ces noms dans des tampons fixes plus petits. Les exemples publics ESP32 incluent des motifs équivalents à :```
strcpy(fn, entry->d_name);
strcat(path, "/");
strcat(path, entry->d_name);
Avec une image FAT spécialement conçue contenant un nom de fichier long, ces copies débordent le tampon de l'appelant.
### Chaîne PoC dans ce dépôt
| Étape | Description | Marqueur |
|------|-------------|--------|
| 1 | L'image de stockage spécialement conçue est montée et renvoie des entrées de répertoire contrôlées par l'attaquant | (le montage réussit) |
| 2 | Le nom de fichier long est copié dans `char name[32]` via un chemin de copie non sécurisé suivant un motif public | `[VULN-BUG7-CONFIRMED]` |
| 3 | La corruption de la variable de garde est journalisée, suivie d'un crash des données de contrôle dans QEMU | `guard=0x61616161`, `Guru Meditation Error` |
Le PoC conserve toujours un chemin hérité d'écrasement du rappel OTA de style CVE-2026-6682
pour le contexte et la sortie du marqueur (`PWNED-UART`), mais la preuve spécifique à ce bug ici
est le marqueur de débordement du tampon de l'appelant pour nom de fichier long ci-dessus.
Sortie représentative:```
I (...) fatfs_vuln: PoC: CVE-2026-6688 long-LFN caller overflow probe (ESP32 public-pattern copy path)
...
PWNED-UART
E (...) fatfs_vuln: [VULN-BUG7-CONFIRMED] guard corrupted after filename copy
E (...) fatfs_vuln: entry='esp32_lfn_trigger_aaaa...aaaa.bin' len=78 guard=0x61616161
Guru Meditation Error: Core 0 panic'ed (...)
Un comportement de soustraction non signée a été précédemment remarqué et signalé au cours de cette recherche, puis retiré du corpus CVE. De ce fait, vous remarquerez un écart de numérotation car nous omettons intentionnellement cet enregistrement retiré de l'ensemble actif de CVE de ce dépôt. Le programme CVE peut être un peu pointilleux concernant les références à des enregistrements non publiés, ce qui évite les problèmes de références croisées tout en préservant l'exactitude de l'historique. Pour les plus curieux, vous pouvez inspecter l'historique git de ce dépôt pour les détails de cette découverte.
Merci à David Brown d'avoir attiré notre attention sur le rapport contesté. Pour l'état en amont et les conseils de correctifs, suivez la page officielle des correctifs FatFs de ChaN : https://elm-chan.org/fsw/ff/patches.html
| Project | Stars | FatFs Version | Bugs |
|---|
| espressif/esp-idf | 17,655 | R0.16 | CVE-2026-6682 |
| STMicroelectronics/stm32-mw-fatfs | tous les STM32Cube | R0.15 w/p2 | CVE-2026-6682, CVE-2026-6683, CVE-2026-6686, CVE-2026-6687 |
| zephyrproject-rtos/zephyr | 14,820 | R0.16 | CVE-2026-6683, CVE-2026-6687, CVE-2026-6688 |
| micropython/micropython | 21,583 | R0.13c (2019) | CVE-2026-6682, CVE-2026-6683, CVE-2026-6684, CVE-2026-6686, CVE-2026-6687 |
| ArduPilot/ardupilot | 14,743 | R0.14b | CVE-2026-6682, CVE-2026-6683, CVE-2026-6686, CVE-2026-6687 |
| RT-Thread/rt-thread | 11,862 | R0.16 | CVE-2026-6683, CVE-2026-6686 |
| nodemcu/nodemcu-firmware | 7,903 | varie | CVE-2026-6688 |
| RIOT-OS/RIOT | 5,701 | R0.15 | CVE-2026-6682, CVE-2026-6683, CVE-2026-6686, CVE-2026-6687 |
| ARMmbed/mbed-os | 4,837 | R0.14b | CVE-2026-6682, CVE-2026-6683, CVE-2026-6686 |
| sbabic/swupdate | 1,780 | R0.16 | CVE-2026-6683 |
| rsta2/circle | 2,222 | à déterminer | CVE-2026-6684 |
| hugen79/NanoVNA-H | 695 | R0.15 | CVE-2026-6683 |
| ChibiOS/ChibiOS | 833 | varie | CVE-2026-6688 |
| Samsung/TizenRT | 643 | R0.16 | CVE-2026-6683, CVE-2026-6688 |
| adafruit/tinyuf2 | 447 | à déterminer | CVE-2026-6684, CVE-2026-6686 |
| grblHAL/Plugin_SD_card | 475 | R0.16 | CVE-2026-6688 |
| JcZou/StarryPilot | 315 | R0.16 | CVE-2026-6688 |
| KeystoneHQ/keystone3-firmware | 199 | R0.16 | CVE-2026-6682 |
| flysight/flysight | 44 | varie | CVE-2026-6682, CVE-2026-6688 |
| eugene-tarassov/vivado-risc-v | 1,061 | à déterminer | CVE-2026-6684 |
| CVE ID | Short Title | CWE |
|---|
| CVE-2026-6682 | Dépassement d'entier lors du montage de volumes FAT32 | CWE-190: Integer Overflow or Wraparound |
| CVE-2026-6683 | Division par zéro dans la synchronisation exFAT | CWE-369: Divide By Zero |
| CVE-2026-6684 | Boucle infinie dans l'analyse des partitions GPT | CWE-835: Loop with Unreachable Exit Condition |
| CVE-2026-6686 | Utilisation de clusters non initialisés après un seek au-delà de l'EOF | CWE-908: Use of Uninitialized Resource |
| CVE-2026-6687 | Débordement de tampon de pile via une longueur de libellé exFAT non plafonnée | CWE-121: Stack-based Buffer Overflow |
| CVE-2026-6688 | Débordement de tampon via une copie de nom de fichier LFN sans limite | CWE-120: Buffer Copy without Checking Size of Input |