# Mind the Config: Detecting and Weaponizing NetScaler CVE-2026-19490

Citrix NetScaler SAML RelayState deserializer uses decoded length as branch selector on failed verification, letting one unauthenticated request mint anonymous Gateway sessions, crash the box, or pivot internally.

- Payout: Research
- Severity: critical
- Program: Citrix
- Write-up by: Samarth Vashisht
- Disclosed: 2026-09-10
- CVE: CVE-2026-19490
- Write-up quality: 9/10
- Original: https://bishopfox.com/blog/mind-the-config-detecting-and-weaponizing-netscaler-cve-2026-19490
- Library page: https://bugbountylibrary.com/r/blog%3Abishopfox-com-blog-mind-the-config-detecting-and-weaponizing-netscaler-cve-2026-19490
- Tags: area:devices domain:network impact:internal-access impact:privesc impact:rce kind:research platform:research sev:critical tech:saml technique:source-review vuln:auth-bypass vuln:dos vuln:ssrf

**Target:** /cgi/samlauth SAML endpoint on Gateway/AAA virtual server
**Root cause:** On failed nFactor context signature verification, the SAML handler propagates the decoded RelayState length as the request's internal disposition code and dispatches on it, so attacker-chosen length selects the next internal branch. The fix substitutes a constant error code (0xe0005).
**Steps:**
1. Identify a Gateway or AAA virtual server with a SAML action configured (show ns runningConfig | grep -i saml).
2. POST to /cgi/samlauth with a SAMLResponse (any junk content) and a RelayState that base64-decodes to `ctx=` plus bytes totaling the chosen decoded length.
3. Length 20: unpatched returns 500 with internal error 43524; patched returns 200 'Malformed Assertion'.
4. Control: same 20-byte length, different bytes after `ctx=`; all builds return 200 Malformed Assertion. Verdict VULNERABLE only if probe and control differ.
5. Length 16: reaches post-login code; on a vpn vserver returns a real NSC_AAAC cookie and logs SSL VPN login for anonymous in clientless mode.
6. Lengths 18/21: crash the packet engine (~45s outage); three crashes in ~90s trigger full appliance reboot via pitboss.
7. Lengths 22/23: fall into client-certificate authentication.
**How found:** Defender-side binary diff of the packet engine across the fix: the entire change in the affected region was one instruction (vulnerable build moves decoded length into status register; fixed build moves constant error 0xe0005). That revealed length-as-selector, then lab mapping of each length to a branch on VPX appliances.
**Exploitation:** Unauthenticated attacker sends one crafted RelayState to /cgi/samlauth. On a Gateway with -defaultAuthorizationAction ALLOW, the anonymous session walks /cgi/setclient?cvpn then the clientless landing page and becomes an HTTP(S) proxy from inside the perimeter, reaching internal apps, appliance management UIs, NSIP/NITRO API on any host/port (HTTP(S) only, loopback refused). With default/reused/phished management creds, NITRO is driven through the proxy and its file interface appends a crontab line executed as root within ~1 minute (confirmed on 13.1-63.18).
**Escalation:** Chain: auth bypass -> anonymous Gateway session -> SSRF pivot into internal network -> NITRO management API via proxied channel -> cron file write -> root on appliance. Repeated crash-length requests escalate DoS to full reboot.
**Insight:** When a fix is a single instruction swapping an attacker-influenced value for a constant, that value is a branch selector: enumerate its small-integer range to map internal dispatch branches, and pick a length between crash values for a safe patch-state oracle.

