Hunt FortiMail CVE-2026-104286: file writes past the gate


Start with a log line from the appliance. It is a system event with user=system and ui=cron, and it shows a root cron job running /bin/sh -c with a variable set to /migadmin. Fortinet's advisory prints the line cut off after that, with three dots. Next to it sits a second line: User admin logged out from (null). A third records an archive account named archive234 that points at 79.141.169.187.
Read together, those lines are the shape Fortinet published on 1 October 2026 for CVE-2026-104286 in FortiMail. Crafted HTTP or HTTPS requests let an unauthenticated attacker write arbitrary files on the underlying system. Fortinet says it has been reported as exploited in the wild, and CISA added it to the KEV catalog the same day.
Carry two questions. Can anyone reach your FortiMail web interface from the internet? And do the appliance's logs leave the box, so a person can read those three lines at all?
How the attack works
Two weaknesses, one file write
Fortinet's advisory pairs two weaknesses. CWE-22 is path traversal, where a request names a location outside the directory the application meant to confine it to. CWE-158 is improper neutralization of a NULL byte, where the application mishandles a NULL character in its input. The advisory lists the component as GUI.
Fortinet publishes no request body, and we will not guess at one. Its workarounds do name the IBE feature, the webmail interface, and POST requests to /ibe that contain ../. Our reading: those are the places to close first.
The attack type is unauthenticated, so no stolen credential has to come first. Fortinet also lists Virtual Patch as No, so there is no signature to switch on while you wait.
Risk: what the mail gateway holds
A mail gateway sits on the path of every message in and out of the company. It holds routing, policy, administrator accounts and, where archiving is on, copies of mail.
Fortinet's own indicators show:
An httpd.conf that has changed. Fortinet says a normal file holds only Include /migadmin/etc/httpd.conf. Its compromised sample repeats LoadModule FMLcheck_module modules/mod_FMLcheck.so under it.
A root cron command that runs the appliance CLI with show and writes the output to an HTML file under /migadmin/www. Our reading: a configuration dump staged where the web server can serve it.
An archive account named archive234 with destination remote, remote-ip 79.141.169.187 and remote-directory /uploads, plus archive policy lines with pattern[*]. Our reading: that copies mail out. Fortinet does not say what was taken.
Fortinet has not said when exploitation began, how many appliances are involved, or who is behind it. CISA lists known ransomware campaign use as Unknown. We name no victims and stop there.
Mitigate and reduce risk
Patch status first. As of 4 October 2026, Fortinet's advisory still lists the fixes as upcoming: 8.0.2 for 8.0.0 through 8.0.1, 7.6.7 for 7.6.0 through 7.6.6, and 7.4.9 for 7.4.0 through 7.4.8. For 7.2.0 through 7.2.9, Fortinet says to upgrade to branch 7.4 or above. No fixed build is listed as available, so do not plan a window around one. Recheck the advisory first.
Fortinet's workarounds:
Disable IBE support. In the GUI, turn IBE Service off under Encryption, then IBE. The CLI form is just below this list.
Alternatively, disable access to the FortiMail webmail interface from the internet, or limit it to a trusted private network.
Or, if a web application firewall sits in front of FortiMail, block POST requests to /ibe that contain '../'.
CLI form of the first workaround:
config system encryption ibe
set status disable
endCISA added the CVE to KEV on 2026-10-01 with a due date of 2026-10-04. It requires vendor mitigations plus forensic triage.
Our reading, separate from Fortinet's guidance. Moving a 7.2 box to 7.4 does not help until 7.4.9 ships, because 7.4.0 through 7.4.8 are affected. NVD's structured version list also differs from the advisory text, so use the advisory ranges for inventory. If an appliance was reachable and matches an indicator below, treat it as suspect and preserve evidence before you change it.
General-knowledge controls, all test first: forward appliance syslog off the box, keep management on an admin network, and review archive accounts and policies today.
How to hunt the activity
EDR usually cannot run on a FortiMail appliance, and its logs arrive as syslog only if you forward them. These hunts bind to Fortinet's published artifacts: the log strings and IPs on the advisory page, and the seven SHA-256 values in the STIX download linked from it. The page does not pair every hash with a file path, so match on the hash. Fortinet defangs its IPs, and we restored the dots. It gives no role for 45.129.0.192.
Fortinet gives no first exploitation date, so use your longest retention. Splunk and KQL depend on forwarded FortiMail logs. Kibana depends on firewall, proxy or DNS telemetry. Falcon depends on files or connections that reach an endpoint. Our query and field names are test first. The table under the hunts, "Interpret before you escalate", says what is benign and what is not.
Hunt in Splunk: Fortinet's log strings in forwarded syslog
index=YOUR_FORTIMAIL_INDEX
("O=/migadmin" OR "logged out from (null)" OR "archive234" OR "79.141.169.187"
OR "45.129.0.192" OR "Invalid Base64 Encoding" OR "failed to log in")
| eval finding=case(
like(_raw, "%archive234%") OR like(_raw, "%79.141.169.187%"), "remote archive account or IP",
like(_raw, "%O=/migadmin%"), "cron migadmin",
like(_raw, "%logged out from (null)%"), "admin logout from (null)",
like(_raw, "%Invalid Base64 Encoding%"), "IBE Base64 decode error",
like(_raw, "%failed to log in%"), "internal user failed login",
like(_raw, "%45.129.0.192%"), "advisory IP",
true(), "other")
| table _time host finding _raw
| sort 0 _timeField mapping: the strings are Fortinet's. The index and raw-text match are ours, since field extraction depends on your syslog parser (test first).
False positives: failed internal-user logins and IBE decode errors happen in normal use. The advisory truncates the cron line, so match only its O=/migadmin start.
Empty result: confirm FortiMail syslog reaches this index. No forwarding looks exactly like a clean box.
Hunt in Kibana: egress to the advisory IPs
destination.ip: ("79.141.169.187" or "45.129.0.192")
or source.ip: ("79.141.169.187" or "45.129.0.192")Field mapping: the IPs are Fortinet's. The ECS fields are ours and depend on your firewall, proxy or DNS integration (test first). Add @timestamp, source.ip, destination.ip and observer.name as columns.
False positives: your own scanner or threat feed may touch these addresses. A workstation doing so differs from the mail gateway doing so.
Empty result: this runs on network telemetry, not the appliance. Confirm egress from the FortiMail segment is logged.
Hunt in Falcon CQL: Fortinet's hashes and the advisory IPs on endpoints
(#event_simpleName=NetworkConnectIP4 RemoteAddressIP4=/^(79\.141\.169\.187|45\.129\.0\.192)$/)
or (SHA256HashData=/^(8015f34dc84922b03688399d7f9fe7a00361789f7e420c7e2a2cdb23e75cef84|8953ec7960b09f544a880b072ad4e6cfda7a8303f486251d3478dcfdfbac23b6|77324ac428bde86d351fc5fc06f6d64a6bfe737dfb2743df1d4c5ac2418a5b6a|7a6cea9f5c9e2e9994d4e3c4da73f86cf5acd05ea5d312c066c9d1dafd69ee38|4000276a150a165d3c2537d1e19fb393c4de8333076a16655e28059cae82157b|703e97c64e61e41dc3aaba580d82bb2aa7b6a11b54ee6fb467ed5d5a3bffdef5|d6fe51c22b91776f4c961ea58bcac5917f15d560a619d7ce726d3d51795609d3)$/)
| table([@timestamp, ComputerName, #event_simpleName, RemoteAddressIP4, FileName, SHA256HashData], limit=1000)Field mapping: the hashes and IPs are Fortinet's. The Falcon event and field names are ours (test first). Falcon cannot sit on the appliance, so hash matches only appear where appliance files reach an endpoint, such as a forensic collection or a file integrity feed.
False positives: connections to the IPs can come from security tooling.
Empty result: expected unless you collect appliance files. It proves little.
Hunt in KQL: archive account changes and cron activity in Sentinel
let StartTime = ago(30d);
union isfuzzy=true Syslog, CommonSecurityLog
| where TimeGenerated >= StartTime
| extend Text = strcat(tostring(column_ifexists("SyslogMessage", "")), " ", tostring(column_ifexists("Message", "")))
| where Text contains "archive234"
or Text contains "remote-ip[79.141.169.187]"
or Text contains "O=/migadmin"
or Text contains "logged out from (null)"
| summarize
Archive = countif(Text contains "archive234" or Text contains "79.141.169.187"),
Cron = countif(Text contains "O=/migadmin"),
Logout = countif(Text contains "logged out from (null)"),
First = min(TimeGenerated),
Last = max(TimeGenerated)
by Computer
| order by Archive desc, Cron descField mapping: the strings are Fortinet's. FortiMail may land in Syslog or, as CEF, in CommonSecurityLog. The column handling and per-host counts are ours (test first).
False positives: your mail team may add archive accounts on purpose. Compare the name and remote address with your change records.
Empty result: confirm the connector ingests appliance data, then widen StartTime.
Interpret before you escalate
Finding | Benign read | Escalate when |
Archive account with remote-ip 79.141.169.187 | None that we know of | Always. Check the wildcard policy and who ran the CLI session |
Cron line starting O=/migadmin | Housekeeping you can reproduce on a clean box | It sits near a logout from (null), or files appear under /migadmin/www |
Admin logout from (null) | A session you can account for | No administrator was working, or it sits near a cron or archive finding |
Connections to the advisory IPs | Your own scanner or feed | The source is the mail gateway or its segment |
SHA-256 match on a collected file | A saved copy of the indicator list | The file came from the appliance |
IBE Base64 errors or failed internal-user logins | Typos, damaged or old IBE messages | They cluster with any finding above |
Empty results | Nothing matched | Forwarding or retention is missing, so fix coverage first |
Sources
Fortinet PSIRT, FG-IR-26-175 (published 1 October 2026), including the STIX download: https://www.fortiguard.com/psirt/FG-IR-26-175
Fortinet STIX indicator file for FG-IR-26-175: https://filestore.fortinet.com/fortiguard/psirt/stix_improper-limitation-of-a-pathname-to-a-restricted-directory_fg-ir-26-175.json
CISA Known Exploited Vulnerabilities Catalog, CVE-2026-104286 (added 1 October 2026, due 4 October 2026): https://www.cisa.gov/known-exploited-vulnerabilities-catalog
NVD, CVE-2026-104286: https://nvd.nist.gov/vuln/detail/CVE-2026-104286
What This Means for Your Team
List every FortiMail you run and its version, then check the exposure of the webmail and management interfaces. Apply Fortinet's workaround now, and watch the advisory for the 7.4.9, 7.6.7 and 8.0.2 builds. Run the hunts back as far as your logs go. If anything matches, treat the appliance as suspect and follow forensic triage.
Inception Protection
Inception Protection is our managed detection and response service, and it works with the Microsoft licenses you already have. FortiMail appliance logs reach us only if you forward them, so we start there. Then we read the mail gateway evidence next to your identity and endpoint signals as one story, and you keep the decisions.
Inception Foresight
If you want to see how well your Microsoft environment would surface activity like this, the free Inception Foresight M365 Assessment is a good place to start: https://www.inceptionsecurity.com/m365assessment. You can also follow Inception Security on LinkedIn and @inceptionsec on X.



