Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-8452-check — 用于 Citrix NetScaler CVE-2026-8452 的基于行为的补丁状态检测器。发送精心构造的 SAML 请求,以判断 PrefixList 大小检查是否存在,而不会利用或破坏内存。 | Kitploit
工具/GitHubGitHub/bishopfox/cve-2026-8452-check
漏洞扫描器漏洞分析Web安全网络安全
GitHubbishopfox/cve-2026-8452-check

CVE-2026-8452-check

用于 Citrix NetScaler CVE-2026-8452 的基于行为的补丁状态检测器。发送精心构造的 SAML 请求,以判断 PrefixList 大小检查是否存在,而不会利用或破坏内存。

查看仓库
14天前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

Citrix NetScaler SAML PrefixList 堆溢出 — 补丁状态检测脚本

针对 CVE-2026-8452 的安全、非破坏性补丁状态检查——这是存在于 Citrix NetScaler ADC / NetScaler Gateway SAML 签名规范化器中的预认证堆溢出漏洞(CTX696604,CVSS 8.8)。在规范化过程中,一个过大的独占规范化 PrefixList 会溢出固定大小的缓冲区,而 NetScaler 在验证携带该列表的签名之前就执行这一操作——因此,无需任何凭据、会话或有效签名即可触达整个路径。由 JPMorgan Chase XOR 团队的 Michael Tucker 报告;根因与利用分析归功于 watchTowr Labs。

该脚本不会利用此漏洞,也不会破坏内存。它针对每个目标回答一个问题:此设备上是否存在修复?——该判断基于行为观察,通过观察补丁而非猜测构建版本来确定。

可以安全运行吗?

安全。它专为生产环境和评估用途而设计:

  • 探测保持在损坏阈值以下。 575 字节足以让已修补和未修补的构建给出不同应答,并且远低于未修补设备内存损坏开始的长度。已在涵盖两个受支持分支和两种补丁状态(包括两个修复构建)的设备上通过实测验证。
  • 它越过的阈值是固定的代码常量,而非某次部署的属性。 修复构建接受 512 字节的 PrefixList 并拒绝 513 字节及以上。该限制精确到字节,在两个受支持分支上完全相同,且不随设备配置或周围 SAML 消息的结构而变化——通过探测两条路由(它们以差异显著的 XML 包装该值)并发现它们在同一字节处改变行为,这一点得到了确认。575 字节以 63 字节的余量越过该限制,因此判定结果不依赖于目标的具体设置方式。
  • 打补丁不会使设备普遍拒绝较长的 SAML 值。 该限制仅专门适用于 PrefixList 属性。将其他字段夸大超过该限制——断言消费者服务 URL、颁发者名称、算法标识符、摘要和签名值——在修复构建上不会引起任何变化,因此应用修复不应导致原本可用的 SAML 配置开始失效。
  • 不会破坏任何内存,也不会重启任何进程。 在已修补构建上,探测在大小检查处被拒绝;在未修补构建上,它会在解析器内部良性地失败。两者都不会触及溢出。
  • 没有任何敏感信息进入扫描输出。 探测仅携带合成的命名空间前缀令牌,并且该工具报告的是判定结果,而非响应体。
  • 两个固定长度,绝不扫描区间。 575 字节的探测,加上应答路由上的 35 字节对照。该工具从不扫描长度范围,也绝不发送任何其他长度。

如果修改探测,请勿更改 PROBE_PREFIXES,也不要扫描长度区间。 575 字节是关键所在。其他 PrefixList 长度可能会使设备不稳定——至少在某个携带此修复的构建上出现过一次——因此长度扫描不是探索此漏洞的安全方式,更短也并不意味着更安全。

工作原理

已修补构建会干净地拒绝过大的 PrefixList,并返回一条独特的消息。未修补构建则会穿过解析器,返回一个通用的内部错误。同一个请求,两种不同的应答:

575 字节 PrefixList应答
未修补500 Internal Server Error 43549
已修补200 Malformed Assertion sent to Netscaler

