AmesianX/CVE-2026-53435

GitHub: AmesianX/CVE-2026-53435

针对 Jenkins 反序列化漏洞 CVE-2026-53435 的 PoC 项目,附带从公告到可用 exploit 的完整 8 小时研究过程记录与差异化验证实验环境。

Stars: 7 | Forks: 2

# CVE-2026-53435 — Jenkins 反序列化 → 任意文件读取 (PoC) ![CVE-2026-53435 PoC 从 Jenkins controller 读取 /etc/passwd](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/8b72ffb7e8005426.png) | | | |---|---| | **CVE** | CVE-2026-53435 (Jenkins SECURITY-3707) | | **类别** | 不安全的反序列化(通过 config.xml 绕过 ClassFilter) | | **影响(本 PoC)** | controller 上的已认证任意文件读取 | | **受影响版本** | Jenkins weekly ≤ 2.567, LTS ≤ 2.555.2 | | **修复版本** | Jenkins weekly 2.568, LTS 2.555.3 | | **安全公告** | https://www.jenkins.io/security/advisory/2026-06-10/ (发布于 2026-06-10) | | **撰写本文时的状态** | 当时无公开 PoC(GitHub PoC 仓库数:0) | ## 为什么创建此仓库 这是一次展示*过程*而不仅仅是最终成果的实验。 多年来,攻击性安全研究人员的产出仅仅是单个最终的 exploit —— 导致产生该 exploit 的那 8 小时的错误尝试都随之消失了。这个仓库保留了那些 错误尝试。人类与 AI 协作从安全公告开始到产出可用 PoC 的完整、经过轻微编辑的 记录被作为附录收录其中。 它想要刻意表达的重点*并不是*“这是 AI 做的”。这 8 小时恰恰证明了 并非如此。AI 从未一次性成功生成整个利用链。真正支撑这项工作的是 领域专业知识 —— 知道安全公告中隐藏着一个反序列化 sink, 知道应去查看 Jenkins **core** 类型而不是插件,知道补丁前 `DescribableList` 不会强制执行其元素类型,并且知道如何 *验证*一个断言而不是盲目相信它。研究人员的价值并没有 消失;它只是从**敲击 exploit 代码**转移到了**引导、剪枝和** **验证**上。 这种转变才是真正值得记录的东西。 ## 漏洞(根本原因) Jenkins 通过自定义的 `ClassFilter` 保护反序列化过程,该过滤器仅允许 Jenkins core 或插件中定义的类型。CVE-2026-53435 表明这*仍然不够*: 能够 POST 一个 `config.xml` 的攻击者,可以让 Jenkins 将**任意的 core/插件类型反序列化到一个从未预期处理它的上下文中**, 随后通过 Stapler 路由经由 HTTP 访问到该对象。 此 PoC 将一个 `hudson.Plugin$DummyImpl`(一个 Jenkins-core 类型,因此它能 通过位置白名单)植入到一个 `ListView` 的 `` 列表中 —— 这是一个 `DescribableList`,在打补丁前,它不会强制校验其元素 类型。植入的对象带有 `baseResourceURL=file:/`。随后将 HTTP 请求路由到该对象,就会直接从 controller 的文件系统提供文件。 通用的 ysoserial 链在此处**不起作用** —— gadget 必须是 Jenkins/插件固有的类型才能绕过过滤器。这个限制条件正是 关键所在。 ## 范围与负责任的漏洞披露 - 此 PoC 仅演示了**任意文件读取**的影响。 - 安全公告还描述了通过同一底层原语实现的**用户模拟**和**Script Console RCE**。 这些利用链在研究过程中已被触达,但在此处被**刻意隐去**: 该 CVE 在发布前几天才被修复,而一个现成的 RCE 主要会被用于对 未修复实例的大规模漏洞利用。文件读取已足以证明其影响。 - 该漏洞**已被修复**。所有测试均在作者自己的机器上针对 **本地的、隔离的实验环境**(见下文)进行。未触及任何外部 或第三方系统。 **仅对你拥有或明确获得授权测试的系统使用此工具。** ## 证明:在受影响版本成功,在修复版本失效 该 exploit 分别针对两个配置完全相同的容器运行 —— 受影响版本 `2.555.2` 和修复版本 `2.555.3` —— 以确认它触发的是*这个* CVE,而不是 某些不相关的文件读取原语: | | **2.555.2 (受影响)** | **2.555.3 (已修复)** | |---|---|---| | `createView` | HTTP 200 | HTTP 200 | | 存储的 `` | `` — **留存** | `` — **被剥离** | | 触发 → `/etc/passwd` | `root:x:0:0:...` — **成功读取** | 空 — **被拦截** | 修复后的版本接受了请求,但修复措施**在反序列化时拒绝了植入的类型**, 因此 properties 列表返回为空,也就没有任何可供路由的对象。 该失败恰好对应于安全公告所描述的机制 —— 这正是它成为 CVE-2026-53435 真正 PoC 的原因。 ## 用法 ``` python3 exploit_cve_2026_53435_v2.py [view_name] # 示例(针对您自己的实验室): python3 exploit_cve_2026_53435_v2.py http://127.0.0.1:8080 /etc/passwd ``` - `base_url` — 目标的 `http://host:port`(纯 HTTP;不要添加 `https` 前缀,除非该实例确实终结了 TLS)。 - 需要一个具有 POST 视图 `config.xml` 权限 (View/Configure) 以及 Overall/Read 权限的账户。 ## 复现实验环境 ``` docker compose -f lab/docker-compose.yml up -d # 存在漏洞: http://127.0.0.1:8080 (Jenkins LTS 2.555.2) # 已修补: http://127.0.0.1:8081 (Jenkins LTS 2.555.3, negative control) ``` 该实验环境通过 Groovy init 配置了一个仅限本地的用户数据库,以便在无需 外部 IdP 的情况下测试已认证低权限路径。 ## 时间线 — 约 8.5 小时,某个星期五的晚上 ``` 2026-06-12 (Fri) 15:00 → 23:23 ≈ 8h 20m 15:00–15:12 Lab built (docker: vuln 2.555.2 / patched 2.555.3) + first recon 15:12–21:00 Deserialization sink & gadget analysis (Commons-Collections bypass attempts failed → pivot from properties to actions and back) 21:00–22:30 ClassFilter analysis + gadget re-hunt, restricted to core types 22:30–23:00 Working PoC (v1 → v2) + differential verification (vuln vs patched) ``` 这些时间大部分都花在*分析*上,而不是敲代码。exploit 本身是 在最后约 30 分钟内完成的 —— 也就是在确定了正确的 sink 和 gadget 之后。 ## 构建方式 使用 **Claude Code** (Anthropic) 构建,由作者交互式驱动: - **主要模型:** Claude **Opus 4.8** (Claude Max) - **部分:** Claude **Fable 5** (Mythos-class 级别)