>
av.Amit VijayanCYBERSECURITY & RESEARCHLet\u2019s connect
Back to the library

Threat Hunting Playbooks

Hunting Cisco BroadWorks XXE Exploitation: CVE-2026-20320 in Splunk and CrowdStrike

Thumbnail for: Hunting Cisco BroadWorks XXE Exploitation: CVE-2026-20320 in Splunk and CrowdStrike

Why this matters now

On November 10, 2026, CISA added CVE-2026-20320 to its Known Exploited Vulnerabilities catalog, with a federal remediation deadline of November 24. The flaw is an unauthenticated XML external entity injection (XXE) in the Open Client Interface (OCI) XML parser of Cisco BroadWorks — the carrier-grade voice and unified communications platform that service providers run for hosted telephony. Two days after the KEV listing, Cisco updated its advisory to confirm active exploitation. And the exploitation report that makes this hunt urgent is not a generic scan: Malbear Labs' "Operation Snowball" documents an autonomous AI intrusion campaign that used this exact flaw as its entry point into a European telecommunications provider, then walked out with the platform's system identity private key.

CVECVE-2026-20320 — Improper Restriction of XML External Entity Reference (XXE) in the Cisco BroadWorks OCI XML parser
CVSS7.5 High (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N), scored by Cisco PSIRT and published on the NVD entry. NVD and the vendor agree on the score — there is no disagreement to reconcile here.
WeaknessCWE-611 — Improper Restriction of XML External Entity Reference ('XXE')
Affected productCisco BroadWorks Application Delivery Platform, Application Server, Profile Server, and Xtended Services Platform (XSP) — all releases earlier than RI.2026.07, regardless of device configuration
VendorCisco (reported by Sandesh M Gawai)
DisclosureCisco advisory first published August 19, 2026; updated to version 1.1 on November 12, 2026 to reflect known active exploitation
CISA KEVAdded November 10, 2026; federal remediation due November 24, 2026. Known ransomware use: Unknown. CISA's required action also invokes its BOD 26-04 forensics triage requirements.
Fixed inRI.2026.07 for all four affected products. There are no workarounds — Cisco's advisory states this plainly, so patching is the only remediation.
ExploitationConfirmed — Cisco PSIRT became aware of active exploitation in November 2026, and the Malbear Labs Operation Snowball report documents the flaw as the entry point into a European telecom provider's network. No victim count has been published.

BroadWorks is not a product most enterprises run themselves — it is the platform their provider runs. That is exactly why it matters to a hunter: the voice platform holds subscriber configuration for every user on it, and the system identity key that authenticates BroadWorks components to each other. In Operation Snowball, the agent that exploited the XSP recovered that key, three SSL credential sets, and three further private keys — then reused passwords pulled from a compromised Cisco telephony server against a separate Cisco Expressway-C management interface. The blast radius of one unauthenticated XML message was the provider's whole voice estate, and from there, the hosted organizations behind it. The campaign ran for more than two weeks, largely unsupervised, and named thirteen organizations as in scope.

The KEV deadline is November 24, but the hunting window is now: the flaw was disclosed in August, the public exploitation report landed in November, and any BroadWorks host that was reachable on its OCI-P port has had months of exposure. If your organization buys hosted voice from a provider running BroadWorks, this is also the week to ask the provider — in writing — whether its XSP fleet is on RI.2026.07 and whether it has hunted its own OCI-P logs.

The technique, in hunt terms

The vulnerable component is the OCI XML parser, reached through the Open Client Interface – Provisioning (OCI-P) service. OCI-P is the provisioning channel that external systems use to manage BroadWorks subscribers, and in the Snowball campaign it was listening on port 2208 on the target XSP, running release 23.0.1.1075. Because the parser resolves external entities by default, a crafted XML message with a malicious external entity makes the server read arbitrary files from its own filesystem — no authentication, no user interaction, just a reachable OCI-P service.

Cisco's advisory title adds a word that shapes the whole hunt: this is an out-of-band blind XXE. The file contents are not returned in the response — the attacker makes the parser fetch an external entity from a server they control, and the file content leaves inside that outbound request. So there are two evidence trails, not one: the crafted XML arriving at the OCI-P service, and the outbound callback leaving the BroadWorks host toward an attacker-controlled destination. Hunt both, because a host that logged the first but not the second may still have been exploited through a channel your logging does not cover.