会尝试两条路由,先 IdP,一旦其中一条给出应答即停止。任意一条单独使用都足够,两者合起来覆盖两种 SAML 角色:

IdP 路由首先被尝试,因为它是两者中更稳健的一个。它对 Issuer 值、AssertionConsumerServiceURL 以及时钟偏移不敏感——即使 IssueInstant 远远超出设备的偏移容限,仍能正确判别,因为规范化先于时间检查和签名检查执行。

路由 1 的 AuthnRequest 必须签名。 未签名的请求在已修补和未修补构建上都会返回 200 Malformed Assertion sent to Netscaler,这与已修补信号逐字节相同,因此省略签名块的探测会把每台设备都报告为已修补。签名不需要有效,本工具的签名也确实是无效的;它只需存在,因为正是其 SignedInfo 将 PrefixList 带入规范化器。

修复边界处的行为

两个受支持分支都在其修复构建处恰好改变行为,且两条路由均如此:

13.1-63.16 和 63.18 是连续版本,因此该变化可归因于补丁本身,而非中间构建之间的漂移。

这些是这个修复首次出现的构建,而该探测正是检测这一转变。它们已不再是应升级到的构建:后续公告已取代它们,因此 13.1-63.18 和 14.1-72.61 在此都会应答 PATCHED,但仍暴露于较新的问题之下。当前修复构建请参阅 修复措施。

为什么不对构建进行指纹识别?

因为在原理上它就无法针对此漏洞奏效。13.1-63.16 和 13.1-63.18 是紧邻修复两侧的构建,它们提供逐字节相同的 tmindex.html、base.css 以及 resources.js——该修复不触碰任何 Web 资源。静态资源哈希在各分支之间也存在碰撞,因此基于哈希的方法可能将易受攻击的设备解析为已修补的构建,并报告其为干净设备——这是检测工具最糟糕的失败模式。因此,构建指纹识别被刻意不实现。补丁状态来自探测,或者在你有凭据时来自 show ns version。

要求

  • Python 3.8+,仅标准库——无第三方包。

用法```bash

single target

./cve_2026_8452_check.py https://gateway.example.com

a specific AAA / Gateway virtual server

./cve_2026_8452_check.py https://gateway.example.com:9443

scan a list, one target per line ('#' comments allowed), compact output

./cve_2026_8452_check.py -f targets.txt --brief

machine-readable output for pipelines

./cve_2026_8452_check.py -f targets.txt --json > results.json

root@kitploit:~
将工具指向 **Gateway 或 AAA 虚拟服务器**,而不是管理接口。前提条件是针对每个虚拟服务器,因此拥有多个 VIP 的设备需要逐一测试。

### 选项

| Flag | 描述 |
| --- | --- |
| `URL` | 一个或多个 `https://HOST[:PORT]` 目标 |
| `-f, --targets-file FILE` | 从文件读取目标(每行一个;`#` 注释) |
| `-b, --brief` | 每个目标单行对齐输出 — 结论、目标、原因标记 — 用于扫描大量主机 |
| `--json` | 输出结构化 JSON 结果 |
| `--no-color` | 禁用彩色输出(同样遵循 `NO_COLOR` 和非 TTY) |
| `--timeout SECS` | 每次请求的超时时间(默认:15) |

### 示例

**未修补的设备,**在 IdP 路由上响应并已对照控制确认:```console
$ ./cve_2026_8452_check.py https://gateway.example.com:9443
====================================================================
  CVE-2026-8452 - NetScaler SAML PrefixList patch-state check
  https://gateway.example.com:9443
====================================================================

>> Identifying the appliance
     [ OK ]  NetScaler indicators: 5 (CSP contains citrixng://)
>> Probing patch state (64 prefixes / 575 bytes, confirmed against a 35-byte control)
     idp /saml/login      HTTP 500 / 43549: no size check present
     idp /saml/login      35-byte control: HTTP 200 "message timestamp outside the appliance's skew tolerance": a different SAML condition, not the size check
     [FAIL]  Size check absent (via the IDP route)

====================================================================
                         RESULT: VULNERABLE
====================================================================

  https://gateway.example.com:9443 via IDP  [size-check-absent]

  The size check is absent. This appliance is unpatched for
  CVE-2026-8452. Upgrade to 13.1-63.21+ / 14.1-73.32+ (12.1 and
  13.0 are EOL and never fixed).

====================================================================

控制行值得仔细阅读:35字节的请求通过了大小检查, 随后因其过期的 IssueInstant 而被拒绝,而575字节的探测请求则根本没走到那一步。 这正是整个方法所依赖的顺序——规范化在时间检查之前运行, 正如它在签名检查之前运行一样。

已修补的设备, 对修复版本发出的相同请求。只有探测行不同—— 超大的 PrefixList 按名称被拒绝,而不是落入内部错误:```console

