BishopFox/CVE-2026-11374-check

GitHub: BishopFox/CVE-2026-11374-check

一款用于检测 ManageEngine AD360 集成环境下 CVE-2026-11374 SSO 票据重放漏洞利用前置条件的安全检测脚本。

Stars: 0 | Forks: 0

# CVE-2026-11374 ManageEngine AD360 前置条件检测脚本 这是一个针对 CVE-2026-11374 漏洞利用前置条件的检测脚本。该漏洞是一个可预测的 SSO 票据(SSO-ticket)缺陷,可导致 ManageEngine AD360 套件遭受未经身份验证的账户接管。范围内的四款产品共享 `ManageEngineADSFramework`: | 产品 | 受影响的构建版本 | 已修复的构建版本 | |---|---|---| | ADSelfService Plus | ≤ 6528 | 6529 | | RecoveryManager Plus | ≤ 6320 | 6321 | | M365 Manager Plus | ≤ 4816 | 4817 | | ADAudit Plus | ≤ 8702 | 8703 | 在受影响的构建版本中,SSO 票据仅仅是 `System.currentTimeMillis()`(一个可预测的时间戳),该值在受害者登录时被采样,因此攻击者可以通过 `CUSTOM_SSO_TICKET` cookie 对其进行重放,从而劫持该会话。该修复方案将票据替换为 `UUID.randomUUID()`(一个具备足够随机性的标识符)。该重放路径仅在产品集成了 AD360 时可达:`ADSFilter` 会通过 `isProductIntegrated()` 对其进行限制。这个限制条件正是本工具所要检测的前置条件。 ## 运行安全吗? 是的。本工具专为生产环境和评估用途而设计。 - 不会进行任何利用操作。探测请求会发送一个无效的 SSO 票据(`1700000000000`,一个足够久远的过去时间毫秒值,因此永远不会驻留在缓存中),所以绝不会恢复任何会话。服务器只会要求我们清除发送的 cookie。 - 不会改变目标状态。每个请求都是纯粹的 `GET` 请求,且受影响的 cookie 仅有工具发送的一次性 cookie。 - 不会进行暴力破解或会话解析。本工具不会尝试进行主动的时间戳票据解析来证明其可利用性;那属于漏洞利用而非检测,这超出了本工具的范围(请参阅 [局限性](#limitations))。 ## 本工具能检测到什么以及不能检测到什么 CVE-2026-11374 的补丁仅更改了票据的生成方式(从毫秒时间戳改为 UUID),并未更改此探测所利用的 cookie 重放路径。因此,对于任何未经身份验证的请求,已修复的安装环境与存在漏洞的安装环境的响应在字节层面是完全一致的。 本工具可以在未经身份验证且不产生破坏的情况下做到: - 确认可达的范围内产品是否已激活 CustomSSO cookie 重放路径(即是否集成了 AD360),这正是 CVE-2026-11374 漏洞利用的前置条件。 - 通过各产品专属的会话 cookie 识别出它具体是这四款产品中的哪一款。 - 尽力读取资产构建版本号作为提示。此功能在 ADSelfService Plus、ADAudit Plus 和 M365 Manager Plus 上可用;在 RecoveryManager Plus 上不可用。 本工具做不到: - 区分存在漏洞和已修复的状态。目前没有安全、被动且无需身份验证的信号能进行区分。`POTENTIALLY_AFFECTED` 结果仅表示前置条件已满足,您应该去核实补丁状态,而并不意味着该主机被确认存在漏洞。 - 确认可利用性。要证明主机确实可被利用,需要观察已生成的票据格式(13位数字代表存在漏洞,UUID 代表已修复,这两者都需要经过身份验证或在主机端具有可见性)、在本地读取 `conf/product.conf`,或者主动解析实时票据(这属于真实的漏洞利用,本工具故意不予实现)。 - 完全信任低于已修复版本的 ADSelfService Plus 构建版本号。ADSSP 的 `?build=` 有时是真实的构建版本,有时则是一个低于已修复版本的固化占位符,因此低于已修复版本的值是模棱两可的,工具会将其标记为 inconclusive(结果不明)。如果该值大于或等于已修复版本,它仍然是一个值得信赖的“已修复”信号,因为占位符的值总是很低,不可能达到已修复版本的数值。 ## 环境要求 - Python 3.7+ 以及 [`requests`](https://pypi.org/project/requests/) 库。可以通过以下命令安装: `pip install requests`。 ## 使用方法 ``` # 单个 host(推荐使用 URL 或 host:port;每个产品的 ports 不同) ./cve_2026_11374_check.py https://adssp.example.com:8888 # 多个 hosts(scheme 可选:优先尝试 https,然后是 http) ./cve_2026_11374_check.py host-a:8081 host-b:8365 # 扫描列表,每行一个 target(允许使用 '#' 注释),compact output ./cve_2026_11374_check.py -f targets.txt --brief # 用于 pipelines 的 machine-readable output ./cve_2026_11374_check.py -f targets.txt --json > results.json ``` 各产品的默认端口有所不同(ADSelfService Plus 为 8888,ADAudit Plus 为 8081,M365 Manager Plus 为 8365,RecoveryManager Plus 为 8090),因此请传入完整的 URL 或 `host:port`。如果仅提供主机名,则默认使用 8888 端口。 ### 选项 | 参数 | 描述 | |------|-------------| | `targets` | 一个或多个 `host`、`host:port` 或 `https://host:port` | | `-f, --targets-file FILE` | 从文件中读取目标(每行一个;支持 `#` 注释) | | `--brief` | 每个目标输出单行对齐结果,适合扫描大量主机 | | `--json` | 输出结构化的 JSON 结果 | | `--timeout SECS` | 单次请求超时时间(默认:15) | | `--no-build` | 在得出阳性检测结果时跳过额外的构建版本号请求 | | `--no-color` | 禁用彩色输出(同时也遵循 `NO_COLOR` 环境变量及非 TTY 环境) | ### 示例 集成了 AD360 的控制台(详细模式,默认)。第二行说明这仅代表满足前置条件,而并非判定为存在漏洞;第三行是尽最大努力获取到的构建版本提示: ``` $ ./cve_2026_11374_check.py https://adssp.example.com:8888 [!] https://adssp.example.com:8888: POTENTIALLY_AFFECTED ADSelfService Plus: AD360-integrated, CustomSSO replay path active - precondition met. Not confirmed vulnerable; verify patch level (fixed build 6529). build: 6519 (below fixed 6529 - inconclusive: ?build= may be a stale placeholder or a hotfix) ``` 同一产品的独立安装环境,其重放路径未被激活: ``` $ ./cve_2026_11374_check.py https://adssp.example.com:8888 [+] https://adssp.example.com:8888: UNAFFECTED ADSelfService Plus: standalone / not AD360-integrated (no cleanup), so the replay path isn't reachable here. Verify build >= 6529 regardless. ``` 以每个主机单行对齐(`--brief`)的方式扫描列表。如果存在任何主机的结果为 `POTENTIALLY_AFFECTED`,退出状态码将为 `1`,否则为 `0`,这在编写脚本时非常实用。末尾的备注会显示识别出的产品,并在检测到结果时附带构建版本号: ``` $ ./cve_2026_11374_check.py -f targets.txt --brief; echo "exit: $?" POTENTIALLY_AFFECTED https://host-a:8888 ADSelfService Plus 6519 POTENTIALLY_AFFECTED http://host-b:8081 ADAudit Plus 8530 UNAFFECTED http://host-c:8365 M365 Manager Plus UNAFFECTED https://host-d:443 INCONCLUSIVE http://host-e:8888 ADSelfService Plus ERROR host-f:8888 timeout exit: 1 ``` 机器可读输出(`--json`)。每个结果包含 `verdict`(判定)、其背后的 `state`(状态)和 `detail`(详情)、识别出的 `product`(产品),以及 —— 在检测到结果时 —— 会附带一个 `build` 对象:`build` 表示查找到的版本号,`fixed_build` 表示该产品的已修复版本阈值,`patch_hint` 表示方向性判断(大于或等于已修复版本时显示为 `likely_patched`,否则为 `inconclusive`),`note` 则提供简短说明: ``` $ ./cve_2026_11374_check.py https://host-b:8081 --json [ { "target": "https://host-b:8081", "state": "potentially_affected", "detail": "ADAudit Plus: AD360-integrated, CustomSSO replay path active - precondition met ...", "product": "ADAudit Plus", "build": { "build": "8530", "fixed_build": "8703", "patch_hint": "inconclusive", "note": "below fixed 8703 - inconclusive: may be a hotfix" }, "verdict": "POTENTIALLY_AFFECTED" } ] ``` ## 判定结果 | 判定结果 | 含义 | |---------|---------| | `POTENTIALLY_AFFECTED` | 集成了 AD360 的范围内产品;CustomSSO cookie 重放路径已激活,满足 CVE-2026-11374 的漏洞利用前置条件。这并非确认存在漏洞的判定;请核实补丁状态(参见后续步骤)。 | | `UNAFFECTED` | 重放路径不可达。可能为以下任意一种情况:独立安装的范围内产品(未集成 AD360 —— 但如果以后进行了集成,该路径将变得可达,因此仍需核实构建版本);属于 ManageEngine ADS-framework 但不在四款范围内的产品;或者响应信息中根本没有范围内的产品(不属于这四款 CVE-2026-11374 产品之一,或者是代理服务器剥离了会话 cookie)。 | | `INCONCLUSIVE` | 返回 `HTTP 400` —— 很可能是触发了 IAM 速率限制锁定从而掩盖了信号;请在约 60 秒后重试。 | | `ERROR` | 连接/超时/TLS 失败。 | ## 退出码 | 代码 | 含义 | |------|---------| | `0` | 没有目标返回 `POTENTIALLY_AFFECTED` | | `1` | 至少有一个目标的结果为 `POTENTIALLY_AFFECTED` | | `2` | 使用错误(参数错误 / 目标文件无法读取) | ## 工作原理 向任何 CustomSSO URL (`*.do`) 发送一个无效票据以及一个应用标签(app tag): ``` GET /AppsHome.do Cookie: CUSTOM_SSO_TICKET=1700000000000; CUSTOM_SSO_APP_TAG_NAME=AD360 ``` 在集成了 AD360 的安装环境中,调用链 `ADSFilter → CustomSSOFilter → CookieSSOImpl` 会运行其解析分支(由于标签指定了不同的产品,因此 `appName != prodName`),在解析伪造票据失败后,会发出清理 cookie 的响应头: ``` Set-Cookie: CUSTOM_SSO_TICKET=removed; Max-Age=0; ... Set-Cookie: CUSTOM_SSO_APP_NAME=removed; Max-Age=0; ... Set-Cookie: CUSTOM_SSO_APP_TAG_NAME=removed; Max-Age=0; ... ``` 独立安装的环境永远不会运行该路径,因此也不会发出清理指令。系统通过产品固定的 Tomcat 专属会话 cookie(例如 ADSelfService Plus 使用 `JSESSIONIDADSSP`)来识别产品,该 cookie 会在每次响应中被设置。该检测主要依据响应头而非状态码,因为集成的 ADSSP 会返回 `302` 状态码,而 ADAudit、M365 和 RMP 在面对相同的探测请求时会返回 `200`。 | 探测响应 | 判定结果 | |----------------|---------| | 包含清理响应头且带有已知的范围内产品 cookie | `POTENTIALLY_AFFECTED` | | 包含产品 cookie,无清理响应头,状态码 ≠ 400 | `UNAFFECTED`(独立安装 / 未集成) | | 没有范围内的产品 cookie,状态码 ≠ 400 | `UNAFFECTED`(不属于这四款产品之一) | | 包含清理响应头但产品 cookie 无法识别 | `UNAFFECTED`(属于 ManageEngine 但不在范围内) | | `HTTP 400` | `INCONCLUSIVE`(可能是触发了 IAM 速率限制锁定;请参阅局限性) | ## 局限性 - `POTENTIALLY_AFFECTED` 并不代表“确认存在漏洞”。它仅代表满足漏洞利用的前置条件。由于补丁并未修改此代码路径,已修复版本的响应是一样的,因此您必须通过非直接交互方式确认补丁状态(参见后续步骤)。这也是未经身份验证的观察者所能获取信息的上限。 - 没有主动确认机制。本工具绝对不会尝试解析真实的、当前时间的票据。该技术可以明确证明主机存在漏洞,但这属于主动利用行为(它会劫持实时会话),受限于限流策略且具有概率性,同时还需要存在处于活动状态的受害者会话,因此本检测工具不予实现。 - `HTTP 400` 可能是由于速率限制锁定造成的,而非真实的响应结果。Zoho IAM 应用了 URL 轮流限流机制,将单个源 IP 的请求限制为每 60 秒约 40 次,随后会锁定该路径约 60 秒。在锁定期间,请求会返回 `HTTP 400`,从而掩盖了集成信号。本工具将这些情况报告为 `INCONCLUSIVE`;请在大约一分钟后再从该 IP 重试。 - 在反向代理后,剥离或重写会话 cookie 的控制台可能会被误报为 `UNAFFECTED`。如果您预期那里存在 ManageEngine 产品,请直接进行确认。 - 构建版本号只是提示,而非最终判定。ADAudit (`?v=`) 和 M365 (`?bN=`) 始终会暴露真实的构建版本;ADSSP 的 `?build=` 有时是真实的,有时则是一个低于已修复版本的固化占位符,因此低于已修复版本的 ADSSP 值具有歧义;而 RMP 不暴露任何版本号。在所有情况下,大于或等于已修复版本的构建号都强烈表明已修复,低于该版本则结果不明。 ## 防御者的后续步骤 如果目标检测结果为 `POTENTIALLY_AFFECTED`,请将其视为已暴露并值得核实,随后请执行以下操作: 1. 直接确认补丁状态(本工具无法做到)。在主机上读取 `conf/product.conf`(`build_number`),并将其与该产品的已修复版本进行比较(ADSelfService Plus 6529,RecoveryManager Plus 6321,M365 Manager Plus 4817,ADAudit Plus 8703)。对此需要进行方向性解读:大于或等于已修复版本的构建版本是主机已安装补丁的有力指标,因为 UUID 修复程序就在该代码树中。低于已修复版本的构建版本只能作为结果不明,而不能作为存在漏洞的证明,因为带外修复程序和向后移植可能会应用 UUID 修复而不提升构建版本号;在这种情况下,请退而求其次使用下方的票据格式检查。 2. 如果您可以登录,请检查生成的票据格式。`CUSTOM_SSO_TICKET` cookie 没有设置 `HttpOnly` 属性,因此在通过身份验证后,您可以读取它的值:13位数字代表存在漏洞,UUID 则代表已修复。这是最清晰的检查手段。 3. 在存在漏洞或无法确认已修复的主机上,更新至已修复版本(或更高版本)。该修复将可预测的票据替换为了随机 UUID。 4. 排查漏洞利用企图。在主机的 `serverOut_.txt` 中,限流策略会被记录为以下信息的爆发: IAMSecurityException ErrorCode: URL_ROLLING_THROTTLES_LIMIT_EX, RequestURI: "/showLogin.cc", RemoteAddr: <源 IP> 如果发现来自单一源 IP 的、针对 SSO/登录调度路径的 `URL_ROLLING_THROTTLES_LIMIT_EXCEEDED` 请求出现峰值,这就是票据暴力破解的有力证明。同时,还应审查最近的成功登录记录和会话活动,寻找被接管的迹象。 5. 在此期间尽量减少暴露面。限制对 AD360 套件的网络访问(它不应暴露在公网上),如果不需要使用重放路径,禁用 CustomSSO 集成可以彻底消除该前置条件。 ## 修复建议 将受影响的产品至少更新至已修复版本(ADSelfService Plus 6529,RecoveryManager Plus 6321,M365 Manager Plus 4817,ADAudit Plus 8703)或更高版本。该修复方案将可预测的 `System.currentTimeMillis()` SSO 票据替换为了 `UUID.randomUUID()`。 ## 许可证 本代码基于 [MIT 许可证](LICENSE) 发布。 ## 法律免责声明 未经双方事先同意,使用本工具攻击目标是违法行为。最终用户有责任遵守所有适用的地方、州和联邦法律。开发者不承担任何责任,也不对由本程序造成的任何误用或损害负责。 ## 另请参阅 - [NVD: CVE-2026-11374](https://nvd.nist.gov/vuln/detail/CVE-2026-11374) - ManageEngine 服务包: [ADSelfService Plus](https://www.manageengine.com/products/self-service-password/service-pack.html) · [RecoveryManager Plus](https://www.manageengine.com/ad-recovery-manager/service-pack.html) · [M365 Manager Plus](https://www.manageengine.com/microsoft-365-management-reporting/service-pack.html) · [ADAudit Plus](https://www.manageengine.com/products/active-directory-audit/service-pack.html) - [Bishop Fox 博客:完整技术分析](https://bishopfox.com/blog/)
标签:无服务器架构, 逆向工具