
Dieses Repository dokumentiert sechs bestätigte Sicherheitslücken in FatFs zusammen mit einer Test-Harness, einem Fuzzer und einem eigenständigen Generator für Exploit-Disk-Images.
Der ursprüngliche FatFs-Quellcode befindet sich im Verzeichnis FatFs-R0.16.
Dieses Projekt ist eine Rückkehr zu einer Sicherheitsbewertung aus dem Jahr 2017, als eine manuelle Prüfung und ein mehrtägiger Fuzzing-Einsatz einige grundlegende, aber nicht interessante Fehler im FatFs-Treiber identifizierten. Neun Jahre später, im März 2026, haben wir dieses Projekt mit Visual Studio Code, GitHub Copilot im „Auto“-Modus und einigen grundlegenden Prompts erneut aufgegriffen, ohne spezielle Schleifen, Harnesses oder Skills. Die Ergebnisse waren überraschend – Fehler, die bei der manuellen Prüfung übersehen wurden, waren trivial zu finden, indem das LLM automatisch einen Fuzzer mit neuartigen Eingaben erstellte. Diese Bemühung fand nicht nur interessante Fehler, sie automatisierte auch den Prozess der Validierung der Ausnutzbarkeit in verschiedenen eingebetteten Entwicklungsszenarien.
Ausführliche Anmerkungen finden Sie in den folgenden Dateien:
FatFs ist eine portable, lizenzkostenfreie FAT/exFAT-Dateisystembibliothek, geschrieben in C von ChaN (elm-chan.org). Sie ist für ressourcenbeschränkte eingebettete Systeme ohne Betriebssystemabhängigkeit ausgelegt und wird typischerweise direkt in die Firmware einkompiliert. Sie unterstützt FAT12, FAT16, FAT32 und exFAT sowie optionalen LFN- (Long File Name) und GPT-Partitionssupport.
Da FatFs klein, in sich geschlossen und unter einer freizügigen Lizenz verfügbar ist,
ist es zum De-facto-Standard für FAT-Implementierungen in Mikrocontroller-Firmware geworden.
Die Bibliothek wird unverändert in offizielle SDKs, RTOSes, Bootloader und
Anwendungsframeworks eingebunden – das bedeutet, dass eine einzige Upstream-Schwachstelle sich auf
jedes Downstream-Projekt ausbreitet, das ff.c kopiert hat.
Die folgenden Projekte wurden als Bündler einer verwundbaren Version von FatFs bestätigt. Die vollständige Analyse, projektspezifische Ausbreitungspfade und Sicherheitskontaktinformationen finden Sie unter 02_CRITICAL.md.
FatFs hat keine CVE-Historie, keine Sicherheits-Mailingliste und keinen Patch-Benachrichtigungsmechanismus.
Jedes Downstream-Projekt, das ff.c einbindet, muss diese Schwachstellen unabhängig entdecken, priorisieren
und patchen – normalerweise ohne zu wissen, dass es betroffen ist. Das bedeutet, dass das Fenster zwischen
öffentlicher Offenlegung und weit verbreiteter Behebung in Jahren gemessen wird, nicht in Tagen.
Die praktische Angriffsfläche ist daher nicht eine Softwareanwendung oder ein Dienst, sondern zig Millionen
von Geräten in Dutzenden unabhängiger Codebasen, von denen viele nie einen Patch erhalten werden.
Das archetypische Ausnutzungsszenario ist die böse SD-Karte: Ein Angreifer mit ein paar Sekunden physischem Zugriff tauscht das Speichermedium in einem Gerät aus – von Verbraucherkameras über Drohnen bis zu 3-D-Druckern und tausend anderen Produktfamilien. Jede Schwachstelle in dieser Sammlung ist durch das Mounten eines präparierten FAT-Images auslösbar, was bei fast allen Geräten automatisch beim Einstecken geschieht, ohne dass eine Benutzerinteraktion erforderlich ist. Das heißt, physischer Zugriff ist nicht der einzige Weg.
Geräte, die FAT-formatierte Update-Pakete aus einer Netzwerkquelle aufnehmen, wie etwa OTA-Update-Frameworks und Drag-and-Drop-Bootloader-Updates, sind für jeden Angreifer ausnutzbar, der ein bösartiges Image in die Update-Pipeline einschleusen kann. Supply-Chain-Kompromittierungen, eine AitM-Injektion in einen unverschlüsselten HTTP-Update-Feed oder ein bösartiges Image, das auf einem Hobby-Firmware-Verteilungsportal veröffentlicht wird. Der OTA-Pfad ist vollständig remote auf jedem Gerät, dem eine Ende-zu-Ende-authentifizierte Integritätsprüfung des Update-Containers vor dem Mounten mit FatFs fehlt.
CVE-2026-6682 – Integer-Überlauf, der zu einer vom Angreifer kontrollierten Leselänge führt
Durch das Präparieren eines FAT32-Volumes mit einem bestimmten Feld, das zum Überlauf gebracht wird, kann ein Angreifer dazu führen, dass ein Opfergerät eine vom Angreifer gewählte Anzahl vom Angreifer gewählter Bytes in einen festen Puffer liest – ein direkter Weg zur Codeausführung. Auf Bare-Metal-Eingebetteten Zielen ist der Exploit deterministisch und erfordert weder Heap-Spray, Brute-Force noch einen Informationsleck als Voraussetzung.
Der Angreifer benötigt Kontrolle über das FAT-Volume, das das Ziel mounten wird. Für die meisten Geräte bedeutet das physischen Zugriff zum Austauschen einer SD-Karte. Geräte, die Firmware-Updates über ein Netzwerk akzeptieren oder die der Integrität eines Update-Pakets erst vertrauen, nachdem FatFs es bereits geparst hat, sind remote ausnutzbar.
CVE-2026-6683 – Division durch Null bei exFAT-Sync
Ein Angreifer, der ein präpariertes exFAT-Volume an ein Gerät mit FatFs vor R0.16 liefern kann, kann bei jedem anschließenden Schreibvorgang einen Absturz garantieren. FatFs R0.16 fügte eine partielle Schutzprüfung beim Mounten hinzu, die das präparierte Volume möglicherweise ablehnt, bevor ein Schreibvorgang erfolgt, aber der zugrunde liegende Arithmetikfehler ist nicht vollständig behoben. Bei Geräten, die OTA-Firmware-Updates durch Schreiben auf ein FAT-formatiertes Medium anwenden, wird ein erfolgreicher Auslöser zu einem einmaligen Remote- Ziegelstein: Der Update-Prozess stürzt mitten im Schreibvorgang ab und das Gerät ist möglicherweise ohne physischen Zugriff auf einen Hardware-Debugger nicht wiederherstellbar.
Der Angreifer benötigt, dass das Ziel ein exFAT-Volume mountet, das er kontrolliert, und dann eine beliebige Schreib- oder Sync-Operation durchführt. Das Szenario der bösen SD-Karte deckt die meisten eingebetteten Geräte ab; für Remote-Ausnutzung muss die OTA-Pipeline des Ziels ein vom Angreifer geliefertes Image akzeptieren und mounten, ohne zuerst dessen Integrität zu verifizieren.
CVE-2026-6684 – Endlosschleife im GPT-Partitionsscan
Die Lieferung eines GPT-Disk-Images mit einem einzigen Feld, das auf seinen Maximalwert gesetzt ist, führt dazu, dass das Ziel beim Lesen von Datenträgersektoren in einer Schleife verharrt, bis die Stromversorgung unterbrochen wird. Bei Bootloadern und Bare-Metal-Firmware, die ohne Watchdog laufen, ist dies ein permanenter Ziegelstein: Das Gerät startet nie wieder vollständig. Diese Schwachstelle ist in FatFs R0.16 behoben, betrifft also nur Geräte, die eine ältere Version einbinden.
Der Angreifer benötigt, dass das Ziel eine GPT-formatierte Festplatte mountet, die er kontrolliert, und das Ziel muss einen FatFs-Build vor R0.16 mit aktivierter 64-Bit-LBA-Unterstützung ausführen. Beachten Sie, dass Bootloader hier die attraktivsten Ziele sind, gerade weil sie tendenziell keinen Watchdog und keinen Wiederherstellungspfad haben.
CVE-2026-6686 – Veraltete Clusterdaten nach Seek über EOF hinaus lesbar
Wenn eine Datei durch Suchen über ihr Ende hinaus erweitert wird, setzt FatFs den neu zugewiesenen Speicher nicht auf Null. Alle Daten, die zuvor von einer gelöschten Datei in diese Sektoren geschrieben wurden, sind für den nächsten Prozess lesbar, der die erweiterte Datei öffnet. Bei Geräten, die Firmware-Images in einem OTA-Bereich durchlaufen oder die eine SD-Karte zwischen einem Bootloader und einer Anwendung teilen, kann dies frühere Firmware-Binärdateien, Schlüssel oder andere sensible Inhalte einem weniger privilegierten Leser zugänglich machen.
Der Angreifer benötigt Lesezugriff auf eine Datei auf dem FAT-Volume des Ziels, die über eine Seek-Operation erweitert wurde. Dies ist in erster Linie ein lokales oder physisches Zugriffsszenario.
CVE-2026-6687 – Stack-Überlauf über exFAT-Volume-Label
Die Lieferung eines exFAT-Volumes mit einem übermäßig großen Label führt dazu, dass FatFs den Label-Puffer des Aufrufers
überläuft, wenn die Anwendung f_getlabel() aufruft. Der STM32CubeMX-Codegenerator von ST
gibt die verwundbare Puffergröße in jedem FatFs-fähigen Projekt aus, das er erzeugt, was
bedeutet, dass diese Schwachstelle in einer enormen und weitgehend nicht katalogisierten Population von
kommerzieller STM32-Firmware existiert. Auf Bare-Metal-Cortex-M-Geräten ohne Stack-Cookies oder
ASLR (der übliche Fall) ist dies eine einmalige Codeausführungs-Primitive.
Der Angreifer benötigt, dass das Ziel ein exFAT-Volume mountet, das er kontrolliert, und dann
f_getlabel() aufruft. Die FatFs-Bibliothek ruft dies nicht intern auf – die Anwendung muss
es explizit aufrufen. Die meisten Projekte tun dies als Teil ihrer eigenen Mount-Zeit-Initialisierung,
was in der Praxis für diese Projekte keine weitere Angreiferinteraktion erfordert.
CVE-2026-6688 – Pufferüberlauf über langen LFN-Dateinamen in der Verzeichnisauflistung
Durch das Platzieren einer Datei mit einem langen Namen in einem FAT-Verzeichnis kann ein Angreifer den Puffer überlaufen lassen, den eine aufrufende Anwendung zum Speichern dieses Namens verwendet, während sie das Verzeichnis durchläuft. Der Überlauf ist proportional zur Dateinamenlänge, bis zu 255 Bytes. Diese Schwachstelle befindet sich im aufrufenden Code, nicht in FatFs selbst, daher variiert die Auswirkung je nach Ziel – aber jede Anwendung, die ein Verzeichnis durchläuft und Dateinamen ohne Längenprüfung in einen Puffer fester Größe kopiert, ist betroffen.
Der Angreifer benötigt, dass das Ziel ein Verzeichnis auf einem FAT-Volume durchläuft, das er kontrolliert. Kein exFAT erforderlich; dies funktioniert auf FAT12, FAT16 und FAT32. Die Unterstützung für lange Dateinamen muss in der FatFs-Konfiguration aktiviert sein, was in jeder großen Distribution die Standard- und empfohlene Einstellung ist.
Sechs verschiedene Fehler wurden in FatFs R0.16 und früheren Versionen identifiziert.
mount_volume() → vom Angreifer kontrolliertes finfo.fsizeOrt: ff.c mount_volume() - fasize *= fs->n_fats
Ein DWORD-Multiplikationsüberlauf tritt auf, wenn BPB_FATSz32 so präpariert ist, dass es einen
großen Wert erzeugt. Mit BPB_FATSz32 = 0x80000001 und NumFATs = 2:```c
fasize = 0x80000001;
fasize *= 2; // DWORD overflow → 0x00000002
Das abgeschnittene `fasize` führt dazu, dass `fs->database` (der Beginn des Datenbereichs) in die FAT-Region
landet. Ein Angreifer, der das Plattenimage kontrolliert, kann am überlappenden Sektor
einen gefälschten Verzeichniseintrag platzieren, sodass `f_stat()` eine
vom Angreifer kontrollierte `finfo.fsize` zurückgibt. Jede Anwendung, die dann
`f_read(fp, buf, finfo.fsize, &br)` aufruft, ohne die Anzahl gegen
`sizeof(buf)` zu begrenzen, lässt den Zielpuffer mit vollständig vom Angreifer kontrollierten
Bytes überlaufen - ein direkter Weg zu RCE.
**Auswirkung im schlimmsten Fall:** Remote-Codeausführung (Heap- oder Stack-Überlauf) auf jedem
eingebetteten Gerät, das eine Dateigröße von FatFs liest und sie als Leselänge verwendet.
---
### CVE-2026-6683 - Division durch Null in `sync_fs()` (exFAT)
**Fundstelle:** `ff.c` `sync_fs()` - `(n_fatent - 2 - free_clst) * 100 / (n_fatent - 2)`
Wenn `BPB_NumClusEx = 0` ist, gilt `n_fatent = 2`, wodurch der Divisor `(n_fatent - 2) = 0` wird.
Dies wird bei jedem Schreib- oder Synchronisierungsvorgang auf einem manipulierten exFAT-Volume erreicht,
was einen SIGFPE / hard-fault erzeugt und das Ziel zum Absturz bringt.
FatFs R0.16 schützt teilweise dagegen beim Mounten (die Bitmap-Cluster-Validierung
schlägt fehl, wenn `NumClusEx = 0` ist). Ältere Versionen - R0.14b (ArduPilot,
Mbed OS), R0.15 (RIOT OS, STM32), R0.13c (MicroPython) - haben keinen solchen Schutz
und stürzen bedingungslos ab.
**Auswirkung im schlimmsten Fall:** Denial of Service / Systemabsturz bei jedem Schreibvorgang auf ein
manipuliertes exFAT-Volume. Während eines OTA-Updates kann dies das Gerät bricken.
---
### CVE-2026-6684 - Unbegrenzte GPT-Partitions-Scanschleife in `find_volume()` (vor R0.16)
**Fundstelle:** `ff.c` `find_volume()` - `for (i = 0; i < n_ent; i++) disk_read()`
Wenn `FF_LBA64 = 1` ist, iteriert `find_volume()` über jeden GPT-Partitionseintrag,
um eine FAT-Partition zu suchen. In Builds vor R0.16 wird die Schleifenanzahl
direkt aus dem Feld `GPTH_PtNum` auf dem Datenträger (0–0xFFFFFFFF) ohne Obergrenze
übernommen. Ein manipuliertes GPT-Image mit `GPTH_PtNum = 0xFFFFFFFF` verursacht ungefähr
eine Milliarde Datenträger-Lesezugriffe, bevor die Funktion "nicht gefunden" zurückgibt, was das
System dauerhaft aufhängt.
R0.16 führte `test_gpt_header()` ein, das die CRC32 validiert und
vor dem Eintreten in die Schleife `PtNum ≤ 128` erzwingt.
**Auswirkung im schlimmsten Fall:** Dauerhafter Denial of Service beim Mounten. Auf Geräten
ohne Watchdog (Bootloader, Bare-Metal-FPGA-Bootrom) macht dies das System
dauerhaft unbrauchbar.
### CVE-2026-6686 - Nicht initialisierte Clusterdaten durch `f_lseek()` über EOF hinaus
**Fundstelle:** `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;
}
Beim Seek über den EOF hinaus wird create_chain() aufgerufen, um neue Cluster zuzuweisen, deren Sektoren jedoch nie genullt werden. Jedes anschließende Lesen des erweiterten Bereichs liefert rohe Altdaten - Inhalte zuvor gelöschter Dateien, die im wiederverwendeten Cluster verbleiben.
Auswirkung im schlimmsten Fall: Informationsoffenlegung des Inhalts gelöschter Dateien (alte Firmware-Images, private Schlüssel, Sensordaten) gegenüber einem weniger privilegierten Leser oder über eine angeschlossene Schnittstelle.
f_getlabel() über exFAT XDIR_NumLabelFundort: 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;
}
Die exFAT-Spezifikation begrenzt `XDIR_NumLabel` auf 11 Zeichen. FatFs liest
dieses als rohes `BYTE` (0–255) ohne Validierung. Ein manipuliertes Volume mit
`XDIR_NumLabel = 128` bewirkt, dass `f_getlabel` 128 Zeichen in den
Puffer des Aufrufers schreibt – typischerweise `char label[12]` oder `char label[24]`, wie von
STM32CubeMX generiert – und den Stack um bis zu 244 Bytes überläuft.
**Auswirkung im schlimmsten Fall:** Stack-Pufferüberlauf in jedem Aufrufer von `f_getlabel()` auf
einem exFAT-Volume. Das kanonische verwundbare Muster (`char label[12]`) ist
in jedem Projekt vorhanden, das von STM32CubeMX, AN3224 und UM1721 generiert wird.
---
### CVE-2026-6688 – Stack-/Heap-Überlauf beim Aufrufer durch langen LFN-Dateinamen
**Grundursache:** Wenn `FF_USE_LFN` aktiviert ist, füllt `f_readdir()` `fno.fname` mit
dem vollständigen Langen Dateinamen – bis zu `FF_LFN_BUF` (255) Zeichen. Aufrufer,
die für den SFN-Betrieb geschrieben wurden, verwenden Pfad- oder Namenspuffer fester Größe (z. B.
`char path[16]`, `char name[14]`) und kopieren `fno.fname` ohne Grenzüberprüfung.
Häufige verwundbare Muster, die in mehreren Projekten gefunden wurden:```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
Worst-Case-Auswirkung: Stack- oder Heap-Überlauf proportional zur LFN-Länge (bis zu 255 Bytes) bei jeder Verzeichnis-Traversierung auf einem präparierten FAT-Volume. Eine präparierte SD-Karte, die entry->name[14] um 241 Bytes überläuft, korrumpiert zuverlässig den Stack-Frame des Zephyr-Schedulers.
├── 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
---
## Harness-Build-Ziele
Alle Ziele werden aus dem Verzeichnis `harness/` ausgeführt. Erfordert `clang` (oder setzen Sie `CC=gcc`).
Um das `afl`-Ziel unter macOS zu bauen, verwenden Sie `brew install afl++` und dann `sudo afl-system-config`, um Ihr System vorzubereiten.
| Ziel | Beschreibung |
|--------|-------------|
| `make` / `make test` | Das deterministische Testpaket mit ASan + UBSan bauen und ausführen |
| `make rce_demo` | Die CVE-2026-6682-RCE-Demo bauen und ausführen (ohne Sanitizer, ohne Stack-Protector) |
| `make exploit_disks` | Alle 14 Exploit-Disk-Images bauen und in `harness/img/` erzeugen |
| `make fuzz_asan` | Die libFuzzer-Binärdatei bauen (`build/fuzz_fatfs`) |
| `make afl` | Das AFL++-Ziel bauen (erfordert `afl-clang-fast` im `PATH`) |
| `make corpus` | Seed-Korpus mit dem Go-Generator in `harness/corpus/` erzeugen |
| `make clean` | `build/` und `img/` entfernen |
### Schnellstart```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 erzeugt 14 rohe Datenträgerabbilder in harness/img/, eines pro Projekt/Schwachstellen-Kombination. Jedes Abbild wird zum Erzeugungszeitpunkt selbst getestet, indem es mit dem gebündelten FatFs eingehängt wird. Die Abbilder können auf eine physische SD-Karte geschrieben werden:```sh
dd if=harness/img/exploit_bug1_espidf.img of=/dev/sdX bs=512
| Image | Bug | Zielprojekt(e) | Auswirkung |
|-------|-----|------------------|--------|
| `exploit_bug1_fat32.img` | CVE-2026-6682 | Generisch | Liefert eine Nutzlast in Zeigergröße über `f_read` |
| `exploit_bug1_espidf.img` | CVE-2026-6682 | espressif/esp-idf | `finfo.fsize=16 MB` → `malloc`/`fread`-Heap-Überlauf |
| `exploit_bug1_stm32.img` | CVE-2026-6682 | STMicro stm32-mw-fatfs | `finfo.fsize=1 MB` → Überlauf des 1-KB-Firmware-Puffers |
| `exploit_bug1_keystone3.img` | CVE-2026-6682 | KeystoneHQ wallet | `finfo.fsize=512 KB` → OTA-Pufferüberlauf |
| `exploit_bug1_ardupilot.img` | CVE-2026-6682 | ArduPilot / Mbed OS / RIOT / MicroPython | `finfo.fsize=2 MB` → Pufferüberlauf beim Lesen von Logs |
| `exploit_bug2_exfat.img` | CVE-2026-6683 | ArduPilot / Mbed OS / MicroPython / RIOT | `BPB_NumClusEx=0` → Division durch Null in `sync_fs` (SIGFPE vor R0.16) |
| `exploit_bug3_gpt.img` | CVE-2026-6684 | vivado-risc-v / tinyuf2 / circle | `GPTH_PtNum=0xFFFFFFFF` → Endlosschleife beim Booten (vor R0.16) |
| `exploit_bug5_stale.img` | CVE-2026-6686 | RT-Thread / tinyuf2 / ArduPilot / RIOT | `f_lseek`-Erweiterung legt mit `0xAA` vorbefüllte Daten gelöschter Cluster offen |
| `exploit_bug6_stm32.img` | CVE-2026-6687 | STMicro stm32-mw-fatfs | `XDIR_NumLabel=128` → 117-Byte-Überlauf von CubeMX `label[12]` |
| `exploit_bug6_zephyr.img` | CVE-2026-6687 | Zephyr / ArduPilot / RIOT / MicroPython | `XDIR_NumLabel=255` → 216-Byte-Überlauf von `label[24]` |
| `exploit_bug7_max255.img` | CVE-2026-6688 | NodeMCU / ChibiOS / StarryPilot / TizenRT | 255-Zeichen-LFN überläuft jeden festen Puffer < 255 Bytes |
| `exploit_bug7_zephyr.img` | CVE-2026-6688 | Zephyr | 14-Zeichen-LFN → 1-Byte-NUL-Überlauf von `entry->name[14]` |
| `exploit_bug7_grblhal.img` | CVE-2026-6688 | grblHAL | Off-by-one: Guard prüft den vorherigen Eintrag; 11-Zeichen-LFN überläuft `dirent.name[12]` um 1 NUL-Byte |
---
## Deterministische Testsuite (`test_harness.c`)
Die Testsuite übt sechs Bugs mit handgefertigten, im Speicher erstellten Disk-Images aus und bestätigt anschließend, dass der verwundbare Codepfad erreicht wurde:
- **CVE-2026-6682** - erstellt ein FAT32-Image mit `BPB_FATSz32=0x80000001`, mountet es und bestätigt, dass `fs.database` innerhalb der FAT-Region liegt; anschließend führt es die vollständige RCE-Kette aus (gefälschter Verzeichniseintrag → `f_read` des eingepflanzten Funktionszeigers → `rce_proof_of_execution()` wird aufgerufen).
- **CVE-2026-6683** - dokumentiert den Divisor `(n_fatent-2)` und bestätigt den arithmetischen Pfad; prüft, dass R0.16 das Image beim Mounten ablehnt.
- **CVE-2026-6684** - erstellt ein GPT-Image mit `GPTH_PtNum=0xFFFFFFFF` und bestätigt, dass R0.16 es innerhalb von ≤ 3 Platten-Lesezugriffen über `test_gpt_header()` ablehnt.
- **CVE-2026-6686** - vorbefüllt alle Datencluster mit `0xAA`, schreibt eine kurze Datei, erweitert sie über `f_lseek` und liest sie zurück, um zu bestätigen, dass veraltete Bytes sichtbar sind.
- **CVE-2026-6687** - erstellt ein exFAT-Image mit `XDIR_NumLabel=128`, ruft `f_getlabel` mit einem Sondenpuffer auf und zählt den Überlauf über Byte 24 hinaus.
- **CVE-2026-6688** - konstruiert ein FAT16-Verzeichnis mit einem LFN aus 50 Zeichen, liest es über `f_readdir` und bestätigt, dass die Länge von `fno.fname` typische Puffer von Aufrufern überschreitet.
---
## CVE-2026-6682 RCE-Demo (`rce_demo.c`)
Eine eigenständige, realistische Demonstration der CVE-2026-6682-Exploit-Kette, die an eingebetteten OTA-Firmware-Update-Code angelehnt ist. Es wird eine Struktur deklariert, bei der auf einen Header-Puffer fester Größe unmittelbar ein Funktionszeiger-Callback folgt:```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;
Das Demo erstellt ein präpariertes Festplatten-Image, bei dem DIR_FileSize = sizeof(ota_ctx_t) gesetzt ist,
platziert die Adresse von rce_win() am korrekten Byte-Offset im Payload-Sektor
und führt dann die OTA-Prüfung aus. f_read schreibt über fw_header hinaus in
on_apply, und der anschließende Aufruf ctx.on_apply() ruft rce_win() auf,
wobei rce_canary = 0xDEAD gesetzt wird.
Erstellen und ausführen: cd harness && make rce_demo
fuzzer/)Der Go-Fuzzer hat zwei Modi:
Korpus-Generator (go run . -out ./corpus oder make corpus): schreibt 18
strukturierte Seed-Images, die sechs Bug-Klassen, alle drei FAT-Varianten,
normales und fehlerhaftes GPT sowie 50 zufällige Einzelbyte-Mutationen eines
gültigen FAT32-Images abdecken.
Nativer Go-Fuzzer (go test -fuzz=FuzzFAT32BPB): strukturelles Fuzzing der
BPB-Feldwerte mit dem integrierten Go-Fuzzer; validiert, dass die
Feldbeziehungen gelten, ohne C-Code aufzurufen.
Der Seed-Korpus speist sowohl das libFuzzer-Binary (build/fuzz_fatfs) als auch
das AFL++-Target (build/afl_fatfs).
Dieses Repository enthält einen eigenständigen Docker-Testfall, der ein ESP32-relevantes CVE-2026-6688-Caller-Overflow-Muster mithilfe von FatFs-Verzeichnis- Traversierung in der ESP-IDF-Firmware im Espressif-QEMU-ESP32-Emulator demonstriert.
Das aktuelle PoC-Image ist bewusst hybrid:
readdir() zurückgegeben wird.strcpy / strcat
Pfadkonstruktion) und kopiert den langen Dateinamen in einen festen 32-Byte-Puffer.Diese letzte Kopie ist die CVE-2026-6688-artige Bedingung: Caller-seitiger Overflow durch unbegrenzte Verwendung langer Dateinamen.``` cd esp32-qemu-test ./run.sh
Oder alternativ:```
docker build -t fatfs-esp32-vuln-test esp32-qemu-test/
docker run --rm fatfs-esp32-vuln-test
f_readdir() kann lange Namen (LFN) mit bis zu 255 Zeichen zurückgeben. Viele reale eingebettete Aufrufer kopieren Namen weiterhin in kleinere feste Puffer. Öffentliche ESP32-Beispiele enthalten Muster, die Folgendem entsprechen:```
strcpy(fn, entry->d_name);
strcat(path, "/");
strcat(path, entry->d_name);
Mit einem präparierten FAT-Image, das einen langen Dateinamen enthält, überlaufen diese Kopien den
Aufrufer-Puffer.
### PoC-Kette in diesem Repository
| Schritt | Beschreibung | Marker |
|------|-------------|--------|
| 1 | Präpariertes Speicher-Image wird gemountet und liefert angreiferkontrollierte Verzeichniseinträge | (Mount erfolgreich) |
| 2 | Langer Dateiname wird über den unsicheren Kopierpfad des öffentlichen Musters in `char name[32]` kopiert | `[VULN-BUG7-CONFIRMED]` |
| 3 | Guard-Korruption wird protokolliert, gefolgt von einem Steuerdaten-Absturz in QEMU | `guard=0x61616161`, `Guru Meditation Error` |
Die PoC enthält weiterhin einen Legacy-CVE-2026-6682-artigen OTA-Callback-Überschreibpfad
für Kontext und Marker-Ausgabe (`PWNED-UART`), aber der bugspezifische Beweis hier
ist der oben genannte Marker für den Aufrufer-Pufferüberlauf durch lange Dateinamen.
Beispielhafte Ausgabe:```
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 (...)
Ein Verhalten bei vorzeichenloser Subtraktion wurde zuvor während dieser Forschung festgestellt und gemeldet, später jedoch aus dem CVE-Bestand entfernt. Deshalb werden Sie eine Nummerierungslücke bemerken, da wir diesen zurückgezogenen Datensatz absichtlich aus dem aktiven CVE-Satz dieses Repositorys weglassen. Das CVE-Programm kann etwas eigen sein, was Verweise auf unveröffentlichte Datensätze betrifft, daher vermeidet dies Querverweis-Drama, während die Historie korrekt bleibt. Für die sehr Neugierigen: Sie können die git-Historie dieses Repositorys auf Details zu diesem Befund untersuchen.
Dank an David Brown, dass er unsere Aufmerksamkeit auf den umstrittenen Bericht gelenkt hat. Informationen zum Upstream-Status und Patch-Anleitungen finden Sie auf ChaN's offizieller FatFs-Patches-Seite: https://elm-chan.org/fsw/ff/patches.html
| Projekt | Stars | FatFs-Version | Fehler |
|---|
| espressif/esp-idf | 17.655 | R0.16 | CVE-2026-6682 |
| STMicroelectronics/stm32-mw-fatfs | alle 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 | variiert | 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 | tbd | CVE-2026-6684 |
| hugen79/NanoVNA-H | 695 | R0.15 | CVE-2026-6683 |
| ChibiOS/ChibiOS | 833 | variiert | CVE-2026-6688 |
| Samsung/TizenRT | 643 | R0.16 | CVE-2026-6683, CVE-2026-6688 |
| adafruit/tinyuf2 | 447 | tbd | 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 | variiert | CVE-2026-6682, CVE-2026-6688 |
| eugene-tarassov/vivado-risc-v | 1.061 | tbd | CVE-2026-6684 |
| CVE-ID | Kurztitel | CWE |
|---|
| CVE-2026-6682 | Integer-Überlauf beim Mounten von FAT32-Volumes | CWE-190: Integer Overflow or Wraparound |
| CVE-2026-6683 | Division durch Null bei exFAT-Sync | CWE-369: Divide By Zero |
| CVE-2026-6684 | Endlosschleife im GPT-Partitionsscan | CWE-835: Loop with Unreachable Exit Condition |
| CVE-2026-6686 | Verwendung nicht initialisierter Cluster nach Seek über EOF hinaus | CWE-908: Use of Uninitialized Resource |
| CVE-2026-6687 | Stack-Pufferüberlauf durch unbegrenzte exFAT-Label-Länge | CWE-121: Stack-based Buffer Overflow |
| CVE-2026-6688 | Pufferüberlauf durch unbegrenzte LFN-Dateinamenkopie | CWE-120: Buffer Copy without Checking Size of Input |