Probing patch state (64 prefixes / 575 bytes, confirmed against a 35-byte control) idp /saml/login HTTP 200 "Malformed Assertion": size check rejected the probe idp /saml/login 35-byte control: HTTP 200 "message timestamp outside the appliance's skew tolerance": a different SAML condition, not the size check [ OK ] Size check present (via the IDP route)

root@kitploit:~
                      RESULT: PATCHED

https://vpn.example.com via IDP [size-check-present]

root@kitploit:~
**回退到 SP 路由。** 此处 IdP 端点可访问,但没有 IdP 策略绑定到
该虚拟服务器,因此路由 1 弃权,路由 2 应答。当*两个*路由都不匹配策略时
裁决为 `INCONCLUSIVE`,标记为 `no-policy-match` — 绝不会是 `PATCHED`,这正是
该裁决存在的原因:```console
>> Probing patch state (64 prefixes / 575 bytes, confirmed against a 35-byte control)
     idp /saml/login      HTTP 200 "Matching policy not found": parser not reached
     sp  /cgi/samlauth    HTTP 500 / 43549: no size check present
     sp  /cgi/samlauth    35-byte control: HTTP 200 "assertion rejected before the size check": a different SAML condition, not the size check
     [FAIL]  Size check absent (via the SP route)

                         RESULT: VULNERABLE

对照组捕获了它。 此处端点在这两种长度下都以修补后的消息响应,因此 大小检查从未被执行,看似决定性的结论被撤回。这就是误报 防护机制在起作用,而触发它的原因被明确说明,而非留待推断:```console

Probing patch state (64 prefixes / 575 bytes, confirmed against a 35-byte control) idp /saml/login HTTP 200 "Malformed Assertion": size check rejected the probe idp /saml/login 35-byte control: HTTP 200 "Malformed Assertion": size check rejected the probe [WARN] Probe and control answered alike, so the size check was never exercised

root@kitploit:~
                    RESULT: INCONCLUSIVE

https://sp-strict.example.com via IDP [flat-response]

The 575-byte probe and the 35-byte control got the same answer, so this endpoint replies the same way whatever it is sent and the size check was never exercised. Unknown, not patched.

root@kitploit:~
**扫描一批目标**(`--brief`),每个目标对应一行对齐输出,以原因标签结尾。退出状态为
`1`(若任何目标为 `VULNERABLE`):```console
$ ./cve_2026_8452_check.py -f targets.txt --brief; echo "exit: $?"
VULNERABLE       https://gateway.example.com:9443   size-check-absent
VULNERABLE       https://gateway.example.com:9444   size-check-absent
PATCHED          https://vpn.example.com            size-check-present
INCONCLUSIVE     https://sp-strict.example.com      flat-response
INCONCLUSIVE     https://gw-nopolicy.example.com    no-policy-match
UNAFFECTED       https://mgmt.example.com           no-saml-endpoint
ERROR            https://offline.example.com        not-identified
exit: 1

机器可读输出(--json),记录每个被尝试的路由。verdict、reason 和 detail 是权威字段;attempts 是原始证据,因此单个尝试可能 在判定为 INCONCLUSIVE 的目标上显示为 patched:```console $ ./cve_2026_8452_check.py https://vpn.example.com --json [ { "target": "https://vpn.example.com", "verdict": "PATCHED", "reason": "size-check-present", "route": "idp", "detail": "HTTP 200 "Malformed Assertion": size check rejected the probe", "attempts": [ { "route": "idp", "path": "/saml/login", "state": "patched", "detail": "HTTP 200 "Malformed Assertion": size check rejected the probe" }, { "route": "idp", "path": "/saml/login", "state": "control:known-error", "detail": "35-byte control: HTTP 200 "message timestamp outside the appliance's skew tolerance": a different SAML condition, not the size check" } ], "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)" ] } ]

