Threat Hunt Plan: ABB Ability zenon IIoT Services — End-of-Life MongoDB Component Exposure and Memory-Disclosure Exploitation
Version 1.0 — 3 August 2026
Hunt Objective and Scope
This hunt seeks evidence of reconnaissance, exploitation, denial of service, and post-exploitation activity against the end-of-life MongoDB 4.2 instance bundled with the IIoT Services component of ABB Ability zenon, as disclosed in ABB cyber security advisory 9AKK108472A9037 dated 30 July 2026. The advisory covers thirteen publicly disclosed MongoDB vulnerabilities that will never be patched in the 4.2 branch. The dominant hunt driver is CVE-2025-14847, publicly known as MongoBleed, which permits an unauthenticated client to read uninitialized heap memory from the database process because the zlib decompression path returns the allocated output buffer size instead of the actual decompressed length. CISA added CVE-2025-14847 to the Known Exploited Vulnerabilities catalog on 29 December 2025 and public proof-of-concept code exists, so the hunt assumes opportunistic scanning and exploitation are already occurring against reachable listeners.
Environment in scope: every host running ABB Ability zenon with IIoT Services installed, including the MongoDB-based Persistence Service; every engineering workstation, HMI, SCADA server, and historian that communicates with those hosts; the Level 3 and Level 3.5 network segments where IIoT Services typically bridge process and enterprise networks; and any internet-facing or vendor-facing network path that terminates on a zenon or IIoT Services host. Hosts running zenon without IIoT Services do not bundle MongoDB and are out of scope, but their exclusion must be evidenced by inventory rather than assumed.
Time window: retrospective 180 days from hunt start, with a mandatory deep-dive on the period from 29 December 2025 forward (the KEV listing date, after which mass scanning for CVE-2025-14847 became likely). Where telemetry retention is shorter than 180 days, hunt the full available window and record the retention limit as a coverage gap in the final report. Long-running database daemons emit process-start telemetry only at start, so any CrowdStrike process-attribution query must be run across at least a 90-day window and preferably one year, otherwise a mongod service that has been running uninterrupted since before the window began will return zero matches and read as a false negative.
Out of scope: exploitation of MongoDB deployments unrelated to zenon; the local privilege escalation in MongoDB Compass for Windows (CVE-2021-20334) except where Compass is confirmed installed on a zenon engineering workstation; and remediation execution, which is a separate change-managed activity governed by the advisory mitigation guidance.
Hypotheses and Hunt Procedures
Hypothesis 1: An unauthenticated external or internal actor has probed or exploited the MongoBleed memory-disclosure flaw against the MongoDB listener bundled with zenon IIoT Services, observable as inbound connections to the MongoDB service ports from unsanctioned sources and as malformed or anomalous zlib-compressed wire-protocol messages in network capture.
MITRE ATT&CK: Reconnaissance | T1595.002 — Active Scanning: Vulnerability Scanning | opportunistic scanners enumerate exposed MongoDB listeners and fingerprint version banners before exploitation. Initial Access | T1190 — Exploit Public-Facing Application | the MongoDB wire protocol listener is the exposed application. Credential Access | T1212 — Exploitation for Credential Access | the disclosed heap memory frequently contains credentials, session tokens, and API keys. ICS | T0866 — Exploitation of Remote Services | the affected service sits inside the industrial environment.
Collection Queries
CrowdStrike Falcon LogScale (CQL) — enumerate every host exposing a MongoDB listener, which establishes the true hunt population independent of the software inventory:
#event_simpleName = "NetworkListenIP4"
| in(LocalPort, values=[27017, 27018, 27019, 27020])
| groupBy([ComputerName, LocalAddressIP4, LocalPort], function=count(as=hits), limit=100000)
| sort(hits, order=desc, limit=100000)
CrowdStrike Falcon LogScale (CQL) — all inbound accepts on the MongoDB service ports, to establish the sanctioned client baseline:
#event_simpleName = "NetworkReceiveAcceptIP4"
| in(LocalPort, values=[27017, 27018, 27019, 27020])
| groupBy([ComputerName, LocalPort, RemoteAddressIP4], function=count(as=hits), limit=100000)
| sort(hits, order=desc, limit=100000)
CrowdStrike Falcon LogScale (CQL) — inbound accepts sourced from outside RFC 1918 space, which for an OT-resident database is an immediate finding rather than a candidate:
#event_simpleName = "NetworkReceiveAcceptIP4"
| in(LocalPort, values=[27017, 27018, 27019, 27020])
| !cidr(RemoteAddressIP4, subnet=["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16","127.0.0.0/8","169.254.0.0/16"])
| groupBy([ComputerName, RemoteAddressIP4, LocalPort], function=count(as=hits), limit=100000)
| sort(hits, order=desc, limit=100000)
CrowdStrike Falcon LogScale (CQL) — process attribution for the listening service. The connection event does not carry ImageFileName, so ProcessRollup2 is the main query and the filtered connection set is the subquery (reverse-direction join). Run this across at least 90 days:
#event_simpleName = "ProcessRollup2"
| join({
#event_simpleName = "NetworkReceiveAcceptIP4"
| in(LocalPort, values=[27017, 27018, 27019, 27020])
},
field=[aid, TargetProcessId], key=[aid, ContextProcessId], mode=inner)
| groupBy([ComputerName, UserName, ImageFileName, CommandLine], function=count(as=cnt), limit=max)
| sort(cnt, order=desc, limit=max)
BPF packet capture — targeted capture of MongoDB wire-protocol traffic at the IIoT Services host, rolling hourly with a size guard. The strftime format in the output filename is mandatory or each rotation overwrites the previous file:
tcpdump -i eth0 -s 0 -G 3600 -C 500 -w /captures/zenon-mongo-%Y%m%d-%H%M%S.pcap 'tcp port 27017 or tcp port 27018 or tcp port 27019'
tcpdump -i eth0 -s 0 -w /captures/zenon-mongo-external.pcap 'tcp port 27017 and not (net 10.0.0.0/8 or net 172.16.0.0/12 or net 192.168.0.0/16)'
tcpdump -i eth0 -s 0 -w /captures/zenon-mongo-opcompressed.pcap 'tcp port 27017 and tcp[((tcp[12] & 0xf0) >> 2) + 12] == 0xdc and tcp[((tcp[12] & 0xf0) >> 2) + 13] == 0x07'
Datadog Log Search — inbound connection events on the MongoDB ports from Windows hosts running zenon IIoT Services:
source:windows @evt.id:5156 @network.destination.port:(27017 OR 27018 OR 27019)
// time range: last 180 days
// Analytics: Table view, group by host, @network.client.ip; time range: last 180 days
Datadog Log Search — MongoDB server log ingestion, where the mongod log is forwarded as a custom source:
source:mongodb ("Unrecognized compressor" OR "decompression" OR "invalid message length" OR "Assertion")
// time range: last 180 days
// Analytics: Timeseries view, group by host; time range: last 180 days
Datadog Live Process Monitoring (Infrastructure > Processes — not a log source, separate interface):
command:mongod user:NETWORK SERVICE
// Free text also works: type "mongod" to fuzzy-match against command lines
// Fallback where Live Process Monitoring is not enabled on OT hosts:
source:windows @evt.id:4688 "mongod.exe"
// time range: last 180 days
Data source gap note: VPC and OT-segment flow logs are frequently not forwarded to Datadog in industrial deployments, and Live Process Monitoring is often not licensed on Purdue Level 2 and Level 3 hosts because of agent-footprint restrictions. Where either gap applies, substitute the source:windows Event ID 5156 and 4688 log searches above and record the substitution in the coverage section of the hunt report.
Windows Event IDs to collect:
- 5156 — Windows Filtering Platform permitted a connection (inbound connections to the MongoDB listener)
- 5157 — Windows Filtering Platform blocked a connection (blocked probe attempts, equally probative of scanning)
- 4688 — A new process has been created (mongod.exe and MongoDB tool invocations)
- 7036 — Service Control Manager: service entered the running or stopped state (MongoDB service state transitions)
- 4624 and 4625 — successful and failed logon on the IIoT Services host
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=5156; StartTime=(Get-Date).AddDays(-180)} |
Where-Object { $_.Message -match '27017|27018|27019' } |
Select-Object TimeCreated, Id, Message |
Export-Csv -NoTypeInformation C:\hunt\zenon_mongo_wfp_5156.csv
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4688; StartTime=(Get-Date).AddDays(-180)} |
Where-Object { $_.Message -match 'mongod\.exe|mongodump|mongoexport|mongosh' } |
Select-Object TimeCreated, Id, Message |
Export-Csv -NoTypeInformation C:\hunt\zenon_mongo_proc_4688.csv
OT Data Collection: Claroty xDome — Devices > All Devices > Advanced Filters, filter Device Type = "SCADA Server" and Device Type = "Industrial Workstation" to build the zenon host population, then use the Protocols & Ports chip to isolate devices exposing port 27017. Then Network > Communication > Communication Analysis: leave Side A empty, set Communication bucket Port = 27017 (add rows with + OR for 27018 and 27019), set Side B to the device set identified above, and set Time Frame to Past Quarter. Export the resulting flow set. Do not encode the time window as a bucket row — Time Frame is a separate dropdown below the buckets.
OT Data Collection: Claroty CTD — the on-prem platform is a different product from xDome with different PCAP retention; use the CTD console's own flow view and pull the packet capture for any flagged MongoDB conversation directly from the CTD sensor, which retains substantially more raw traffic than xDome.
OT Data Collection: Dragos Platform — in Assets, scope to the zenon and IIoT Services host population by vendor and Purdue level and carry it forward as the hunt population. In the Communications Hub, filter destination port 27017 across a 30-day window with source zone set to Level 3.5 or Level 4 and destination zone Level 2 or Level 3, which surfaces every cross-Purdue MongoDB session in one query, then pivot each session to its asset record and event PCAP. Query the Server Stats / PCR Query Focused Dataset for any peer of an IIoT Services host trending toward a producer-consumer ratio near minus 0.99, which is the exfiltration signature. Export the event PCAP or use Export PCAP for window from SiteStore for offline analysis.
OT Data Collection: Nozomi Guardian and Vantage — run the following N2QL queries and export the results:
nodes | where_link protocol == mongodb
links | where port == 27017 and from_zone != to_zone
alerts | where name ~= "mongo" | sort record_created_at asc | select id name severity host_ip created
OT Data Collection: Armis Centrix — run the following ASQ in the console search bar. Set the time window in the UI time-picker (Past Month minimum); do not embed timeFrame in the query body. Where the tenant has boundary literals provisioned, add device:(boundary:"<your tenant literal>") inside the endpoint predicate to scope to the OT zone:
in:services
port:27017,27018,27019,27020
in:ipConnections
serverPort:27017,27018,27019,27020
in:ipConnections
serverPort:27017,27018,27019,27020
endpointA:(networkLocation:"External")
in:activity
type:"Port Scan Detected"
OT Data Collection: Tenable OT Security — in Inventory > All Assets, filter to Windows-based OT assets and export the asset list; in Risks > Findings, filter by Plugin Name for MongoDB plugins and by affected asset to enumerate hosts where the plugin pipeline has matched a MongoDB CVE. Use the GraphQL endpoint for any repeatable sweep; note that the origins field is deprecated in favour of networkAreas as of v4.7.44, so update existing hunt scripts accordingly.
OT Data Collection: Forescout eyeInspect — use the Command Center Asset Inventory view filtered by Purdue level and vendor to identify zenon hosts, and the Alerts view filtered by protocol and destination port for MongoDB flows. eyeInspect has no analyst-facing query language, so forward CEF or syslog to the SIEM and perform the free-text correlation there; the Forescout OT Network Security Monitoring App for Splunk is the canonical path.
SNMP polling — poll the switch port facing each IIoT Services host to detect the traffic volume signature of repeated memory-disclosure requests, which produce a high count of small requests with disproportionately large responses:
snmpwalk -v3 -l authPriv -u <hunt_user> -a SHA-256 -A <authpass> -x AES-256 -X <privpass> <switch_ip> IF-MIB::ifTable
snmpget -v3 -l authPriv -u <hunt_user> -a SHA-256 -A <authpass> -x AES-256 -X <privpass> <switch_ip> IF-MIB::ifHCInOctets.<ifIndex> IF-MIB::ifHCOutOctets.<ifIndex> IF-MIB::ifInErrors.<ifIndex> IF-MIB::ifOutErrors.<ifIndex>
snmpwalk -v3 -l authPriv -u <hunt_user> -a SHA-256 -A <authpass> -x AES-256 -X <privpass> <device_ip> system
Poll at 60-second intervals across the hunt window and diff successive values; a sustained outbound-to-inbound octet ratio far above the historical baseline on the IIoT host port is the volumetric signature of bulk heap-memory harvesting. Prefer SNMPv3 authPriv throughout and provision credentials via snmp.conf rather than inline flags, since inline passphrases are visible in the process table. Where a device offers only SNMPv1 or v2c community-string access, record that as a finding in its own right. Collect trap-receiver logs for the window and flag coldStart (1.3.6.1.6.3.1.1.5.1) and warmStart (1.3.6.1.6.3.1.1.5.2) traps from the IIoT host range, which corroborate the denial-of-service hypothesis, and authenticationFailure (1.3.6.1.6.3.1.1.5.5) traps indicating unauthorized access attempts.
YARA file-system scan — scan the zenon installation tree and the MongoDB data and binary directories for end-of-life component artifacts and for staged exploitation tooling:
yara -r rules/zenon_mongodb.yar "C:\Program Files\COPA-DATA" >> C:\hunt\yara_zenon_hits.txt
yara -r rules/zenon_mongodb.yar C:\ProgramData\ C:\Users\ C:\Windows\Temp\ >> C:\hunt\yara_staging_hits.txt
Analysis Queries
CrowdStrike Falcon LogScale (CQL) — rate analysis on inbound MongoDB accepts, bucketed by hour, to separate a sanctioned polling client from a scanner or a repeated memory-harvesting loop. The formatTime approach is used instead of bucket() because bucket()'s limit parameter caps series at 500 and would silently truncate a fleet-wide hunt:
#event_simpleName = "NetworkReceiveAcceptIP4"
| in(LocalPort, values=[27017, 27018, 27019, 27020])
| formatTime(format="%Y-%m-%dT%H:00", as=hourBucket)
| groupBy([ComputerName, RemoteAddressIP4, hourBucket], function=count(as=hits), limit=100000)
| hits > 200
| sort(hits, order=desc, limit=100000)
Wireshark display filters — isolate MongoDB wire-protocol traffic and the specific opcode used by MongoBleed. Opcode 2012 (0x000007DC) is OP_COMPRESSED; compressor identifier 2 is zlib:
mongo
tcp.port == 27017 && tcp.len > 0
tcp.port == 27017 && tcp.payload[12:4] == dc:07:00:00
tcp.port == 27017 && tcp.payload[12:4] == dc:07:00:00 && tcp.payload[24:1] == 02
tcp.port == 27017 && tcp.analysis.retransmission
tshark -r zenon-mongo.pcap -Y "tcp.port == 27017 && tcp.payload[12:4] == dc:07:00:00" -T fields -e frame.time -e ip.src -e ip.dst -e tcp.len
tshark -r zenon-mongo.pcap -q -z conv,tcp | sort -k7 -n -r | head -40
The third and fourth filters are the highest-value analytical step in this hunt. A client that sends OP_COMPRESSED messages whose declared uncompressed size does not match the actual decompressed payload is exercising the vulnerable code path, and a response frame substantially larger than the request that produced it is the observable signature of leaked heap memory returning to the attacker.
Datadog Log Analytics — inbound MongoDB connection distribution by source:
source:windows @evt.id:5156 @network.destination.port:(27017 OR 27018 OR 27019)
// Use Table view; group by @network.client.ip, host; time range: last 180 days
// Equivalent to the CQL groupBy on [ComputerName, RemoteAddressIP4, LocalPort]
Datadog Log Analytics — rarity analysis to surface the source addresses that appear least often, which is where a one-off exploitation attempt hides:
source:windows @evt.id:5156 @network.destination.port:(27017 OR 27018 OR 27019)
// Use Top List view; group by @network.client.ip; sort ascending for rarest-first; time range: last 180 days
Datadog CloudTrail integration — where IIoT Services or its MongoDB instance runs on cloud infrastructure, examine security-group and network-ACL modifications that could have exposed the listener:
source:cloudtrail @evt.name:(AuthorizeSecurityGroupIngress OR ModifyNetworkInterfaceAttribute OR CreateNetworkAclEntry) -@network.client.ip:10.* -@network.client.ip:172.16.* -@network.client.ip:192.168.*
// Use Table view; group by @network.client.ip, @userIdentity.arn; time range: last 180 days
Datadog Audit Trail — confirm no monitoring or log-forwarding configuration was altered around the suspect window, which would indicate an attempt to blind the defender:
source:datadog @evt.name:"Access Management"
// Use Table view; group by @asset.type, @action; time range: last 180 days
Datadog Monitor definition:
Type: Log Alert
Query: source:windows @evt.id:5156 @network.destination.port:(27017 OR 27018 OR 27019) -@network.client.ip:10.* -@network.client.ip:172.16.* -@network.client.ip:192.168.*
Evaluation window: last 5 minutes
Alert condition: count > 0
Message: "ALERT: non-RFC1918 source connected to a zenon IIoT Services MongoDB listener — immediate investigation required @ot-soc-pagerduty"
Prerequisites: Windows Security log with WFP auditing (Event IDs 5156/5157) enabled and forwarded from every zenon IIoT Services host; host tags identifying zenon hosts
Create via: Monitors > New Monitor > Log Alert OR POST /api/v1/monitors
Windows Event Log PowerShell analysis — connection hunting and source-address frequency ranking:
$ev = Get-WinEvent -FilterHashtable @{LogName='Security'; Id=5156; StartTime=(Get-Date).AddDays(-180)}
$ev | Where-Object { $_.Message -match 'Destination Port:\s+2701[789]' } |
ForEach-Object {
if ($_.Message -match 'Source Address:\s+(\S+)') { $matches[1] }
} |
Group-Object |
Sort-Object Count |
Select-Object Name, Count |
Export-Csv -NoTypeInformation C:\hunt\zenon_mongo_sources_ranked.csv
Sorting ascending rather than descending is deliberate: the sanctioned Persistence Service client will dominate the top of a descending sort, while a single exploitation attempt appears exactly once and would be buried.
OT network and protocol analysis — for each flagged MongoDB conversation, export the PCAP from Dragos or Claroty CTD and analyse offline. Correlate the timestamp of every flagged conversation against the historian for gaps in process-value recording and against the SCADA alarm log for communication-failure alarms on the IIoT Services host, since a successful denial of service against mongod manifests operationally as a historization gap before it manifests as a security alert. Baseline the flagged source against the platform's learned communication model — in Nozomi this is the link baseline, in Claroty the Communication Analysis flow history, in Dragos the Communications Hub baseline status attribute — and treat any source that has no prior communication history with the IIoT host as a priority finding regardless of volume.
YARA memory scan — scan the running mongod process and any suspicious child process for exploitation tooling resident in memory. Classic YARA 4.5.x is required for process-memory scanning; YARA-X (binary yr) has no PID scanning capability:
Get-Process mongod | ForEach-Object { yara rules/zenon_mongodb.yar $_.Id } >> C:\hunt\yara_mongod_mem.txt
Get-Process | Where-Object { $_.ProcessName -match 'mongo|python|powershell|node' } | ForEach-Object { yara rules/zenon_mongodb.yar $_.Id } >> C:\hunt\yara_proc_mem.txt
Where hosts cannot be reached interactively, CrowdStrike Falcon Real Time Response can execute the YARA binary and rule file on remote endpoints via the put and run commands, and a Custom IOA can be authored to alert on the process-creation pattern once the hunt has validated it.
Hypothesis 2: An actor has triggered one or more of the denial-of-service vulnerabilities in the bundled MongoDB 4.2 component, observable as repeated mongod process termination and restart cycles, MongoDB service state transitions outside the change window, and corresponding gaps in zenon historization and reporting.
MITRE ATT&CK: Impact | T1499.004 — Endpoint Denial of Service: Application or System Exploitation | six of the thirteen CVEs crash the database process through crafted queries, aggregation pipelines, role names, or oplog entries. ICS | T0814 — Denial of Service | the industrial consequence of the crashed service. ICS | T0826 — Loss of Availability | historization and integration functions become unavailable. ICS | T0815 — Denial of View | operators lose the trend and reporting view built on the Persistence Service data.
Collection Queries
CrowdStrike Falcon LogScale (CQL) — mongod process start events, grouped by parent, which reveals both the restart frequency and whether restarts are service-manager driven or something else:
#event_simpleName = "ProcessRollup2"
| ImageFileName = /\\mongod\.exe$/i
| groupBy([ComputerName, ImageFileName, ParentBaseFileName, UserName], function=count(as=starts), limit=100000)
| sort(starts, order=desc, limit=100000)
CrowdStrike Falcon LogScale (CQL) — process lifetime derivation. EndOfProcess does not carry ImageFileName, so the image name must come from ProcessRollup2 and the end time is joined in:
#event_simpleName = "ProcessRollup2"
| ImageFileName = /\\mongod\.exe$/i
| join({#event_simpleName = "EndOfProcess"},
field=[aid, TargetProcessId], key=[aid, TargetProcessId],
mode=inner, include=[ProcessEndTime])
| table([@timestamp, ComputerName, ImageFileName, ProcessStartTime, ProcessEndTime], limit=20000)
CrowdStrike Falcon LogScale (CQL) — MongoDB service start events bucketed by hour, which is the cleanest signal for a crash-loop:
#event_simpleName = "ServiceStarted"
| ServiceDisplayName = /mongo/i
| formatTime(format="%Y-%m-%dT%H:00", as=hourBucket)
| groupBy([ComputerName, ServiceDisplayName, hourBucket], function=count(as=starts), limit=100000)
| sort(starts, order=desc, limit=100000)
BPF packet capture — capture the request that precedes each crash. Run a continuous ring buffer so the traffic immediately before an unplanned restart is retained rather than lost:
tcpdump -i eth0 -s 0 -G 300 -W 288 -w /captures/zenon-mongo-ring-%Y%m%d-%H%M%S.pcap 'tcp port 27017'
Datadog Log Search — Service Control Manager state transitions for the MongoDB service:
source:windows @evt.id:(7031 OR 7034 OR 7036) "MongoDB"
// time range: last 180 days
// Analytics: Timeseries view, group by host; time range: last 180 days
Datadog Log Search — Windows Error Reporting and application crash records naming mongod:
source:windows @evt.id:(1000 OR 1001) "mongod.exe"
// time range: last 180 days
// Analytics: Table view, group by host; time range: last 180 days
Datadog Live Process Monitoring (Infrastructure > Processes):
command:mongod
// Watch for the process disappearing and reappearing with a new PID; the Processes page shows live state only
// Fallback log search where Live Process Monitoring is unavailable:
source:windows @evt.id:4688 "mongod.exe"
// time range: last 180 days
Windows Event IDs to collect:
- 7031 — Service Control Manager: service terminated unexpectedly (the primary crash indicator)
- 7034 — Service Control Manager: service terminated unexpectedly a given number of times
- 7036 — Service Control Manager: service entered the running or stopped state
- 1000 — Application Error (mongod.exe faulting module and offset)
- 1001 — Windows Error Reporting bucket record for the crash
Get-WinEvent -FilterHashtable @{LogName='System'; Id=7031,7034,7036; StartTime=(Get-Date).AddDays(-180)} |
Where-Object { $_.Message -match 'MongoDB|mongod' } |
Select-Object TimeCreated, Id, Message |
Export-Csv -NoTypeInformation C:\hunt\zenon_mongo_scm.csv
Get-WinEvent -FilterHashtable @{LogName='Application'; Id=1000,1001; StartTime=(Get-Date).AddDays(-180)} |
Where-Object { $_.Message -match 'mongod' } |
Select-Object TimeCreated, Id, Message |
Export-Csv -NoTypeInformation C:\hunt\zenon_mongo_appcrash.csv
OT Data Collection: Claroty xDome — in Alerts & Threats > Alerts > All Alerts, filter Alert Category to Threat Alert and Policy Deviation Alert and use the free-text Search box, which scans Alert Name and Description, for the affected host name. There is no time-frame selector on this surface, so sort by ALERT UPDATED descending and scan, or use the API detected_time filter for a hard window.
OT Data Collection: Dragos Platform — triage Notifications filtered to ATT&CK for ICS Impact techniques across the IIoT Services host set; each notification carries an event-based PCAP slice of the triggering conversation, which is the fastest route to the crafted request that caused a crash. Open a Case for any confirmed crash correlated with an inbound MongoDB conversation and attach the event PCAP.
OT Data Collection: Nozomi Guardian and Vantage:
alerts | where host_ip == <iiot_host_ip> | sort record_created_at asc
nodes | where last_activity_time > days_ago(7)
OT Data Collection: Tenable OT Security — in Events, filter for policy violations and network-detection events referencing the IIoT Services host across the hunt window; correlate any communication-failure event with the Service Control Manager timeline built above.
OT Data Collection: Armis Centrix — set the window in the UI time-picker:
in:ipConnections
serverPort:27017,27018,27019,27020
endpointA:(networkLocation:"Internal")
orderBy:(bytesCount desc)
Historian and SCADA alarm correlation — export the process historian for the hunt window and identify every interval where tag recording stopped for the zenon IIoT Services collection, then export the SCADA alarm and event log and extract every communication-failure, server-unreachable, and data-collection alarm referencing the IIoT Services host. Build a single merged timeline of mongod terminations, service restarts, historian gaps, and SCADA alarms. Correlated entries across all four sources establish operational impact and convert a technical finding into an incident.
YARA file-system scan — search for crash artifacts and staged crafted-query payloads:
yara -r rules/zenon_mongodb.yar C:\ProgramData\MongoDB\ C:\data\ C:\Windows\Temp\ >> C:\hunt\yara_mongo_crash_artifacts.txt
Analysis Queries
CrowdStrike Falcon LogScale (CQL) — surface hosts whose mongod restart count materially exceeds the fleet norm:
#event_simpleName = "ServiceStarted"
| ServiceDisplayName = /mongo/i
| groupBy([ComputerName], function=count(as=restarts), limit=100000)
| restarts > 5
| sort(restarts, order=desc, limit=100000)
Wireshark display filters — identify the malformed request in the capture immediately preceding a crash:
tcp.port == 27017 && tcp.flags.reset == 1
tcp.port == 27017 && tcp.len > 4000
mongo.opcode == 2013
tshark -r zenon-mongo-ring.pcap -Y "tcp.port == 27017 && tcp.flags.reset == 1" -T fields -e frame.time -e ip.src -e ip.dst
tshark -r zenon-mongo-ring.pcap -q -z io,stat,60,"tcp.port==27017"
Datadog Log Analytics — crash frequency over time and by host:
source:windows @evt.id:(7031 OR 7034) "MongoDB"
// Use Timeseries view; group by host; time range: last 180 days
Datadog Log Analytics — correlate crashes with the preceding inbound connection source:
source:windows @evt.id:5156 @network.destination.port:27017
// Use Table view; group by @network.client.ip; time range: the 30 minutes preceding each 7031 event identified above
Datadog Audit Trail — verify no monitor or alerting configuration was disabled around the crash window:
source:datadog @evt.name:Monitor
// Use Table view; group by @action, @asset.type; time range: last 180 days
Datadog Monitor definition:
Type: Log Alert
Query: source:windows @evt.id:(7031 OR 7034) "MongoDB"
Evaluation window: last 15 minutes
Alert condition: count > 2
Message: "ALERT: repeated unexpected termination of the MongoDB service on a zenon IIoT Services host — possible denial-of-service exploitation @ot-soc-pagerduty"
Prerequisites: Windows System log forwarded from every zenon IIoT Services host; MongoDB service installed under a recognisable display name
Create via: Monitors > New Monitor > Log Alert OR POST /api/v1/monitors
Windows Event Log PowerShell analysis — build the crash-to-restart interval series, where a tightening interval indicates an active crash loop rather than isolated instability:
$scm = Get-WinEvent -FilterHashtable @{LogName='System'; Id=7031,7036; StartTime=(Get-Date).AddDays(-180)} |
Where-Object { $_.Message -match 'MongoDB|mongod' } |
Sort-Object TimeCreated
$prev = $null
$scm | ForEach-Object {
if ($prev) {
[PSCustomObject]@{
Time = $_.TimeCreated
Id = $_.Id
DeltaMin = [math]::Round((New-TimeSpan -Start $prev.TimeCreated -End $_.TimeCreated).TotalMinutes, 2)
}
}
$prev = $_
} | Export-Csv -NoTypeInformation C:\hunt\zenon_mongo_restart_intervals.csv
YARA memory scan — where a crash dump exists, scan it alongside the live process:
yara rules/zenon_mongodb.yar C:\ProgramData\Microsoft\Windows\WER\ReportQueue\ >> C:\hunt\yara_wer_hits.txt
Get-Process mongod | ForEach-Object { yara rules/zenon_mongodb.yar $_.Id } >> C:\hunt\yara_mongod_mem_h2.txt
Hypothesis 3: Credential material disclosed through the MongoBleed heap leak has been reused to authenticate to zenon, engineering, or domain resources, observable as authentication from the IIoT Services host or from an external source using accounts scoped to the Persistence Service, followed by lateral movement and data staging.
MITRE ATT&CK: Credential Access | T1212 — Exploitation for Credential Access | heap memory disclosure yields credentials and tokens without any authentication. Credential Access | T1003 — OS Credential Dumping | follow-on collection once an initial foothold exists. Lateral Movement | T1021.001 and T1021.002 — Remote Services: Remote Desktop Protocol and SMB/Windows Admin Shares | the observed movement path from an IIoT host into the engineering network. Collection | T1005 — Data from Local System | staging of historized process data. ICS | T0859 — Valid Accounts | reuse of legitimate credentials inside the industrial environment. ICS | T0867 — Lateral Tool Transfer.
Collection Queries
CrowdStrike Falcon LogScale (CQL) — network and remote-interactive logons with a source address, which is the population from which credential reuse is identified:
#event_simpleName = "UserLogon"
| in(LogonType, values=[3, 10])
| RemoteAddressIP4 = *
| groupBy([ComputerName, UserName, LogonType, RemoteAddressIP4], function=count(as=hits), limit=100000)
| sort(hits, order=desc, limit=100000)
CrowdStrike Falcon LogScale (CQL) — failed authentication clusters, which precede successful credential reuse when the leaked material is partial or stale:
#event_simpleName = "UserLogonFailed2"
| groupBy([ComputerName, UserName, LogonType, RemoteAddressIP4], function=count(as=fails), limit=100000)
| fails > 10
| sort(fails, order=desc, limit=100000)
CrowdStrike Falcon LogScale (CQL) — MongoDB client tooling execution, which on a production IIoT Services host is administrative at best and data staging at worst:
#event_simpleName = "ProcessRollup2"
| ImageFileName = /\\(mongo|mongosh|mongodump|mongoexport|mongorestore|mongofiles)\.exe$/i
| groupBy([ComputerName, UserName, ImageFileName, CommandLine], function=count(as=cnt), limit=max)
| sort(cnt, order=desc, limit=max)
CrowdStrike Falcon LogScale (CQL) — lateral-movement and living-off-the-land tooling on the hunt population:
#event_simpleName = "ProcessRollup2"
| ImageFileName = /\\(psexec|psexesvc|wmic|net|net1|reg|schtasks|rundll32|certutil|curl)\.exe$/i
| groupBy([ComputerName, UserName, ImageFileName, CommandLine], function=count(as=cnt), limit=max)
| sort(cnt, order=desc, limit=max)
CrowdStrike Falcon LogScale (CQL) — outbound remote-service connections originating from hosts that also expose the MongoDB listener, joining on agent ID to constrain the analysis to the hunt population:
#event_simpleName = "NetworkConnectIP4"
| in(RemotePort, values=[22, 445, 3389, 5985, 5986])
| join({
#event_simpleName = "NetworkReceiveAcceptIP4"
| in(LocalPort, values=[27017, 27018, 27019, 27020])
},
field=[aid], key=[aid], mode=inner)
| groupBy([ComputerName, RemoteAddressIP4, RemotePort], function=count(as=hits), limit=100000)
| sort(hits, order=desc, limit=100000)
CrowdStrike Falcon LogScale (CQL) — DNS resolution of exfiltration-adjacent and database-hosting infrastructure from the hunt population. DnsRequest carries resolved addresses in IP4Records, not RemoteAddressIP4:
#event_simpleName = "DnsRequest"
| DomainName = /(mongodb|mongo-atlas|pastebin|transfer\.sh|anonfiles)/i
| groupBy([ComputerName, DomainName], function=count(IP4Records, distinct=true, as=UniqueIPs), limit=100000)
| sort(UniqueIPs, order=desc, limit=100000)
BPF packet capture — capture outbound remote-service and bulk-transfer traffic from the IIoT Services host:
tcpdump -i eth0 -s 0 -G 3600 -w /captures/zenon-lateral-%Y%m%d-%H%M%S.pcap 'host <iiot_host_ip> and (tcp port 445 or tcp port 3389 or tcp port 22 or tcp port 5985 or tcp port 5986)'
tcpdump -i eth0 -s 0 -w /captures/zenon-egress.pcap 'src host <iiot_host_ip> and greater 1400 and not (dst net 10.0.0.0/8 or dst net 172.16.0.0/12 or dst net 192.168.0.0/16)'
Datadog Log Search — authentication activity on the hunt population:
source:windows @evt.id:(4624 OR 4625) @winlog.event_data.LogonType:(3 OR 10)
// time range: last 180 days
// Analytics: Table view, group by host, @winlog.event_data.TargetUserName; time range: last 180 days
Datadog Log Search — MongoDB tooling execution:
source:windows @evt.id:4688 ("mongodump" OR "mongoexport" OR "mongosh" OR "mongofiles")
// time range: last 180 days
// Analytics: Table view, group by host; time range: last 180 days
Datadog Live Process Monitoring (Infrastructure > Processes):
command:mongodump user:SYSTEM
// Also check: command:mongoexport, command:psexec, command:wmic
// Fallback log search where Live Process Monitoring is unavailable:
source:windows @evt.id:4688 ("psexec" OR "wmic" OR "schtasks")
// time range: last 180 days
Windows Event IDs to collect:
- 4624 — successful logon (types 3 and 10 in particular)
- 4625 — failed logon
- 4648 — logon attempted using explicit credentials (the signature of reused harvested credentials)
- 4672 — special privileges assigned to new logon
- 4688 — process creation
- 5140 — network share object accessed
- 7045 — new service installed (PsExec service artifact)
- 4104 — PowerShell script block logging
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4648; StartTime=(Get-Date).AddDays(-180)} |
Select-Object TimeCreated, Id, Message |
Export-Csv -NoTypeInformation C:\hunt\zenon_explicit_creds_4648.csv
Get-WinEvent -FilterHashtable @{LogName='System'; Id=7045; StartTime=(Get-Date).AddDays(-180)} |
Select-Object TimeCreated, Id, Message |
Export-Csv -NoTypeInformation C:\hunt\zenon_new_services_7045.csv
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-PowerShell/Operational'; Id=4104; StartTime=(Get-Date).AddDays(-180)} |
Where-Object { $_.Message -match 'FromBase64String|Invoke-Expression|DownloadString|mongo' } |
Select-Object TimeCreated, Id, Message |
Export-Csv -NoTypeInformation C:\hunt\zenon_ps_scriptblock_4104.csv
OT Data Collection: Claroty xDome — Network > Communication > Communication Analysis, set Side A to the IIoT Services host set, set the Communication bucket Port rows to 445, 3389, 22, 5985 and 5986 joined with + OR, leave Side B empty to catch every destination, and set Time Frame to Past Quarter. Export the flow set; every destination that is new relative to the prior baseline is a candidate lateral-movement target.
OT Data Collection: Dragos Platform — Communications Hub filtered to source equal to the IIoT Services host set and protocol in RDP, SSH, VNC and SMB over a 30-day window, then pivot each session to its asset record and event PCAP. Query the SSH-sessions and file-transfer Query Focused Datasets for any session originating from the hunt population, and the Server Stats QFD for peers with a producer-consumer ratio approaching minus 0.99.
OT Data Collection: Nozomi Guardian and Vantage:
links | where from_zone != to_zone and protocol == "rdp"
alerts | where mitre_attack ~= "T0859" | sort record_created_at asc
OT Data Collection: Armis Centrix — set the window in the UI time-picker:
in:alerts
type:"Multiple Failed Login Attempts"
in:vulnerabilities
cveId:CVE-2025-14847
OT Data Collection: Tenable OT Security — in Events, hunt for any project upload or download, code revision, or PLC mode change in the window and cross-reference against the change-management ticket queue; anything without a ticket that follows a flagged MongoDB conversation in time is a priority finding. Use the GraphQL endpoint with pyTenable for a repeatable fleet-wide sweep.
OT Data Collection: Forescout eyeInspect — Alerts view filtered by MITRE ATT&CK for ICS technique and by source asset, restricted to the IIoT Services host set; forward to the SIEM for correlation with the Windows authentication timeline.
YARA file-system scan — hunt for credential-access tooling and staged archives on the hunt population:
yara -r rules/cred_dump_memory.yar C:\Users\ C:\ProgramData\ C:\Windows\Temp\ >> C:\hunt\yara_creddump_disk.txt
yara -r rules/zenon_mongodb.yar C:\Users\ C:\ProgramData\ >> C:\hunt\yara_staging_h3.txt
Analysis Queries
CrowdStrike Falcon LogScale (CQL) — rarity analysis on the account and source-address pairs authenticating to the hunt population, ascending so the single-occurrence pairs surface first:
#event_simpleName = "UserLogon"
| in(LogonType, values=[3, 10])
| RemoteAddressIP4 = *
| groupBy([UserName, RemoteAddressIP4], function=count(as=hits), limit=100000)
| sort(hits, order=asc, limit=100000)
Wireshark display filters — examine the lateral-movement and egress captures:
smb2.cmd == 5 && smb2.filename contains "ADMIN$"
rdp || tpkt
ntlmssp.messagetype == 0x00000003
tshark -r zenon-lateral.pcap -Y "smb2.cmd == 5" -T fields -e frame.time -e ip.src -e ip.dst -e smb2.filename
tshark -r zenon-egress.pcap -q -z conv,tcp | sort -k9 -n -r | head -40
Datadog Log Analytics — explicit-credential usage distribution, the strongest single signal of harvested-credential reuse:
source:windows @evt.id:4648
// Use Table view; group by host, @winlog.event_data.SubjectUserName, @winlog.event_data.TargetUserName; time range: last 180 days
Datadog Log Analytics — rarity ranking of authenticating source addresses:
source:windows @evt.id:4624 @winlog.event_data.LogonType:(3 OR 10)
// Use Top List view; group by @winlog.event_data.IpAddress; sort ascending for rarest-first; time range: last 180 days
Datadog Audit Trail — check for credential and access-management changes in the platform itself during the suspect window:
source:datadog @evt.name:Authentication
// Use Table view; group by @action, @usr.email; time range: last 180 days
Datadog CloudTrail integration — where any part of the zenon or IIoT estate is cloud-hosted, look for role assumption and credential use from unexpected addresses:
source:cloudtrail @evt.name:(AssumeRole OR GetSessionToken OR CreateAccessKey) -@network.client.ip:10.* -@network.client.ip:172.16.* -@network.client.ip:192.168.*
// Use Table view; group by @userIdentity.arn, @network.client.ip; time range: last 180 days
Datadog Monitor definition:
Type: Log Alert
Query: source:windows @evt.id:4648 host:<zenon_iiot_host_tag>
Evaluation window: last 10 minutes
Alert condition: count > 0
Message: "ALERT: explicit-credential logon originating from a zenon IIoT Services host — possible reuse of credentials disclosed through MongoDB heap leak @ot-soc-pagerduty"
Prerequisites: Windows Security log forwarded with Event ID 4648 auditing enabled; host tags identifying zenon IIoT Services hosts
Create via: Monitors > New Monitor > Log Alert OR POST /api/v1/monitors
Windows Event Log PowerShell analysis — scheduled task and service persistence review on the hunt population:
Get-ScheduledTask | Where-Object { $_.Date -gt (Get-Date).AddDays(-180) } |
Select-Object TaskName, TaskPath, Date, Author, @{n='Action';e={($_.Actions | ForEach-Object { $_.Execute + ' ' + $_.Arguments }) -join '; '}} |
Export-Csv -NoTypeInformation C:\hunt\zenon_scheduled_tasks.csv
Get-CimInstance Win32_Service |
Where-Object { $_.PathName -notmatch '^"?C:\\(Windows|Program Files|Program Files \(x86\))\\' } |
Select-Object Name, DisplayName, StartMode, StartName, PathName |
Export-Csv -NoTypeInformation C:\hunt\zenon_nonstandard_services.csv
YARA memory scan — the credential-access rule is scanned against every plausible host process:
Get-Process | Where-Object { $_.ProcessName -match 'lsass|powershell|rundll32|svchost|mongod' } | ForEach-Object { yara rules/cred_dump_memory.yar $_.Id } >> C:\hunt\yara_creddump_mem.txt
Scanning LSASS requires SeDebugPrivilege; run the scan from an elevated context and expect the security product to flag the read itself. CrowdStrike Real Time Response can stage the YARA binary and rule file and execute the scan remotely on hosts where interactive access is impractical.
Threat Actor Profile
Opportunistic financially motivated actors are the dominant and most probable threat for this exposure. CVE-2025-14847 entered the CISA Known Exploited Vulnerabilities catalog on 29 December 2025, public proof-of-concept code is available, and the vulnerable code path executes before authentication. Sophistication required is low: mass scanning for TCP/27017, a scripted OP_COMPRESSED request loop, and automated triage of the returned heap fragments for credential-shaped strings. The access path is direct internet exposure of the listener, or exposure through a flat enterprise network reachable from a phished workstation. Their TTPs are broad untargeted scanning, credential harvesting from leaked memory, credential reuse against adjacent services, and — where the harvested access permits — deployment of ransomware or a cryptominer. They will not know or care that the database is embedded inside a supervisory control platform, which makes the operational consequences of their activity effectively random.
Ransomware affiliates and initial-access brokers represent the second tier. Sophistication is moderate. Their access path is the same exposed listener, but their objective is a durable foothold that can be sold or escalated rather than immediate monetisation. Their TTPs include enumerating the compromised host's network position, harvesting further credentials with standard tooling, establishing persistence through scheduled tasks or new services, and identifying whether the host bridges to a higher-value network — which, for an IIoT Services host sitting between process and enterprise networks, it usually does. This tier is the most consequential realistic threat because the industrial network is reached as a consequence of the broker's ordinary workflow, not as a deliberate target.
Nation-state actors with an interest in industrial operations represent the low-probability, high-impact tier. Sophistication is high. For this threat their relevant behaviour is not the exploitation of the MongoDB flaw itself but the exploitation of an unpatchable component as a quiet, durable foothold inside an OT environment. An actor of this class would use the memory disclosure sparingly to avoid detection, would harvest credentials for slow lateral movement toward engineering workstations and controllers, and would prioritise persistence and reconnaissance over immediate impact. The relevant hunt tell is low-volume, patient activity — a handful of connections from a single source across months rather than a scanning burst — which is precisely what the volumetric analyses in this plan would otherwise miss, and why the rarity-ascending sorts in Hypotheses 1 and 3 are specified.
Insider and third-party maintenance access is the final category. Sophistication varies. A vendor support engineer or integrator with legitimate remote access to the IIoT Services host may connect to the MongoDB instance directly with client tooling for legitimate diagnostic reasons, producing telemetry that is indistinguishable from data staging without corroboration against the change record. This category is the principal source of false positives in this hunt and is addressed explicitly in the baseline section.
Data Sources Required
Network: full packet capture at the IIoT Services host segment and at the Level 3.5 boundary, NetFlow or IPFIX from the OT and enterprise core, firewall accept and deny logs covering every path to TCP/27017, and internal DNS resolver query logs. Packet capture is not optional for this hunt — the distinguishing evidence for MongoBleed exploitation is the mismatch between declared and actual decompressed length inside the OP_COMPRESSED message, which no flow record or metadata source can express.
Endpoint: CrowdStrike Falcon telemetry (ProcessRollup2, SyntheticProcessRollup2, EndOfProcess, NetworkListenIP4, NetworkReceiveAcceptIP4, NetworkConnectIP4, DnsRequest, ServiceStarted, UserLogon, UserLogonFailed2, ScheduledTaskRegistered) from every zenon and IIoT Services host; Windows Security, System, Application, and PowerShell Operational event logs with WFP connection auditing, process-creation auditing with command line, and script block logging enabled; Sysmon where deployed, in particular Event IDs 1, 3, 7, 11 and 22.
Application: the MongoDB server log from every bundled instance, forwarded to the SIEM. Note that CVE-2021-20333 permits newline injection into MongoDB server log entries, so these logs must be treated as potentially manipulated during an investigation and every conclusion drawn from them corroborated against network telemetry or host process records.
OT and ICS: process historian tag-recording continuity data for the zenon collection; SCADA alarm and event logs; zenon platform logs including the IIoT Services and Persistence Service logs; PLC and controller communication logs where available; and the OT monitoring platform deployed in the environment — Claroty xDome or CTD, Dragos Platform, Nozomi Guardian and Vantage, Armis Centrix, Tenable OT Security, or Forescout eyeInspect — as the authoritative asset inventory and flow baseline.
Vendor and device: ABB cyber security advisory 9AKK108472A9037 as the authoritative affected-component definition; the zenon software inventory identifying which installations include IIoT Services; switch SNMP interface counters and the SNMP trap receiver log for the ports facing IIoT Services hosts; and remote-access gateway or jump-host session logs covering vendor and integrator access.
Detection Signatures
The SIGMA rules below span four distinct logsource categories — network_connection, process_creation, the Windows System log service channel, and file_event — so that a single missing telemetry source does not silently disable the entire detection set.
title: Inbound Connection to MongoDB Listener From Non-RFC1918 Source
id: 7b3c1a92-4d6e-4f18-9c02-3ea15d7b46c1
status: experimental
description: Detects an inbound network connection to a MongoDB service port from a source outside RFC 1918 private address space, which for the end-of-life MongoDB instance bundled with ABB Ability zenon IIoT Services indicates external reachability and probable exploitation attempt against CVE-2025-14847.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2025-14847
- https://www.cisa.gov/known-exploited-vulnerabilities-catalog
author: 1898 & Co.
date: 2026/08/03
tags:
- attack.initial-access
- attack.t1190
- attack.credential-access
- attack.t1212
logsource:
category: network_connection
product: windows
detection:
selection:
Initiated: 'false'
DestinationPort:
- 27017
- 27018
- 27019
filter_private:
SourceIp|cidr:
- '10.0.0.0/8'
- '172.16.0.0/12'
- '192.168.0.0/16'
- '127.0.0.0/8'
- '169.254.0.0/16'
condition: selection and not filter_private
falsepositives:
- Cloud-hosted IIoT Services deployments where the MongoDB client legitimately resides in a public address range
- Vendor remote support sessions terminating on a public-facing jump host
level: high
title: MongoDB Client Tooling Executed on zenon IIoT Services Host
id: 2f5a8c41-9b17-4e63-8d5a-06c9f27b1e38
status: experimental
description: Detects execution of MongoDB client and export tooling on a host running ABB Ability zenon IIoT Services. On a production Persistence Service host these binaries are administrative at best and indicate database enumeration or bulk data staging following credential disclosure at worst.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2025-14847
author: 1898 & Co.
date: 2026/08/03
tags:
- attack.collection
- attack.t1005
- attack.credential-access
- attack.t1212
logsource:
category: process_creation
product: windows
detection:
selection_image:
Image|endswith:
- '\mongodump.exe'
- '\mongoexport.exe'
- '\mongofiles.exe'
- '\mongosh.exe'
- '\mongo.exe'
selection_cmd:
CommandLine|contains:
- '--out'
- '--archive'
- '--gzip'
- 'db.getSiblingDB'
- 'system.users'
condition: selection_image or selection_cmd
falsepositives:
- Sanctioned ABB or integrator maintenance activity performed under an approved change ticket
- Scheduled backup jobs invoking mongodump against the Persistence Service
level: high
title: MongoDB Service Repeated Unexpected Termination
id: 9c47e2b6-3a58-41df-b0e9-7d13f6a85c24
status: experimental
description: Detects the Service Control Manager reporting unexpected termination of the MongoDB service bundled with ABB Ability zenon IIoT Services, which is the observable signature of the six denial-of-service vulnerabilities affecting the end-of-life MongoDB 4.2 branch.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2021-32040
- https://nvd.nist.gov/vuln/detail/CVE-2020-7925
author: 1898 & Co.
date: 2026/08/03
tags:
- attack.impact
- attack.t1499.004
logsource:
product: windows
service: system
detection:
selection:
Provider_Name: 'Service Control Manager'
EventID:
- 7031
- 7034
param1|contains: 'MongoDB'
condition: selection
falsepositives:
- Host resource exhaustion unrelated to exploitation
- Planned maintenance where the service was stopped ungracefully
level: high
title: Database Export Artifact Written Outside Sanctioned Backup Path
id: 4e18d9a3-6c72-4b05-a1f4-25b8073ce9d6
status: experimental
description: Detects creation of MongoDB dump and archive artifacts in user, temporary, or public directories rather than the sanctioned backup path, which indicates staging of exported Persistence Service data for exfiltration.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2025-14847
author: 1898 & Co.
date: 2026/08/03
tags:
- attack.collection
- attack.t1005
- attack.exfiltration
logsource:
category: file_event
product: windows
detection:
selection_ext:
TargetFilename|endswith:
- '.bson'
- '.metadata.json'
- '.agz'
selection_path:
TargetFilename|contains:
- '\Users\Public\'
- '\Windows\Temp\'
- '\ProgramData\Temp\'
- '\$Recycle.Bin\'
condition: selection_ext and selection_path
falsepositives:
- A backup process misconfigured to write to a temporary directory
- Vendor diagnostic export performed under an approved change ticket
level: medium
Snort and Suricata rules. Local signature identifiers begin at 1,000,000, which is the Suricata local range. The first rule targets the exact wire-protocol construct MongoBleed abuses: a MongoDB message header whose opCode field at offset 12 is OP_COMPRESSED (2012, encoded little-endian as DC 07 00 00) with compressorId 2 (zlib) at offset 24.
alert tcp $EXTERNAL_NET any -> $HOME_NET [27017,27018,27019] (msg:"OT-ZENON MongoDB OP_COMPRESSED zlib message from external source - possible CVE-2025-14847 MongoBleed exploitation"; flow:to_server,established; content:"|DC 07 00 00|"; offset:12; depth:4; content:"|02|"; offset:24; depth:1; detection_filter:track by_src, count 5, seconds 60; classtype:attempted-recon; sid:1000001; rev:1; reference:cve,2025-14847; reference:url,www.cisa.gov/known-exploited-vulnerabilities-catalog; metadata:service mongodb;)
alert tcp $EXTERNAL_NET any -> $HOME_NET [27017,27018,27019] (msg:"OT-ZENON MongoDB wire protocol connection from external source to industrial network"; flow:to_server,established; threshold:type limit, track by_src, count 1, seconds 300; classtype:policy-violation; sid:1000002; rev:1; reference:url,library.e.abb.com; metadata:service mongodb;)
alert tcp $HOME_NET [27017,27018,27019] -> any any (msg:"OT-ZENON MongoDB oversized response following compressed request - possible heap memory disclosure"; flow:to_client,established; dsize:>8192; content:"|DC 07 00 00|"; offset:12; depth:4; threshold:type both, track by_dst, count 10, seconds 60; classtype:attempted-recon; sid:1000003; rev:1; reference:cve,2025-14847;)
alert tcp any any -> $HOME_NET [27017,27018,27019] (msg:"OT-ZENON MongoDB administrative command from non-sanctioned client"; flow:to_server,established; content:"admin.$cmd"; nocase; content:"usersInfo"; nocase; distance:0; classtype:attempted-admin; sid:1000004; rev:1; reference:cve,2025-14847;)
YARA rules. The first rule targets file and disk artifacts. It is written as a hunt-scoping and exploitation-tooling rule in one file with two independent rules: the first identifies the end-of-life MongoDB 4.2 component itself so that the affected population can be enumerated from disk rather than from an inventory that may be incomplete, and the second identifies proof-of-concept exploitation tooling staged on a host. The condition on the first rule requires the mongod identity string together with a 4.2-series version string, because either alone appears in unrelated files — MongoDB documentation, driver packages, and log excerpts all carry one or the other. The condition on the second rule requires two of the exploitation-specific strings rather than any single one, because the individual tokens (OP_COMPRESSED, zlib, 27017) each appear legitimately in MongoDB driver source and client libraries; requiring a pair suppresses that false-positive class while still matching a script that combines protocol construction with the target port.
rule MongoDB_EOL_42_Component_Present
{
meta:
description = "Identifies the end-of-life MongoDB 4.2 server component bundled with ABB Ability zenon IIoT Services (ABB advisory 9AKK108472A9037)"
author = "1898 & Co."
date = "2026-08-03"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2025-14847"
strings:
$id1 = "mongod" ascii wide // server binary identity string
$id2 = "MongoDB Server" ascii wide // buildInfo / banner identity
$ver1 = "4.2.0" ascii wide // EOL 4.2-series version markers
$ver2 = "4.2.1" ascii wide
$ver3 = "4.2.2" ascii wide
$ver4 = "\"version\" : \"4.2" ascii // buildInfo JSON form as emitted by the server
$cfg = "storage.dbPath" ascii wide // mongod configuration key
condition:
uint16(0) == 0x5A4D and filesize < 200MB and
(any of ($id*)) and (any of ($ver*) or $cfg)
}
rule MongoBleed_Exploit_Tooling_Artifacts
{
meta:
description = "Detects proof-of-concept tooling for the MongoDB zlib compressed-header memory disclosure (MongoBleed) staged on disk or resident in process memory"
author = "1898 & Co."
date = "2026-08-03"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2025-14847"
strings:
$s1 = "mongobleed" nocase ascii wide // common PoC project name
$s2 = "OP_COMPRESSED" ascii wide // the abused wire-protocol opcode name
$s3 = "compressorId" ascii wide // header field manipulated by the exploit
$s4 = "uncompressedSize" ascii wide // the mismatched length field
$s5 = "27017" ascii wide // default MongoDB listener port
$s6 = "CVE-2025-14847" ascii wide // literal CVE reference in tooling
$h1 = { DC 07 00 00 } // OP_COMPRESSED opcode 2012, little-endian
$z1 = "zlib" nocase ascii wide // the compressor the exploit selects
condition:
filesize < 20MB and (
$s1 or $s6 or
(2 of ($s2, $s3, $s4, $s5)) or
($h1 and $z1 and $s5)
)
}
The second YARA rule below targets process memory. It is the standing credential-access rule required whenever a hunt covers lateral movement or credential dumping, which Hypothesis 3 does. Each branch matches a distinct tooling family, and the fifth branch is a catch-all for any tool that reads LSASS memory through the documented APIs without matching a known family signature. The condition is structured as an OR across independent branches rather than a threshold across all strings, because the tools do not co-occur and requiring a count would suppress every single-tool detection.
rule Credential_Dump_Tool_Memory_Artifacts
{
meta:
description = "Detects credential-dumping tooling resident in process memory following credential disclosure via the zenon IIoT Services MongoDB heap leak"
author = "1898 & Co."
date = "2026-08-03"
reference = "https://attack.mitre.org/techniques/T1003/"
strings:
$mk1 = "sekurlsa::logonpasswords" nocase ascii wide // mimikatz credential module
$mk2 = "lsadump::sam" nocase ascii wide // mimikatz SAM dump module
$mk3 = "privilege::debug" nocase ascii wide // mimikatz privilege escalation command
$mk4 = "mimikatz" nocase ascii wide // tool name string
$mkh = { 6D 69 6D 69 6B 61 74 7A } // "mimikatz" hex form, survives some obfuscation
$wce1 = "wce.exe" nocase ascii wide // Windows Credentials Editor
$gs1 = "gsecdump" nocase ascii wide // gsecdump tool name
$cs1 = "MiniDump" ascii wide // comsvcs.dll MiniDump export
$cs2 = "comsvcs" nocase ascii wide
$lsa = "lsass.exe" nocase ascii wide // the target process
$api1 = "NtReadVirtualMemory" ascii wide // memory-read APIs used by any dumper
$api2 = "ReadProcessMemory" ascii wide
condition:
(any of ($mk1, $mk2, $mk3, $mk4, $mkh)) or
($wce1 and $lsa) or
$gs1 or
($cs1 and $cs2 and $lsa) or
((any of ($api1, $api2)) and $lsa and (any of ($mk4, $wce1, $gs1, $cs2)))
}
Scanning LSASS process memory requires SeDebugPrivilege and will itself generate endpoint-protection telemetry; coordinate the scan with the security operations team so the resulting detections are attributed to the hunt rather than triaged as an incident. On hosts that cannot be reached interactively, CrowdStrike Real Time Response can stage the YARA binary and rule file and execute the scan remotely, and a validated hit pattern can subsequently be promoted to a Custom IOA.
Indicators of Compromise
Network indicators, expressed as behaviour rather than fixed addresses, because no attacker infrastructure has been published for this exposure:
- Any inbound TCP connection to port 27017, 27018, or 27019 on a zenon IIoT Services host from a source address outside the sanctioned Persistence Service client set
- Any inbound connection to those ports from a non-RFC1918 address, which for an OT-resident database is a finding in its own right regardless of subsequent activity
- MongoDB OP_COMPRESSED messages (opcode 2012, header bytes DC 07 00 00 at offset 12) carrying compressorId 2 where the declared uncompressed size does not match the actual decompressed payload length
- A response frame from the MongoDB listener substantially larger than the request that produced it, repeated across a session — the wire signature of leaked heap memory returning to the client
- Repeated short-lived TCP sessions to the MongoDB port from a single source at a regular interval, consistent with a scripted memory-harvesting loop
- Connections to the MongoDB port originating from a network zone that has no prior communication history with the IIoT Services host in the platform baseline
- Outbound remote-service traffic (TCP 445, 3389, 22, 5985, 5986) from an IIoT Services host to destinations with no prior communication history
- A producer-consumer ratio approaching minus 0.99 on any peer of an IIoT Services host, indicating bulk outbound transfer
Host indicators:
- Presence of a MongoDB 4.2 series server binary on any zenon host, which by itself establishes the vulnerable condition
- mongod.exe process termination followed by service restart, repeated more than twice within a fifteen-minute window
- Service Control Manager Event ID 7031 or 7034 naming the MongoDB service
- Windows Error Reporting or Application Error records naming mongod.exe as the faulting application
- Execution of mongodump, mongoexport, mongofiles, mongosh, or mongo on a production IIoT Services host outside an approved change window
- MongoDB export artifacts (.bson, .metadata.json, .agz) written to user, temporary, or public directories rather than the sanctioned backup path
- Event ID 4648 explicit-credential logon originating from an IIoT Services host
- New service installation (Event ID 7045) or scheduled task registration on an IIoT Services host with no corresponding change record
- MongoDB server log entries containing embedded newline characters or structurally inconsistent records, which indicate log injection via CVE-2021-20333 and mean the log cannot be treated as reliable evidence
- MongoDB Compass installed on a zenon engineering workstation at a version between 1.3.0 and 1.24.x, which carries the local privilege escalation in CVE-2021-20334
OT and operational indicators:
- A gap in zenon historization or Persistence Service tag recording that aligns in time with a mongod termination
- SCADA communication-failure or server-unreachable alarms referencing the IIoT Services host
- Reporting and analytics jobs that depend on the Persistence Service failing or returning incomplete data sets
- SNMP coldStart or warmStart traps from the IIoT Services host range outside a maintenance window
- A sustained shift in the outbound-to-inbound octet ratio on the switch port facing an IIoT Services host, relative to its historical baseline
- Any engineering activity — project upload or download, code revision, controller mode change — on a controller reachable from an IIoT Services host that follows a flagged MongoDB conversation in time and has no change ticket
False Positive Baseline
1. The zenon IIoT Services Persistence Service client itself connects to the bundled MongoDB instance continuously and will dominate every connection-volume analysis. Establish the exact source address, source process, and connection cadence of the sanctioned client on each host before any volumetric analysis, and suppress it by identity rather than by volume — a threshold-based suppression will also hide an attacker that paces requests below the legitimate client's rate.
2. Scheduled backup jobs invoke mongodump or mongoexport against the Persistence Service on a fixed cadence, producing exactly the process-creation and file-write telemetry that Hypothesis 3 treats as data staging. Enumerate every backup job, its schedule, its service account, and its destination path, and suppress matches on that tuple. Any invocation of the same binaries by a different account, at a different time, or writing to a different path remains in scope.
3. ABB support engineers and system integrators connect to zenon and IIoT Services hosts for legitimate diagnostic work, frequently using MongoDB client tooling and frequently outside business hours. Correlate every tooling execution and remote-access session against the change and support-ticket record before dispositioning it. Absence of a ticket is a finding; presence of one is a suppression, but record the ticket number in the hunt evidence so the suppression is auditable.
4. mongod process restarts occur routinely from host patching, planned reboots, and resource pressure unrelated to exploitation. Obtain the patch and maintenance calendar for the hunt window and suppress restarts that fall inside a scheduled window and are preceded by an orderly service-stop record (Event ID 7036 stopped) rather than an unexpected-termination record (7031 or 7034). The distinguishing feature of exploitation is unexpected termination without an orderly stop.
5. Vulnerability scanners operated by the organisation's own security team will connect to TCP/27017, send protocol probes, and in some configurations trigger the same signature content as an exploitation attempt. Obtain the scanner source addresses and scan schedule and suppress those source addresses explicitly, by address, not by behaviour — a suppression written as "traffic that looks like scanning" would also suppress the adversary.
6. Cloud-hosted or vendor-hosted IIoT Services deployments legitimately place the MongoDB client in a public address range, which will trigger the non-RFC1918 detection in Hypothesis 1 and SIGMA rule one on every legitimate connection. Where such a topology exists, document the specific public addresses involved and convert the detection to an allowlist-anchored form rather than disabling it.
7. MongoDB driver packages, client libraries, and vendor documentation bundled with unrelated software contain the strings OP_COMPRESSED, compressorId, zlib, and 27017 and will produce YARA hits from the exploitation-tooling rule if the two-string condition is loosened. Retain the two-of-four condition, and triage any hit by confirming the file is a script or executable rather than a library or documentation artifact before escalating.
Escalation Criteria
The following conditions require immediate escalation to incident response. They are not analyst-discretionary.
1. Any inbound connection to a MongoDB service port on a zenon IIoT Services host from a non-RFC1918 source address that is not an explicitly documented cloud or vendor client.
2. Any packet capture evidence of a MongoDB OP_COMPRESSED message whose declared uncompressed size does not match the actual decompressed payload length, or of a response frame substantially larger than the request that produced it — this is direct evidence of CVE-2025-14847 exploitation and constitutes a confirmed data-disclosure event.
3. Three or more unexpected terminations of the MongoDB service (Event ID 7031 or 7034) within any fifteen-minute window, or any unexpected termination that correlates in time with an inbound connection from an unsanctioned source.
4. Any correlation between a mongod termination and a gap in zenon historization or a SCADA communication-failure alarm, which establishes operational impact and converts the finding into a safety-relevant incident.
5. Any Event ID 4648 explicit-credential logon originating from an IIoT Services host, or any successful authentication to a domain or engineering resource using an account scoped to the Persistence Service.
6. Any YARA hit on MongoDB_EOL_42_Component_Present on a host that the software inventory did not identify as running IIoT Services — this is an undocumented instance of the vulnerable component and means the remediation scope defined from inventory is incomplete.
7. Any YARA hit on MongoBleed_Exploit_Tooling_Artifacts against any file on disk or any process memory on any host in the environment, which indicates exploitation tooling has been staged inside the estate.
8. Any YARA hit on Credential_Dump_Tool_Memory_Artifacts against any process on a zenon, IIoT Services, or engineering workstation host.
9. Execution of mongodump, mongoexport, or mongofiles on a production IIoT Services host outside an approved change window, or the appearance of .bson or .agz artifacts outside the sanctioned backup path.
10. Any engineering activity on a controller — project upload or download, code revision, or controller mode change — that follows a flagged MongoDB conversation in time and has no corresponding change ticket. This escalates to both incident response and plant engineering simultaneously.
11. Any evidence of MongoDB server log manipulation consistent with CVE-2021-20333, since it indicates a deliberate attempt to degrade the evidentiary record.
Hunt Completion Criteria and Reporting
The hunt is complete when all of the following are satisfied. First, the affected population is definitively enumerated: every zenon installation in the environment has been classified as with or without IIoT Services, that classification is evidenced by disk-level or endpoint telemetry rather than by inventory record alone, and every host bundling MongoDB 4.2 is listed with its version, listener configuration, and network reachability. Second, all three hypotheses have been executed across the full available telemetry window for every host in the affected population, with every query in Section 2 run and its result — including a zero result — recorded. Third, every escalation criterion in Section 8 has been evaluated against the collected evidence and either confirmed absent or escalated. Fourth, every finding has been either escalated to incident response or dispositioned as a documented false positive with its suppression rationale and supporting evidence recorded.
Where telemetry retention is shorter than the 180-day target window, or where a data source in Section 4 is unavailable, the hunt is complete for the available scope only. The gap must be stated explicitly in the report as a coverage limitation with the specific window and source named. A hunt that reports no findings without stating which sources and windows it could not see communicates a false negative, and that is the single most damaging outcome this hunt can produce given that the driving vulnerability is confirmed exploited in the wild.
The hunt report must contain: the scope statement and the enumerated affected population with per-host MongoDB version and listener reachability; the time window actually achieved per data source, with retention limits named; every hypothesis with its queries, its result, and its disposition; all findings ranked by severity with supporting evidence artifacts (packet capture extracts, event log records, YARA hit output, platform exports) attached or referenced by evidence identifier; all false positives dispositioned with suppression rationale; a coverage assessment naming every gap in telemetry, sensor placement, and retention discovered during the hunt; the remediation status of each affected host against the ABB advisory guidance, specifically whether IIoT Services has been uninstalled, whether the bundled MongoDB has been replaced with a supported release, and where neither has occurred, what network-layer compensating control is in place; and a recommendation set covering both the immediate remediation and the detection content that should be promoted to standing coverage.
Detection content validated during the hunt should be promoted to standing detection rather than retired with the hunt. In CrowdStrike this means converting the validated CQL queries into scheduled searches and NG-SIEM correlation rules, and the validated YARA patterns into Custom IOAs. In Datadog it means deploying the three monitor definitions specified in Section 2. In the OT monitoring platform it means authoring the equivalent standing detection — a Dragos custom analytic registered through the analytic manager, a Claroty Custom Alert with an Auto-Action, a Nozomi custom rule, or an Armis policy — so that the next occurrence is detected rather than hunted. Because the underlying component cannot be patched, this standing detection is not a supplement to remediation; until IIoT Services is removed or the MongoDB instance is replaced, it is the compensating control that the organisation will need to evidence to its auditors.
Advisory IoC Reference
| IOC Type | IOC |
|---|---|
| CVE | CVE-2025-14847 | CVSS v3.1 7.5 / v4.0 8.7 | MongoDB Server 4.2.0 and later 4.2.x (no fix in branch); fixed in 7.0.28, 8.0.17, 8.2.3, 6.0.27, 5.0.32, 4.4.30 | MongoBleed — mismatched length fields in zlib-compressed protocol headers allow an unauthenticated client to read uninitialized heap memory; KEV-listed 29 Dec 2025, public PoC, exploited in the wild. |
| CVE | CVE-2020-7928 | CVSS v3.1 6.5 | MongoDB Server 4.2 prior to 4.2.9 | Improper neutralization of null byte allows an authorized user to trigger a read overrun and access arbitrary memory via crafted queries. |
| CVE | CVE-2020-7921 | CVSS v3.1 5.3 | MongoDB Server 4.2 prior to 4.2.3 | Improper serialization of authorization-subsystem state lets a credentialed user bypass per-user IP whitelisting after an administrative action. |
| CVE | CVE-2020-7923 | CVSS v3.1 6.5 | MongoDB Server 4.2 prior to 4.2.8 | Crafted geoNear queries violate a query-subsystem invariant and cause denial of service. |
| CVE | CVE-2020-7924 | CVSS v3.1 6.5 | MongoDB Database Tools 4.2 prior to 4.2.11 | A command line parameter intended to skip host name checks causes MongoDB tools to skip certificate validation entirely. |
| CVE | CVE-2020-7925 | CVSS v3.1 7.5 | MongoDB Server 4.2 prior to 4.2.9 | Incorrect validation in the role name parser lets an unauthenticated attacker cause denial of service via a crafted request. |
| CVE | CVE-2020-7929 | CVSS v3.1 6.5 | MongoDB Server 4.0 prior to 4.0.20, 3.6 prior to 3.6.21 | Crafted regular-expression queries cause denial of service. |
| CVE | CVE-2021-20328 | CVSS v3.1 6.8 | MongoDB Java driver versions supporting CSFLE | Client-side field level encryption fails to verify the KMS server certificate host name, enabling machine-in-the-middle interception. |
| CVE | CVE-2021-20330 | CVSS v3.1 6.5 | MongoDB Server 4.2 prior to 4.2.16 | applyOps with malformed oplog entries from a user with basic CRUD permissions crashes replica-set secondaries. |
| CVE | CVE-2021-20333 | CVSS v3.1 5.3 | MongoDB Server 4.2 prior to 4.2.10 | Newline injection into server log entries generates artificial records or splits genuine ones, degrading evidentiary integrity. |
| CVE | CVE-2021-20334 | CVSS v3.1 7.8 | MongoDB Compass 1.x 1.3.0 through versions prior to 1.25.0 on Windows | Local privilege escalation allowing arbitrary code execution with the privileges of the user running Compass. |
| CVE | CVE-2021-32036 | CVSS v3.1 7.1 | MongoDB Server 4.2 up to and including 4.2.16 | Repeated invocation of the features command by an unprivileged authenticated user causes resource depletion and lock contention. |
| CVE | CVE-2021-32040 | CVSS v3.1 7.5 | MongoDB Server 4.2 up to and including 4.2.16 | An extremely long aggregation pipeline overflows the stack and crashes mongod under default configuration. |
| Threat Actor | None attributed in source material — ABB reports no zenon-specific exploitation at advisory issuance; CVE-2025-14847 exploitation is opportunistic and unattributed. Monitor https://www.cisa.gov/known-exploited-vulnerabilities-catalog |
| Malware | None named in source material — exploitation of CVE-2025-14847 is via public proof-of-concept tooling rather than a named family. Monitor https://www.cisa.gov/known-exploited-vulnerabilities-catalog |
| Network IOC | None published in source material — monitor https://www.cisa.gov/known-exploited-vulnerabilities-catalog |
| File IOC | None published in source material — monitor https://www.cisa.gov/known-exploited-vulnerabilities-catalog |
| Behavioral | Inbound TCP connection to port 27017, 27018 or 27019 on a zenon IIoT Services host from a source outside the sanctioned Persistence Service client set |
| Behavioral | Inbound connection to a MongoDB service port on an OT-resident host from a non-RFC1918 source address |
| Behavioral | MongoDB OP_COMPRESSED message (opcode 2012, header bytes DC 07 00 00 at offset 12) with compressorId 2 where declared uncompressed size does not match the actual decompressed payload length |
| Behavioral | MongoDB response frame substantially larger than the request that produced it, repeated across a session |
| Behavioral | Repeated short-lived TCP sessions to the MongoDB port from a single source at a regular interval |
| Behavioral | mongod.exe termination followed by service restart more than twice within a fifteen-minute window |
| Behavioral | Service Control Manager Event ID 7031 or 7034 naming the MongoDB service outside a maintenance window |
| Behavioral | Execution of mongodump, mongoexport, mongofiles, mongosh or mongo on a production IIoT Services host outside an approved change window |
| Behavioral | MongoDB export artifacts (.bson, .metadata.json, .agz) written to user, temporary or public directories rather than the sanctioned backup path |
| Behavioral | Event ID 4648 explicit-credential logon originating from a zenon IIoT Services host |
| Behavioral | New service installation (Event ID 7045) or scheduled task registration on an IIoT Services host with no corresponding change record |
| Behavioral | Outbound TCP 445, 3389, 22, 5985 or 5986 from an IIoT Services host to a destination with no prior communication history in the platform baseline |
| Behavioral | Producer-consumer ratio approaching minus 0.99 on any peer of an IIoT Services host |
| Behavioral | Gap in zenon historization or Persistence Service tag recording aligned in time with a mongod termination |
| Behavioral | SCADA communication-failure or server-unreachable alarm referencing the IIoT Services host |
| Behavioral | SNMP coldStart (1.3.6.1.6.3.1.1.5.1) or warmStart (1.3.6.1.6.3.1.1.5.2) trap from the IIoT Services host range outside a maintenance window |
| Behavioral | MongoDB server log entries containing embedded newline characters or structurally inconsistent records, indicating log injection via CVE-2021-20333 |
| Behavioral | MongoDB 4.2 series server binary present on a host not identified by the software inventory as running IIoT Services |