What the file read buys the attacker is the platform's trust material. The Snowball report is specific about what came out of the XSP: the system identity private key, three SSL credential sets, and three additional private keys with certificate matches confirmed. The system identity key authenticates the XSP to other BroadWorks components, so possessing it allows impersonation of the XSP in inter-component communication. Separately, the provider's BroadWorks Provisioning Server was exposed with an unauthenticated directory listing — and the Provisioning Server holds subscriber configuration for every user on the platform. Neither detail requires guessing: both are documented in the campaign report, and both are what the hunts below are built to find.

In MITRE ATT&CK terms, the exploitation itself maps to T1190 (Exploit Public-Facing Application) for the unauthenticated OCI-P request, T1083 (File and Directory Discovery) for the file reads the XXE performs, T1005 (Data from Local System) for the configuration and key material that leaves the host, and T1552.004 (Private Keys) for the system identity and SSL keys recovered in the campaign. The post-exploitation activity documented in Operation Snowball — Sliver command-and-control, lateral movement with the Impacket suite, and an NTDS dump from a healthcare domain controller — maps to T1071, T1021, and T1003.003, but those are campaign observations, not BroadWorks behavior: treat hits on them as evidence the campaign reached your environment, not as proof the XXE itself did those things.

The shape will feel familiar if you ran the Barracuda ESG hunt: another edge appliance, another unauthenticated flaw, another case where the patch does not evict an attacker who already got in. The difference here is the target — a carrier voice platform rather than a mail gateway — and the attacker: an autonomous agent that adapted to defensive controls without pausing for operator input. The same edge-appliance lesson from the Fortinet edge deep-dive applies: the platform's own logs are the primary evidence, and the surrounding network telemetry is the corroboration.

A note on what is a hunting hypothesis and what is confirmed: the OCI-P service on port 2208, the crafted XML request, the file read with BroadWorks-user privileges, the recovered keys, and the exposed Provisioning Server directory listing are all documented in Cisco's advisory and the Malbear Labs report. No public report gives the source addresses, the exact XML payloads, or the exfiltration domains used in the confirmed exploitation, so the hunts look for the pattern — the request shape, the XXE markers, the outbound callback — not a single tell-tale indicator, and the triage section tells you how to confirm a hit against the platform itself.

Hunt 1: The OCI-P request — crafted XML against port 2208

The entry point is a crafted OCI request to the OCI-P service, which the Snowball campaign reached on port 2208. Legitimate provisioning traffic hits that port too — provisioning systems, admin hosts, and partner integrations all speak OCI — so the signal is not the port alone. It is the source and the shape: OCI-P traffic from an address that has never provisioned anything, especially an external address outside your provisioning ranges, and XML carrying the markers of an external entity. Run this over at least 90 days, back to mid-August: the flaw was disclosed August 19, and the campaign report covers more than two weeks of activity in November, so the exposure window is long.

This Splunk search counts OCI-P connections by source in your firewall or proxy logs. Replace index=firewall with your own network-log index, and replace the placeholder BroadWorks addresses with your XSP and Application Server IPs. Any source on the list that is not a known provisioning system or admin host deserves the same scrutiny as a hit in the web logs.

index=firewall earliest=-90d dest_port=2208
| stats count as requests, earliest(_time) as first_seen, latest(_time) as last_seen by src_ip, dest_ip
| sort - requests

If your WAF, reverse proxy, or web gateway inspects request bodies, the payload itself has markers the connection log cannot show: a DOCTYPE declaration, an ENTITY definition, or a SYSTEM reference to a local file path. This second Splunk search finds them — but only where body inspection is on, which is uncommon for OCI-P traffic, so treat a lack of results here as absence of logging, not absence of attack.

index=waf earliest=-90d ("<!ENTITY" OR "SYSTEM \"file:" OR "<!DOCTYPE")
| table _time, src, dest, uri_path, status
| sort _time desc

On the CrowdStrike side, the same story shows up in the firewall or proxy data ingested into Falcon LogScale. This CQL query lists OCI-P connections by source; adjust the field names to how your network data lands in LogScale.

dest_port=2208
| table([@timestamp, src, dest, dest_port])
| sort(@timestamp, order=desc)

And this CQL query covers the surrounding hosts: Falcon-monitored servers and workstations talking to the BroadWorks OCI-P port. Replace the placeholder address with your XSP's real IP; any host on the list that is not a known provisioning system is a lead.

