OpenMcdf: Uncatchable infinite loop in DirectoryTree.TryGetDirectoryEntry on crafted CFB directory cycle
OpenMcdf: Uncatchable infinite loop in DirectoryTree.TryGetDirectoryEntry on crafted CFB directory cycle
Prioriteit & onderbouwing
Prioriteit: Laag
Monitoren
Laag (34/100): monitoren. Zwaarst wegend: technische ernst en betrouwbaarheid van het signaal.
midden
- Technische ernst (severity): Genormaliseerde ernst 'medium'; geen CVSS-score beschikbaar.
laag
- Geen exploit bekend: Er is geen exploit of actief misbruik bekend.
laag
- Gemeentelijke relevantie: Relevantiescore 15/100 uit de relevantie-engine (module 5).
midden
- Technische ernst: Threat Score 42/100 x gewicht 25%.
- Exploitatie: Exploit Score 10/100 x gewicht 25%.
- Gemeentelijke relevantie: Relevantiescore 15/100 x gewicht 22%.
- Betrouwbaarheid van het signaal: Confidence 'likely' x gewicht 12%.
- Blootstellingskans: Geschatte blootstelling 30% x gewicht 10%.
- Betrouwbaarheid van de bron: Bronbetrouwbaarheid 88% x gewicht 6%.
De priority_score is de Action Urgency Score: een gewogen combinatie van de technische ernst, de exploitatie en de gemeentelijke relevantie.
Toelichting
### Summary The BST name-lookup loop in `DirectoryTree.TryGetDirectoryEntry` (`OpenMcdf/DirectoryTree.cs:35-46`) walks directory entries by repeatedly calling `directories.TryGetSibling(child, siblingType, validateColor)`. A crafted CFB file with cyclic Left/Right sibling links among directory entries - constructed so the per-step BST-order check in `TryGetSibling` (`DirectoryEntries.cs:84-85`) is satisfied at every step - drives this `while (child is not null)` loop forever. There is no cycle detection in `TryGetDirectoryEntry`. ### Details The recent Brent's-algorithm commit ([`24f445a`](https://github.com/openmcdf/openmcdf/commit/24f445a557fc4f46461cf6d02d296cce16c293a0)) protects `DirectoryTreeEnumerator` and works correctly for both attached repros - pure `EnumerateEntries()` throws `FileFormatException: Directory tree contains a loop` cleanly. The unprotected code path is the lookup-by-name loop, which is reached from multiple public APIs: - `RootStorage.OpenStorage(name)` / `TryOpenStorage(name)` - `RootStorage.OpenStream(name)` / `TryOpenStream(name)` The second one matters most: typical consumers iterate `EnumerateEntries()` and call `OpenStream(entry.Name)` per Stream entry. With Brent's algorithm catching the enumeration cycle but not the per-entry lookup, callers can still hang as soon as they touch a streamed entry. ### PoC Two minimal repros attached, demonstrating the same lookup-loop bug reached via two different public APIs: - `repro_lookup.cfb` (5,632 bytes) - hangs on direct `OpenStorage(name)` for a name not present in the directory - `repro_enumerate.cfb` (7,936 bytes) - hangs on `OpenStream(entry.Name)` called for an entry returned by `EnumerateEntries()` (the common consumer pattern) ### Repro 1 - `OpenStorage(name)` ```csharp using OpenMcdf; using var fs = File.OpenRead("repro_lookup.cfb"); using var root = RootStorage.Open(fs); root.TryOpenStorage("__substg1.0_3001001F", out _); // process spins at 100% CPU; Ctrl+C required. ``` ### Repro 2 - `OpenStream` from inside an enumeration loop ```csharp using OpenMcdf; using var fs = File.OpenRead("repro_enumerate.cfb"); using var root = RootStorage.Open(fs); foreach (var entry in root.EnumerateEntries()) // safe: Brent's catches enumeration cycles { if (entry.Type == EntryType.Stream) _ = root.OpenStream(entry.Name); // hangs: lookup path has no cycle detection } ``` Both processes will not terminate. (Note: pure `foreach (var entry in root.EnumerateEntries()) { }` with no per-entry lookup is **safe** - Brent's algorithm in `DirectoryTreeEnumerator` catches the enumeration cycle and throws `FileFormatException: Directory tree contains a loop`. The hang only manifests once a name lookup is performed.) [repros.zip](https://github.com/user-attachments/files/27084338/repros.zip) ### Impact A denial of service affecting any application that opens untrusted CFB files with OpenMcdf. A small crafted input with a cyclic directory tree reaches the unprotected BST name-lookup in `DirectoryTree.TryGetDirectoryEntry`, hit by any caller of `OpenStorage` / `TryOpenStorage` / `OpenStream` / `TryOpenStream` - including the very common pattern of iterating `EnumerateEntries()` and calling `OpenStream(entry.Name)` per Stream entry. The cycles bypass the per-step BST-order check in `TryGetSibling`, so no exception is thrown and `try/catch` cannot protect callers. The affected thread is unrecoverable without killing the process. Downstream CFB consumers (e.g. `.msg`-file parsers) inherit transitively.
Onderbouwing van de classificatie
Categorie 'ddos' op basis van trefwoord 'denial of service'. Severity 'medium' bepaald op basis van: bronlabel 'medium'. Confidence 'likely': gerenommeerd securityonderzoek (GitHub Security Advisories). Geen bekende leveranciers of producten herkend.
Kwetsbaarheden
- CVSS
- —
- EPSS
- —
- KEV
- Nee
Gemeentelijke relevantie
Deze dreiging scoort 15/100 voor de gemeentelijke relevantie. Meegewogen: een leveranciers- of ketenrisico. Geraakte processen: Leveranciersketen, Website en publiekscommunicatie, Telefonie en klantcontactcentrum.
Bestuurlijke duiding
Deze dreiging heeft een beperkte gemeentelijke relevantie. Een aanval op de bereikbaarheid raakt direct de online dienstverlening aan inwoners en ondernemers. Reguliere opvolging door ICT-beheer en de ISO volstaat; bestuurlijke betrokkenheid is op dit moment niet nodig.
Geraakte processen
Geraakte technologie
Betrokken rollen
CISO · ISO · SOC · ICT beheer · Leveranciersmanager · Proceseigenaar
Operationele acties
- Schakel de scrubbing- of anti-DDoS-dienst in en toets de drempelwaarden.
- Monitor de capaciteit van de internetkoppeling en kritieke publieksdiensten.
- Houd een statuspagina en alternatief contactkanaal gereed.
Concrete stappen voor ICT-beheer en het securityteam.
Aanbevolen acties
- Activeer of toets de anti-DDoS-maatregelen.
- Maak afspraken met de hosting- en netwerkleveranciers.
- Bereid een communicatiescenario voor bij uitval.
Dit zijn algemene handelingsperspectieven. Stem de opvolging af op de eigen omgeving en het ISMS van uw gemeente.
Kenmerken
- Ernst
- Midden
- Categorie
- DDoS
- Zekerheid
- Waarschijnlijk
- Status
- Verrijkt
- CVE's
- CVE-2026-45785
- Prioriteitsscore
- 34 / 100 · Laag
- Bron
- GitHub Security Advisories
- Gepubliceerd
- 19 mei 2026