# CVE-2025-54322 (ZERODAY) - Unauthenticated Root RCE affecting ~70,000+ Hosts

Unauthenticated eval() of base64-decoded chkid GET param in XSpeeder SXZOS Django web UI yields root RCE via single HTTP request.

- Payout: Research
- Severity: critical
- Program: XSpeeder SXZOS
- Credited: PWNAI Research
- Disclosed: 2025-12-26
- CVE: CVE-2025-54322
- Write-up quality: 7/10
- Original: https://pwn.ai/blog/cve-2025-54322-zeroday-unauthenticated-root-rce-affecting-70-000-hosts
- Library page: https://bugbountylibrary.com/r/blog%3Apwn-ai-blog-cve-2025-54322-zeroday-unauthenticated-root-rce-affecting-70-000-hosts
- Tags: domain:iot domain:web impact:privesc impact:rce kind:research platform:research sev:critical tech:python technique:reverse-engineering technique:source-review vuln:command-injection vuln:rce

**Target:** Django web UI on SD-WAN appliance firmware (vLogin view)
**Root cause:** vLogin.index base64-decodes the chkid GET parameter and passes it directly to eval() after a weak substring check for sUserCode/sPwd, with no authentication.
**Steps:**
1. Mount firmware VDI via qemu-nbd, inspect /xspeeder/xweb (Django app, xapp views, GateKeeper middleware)
2. Compute rotating header nonce: `int(time.time()//60)%7`
3. Prime session: `curl -A 'SXZ/2.3' -H "X-SXZ-R: $HX" https://TARGET/webInfos/` to get sessionid cookie
4. Craft payload string containing `sUserCode` and `sPwd` substrings plus eval code, base64-encode as chkid
5. Send `GET /?title=ABC&oIp=XYZ&chkid=<b64>` with UA containing SXZ, X-SXZ-R nonce, and sessionid cookie
6. Observe reverse shell/OOB callback as root
**How found:** Agent emulated firmware offline, mounted rootfs, fingerprinted Django via manage.py/settings.py/urls.py, read GateKeeper middleware and nginx config to map gates, then grepped xapp for dangerous sinks (eval/exec/pickle/subprocess/b64decode) and found eval() on decoded chkid in vLogin.py.
**Exploitation:** Single unauthenticated HTTP GET satisfying three superficial gates (UA containing SXZ, minute-rotating X-SXZ-R header, warmed session cookie) reaches vLogin.index, which base64-decodes chkid and eval()s it, executing arbitrary Python as root.
**Insight:** Embedded Django UIs often gate routes with middleware/nginx header checks that are orthogonal to the vulnerable view's own param constraints; enumerate sinks with grep for eval/b64decode and satisfy gates via headers/cookies so the vulnerable view still sees its expected param count.