#event_simpleName=NetworkConnectIP4
| RemotePort=2208
| table([@timestamp, ComputerName, UserName, ImageFileName, RemoteAddress, RemotePort])
| sort(@timestamp, order=desc)

Hunt 2: The blind exfiltration channel — outbound callbacks from BroadWorks hosts

A blind out-of-band XXE only pays off if the file content leaves the host, and it leaves through an outbound request the parser makes to an attacker-controlled server — typically an HTTP fetch or a DNS lookup carrying the stolen data. That means the BroadWorks host itself initiates the connection, which is the anomaly: an XSP or Application Server should only talk outbound to a short list of destinations — its peer BroadWorks components, NTP, DNS resolvers, and update servers. A first-seen external destination, or a burst of DNS queries from the host to domains nobody recognizes, is the exfiltration signal. Hunt this even if Hunt 1 came back empty: the callback is the half of the attack your perimeter logging is most likely to have captured.

This Splunk search lists outbound connections from your BroadWorks hosts in firewall or proxy logs; replace the placeholder addresses with your real XSP, Application Server, Profile Server, and ADP IPs, and baseline the destinations against the known-good list before calling anything a hit.

index=firewall earliest=-90d src_ip IN ("203.0.113.20", "203.0.113.21", "203.0.113.22")
| stats count as connections, dc(dest_ip) as distinct_dests, values(dest_ip) as destinations by src_ip, dest_port
| sort - connections

This Splunk search looks at the DNS side: queries from the BroadWorks hosts to domains outside your normal resolver traffic. A burst of lookups to a single unusual domain, or queries with long encoded labels, is the shape of data leaving inside DNS.

index=dns earliest=-90d src_ip IN ("203.0.113.20", "203.0.113.21", "203.0.113.22")
| stats count as queries, dc(query) as distinct_queries, values(query) as queries by src_ip
| sort - queries

The CrowdStrike equivalents, against firewall, proxy, or DNS data ingested into LogScale:

src IN ("203.0.113.20", "203.0.113.21", "203.0.113.22")
| table([@timestamp, src, dest, dest_port])
| sort(@timestamp, order=desc)
src IN ("203.0.113.20", "203.0.113.21", "203.0.113.22")
| table([@timestamp, src, query])
| sort(@timestamp, order=desc)

One more hunt, labelled a hypothesis: the Snowball campaign found the BroadWorks Provisioning Server exposed with an unauthenticated directory listing, but no public report gives the listing's URL pattern or the files it exposed. This Splunk search looks for directory-listing responses from your Provisioning Server in web logs — a 200 response with a large body on a directory path, from an external source, with no authentication. Treat a hit as a lead to confirm against the server itself, not as proof of compromise on its own.

index=web sourcetype=access_combined earliest=-90d dest_ip="203.0.113.23" status=200
| stats count as hits, values(uri_path) as paths by clientip
| sort - hits

Hunt 3: Post-exploitation — stolen identity keys and the campaign that followed

If the XXE succeeded, the attacker holds the platform's trust material — and the Snowball campaign shows what that material is used for. The stolen system identity key lets the attacker impersonate the XSP in inter-component communication, and passwords pulled from a compromised Cisco telephony server were tried against a separate Cisco Expressway-C management interface. So hunt for the key being used from somewhere it should never come from: inter-component authentication attempts from hosts that are not your BroadWorks servers, and admin-API logins to your voice infrastructure from new sources.

This Splunk search pulls authentication events against your voice infrastructure's admin interfaces from your SIEM's authentication logs; replace the index and sourcetype with your own, and treat a login from an address with no administrative history as a lead.

index=auth earliest=-90d (dest_port=8443 OR dest_port=443) (uri_path="/getxml*" OR "admin")
| stats count as logins, earliest(_time) as first_seen, latest(_time) as last_seen by src_ip, user
| sort - logins

The campaign's Windows-side activity is also huntable where you have endpoint telemetry — and this is the one place a Defender KQL set is genuinely natural. Operation Snowball documents a file-based PowerShell command-and-control chain running entirely through files in C:\Windows\Temp: a watchdog script polling a command file by MD5 hash, a command runner executing whatever it finds, and heartbeat markers written to lock files. This KQL query finds PowerShell writing or executing scripts from that directory; legitimate software rarely does.

DeviceFileEvents
| where Timestamp > ago(90d)
| where FolderPath startswith @"C:\Windows\Temp"
| where FileName endswith ".ps1"
| summarize count(), min(Timestamp), max(Timestamp) by DeviceName, FileName
| sort by count_ desc
DeviceProcessEvents
| where Timestamp > ago(90d)
| where ProcessCommandLine contains "Windows\\Temp"
| where FileName in~ ("powershell.exe", "cmd.exe")
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine
| sort by Timestamp desc

The CrowdStrike equivalent for the same campaign behavior, against Falcon process data:

#event_simpleName=ProcessRollup2
| FileName=/powershell\.exe|cmd\.exe/
| CommandLine=/Windows\\Temp/
| table([@timestamp, ComputerName, UserName, FileName, CommandLine])
| sort(@timestamp, order=desc)

One more CrowdStrike query, for the campaign's persistence path: Sliver beacons and the tunneling tools the agent used (Chisel, frp, suo5) all show up as first-seen outbound connections from compromised hosts on unusual ports. This query lists first-seen external destinations from your servers — baseline the known-good list first, then chase the rest.

#event_simpleName=NetworkConnectIP4
| RemotePort!=2208
| table([@timestamp, ComputerName, UserName, ImageFileName, RemoteAddress, RemotePort])
| sort(@timestamp, order=desc)

Triage: sorting real compromise from noise

First, confirm the hit in the platform's own logs. A Hunt 1 hit (an OCI-P request from an unknown source) plus a Hunt 2 hit (an outbound callback from the same BroadWorks host within minutes) is a confirmed compromise, not a false positive to tune away. Pull the BroadWorks OCI-P and Application Server logs for the matching window and look for the crafted XML, the XML parse errors, and any file-access errors that followed it.

Second, check the trust material directly. If the XXE succeeded, the attacker may hold the system identity private key and SSL credential sets. Review inter-component authentication for logins from hosts that are not your BroadWorks servers, and check whether any new component has registered against the platform since August. If any authentication cannot be explained, rotate the system identity key and the SSL credentials — a patched server still trusts a stolen key, and the same discipline the Ivanti edge hunt applies to a patched management plane applies here: patching closes the hole, it does not evict the attacker.

Third, separate the noise. Legitimate OCI-P traffic comes from known provisioning systems inside a change window — check the provisioning records before you escalate. Legitimate outbound connections from a BroadWorks host go to a short, stable list of peers, NTP, and DNS. What has no innocent explanation is an OCI-P request from an address with no provisioning history, a DNS burst from the host to a domain nobody can name, or an admin-API login to your voice infrastructure from a first-seen source.

Fourth, if your voice service is hosted by a provider, do not stop at your own logs — you may not have any. Ask the provider, in writing, whether its BroadWorks fleet is on RI.2026.07, whether it has hunted OCI-P traffic back to August, and whether it has rotated system identity keys on any host that was reachable on port 2208. A provider that cannot answer the second question has not done the hunt.

Remediation and hardening

Patch every BroadWorks Application Delivery Platform, Application Server, Profile Server, and Xtended Services Platform to RI.2026.07 or later. There are no workarounds — Cisco's advisory says so explicitly — so there is no mitigation to buy time with, only the upgrade. CISA's November 24 deadline binds federal agencies, but the KEV listing is the signal every other BroadWorks operator should act on, and the confirmed exploitation means the patch window has already closed for anyone who was reachable.

Restrict the OCI-P service to trusted provisioning systems permanently, not just until the patch window closes: the OCI-P port should never be reachable from general user networks or the open internet. Audit every account and credential on the platform, remove stale ones, and require phishing-resistant multi-factor authentication for administrative access where the platform supports it. Review the Provisioning Server for unauthenticated directory listings and close them — the Snowball campaign found one holding subscriber configuration for every user on the platform.

Finally, keep the BroadWorks OCI-P logs, the platform syslog, and the surrounding firewall and DNS logs in your SIEM with standing alerts on the Hunt 1 and Hunt 2 patterns — OCI-P requests from unknown sources, XXE markers in request bodies, and outbound callbacks from BroadWorks hosts to first-seen destinations — so the next exploited voice-platform flaw is a detection, not a disclosure. And if you buy hosted voice rather than running it, put the same expectation on your provider in the contract: patch currency, OCI-P exposure, and key rotation after any confirmed exploitation.

Sources

Keep exploring.

All articles