root@kitploit:~
## 判定

每个判定都带有一个简短的 `reason` 标签,指明其背后的条件。`--brief` 会在第三列打印该标签,`--json` 则以 `reason` 字段携带它。

| 判定 | 原因标签 | 含义 |
| --- | --- | --- |
| `VULNERABLE` | `size-check-absent` | 缺少大小检查。此设备未打补丁 — 请修补它。 |
| `PATCHED` | `size-check-present` | 大小检查在探针到达的代码路径上被触发。**仅限此 CVE:** 这并不表示设备运行在最新构建上。 |
| `UNAFFECTED` | `no-saml-endpoint` | 此虚拟服务器上没有 SAML 端点应答,因此易受攻击的路径在此处不可达。**按 vserver 判定,而非按设备判定:** 同一台机器上的另一个 vserver 或 VIP 上可能配置了 SAML。 |
| `INCONCLUSIVE` | `flat-response` | 端点对 575 字节的探针和 35 字节的对照请求返回相同的应答,因此大小检查从未被触发。看似决定性的应答被撤回 — 这是误报防护在起作用。 |
| `INCONCLUSIVE` | `no-policy-match` | 有 SAML 端点应答,但没有绑定的策略匹配探针,因此两条路由都未到达规范化器。 |
| `INCONCLUSIVE` | `other-saml-error` | 某个可识别但不具诊断性的 SAML 条件在大小检查之前拒绝了探针 — 例如不同的长度限制、签名策略或时间戳。 |
| `INCONCLUSIVE` | `unrecognized-reply` | 某个 SAML 端点返回了识别集合之外的应答。 |
| `ERROR` | `not-identified` | 未识别为 NetScaler,或不可达。 |

所有四种 `INCONCLUSIVE` 原因对于决策而言含义相同 — **未知,而非已修补。**
请用 `show ns version` 确认。该标签用于告诉运维人员重新运行前需要修复*哪种*条件:将探针指向不同的虚拟服务器,或绑定匹配的策略。

`INCONCLUSIVE` 作为独立判定存在,并拥有自己的退出码,因为易受攻击的设备可能拒绝应答探针。如果绑定到虚拟服务器的 SAML 策略与探针的请求不匹配,设备会在规范化器之前短路,不返回任何诊断性内容。仅仅匹配失败的扫描器在这类主机上会保持静默,而静默会被解读为“已修补”。本工具则将其报告为未知。

### 每个判定都经由对照确认

`PATCHED` 和 `VULNERABLE` 都基于*单个*区分性应答,因此该工具会验证应答实际上取决于发送的内容。在得到决定性应答后,它会用一个 35 字节的短 `PrefixList` 重复该请求 — 低于任何大小检查 — 仅当两次应答不同时判定才成立。如果两次应答相同,则说明端点无论收到什么都会以同样方式应答,大小检查从未被触发,结果为 `INCONCLUSIVE`。

这并非假设。配置了 `samlRejectUnsignedAssertion STRICT` 的服务提供商会在*规范化之前*因缺少签名而拒绝探针,并在所有长度下都返回已修补的消息。没有对照时,此类设备会以退出码 0 报告 `PATCHED` — 这一现象曾在真正易受攻击的构建上被观察到。现在它会报告带有原因标签 `flat-response` 的 `INCONCLUSIVE`,运行输出会明确说明大小检查从未被触发。同样的对照还能捕获镜像情况:端点对从未解析的请求返回通用内部错误。

### 可识别的非诊断性应答

