
Detecta de forma segura el bypass de autenticación SAML de Citrix NetScaler CVE-2026-19490
Una comprobación de vulnerabilidad segura y no autenticada para CVE-2026-19490, el bypass de
autenticación previo a la autenticación en la ruta del proveedor de servicios SAML de Citrix NetScaler ADC / NetScaler Gateway
(CTX696939,
publicado el 2026-08-19). CWE-288, CVSS v4.0 9.3
(AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:L/SI:L/SA:L). Reportado por Samarth Vashisht del
equipo de pruebas de penetración de JPMorgan Chase.
El dispositivo decodifica en base64 el parámetro RelayState de una respuesta SAML y, cuando el texto plano
comienza con ctx=, entrega el resto al deserializador de contexto nFactor. En una compilación sin parchear, un
fallo de deserialización propaga la longitud del RelayState decodificado como el código de disposición interno
de la solicitud en lugar de un error, por lo que un atacante no autenticado elige qué rama interna
toma el dispositivo a continuación simplemente eligiendo la longitud del RelayState. Algunas ramas generan una sesión
real de Gateway; otras provocan un fallo del motor de paquetes y reinician el dispositivo. Este script no hace ninguna de las dos cosas
— envía la única longitud validada que no crea ninguna sesión y deja en paz al motor de paquetes, y
responde a una única pregunta por objetivo: ¿es vulnerable este dispositivo? Un resultado distinto de
VULNERABLE no es por sí mismo un certificado de buena salud.
# single target
./cve_2026_19490_check.py https://gateway.example.com
# a specific Gateway or AAA virtual server
./cve_2026_19490_check.py https://gateway.example.com:9443
# several targets; the scheme defaults to https://
./cve_2026_19490_check.py gw-a.example.com gw-b.example.com:9443
# scan a list, one target per line ('#' comments allowed), compact output
./cve_2026_19490_check.py -f targets.txt --brief
# machine-readable output for pipelines
./cve_2026_19490_check.py -f targets.txt --json > results.json
Python 3.8+, solo biblioteca estándar — sin paquetes de terceros.
Apunte la herramienta al servidor virtual Gateway o AAA, no a la interfaz de gestión. La exposición es
por servidor virtual, por lo que un dispositivo con varias VIP necesita que se pruebe cada una. La sonda lleva un
estricto envoltorio de seguridad — una única longitud de RelayState validada, nunca un barrido — que
¿Es seguro ejecutarlo? detalla.
| Flag | Descripción |
|---|---|
TARGET | Uno o más objetivos [https://]HOST[:PORT]; el esquema por defecto es https:// |
-f, --targets-file FILE | Leer objetivos desde un archivo (uno por línea; comentarios con #) |
--timeout SECS | Tiempo de espera por solicitud (por defecto: 15) |
--workers N | Objetivos concurrentes (por defecto: 16); la salida mantiene el orden de entrada |
-b, --brief | Una sola línea alineada por objetivo — ideal para escanear muchos hosts |
--json | Emitir JSON estructurado, incluyendo cada solicitud enviada por objetivo |
--no-color | Deshabilitar la salida con color (también respeta NO_COLOR y entornos no TTY) |
Un dispositivo vulnerable (la salida predeterminada de dos líneas). El marcador [!] y VULNERABLE se muestran
en rojo en una TTY:
$ ./cve_2026_19490_check.py https://gateway.example.com:9443
[!] https://gateway.example.com:9443: VULNERABLE [internal-error-43524]
HTTP 500 / 43524: the decoded RelayState length was propagated as the internal error, so the CTX696939 fix is absent
Un dispositivo parcheado:
$ ./cve_2026_19490_check.py https://vpn.example.com
[+] https://vpn.example.com: PATCHED [fixed-error-returned]
HTTP 200 "Malformed Assertion": the fixed error was returned on the path this probe reached, so the CTX696939 fix is present (>= 13.1-63.21 / 14.1-73.32)
La activación de la protección contra falsos positivos. Tanto la sonda como el control de la misma longitud devolvieron la señal sin parchear, por lo que la respuesta no depende de lo que se envió y se retira la respuesta que parecía decisiva:
$ ./cve_2026_19490_check.py https://sp-strict.example.com
[?] https://sp-strict.example.com: INCONCLUSIVE [flat-response]
the probe and the same-length control both answered HTTP 500 / 43524, so the reply does not depend on what was sent and the fix was never exercised; unknown, not patched
Barriendo un parque (--brief). Las dos filas de gateway.example.com son los servidores virtuales SP y solo-IdP
en el mismo dispositivo — ambos responden, algo que una comprobación de precondición de configuración no lograría:
$ ./cve_2026_19490_check.py -f targets.txt --brief; echo "exit: $?"
VULNERABLE https://gateway.example.com:9443 internal-error-43524
VULNERABLE https://gateway.example.com:9444 internal-error-43524
PATCHED https://vpn.example.com fixed-error-returned
INCONCLUSIVE https://sp-strict.example.com flat-response
UNAFFECTED https://lb.example.com no-saml-endpoint
ERROR https://www.example.com not-identified
exit: 1
Salida legible por máquina (--json). Se incluye cada solicitud, por lo que un hallazgo puede volver a derivarse
de la evidencia en lugar de confiar en él. El control se registra por su relación con la sonda en lugar
de como un veredicto propio, porque un control que se lee como una compilación parcheada es el resultado esperado en
todas las compilaciones:
$ ./cve_2026_19490_check.py https://gateway.example.com:9443 --json
[
{
"target": "https://gateway.example.com:9443",
"verdict": "VULNERABLE",
"reason": "internal-error-43524",
"detail": "HTTP 500 / 43524: the decoded RelayState length was propagated as the internal error, so the CTX696939 fix is absent",
"netscaler_indicators": [
"CSP contains citrixng://",
"CSP contains com.citrix.nsgclient://",
"CSP contains nsgcepa://",
"CSP report-uri /nscsp_violation/report_uri",
"/vpn/js/rdx/ present (HTTP 404)"
],
"attempts": [
{
"kind": "probe",
"path": "/cgi/samlauth",
"status": 500,
"state": "unpatched",
"detail": "HTTP 500 / 43524: the decoded RelayState length was propagated as the internal error"
},
{
"kind": "control",
"path": "/cgi/samlauth",
"status": 200,
"state": "differs-from-probe",
"detail": "same-length control: HTTP 200 \"Malformed Assertion\": the fixed error was returned"
}
]
}
]
Sí. Está diseñado para uso en producción y evaluación: