FortiMail IBE unauthenticated file-write KEV — feature-gated pre-auth surface and NULL-byte writers¶
Sources: CISA KEV 2026.10.01 addition on CVE-2026-104286, FG-IR-26-175. Added 2026-10-01, due 2026-10-04.
This is durable for operators for three reasons the advisory itself supplies: the vendor workaround names the exact feature gate that opens the exploited handler, the vulnerability class is a NULL-byte-plus-traversal writer pair (an "old" class being re-weaponized on appliances), and the published IoC set is a complete map of how attackers persist on a FortiMail-class mail appliance.
Authorized validation only
Keep proofs to synthetic/lab FortiMail appliances or explicitly approved customer windows, owned source IPs, and route decision tables. Do not publish working exploit requests, write files on production appliances, touch IBE keystore data, or plant/verify persistence artifacts outside disposable systems. Reading IoC artifact hashes on an in-scope host is a defensive evidence action; confirm written scope before any host forensics.
Confirmed source facts¶
| Field | Value |
|---|---|
| CVE | CVE-2026-104286 (CVSSv3 9.8, AV:N/AC:L/PR:N/UI:N, temporal E:P — exploited in the wild) |
| Product range | FortiMail 8.0.0–8.0.1, 7.6.0–7.6.6, 7.4.0–7.4.8, 7.2.0–7.2.9 |
| Class | Path traversal (CWE-22) + improper neutralization of NULL byte (CWE-158) |
| Impact | Unauthenticated attacker writes arbitrary files on the underlying system via crafted HTTP/HTTPS requests |
| Feature gate | Vendor workaround: config system encryption ibe → set status disable — the exploited handler sits behind the IBE (Identity Based Encryption) feature |
| IoC anchors | /data/lib/liblog.so + /data/etc/ld.so.preload (preload rootkit), modified /bin/smit, /data/bin/webconsole, /data/bin/mailservice, modified /data/etc/httpd.conf, modified /data/migadmin.tar.gz, rogue archive account entry with attacker remote-ip/remote-directory, cron CMD (/bin/sh -c 'O=/migadmin ... |
Inference (separate from confirmed facts): the IoC log line FortiMail::IBE::DecrypterMediaIn ... Invalid Base64 Encoding at pos 0 alongside the IBE-only workaround suggests the write path crosses the IBE media-decrypt/enrollment handler that accepts base64 media content; treat that as the pre-auth entry-point family to map, pending vendor detail.
Operator lessons¶
1. Feature toggles are attack-surface maps¶
The vendor's own mitigation — disable IBE — is a free disclosure: one admin-toggled feature exposes an unauthenticated file-writing handler. On any mail/security appliance engagement:
- Enumerate feature-specific pre-auth endpoint families separately from the main admin GUI: IBE enrollment/decrypt pages, quarantine access, guest approval links, remote-queue handlers, password-reset/recipient-lookup flows.
- Fingerprint which features are enabled (distinct 404 vs 403 vs 200 responses, embedded JS page families, footer/version strings).
- Treat every enabled-but-rarely-used feature as its own unauthenticated attack surface with its own file/upload/decrypt handlers — the flagged KEV class here lives in exactly one of them.
2. NULL-byte + traversal writer pairs are alive on appliances¶
The dual CWE (22 + 158) means the validator and the writer disagree: the path/extension check runs against one normalization of the filename while the underlying open/write consumes the raw bytes, so %00 truncation slips an allowlisted suffix (.gif%00 → writes .gif, or a truncated long path) and traversal escapes the confinement directory. Reusable sweep on any upload/save/download-name parameter:
%00,%2500, double-encoded and Unicode-folded NUL variants;../,....//, backslash, and mixed-encoding traversal in the same parameter;- suffix allowlists tested against the stored artifact extension (does
.php%00.pngland as.php?), not just the validator's parsed extension; - differential evidence: validator-visible filename vs actual on-disk path/hash from an owned appliance in the lab — never against production.
3. The IoC set is a persistence-pattern reference¶
Even without the exploit detail, the published artifacts teach the post-compromise shape of a mail-appliance intrusion, which is what to look for in authorized post-exploitation review and what makes convincing lab proof-of-write targets (disposable, non-config paths):
ld.so.preload-based global preload (/data/lib/liblog.so) — a file write alone becomes code-exec persistence when any preload path is writable;- modification of a stock binary (
/bin/smit) and the runninghttpd.conf— web-layer hooking from a single write primitive; - drop binaries under a data partition (
/data/bin/*) instead of system paths to survive upgrades; - abuse of a legitimate feature as the exfil channel: a rogue
archive accountentry (rotation settings + attackerremote-ip+/uploads) — outbound-looking, credentialed, allowlisted traffic; - log anomalies to grep:
ui=(null)admin logout entries, cronCMD (/bin/sh -c 'O=/migadmin, and IBEBufferExceptionnoise preceding compromise.
Validation boundaries¶
- Version/attribution evidence only on production: build/version fingerprint via the login surface, management-ACL posture, and whether the appliance is internet-reachable at all.
- Route-level gating checks (IBE/quarantine endpoints: reachable pre-auth? 200/403/404 decision table) with owned source IPs.
- Any write-primitive proof in a lab appliance only, to disposable marker paths outside
/data/etc,/bin, and mail spool; clean up immediately. - Report as: unauthenticated pre-auth handler in feature X → filename/traversal handling → arbitrary file write on affected range, with exposure evidence and feature-gate state. No request syntax, no payload bytes, no IoC-targeting commands.
October 1 21:3xZ follow-up: the GHSA twin lands + FLIR feature-surface cluster¶
- The GHSA twin of this KEV entry is now published: CVE-2026-104286 / GHSA-6gxc-3vv7-7w24 (9.8) — same affected ranges (8.0.0–8.0.1, 7.6.0–7.6.6, 7.4.0–7.4.8, 7.2.0–7.2.9), "crafted HTTP or HTTPS requests", unauthenticated arbitrary file write. Use it as the machine-readable cross-reference in reports; the KEV remains the exploitation-in-the-wild evidence.
- Adjacent same-day product cluster — Teledyne FLIR Aware2 ≤6.9.0.2 four-pack (hardcoded passwords r959-63hv-grw3, missing web-interface authentication qr3q-9g2p-q6vc, unvalidated pathnames 52c8-5776-8c84, cleartext control endpoints f87c/qx8v): thermal-camera management software reproduces the feature-surface lesson of this page in one vendor — the web interface has no authentication at all, pathnames are unvalidated, and vendor defaults ship hardcoded credentials. Operator rule for building-vision/OT engagements: enumerate the management software's web service separately from the cameras; a whole-server product cluster (auth absent + traversal + hardcoded creds) is a recon shortcut, prove with route decision tables and version fingerprint only, never touch live camera control planes. Tracked as a class cluster, not a new page: each leg is an already-promoted pattern (feature-gate enumeration here, unvalidated pathnames on the traversal pages, hardcoded-credential appliance class).