NetScaler SAML 端点拥有一大组可能的应答,其中只有两种能够确定补丁状态。该工具可识别其余 20 种,并在每条路由的行上指明对应条件,而不是回显响应主体,例如:```text
     idp /saml/login      HTTP 200 "post body over the appliance's maximum": a different length limit rejected the probe first
     sp  /cgi/samlauth    HTTP 200 "assertion rejected before the size check": a different SAML condition, not the size check

其中三项是 长度限制——过大的 POST 请求体、过大的 RelayState、过长的提取用户名。这些最为重要,因为它们意味着请求在到达那个区分补丁状态的检查之前,已被另一个长度检查拒绝。这通常意味着探测需要指向不同的虚拟服务器,而不是说明设备没有问题。

20 种响应中,有一种会在每次 IdP 路由运行中出现:控制项的消息时间戳超出设备的偏移容差。探测携带固定的 IssueInstant,因此通过大小检查的控制项随后会因其时间戳过旧而被拒绝——这是探测本身的属性,而非设备的属性。不属于这 20 种集合的回复会作为独立的第一行打印,而不是作为命名条件。

所有这些响应仍然产生 INCONCLUSIVE,并带有 other-saml-error 标记。识别出某个响应绝不会将其升级为 PATCHED:只有显式的已修补构建应答才能做到这一点,而且每个无法识别的回复同样会落入 INCONCLUSIVE——标记为 unrecognized-reply。这种识别的作用是告诉操作员目标为何无法被分类,而不是对其进行分类。

Exit codes

2 是 argparse 自身用于错误调用的退出码,因此判定结果码会跳过它。这样,包装脚本就能区分“此设备无法分类”(3)和“我调用工具的方式有误”(2),而一个重载了 2 的方案则无法做到这一点。

在多目标扫描中,退出码按 优先级而不是按最差状态 选择:VULNERABLE > INCONCLUSIVE > ERROR > 干净。因此,不可达的主机永远不会在退出码中掩盖易受攻击的发现。

限制

  • 此工具检查的是单个 CVE,而非设备的补丁级别。 PATCHED 和退出码 0 表示探测所到达的路径上存在 CVE-2026-8452 大小检查。它们对任何其他 NetScaler 漏洞不提供任何信息,包括在此漏洞之后披露并在后续构建中修复的漏洞。不要将本工具的退出码 0 视为设备健康状况良好的证明。
  • “不易受攻击”的判定仅限于你所探测的端点。 该前提条件是针对每个虚拟服务器的。UNAFFECTED 表示“在此处不可达”,而不是“此设备是安全的”。
  • 策略匹配会拦截解析器。 /saml/login 在整个设备范围内生效,但在未绑定任何 IdP 策略的虚拟服务器上,它会返回 Matching policy not found,并在规范化器之前短路。如果 IdP 的策略使用探测请求不满足的表达式规则,则会落入 INCONCLUSIVE,而不是给出答案。
  • INCONCLUSIVE 并非健康状况良好的证明。 它被刻意与 PATCHED 区分开来,并配有独立的退出码,这样“沉默”永远不会被误认为是通过的结果。
  • SAML 位于第一因素之后的 nFactor 部署报告 INCONCLUSIVE。 当 SAML 策略位于通过 nextFactor 到达的策略标签中,而不是直接绑定到虚拟服务器时,未经请求的断言会找不到匹配的策略,并在规范化器之前短路。已在易受攻击的构建上验证,其报告为 INCONCLUSIVE。由于 SAML 位于设备状态或登录架构第一因素之后是常见模式,请将 nFactor 网关上的 视为“可能可达,请使用 确认”,而不是一种异常情况。

修复建议

升级到 13.1-63.21 或更高版本,或 14.1-73.32 或更高版本(FIPS 和 NDcPP:14.1-73.32 FIPS,或适用于 13.1-FIPS 和 13.1-NDcPP 的 13.1-37.277)。

CVE-2026-8452 本身的修复首次随 13.1-63.18 / 14.1-72.61 发布,参见 CTX696604, 而这正是本工具检测的转换点。这些构建此后已被 CTX696939 (2026-08-19)取代,该公告新增了 CVE-2026-19489 和 CVE-2026-19490,后者是一个 CVSS 9.3 的预认证身份验证绕过。其在 14.1-43.56 / 13.1-61.28 及更高版本构建上的前提条件是配置了 SAML action—— 因此,本工具所检查漏洞范围内的设备很可能也在该漏洞的范围内,而且这里的 PATCHED 判定并不是推迟升级的理由。上述构建已清除两份公告中的问题。

12.1 或 13.0 上的设备没有修复方案,也不会获得修复——这些分支已停止维护,应被视为永久易受攻击,并迁移到受支持的版本分支。

还有两点补充说明:

  • 修补 HA 对的两个节点。 未修补的备用节点一旦接管,就是一个完全暴露的设备。

  • 按 SAML 配置而不是按虚拟服务器类型来界定资产范围。 厂商公告中的措辞(Gateway 或 AAA 虚拟服务器)比触发条件更为宽泛。请在运行配置中检查 add authentication samlAction 和 add authentication samlIdPProfile,同时也要检查 add authentication vserver 和 add vpn vserver。

    这一点经过实测,而非推测。在一台确认易受攻击的设备上,我们移除了所有 SAML 对象,绑定了一个非 SAML 身份验证因素作为替代,并让 AAA 虚拟服务器保持运行和服务状态:随后 SAML 端点对每个请求都返回 404。这些端点并非仅仅在没有 SAML 配置时被策略门控——它们根本不存在。因此,一个没有 SAML 的虚拟服务器确实不在该漏洞的范围内,UNAFFECTED 在此类目标上是一个真实的答案,而不是盲点。仍然适用的注意事项是上述范围界定问题:它是按虚拟服务器划分的,因此请逐一确认每个 VIP,而不是对整个设备得出任何结论。

CVE-2026-8452 与同一公告中的五个姊妹漏洞一同发布。其中值得紧随其后关注的是 CVE-2026-8451,这是 SAML IdP 路径中的一个预认证内存越界读取(overread)漏洞,已在野外遭到积极利用。这两个漏洞共享相同的攻击面,因此相同的配置审计即可覆盖两者。

许可证

本代码根据 MIT 许可证 分发。

法律免责声明

未经事先双方同意,使用此工具攻击目标属于违法行为。遵守所有适用的地方、州和联邦法律是最终用户的责任。开发者不承担任何责任,也不对本程序造成的任何误用或损害负责。

另请参阅

  • Citrix CTX696604 — NetScaler 安全公告
  • Citrix CTX696939 — 取代上述已修复构建的后续 NetScaler 公告
  • watchTowr Labs — CVE-2026-8452 技术分析
  • NVD — CVE-2026-8452
下载工具
路由请求要求
1(首选)POST /saml/login — 签名后的 AuthnRequest,PrefixList 位于 ds:SignedInfo 中绑定到目标 vserver 的 SAML IdP 策略
2(后备)POST /cgi/samlauth — SAMLResponse,PrefixList 位于断言签名中目标 vserver 上的 SAML SP 断言消费者服务
构建判定
13.1-63.16最后一个存在漏洞的 13.1VULNERABLE
13.1-63.18第一个修复的 13.1PATCHED
14.1-66.59存在漏洞的 14.1VULNERABLE
14.1-72.61第一个修复的 14.1PATCHED
CodeMeaning
0已修补,或在目标虚拟服务器上不受影响
1至少一个目标为 VULNERABLE
2用法错误(参数错误 / 目标文件不可读)
3至少一个目标为 INCONCLUSIVE,且没有易受攻击的目标
4至少一个目标出错,且没有易受攻击或无法定论的目标
INCONCLUSIVE
show ns version
  • 这不是漏洞利用检测。 VULNERABLE 判定确认了缺失的大小检查,即补丁状态。它不会衡量攻击者能在你的构建上将内存破坏推进到什么程度。
  • 仅代表可达性。 结果反映的是设备在你运行探测的网络位置上所暴露的内容。设备前面的 WAF 可能会掩盖响应。