
Vulnerabilità di sicurezza documentate nella libreria del filesystem embedded FatFs con dettagli CVE, harness di fuzzing, generatore di immagini disco di exploit e analisi dell'impatto della supply chain su dozzine di progetti firmware a valle.
Questo repository documenta sei vulnerabilità di sicurezza confermate in FatFs insieme a un test harness, un fuzzer e un generatore autonomo di immagini disco per exploit.
Il codice sorgente originale di FatFs può essere trovato nella directory FatFs-R0.16.
Questo progetto rappresenta un ritorno a una valutazione della sicurezza del 2017, quando un audit manuale e uno sforzo di fuzzing durato più giorni identificarono alcuni bug di base, ma non interessanti, nel driver FatFs. Nove anni dopo, nel marzo 2026, abbiamo rivisitato questo progetto usando Visual Studio Code, GitHub Copilot in modalità "auto" e alcuni prompt di base, senza loop, harness o skill specifici. I risultati sono stati sorprendenti: i bug che erano stati trascurati durante l'audit manuale sono diventati banali da trovare, usando l'LLM per costruire automaticamente un fuzzer con input inediti. Questo sforzo non solo ha trovato bug interessanti, ma ha anche automatizzato il processo di validazione della sfruttabilità in diversi scenari di sviluppo embedded.
Consulta i seguenti file per note dettagliate:
FatFs è una libreria filesystem FAT/exFAT portabile e royalty-free scritta in C da ChaN (elm-chan.org). È progettata per sistemi embedded con risorse limitate, senza dipendenza da un sistema operativo e viene tipicamente compilata direttamente nel firmware. Supporta FAT12, FAT16, FAT32 ed exFAT, oltre al supporto opzionale per LFN (Long File Name) e partizioni GPT.
Poiché FatFs è piccolo, autonomo e con licenza permissiva, è diventato
lo standard de facto per l'implementazione FAT nei firmware per microcontrollori.
La libreria viene incorporata integralmente in SDK ufficiali, RTOS, bootloader e
framework applicativi: una singola vulnerabilità upstream si propaga a
ogni progetto a valle che ha copiato ff.c.
I seguenti progetti hanno confermato di includere una versione vulnerabile di FatFs. Consulta 02_CRITICAL.md per l'analisi completa, i percorsi di propagazione per progetto e le informazioni di contatto per la sicurezza.
FatFs non ha una storia di CVE, nessuna mailing list di sicurezza e nessun meccanismo
di notifica delle patch. Ogni progetto a valle che incorpora ff.c deve scoprire, fare triage
e correggere queste vulnerabilità in modo indipendente, di solito senza sapere di essere
coinvolto. Ciò significa che la finestra tra la divulgazione pubblica e la
bonifica diffusa sarà misurata in anni, non in giorni. La superficie d'attacco pratica
non è quindi una singola applicazione o un singolo servizio, ma decine di milioni di
dispositivi in dozzine di codebase indipendenti, molti dei quali non riceveranno mai
una patch.
Lo scenario di sfruttamento archetipico è la scheda SD malvagia: un attaccante con pochi secondi di accesso fisico sostituisce il supporto di archiviazione in un dispositivo, dalle fotocamere consumer ai droni, dalle stampanti 3D a mille altre famiglie di prodotti. Ogni vulnerabilità di questo set è attivabile montando un'immagine FAT manipolata, che quasi sempre avviene automaticamente all'inserimento, senza richiedere alcuna interazione da parte dell'utente. Detto questo, l'accesso fisico non è l'unico percorso.
I dispositivi che acquisiscono pacchetti di aggiornamento formattati FAT da una sorgente di rete, come framework di aggiornamento OTA e aggiornamenti bootloader tramite drag-and-drop, sono sfruttabili da qualsiasi attaccante in grado di consegnare un'immagine dannosa alla pipeline di aggiornamento. Compromissioni della supply chain, un'iniezione AitM su un feed di aggiornamento HTTP in chiaro, o un'immagine dannosa pubblicata su un portale hobbistico di distribuzione firmware. Il percorso OTA è completamente remoto su qualsiasi dispositivo privo di verifica end-to-end autenticata dell'integrità del proprio contenitore di aggiornamento prima di montarlo con FatFs.
CVE-2026-6682 - Overflow di interi che porta a una lunghezza di lettura controllata dall'attaccante
Creando un volume FAT32 con un campo specifico impostato per generare overflow, un attaccante può indurre un dispositivo vittima a leggere un numero di byte scelto dall'attaccante e a sua scelta in un buffer fisso: un percorso diretto verso l'esecuzione di codice. Su target embedded bare-metal l'exploit è deterministico e non richiede heap spray, brute force o leak di informazioni come prerequisito.
L'attaccante deve avere il controllo del volume FAT che il target monterà. Per la maggior parte dei dispositivi ciò significa accesso fisico per sostituire una scheda SD. I dispositivi che accettano aggiornamenti firmware via rete, o che considerano affidabile l'integrità di un pacchetto di aggiornamento solo dopo che FatFs lo ha già analizzato, sono sfruttabili da remoto.
CVE-2026-6683 - Divisione per zero nella sync exFAT
Un attaccante in grado di consegnare un volume exFAT manipolato a un dispositivo che esegue FatFs pre-R0.16 può garantire un crash a qualsiasi successiva scrittura. FatFs R0.16 ha aggiunto una protezione parziale al momento del mount che può rifiutare il volume manipolato prima che avvenga una scrittura, ma il difetto aritmetico sottostante non è completamente corretto. Contro i dispositivi che applicano aggiornamenti firmware OTA scrivendo su un supporto formattato FAT, un trigger riuscito diventa un brick remoto in un colpo solo: il processo di aggiornamento va in crash a metà scrittura e il dispositivo può essere irrecuperabile senza accesso fisico a un debugger hardware.
L'attaccante deve fare in modo che il target monti un volume exFAT da lui controllato e poi esegua qualsiasi operazione di scrittura o sync. Lo scenario della scheda SD malvagia copre la maggior parte dei dispositivi embedded; per lo sfruttamento remoto, la pipeline OTA del target deve accettare e montare un'immagine fornita dall'attaccante senza prima verificarne l'integrità.
CVE-2026-6684 - Loop infinito nella scansione delle partizioni GPT
Consegnare un'immagine disco GPT con un singolo campo impostato al suo valore massimo fa sì che il target entri in un loop leggendo i settori del disco finché non viene tolta l'alimentazione. Contro i bootloader e il firmware bare-metal che girano senza watchdog, questo è un brick permanente: il dispositivo non completa più l'avvio. Questa vulnerabilità è corretta in FatFs R0.16, quindi colpisce solo i dispositivi che includono una release precedente.
L'attaccante deve fare in modo che il target monti un disco formattato GPT da lui controllato, e il target deve eseguire una build FatFs pre-R0.16 con supporto LBA a 64 bit abilitato. Nota che i bootloader sono i target più interessanti proprio perché tendono a non avere watchdog né percorso di recupero.
CVE-2026-6686 - Dati di cluster obsoleti leggibili dopo un seek oltre EOF
Quando un file viene esteso cercando oltre la sua fine, FatFs non azzera la memoria appena allocata. Qualsiasi dato precedentemente scritto in quei settori da un file cancellato è leggibile dal successivo processo che apre il file esteso. Su dispositivi che alternano immagini firmware in un'area di staging OTA, o che condividono una scheda SD tra un bootloader e un'applicazione, ciò può esporre blob firmware precedenti, chiavi o altro contenuto sensibile a un lettore con privilegi ridotti.
L'attaccante ha bisogno di accesso in lettura a un file sul volume FAT del target che è stato esteso tramite un'operazione di seek. Questo è principalmente uno scenario locale o di accesso fisico.
CVE-2026-6687 - Stack overflow tramite etichetta del volume exFAT
Fornire un volume exFAT con un'etichetta sovradimensionata fa sì che FatFs provochi un overflow del buffer
dell'etichetta del chiamante quando l'applicazione chiama f_getlabel(). Il generatore di codice STM32CubeMX di ST
emette la dimensione vulnerabile del buffer in ogni progetto abilitato a FatFs che produce, il che
significa che questa vulnerabilità esiste in una popolazione enorme e in gran parte non catalogata di
firmware STM32 commerciali. Su dispositivi bare-metal Cortex-M senza stack cookies o
ASLR (il caso comune) questa è una primitiva di esecuzione di codice in un colpo solo.
L'attaccante deve fare in modo che il target monti un volume exFAT da lui controllato e poi chiami
f_getlabel(). La libreria FatFs non chiama questo metodo internamente: l'applicazione deve
chiamarlo esplicitamente. La maggior parte dei progetti lo fa come parte della propria inizializzazione al mount,
senza richiedere ulteriori interazioni da parte dell'attaccante in pratica per questi progetti.
CVE-2026-6688 - Buffer overflow tramite nome file LFN lungo nell'elencazione delle directory
Inserendo un file con un nome lungo in una directory FAT, un attaccante può far overflow del buffer che un'applicazione chiamante usa per memorizzare quel nome durante l'iterazione della directory. L'overflow è proporzionale alla lunghezza del nome file, fino a 255 byte. Questa vulnerabilità si trova nel codice chiamante, non in FatFs stesso, quindi l'impatto varia in base al target: ma qualsiasi applicazione che itera una directory e copia i nomi file in un buffer a dimensione fissa senza controllare la lunghezza è vulnerabile.
L'attaccante deve fare in modo che il target attraversi una directory su un volume FAT da lui controllato. Non è richiesto exFAT; funziona su FAT12, FAT16 e FAT32. Il supporto dei nomi file lunghi deve essere abilitato nella configurazione di FatFs, che è l'impostazione predefinita e raccomandata in ogni distribuzione principale.
Sei bug distinti sono stati identificati in FatFs R0.16 e versioni precedenti.
mount_volume() → finfo.fsize controllato dall'attaccantePosizione: ff.c mount_volume() - fasize *= fs->n_fats
Un overflow di moltiplicazione DWORD si verifica quando BPB_FATSz32 viene manipolato per produrre un
valore grande. Con BPB_FATSz32 = 0x80000001 e NumFATs = 2:```c
fasize = 0x80000001;
fasize *= 2; // DWORD overflow → 0x00000002
Il `fasize` troncato fa sì che `fs->database` (l'inizio dell'area dati) ricada
all'interno della regione FAT. Un attaccante che controlla l'immagine del disco
può inserire una falsa voce di directory nel settore sovrapposto, inducendo
`f_stat()` a restituire un `finfo.fsize` controllato dall'attaccante. Qualsiasi
applicazione che poi chiami `f_read(fp, buf, finfo.fsize, &br)` senza limitare
il conteggio rispetto a `sizeof(buf)` causa l'overflow del buffer di destinazione
con byte interamente controllati dall'attaccante - un percorso diretto verso RCE.
**Impatto nel caso peggiore:** Remote code execution (heap o stack overflow) su
qualsiasi dispositivo embedded che legga una dimensione di file da FatFs e la
usi come lunghezza di lettura.
---
### CVE-2026-6683 - Divisione per zero in `sync_fs()` (exFAT)
**Posizione:** `ff.c` `sync_fs()` - `(n_fatent - 2 - free_clst) * 100 / (n_fatent - 2)`
Quando `BPB_NumClusEx = 0`, `n_fatent = 2`, quindi il divisore `(n_fatent - 2) = 0`.
Ci si arriva durante qualsiasi operazione di scrittura o sync su un volume exFAT
creato ad arte, producendo un SIGFPE / hard-fault e facendo crashare il target.
FatFs R0.16 lo protegge parzialmente al momento del mount (la validazione del
bitmap-cluster fallisce quando `NumClusEx = 0`). Le versioni precedenti -
R0.14b (ArduPilot, Mbed OS), R0.15 (RIOT OS, STM32), R0.13c (MicroPython) - non
hanno questa protezione e vanno in crash in modo incondizionato.
**Impatto nel caso peggiore:** Denial of service / crash di sistema su qualsiasi
scrittura verso un volume exFAT creato ad arte. Durante un aggiornamento OTA
questo può rendere inutilizzabile il dispositivo.
---
### CVE-2026-6684 - Ciclo di scansione illimitato delle partizioni GPT in `find_volume()` (pre-R0.16)
**Posizione:** `ff.c` `find_volume()` - `for (i = 0; i < n_ent; i++) disk_read()`
Quando `FF_LBA64 = 1`, `find_volume()` itera su ogni voce di partizione GPT
per cercare una partizione FAT. Nelle build pre-R0.16 il numero di iterazioni
viene preso direttamente dal campo su disco `GPTH_PtNum` (0–0xFFFFFFFF) senza
limite superiore. Un'immagine GPT creata ad arte con `GPTH_PtNum = 0xFFFFFFFF`
causa circa un miliardo di letture dal disco prima che la funzione restituisca
"not found", bloccando il sistema in modo permanente.
R0.16 ha introdotto `test_gpt_header()`, che valida il CRC32 e impone
`PtNum ≤ 128` prima di entrare nel ciclo.
**Impatto nel caso peggiore:** Denial of service permanente al momento del mount.
Su dispositivi senza watchdog (bootloader, bootrom FPGA bare-metal) questo rende
il sistema permanentemente inutilizzabile.
### CVE-2026-6686 - Dati di cluster non inizializzati tramite `f_lseek()` oltre EOF
**Posizione:** `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 ricerca oltre EOF chiama create_chain() per allocare nuovi cluster ma non azzera mai i relativi settori. Qualsiasi lettura successiva della regione estesa restituisce dati grezzi obsoleti - contenuti di file precedentemente eliminati rimasti nel cluster riciclato.
Impatto nel caso peggiore: divulgazione delle informazioni contenute nei file eliminati (vecchie immagini firmware, chiavi private, dati dei sensori) a un lettore con privilegi inferiori o tramite un'interfaccia collegata.
f_getlabel() tramite exFAT XDIR_NumLabelPosizione: 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 specifica exFAT limita `XDIR_NumLabel` a 11 caratteri. FatFs legge
questo come un `BYTE` grezzo (0–255) senza validazione. Un volume appositamente creato con
`XDIR_NumLabel = 128` fa sì che `f_getlabel` scriva 128 caratteri nel
buffer del chiamante - tipicamente `char label[12]` o `char label[24]` come generati
da STM32CubeMX - provocando un overflow dello stack fino a 244 byte.
**Impatto nel caso peggiore:** Overflow del buffer di stack in qualsiasi chiamante di `f_getlabel()` su
un volume exFAT. Il pattern vulnerabile canonico (`char label[12]`) appare
in ogni progetto generato da STM32CubeMX, AN3224 e UM1721.
---
### CVE-2026-6688 - Overflow dello stack/heap del chiamante tramite nome file LFN lungo
**Causa principale:** Con `FF_USE_LFN` abilitato, `f_readdir()` riempie `fno.fname` con
il nome file lungo completo - fino a `FF_LFN_BUF` (255) caratteri. I chiamanti
scritti per il funzionamento solo-SFN usano buffer di percorso o nome a dimensione fissa (es.,
`char path[16]`, `char name[14]`) e copiano `fno.fname` senza controlli dei
limiti.
Pattern vulnerabili comuni trovati in più progetti:```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
Impatto nel caso peggiore: overflow dello stack o dell'heap proporzionale alla lunghezza LFN
(fino a 255 byte) su qualsiasi traversata di directory su un volume FAT appositamente costruito. Una
scheda SD appositamente costruita che provoca un overflow di entry->name[14] di 241 byte corrompe in modo affidabile
il frame dello stack dello scheduler 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
---
## Obiettivi di Build Harness
Tutti gli obiettivi vengono eseguiti dalla directory `harness/`. Richiede `clang` (oppure imposta `CC=gcc`).
Per compilare l'obiettivo `afl` su macOS, usa `brew install afl++` e poi `sudo afl-system-config` per preparare il sistema.
| Obiettivo | Descrizione |
|--------|-------------|
| `make` / `make test` | Compila ed esegui la suite di test deterministica con ASan + UBSan |
| `make rce_demo` | Compila ed esegui la demo RCE CVE-2026-6682 (senza sanitizer, senza stack-protector) |
| `make exploit_disks` | Compila e genera tutte le 14 immagini disco degli exploit in `harness/img/` |
| `make fuzz_asan` | Compila il binario libFuzzer (`build/fuzz_fatfs`) |
| `make afl` | Compila il target AFL++ (richiede `afl-clang-fast` in `PATH`) |
| `make corpus` | Genera il corpus seed tramite il generatore Go in `harness/corpus/` |
| `make clean` | Rimuove `build/` e `img/` |
### Avvio rapido```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 produce 14 immagini disco non formattate in harness/img/, una per
combinazione progetto/vulnerabilità. Ogni immagine viene testata automaticamente al momento
della generazione montandola con il FatFs incluso. Le immagini possono essere scritte su una
scheda SD fisica:```sh
dd if=harness/img/exploit_bug1_espidf.img of=/dev/sdX bs=512
| Immagine | Bug | Progetti target | Effetto |
|-------|-----|------------------|--------|
| `exploit_bug1_fat32.img` | CVE-2026-6682 | Generico | Consegna un payload di dimensioni pari a un puntatore tramite `f_read` |
| `exploit_bug1_espidf.img` | CVE-2026-6682 | espressif/esp-idf | `finfo.fsize=16 MB` → overflow dell'heap in `malloc`/`fread` |
| `exploit_bug1_stm32.img` | CVE-2026-6682 | STMicro stm32-mw-fatfs | `finfo.fsize=1 MB` → overflow del buffer firmware da 1 KB |
| `exploit_bug1_keystone3.img` | CVE-2026-6682 | KeystoneHQ wallet | `finfo.fsize=512 KB` → overflow del buffer OTA |
| `exploit_bug1_ardupilot.img` | CVE-2026-6682 | ArduPilot / Mbed OS / RIOT / MicroPython | `finfo.fsize=2 MB` → overflow del buffer di lettura dei log |
| `exploit_bug2_exfat.img` | CVE-2026-6683 | ArduPilot / Mbed OS / MicroPython / RIOT | `BPB_NumClusEx=0` → divisione per zero in `sync_fs` (SIGFPE nelle versioni pre-R0.16) |
| `exploit_bug3_gpt.img` | CVE-2026-6684 | vivado-risc-v / tinyuf2 / circle | `GPTH_PtNum=0xFFFFFFFF` → ciclo infinito all'avvio (pre-R0.16) |
| `exploit_bug5_stale.img` | CVE-2026-6686 | RT-Thread / tinyuf2 / ArduPilot / RIOT | l'estensione di `f_lseek` espone dati di cluster eliminati pre-inizializzati con `0xAA` |
| `exploit_bug6_stm32.img` | CVE-2026-6687 | STMicro stm32-mw-fatfs | `XDIR_NumLabel=128` → overflow di 117 byte del buffer `label[12]` di CubeMX |
| `exploit_bug6_zephyr.img` | CVE-2026-6687 | Zephyr / ArduPilot / RIOT / MicroPython | `XDIR_NumLabel=255` → overflow di 216 byte del buffer `label[24]` |
| `exploit_bug7_max255.img` | CVE-2026-6688 | NodeMCU / ChibiOS / StarryPilot / TizenRT | un LFN di 255 caratteri causa overflow di qualsiasi buffer fisso < 255 byte |
| `exploit_bug7_zephyr.img` | CVE-2026-6688 | Zephyr | LFN di 14 caratteri → overflow di 1 byte NUL in `entry->name[14]` |
| `exploit_bug7_grblhal.img` | CVE-2026-6688 | grblHAL | Off-by-one: la guardia verifica la voce precedente; un LFN di 11 caratteri causa overflow di `dirent.name[12]` di 1 byte NUL |
---
## Suite di test deterministica (`test_harness.c`)
L'harness di test esercita sei bug con immagini disco realizzate a mano e costruite
in memoria, quindi conferma che il percorso di codice vulnerabile è stato raggiunto:
- **CVE-2026-6682** - costruisce un'immagine FAT32 con `BPB_FATSz32=0x80000001`, la monta e
conferma che `fs.database` rientra nella regione FAT; quindi esegue l'intera
catena RCE (voce di directory fittizia → `f_read` di un puntatore a funzione piazzato →
`rce_proof_of_execution()` chiamata).
- **CVE-2026-6683** - documenta il divisore `(n_fatent-2)` e conferma il
percorso aritmetico; verifica che la R0.16 rifiuti l'immagine al momento del mount.
- **CVE-2026-6684** - costruisce un'immagine GPT con `GPTH_PtNum=0xFFFFFFFF` e conferma che
la R0.16 la rifiuta entro ≤ 3 letture del disco tramite `test_gpt_header()`.
- **CVE-2026-6686** - pre-inizializza tutti i cluster dati con `0xAA`, scrive un file breve,
lo estende tramite `f_lseek` e rilegge per confermare che i byte residui siano visibili.
- **CVE-2026-6687** - costruisce un'immagine exFAT con `XDIR_NumLabel=128`, chiama
`f_getlabel` con un buffer di prova e conta l'overflow oltre il byte 24.
- **CVE-2026-6688** - costruisce una directory FAT16 con un LFN di 50 caratteri, la legge tramite
`f_readdir` e conferma che la lunghezza di `fno.fname` superi i buffer tipici del chiamante.
---
## Demo RCE della CVE-2026-6682 (`rce_demo.c`)
Una dimostrazione autonoma e realistica della catena di sfruttamento della CVE-2026-6682
modellata su codice di aggiornamento firmware OTA embedded. Una struct viene dichiarata con un
buffer di intestazione a dimensione fissa seguito immediatamente da un callback puntatore a funzione:```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 demo crea un'immagine del disco appositamente costruita dove DIR_FileSize = sizeof(ota_ctx_t),
posiziona l'indirizzo di rce_win() all'offset byte corretto nel settore del payload,
quindi esegue il controllo OTA. f_read scrive oltre fw_header in
on_apply, e la successiva chiamata a ctx.on_apply() invoca rce_win(),
impostando rce_canary = 0xDEAD.
Compila ed esegui: cd harness && make rce_demo
fuzzer/)Il fuzzer Go ha due modalità:
Generatore di corpus (go run . -out ./corpus o make corpus): scrive 18
immagini seed strutturate che coprono sei classi di bug, tutte e tre le varianti FAT,
GPT normale e malformato, e 50 mutazioni casuali a singolo byte di un'immagine
FAT32 valida.
Fuzzer nativo Go (go test -fuzz=FuzzFAT32BPB): fuzzing strutturale dei
valori dei campi BPB con il fuzzer integrato di Go; verifica che le relazioni
tra i campi rimangano valide senza chiamare codice C.
Il corpus seed alimenta sia il binario libFuzzer (build/fuzz_fatfs) che il target AFL++ (build/afl_fatfs).
Questo repository include un caso di test Docker autocontenuto che dimostra un pattern di overflow del chiamante relativo alla CVE-2026-6688 su ESP32, utilizzando il directory traversal di FatFs sul firmware ESP-IDF all'interno dell'emulatore QEMU ESP32 di Espressif.
L'immagine PoC attuale è volutamente ibrida:
readdir().strcpy / strcat
per l'assemblaggio del percorso) e copia il nome file lungo in un buffer fisso di 32 byte.Quella copia finale è la condizione in stile CVE-2026-6688: overflow lato chiamante tramite uso senza limiti di nomi file lunghi.``` cd esp32-qemu-test ./run.sh
Oppure, in alternativa:```
docker build -t fatfs-esp32-vuln-test esp32-qemu-test/
docker run --rm fatfs-esp32-vuln-test
f_readdir() può restituire nomi lunghi (LFN) fino a 255 caratteri. Molti chiamanti embedded reali copiano ancora i nomi in buffer fissi più piccoli. Gli esempi ESP32 pubblici includono pattern equivalenti a:```
strcpy(fn, entry->d_name);
strcat(path, "/");
strcat(path, entry->d_name);
Con un'immagine FAT appositamente costruita contenente un nome file lungo, queste copie provocano un overflow del buffer del chiamante.
### Catena di PoC in questo repository
| Passo | Descrizione | Marker |
|------|-------------|--------|
| 1 | L'immagine di archiviazione appositamente costruita viene montata e restituisce voci di directory controllate dall'attaccante | (montaggio riuscito) |
| 2 | Il nome file lungo viene copiato in `char name[32]` tramite un percorso di copia non sicuro a schema pubblico | `[VULN-BUG7-CONFIRMED]` |
| 3 | Viene registrata la corruzione della guardia, seguita da un crash dei dati di controllo in QEMU | `guard=0x61616161`, `Guru Meditation Error` |
La PoC conserva ancora un percorso legacy di sovrascrittura della callback OTA in stile CVE-2026-6682, per contesto e output del marcatore (`PWNED-UART`), ma la prova specifica del bug qui è il marcatore di overflow del chiamante per nome file lungo mostrato sopra.
Output rappresentativo:```
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 comportamento di sottrazione senza segno è stato precedentemente notato e segnalato durante questa
ricerca, per poi essere rimosso dal corpus CVE. Per questo motivo, noterai
un vuoto nella numerazione perché omettiamo intenzionalmente quel record ritirato
dal set CVE attivo di questo repository. Il programma CVE può essere un po'
particolare riguardo ai riferimenti a record non pubblicati, quindi questo evita
drammi di collegamenti incrociati mantenendo accurata la storia. Per i molto curiosi,
puoi ispezionare la storia git di questo repo per i dettagli su quel risultato.
Grazie a David Brown per aver portato la nostra attenzione sul report contestato. Per lo stato upstream e le indicazioni sulle patch, segui la pagina ufficiale delle patch FatFs di ChaN: https://elm-chan.org/fsw/ff/patches.html
| Progetto | Stelle | Versione FatFs | Bug |
|---|
| espressif/esp-idf | 17,655 | R0.16 | CVE-2026-6682 |
| STMicroelectronics/stm32-mw-fatfs | tutti gli 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 | varia | 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 | da determinare | CVE-2026-6684 |
| hugen79/NanoVNA-H | 695 | R0.15 | CVE-2026-6683 |
| ChibiOS/ChibiOS | 833 | varia | CVE-2026-6688 |
| Samsung/TizenRT | 643 | R0.16 | CVE-2026-6683, CVE-2026-6688 |
| adafruit/tinyuf2 | 447 | da determinare | 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 | varia | CVE-2026-6682, CVE-2026-6688 |
| eugene-tarassov/vivado-risc-v | 1,061 | da determinare | CVE-2026-6684 |
| ID CVE | Titolo breve | CWE |
|---|
| CVE-2026-6682 | Overflow di interi nel mount di volumi FAT32 | CWE-190: Overflow di interi o wraparound |
| CVE-2026-6683 | Divisione per zero nella sync exFAT | CWE-369: Divisione per zero |
| CVE-2026-6684 | Loop infinito nella scansione delle partizioni GPT | CWE-835: Ciclo con condizione di uscita irraggiungibile |
| CVE-2026-6686 | Uso di cluster non inizializzati dopo un seek oltre EOF | CWE-908: Uso di risorsa non inizializzata |
| CVE-2026-6687 | Stack buffer overflow tramite lunghezza senza limiti dell'etichetta exFAT | CWE-121: Buffer overflow basato su stack |
| CVE-2026-6688 | Buffer overflow tramite copia senza limiti del nome file LFN | CWE-120: Copia di buffer senza controllo della dimensione dell'input |