WordPress wp2shell 漏洞复盘:REST API 批处理路由混淆一路杀到 RCE
前言
今天群里有人甩了条安恒的漏洞通告过来,标题挺唬人——WordPress REST API 批处理路由混淆与 SQL 注入远程代码执行漏洞,CVSS 9.8。我自己就是 WordPress 跑的博客,这种「未授权 RCE」级别的洞,不管三七二十一先看一眼。
看完原文又去翻了一圈官方公告和研究团队原文,发现通告里只提了一个 CVE,实际是两个 CVE 串在一起的链条利用。而且影响范围也比原文写的更广——6.8 分支也中招。这里记一下,免得后面自己又忘了。
漏洞概览:wp2shell,一条链杀到 RCE
这次漏洞代号 wp2shell,由 Searchlight Cyber 的安全研究团队 Adam Kues 报告。核心是 WordPress 核心代码里两个问题串起来:
- CVE-2026-63030:REST API
/batch/v1端点的路由混淆。处理批量子请求时,serve_batch_request_v1()构建了$matches(处理程序)和$validation(验证结果)两个并行数组。但当子请求路径在wp_parse_url()解析失败时,该子请求只被追加到$validation,没进$matches,数组错位了,后续子请求就被错配到别的处理程序上。 - CVE-2026-60137:借着上面的错位,攻击者把 GET 参数(如
author_exclude)塞进内层 POST 请求里。这个参数到了WP_Query时没经过净化就直接拼到 SQL 语句里,形成布尔型 + 时间型盲注。
光 SQL 注入已经够烦了,但作者把链拉满了:通过注入读数据库 → 拿到管理员密码哈希 → 离线破解 → 后台上传恶意插件 → 任意代码执行。从「未授权」一路杀到「拿 shell」,这就是 wp2shell 名字的由来。
CVSS 9.8,攻击复杂度低,无需任何权限,无需用户交互,通过网络直接可达。500万+ WordPress 站点都在射程内。
影响范围:6.8 也在里面,别只看 7.0
安恒原文只写了 6.9.0-6.9.4、7.0.0-7.0.1。但去 WordPress 官方公告一看,6.8 分支也受影响(只中了第一个 CVE,没中第二个,但也得修)。完整范围如下:
- WordPress 6.8.0 - 6.8.5(仅 CVE-2026-60137)
- WordPress 6.9.0 - 6.9.4(两个 CVE 全中)
- WordPress 7.0.0 - 7.0.1(两个 CVE 全中)
- WordPress 7.1 beta1(两个 CVE 全中)
6.8 之前的版本不受影响。安全版本是 6.8.6 / 6.9.5 / 7.0.2 / 7.1 beta2。
我自己的站是 7.0.1,正好在坑里。 ![]()
技术原理:数组错位是怎么发生的
这块我边看边记,方便理解。REST API 的 batch 端点允许一次请求里塞多个子请求,本意是减少 HTTP 往返。处理逻辑大概是这样:
- 遍历每个子请求,用
wp_parse_url()解析它的 path。 - 根据解析结果,把对应的处理程序追加到
$matches,把验证结果追加到$validation。 - 两个数组按下标一一对应,后续按
$matches[i]取处理程序,$validation[i]取验证结果。
坑在哪?当 wp_parse_url() 解析失败时(比如构造了畸形的 path),代码只往 $validation 追加,没往 $matches 追加。$matches 少了一个元素,下标全错位。第 N 个子请求拿到的处理程序,其实是第 N+1 个的。
攻击者就利用这个错位:把一个本该走 A 处理程序的请求,送到本该走 B 处理程序的逻辑里。B 处理程序恰好接受 author_exclude 这种 GET 参数,并把它喂给 WP_Query。WP_Query 没对这个参数做类型/格式校验,直接拼进 SQL。注入就成立了。
盲注虽然慢,但稳。一点点把 wp_users 表里的 user_pass 字段 dump 出来,拿到 phpass 哈希,离线爆破。WordPress 默认用户名 admin 加弱口令哈希,破解不算难。拿到管理员账号后,后台「上传插件」上传个伪装成 .zip 的恶意插件,激活,shell 就落地了。
整个链路零前置条件——不需要插件,不需要特殊配置,开箱即用的 WordPress 就能打。
自查:先看自己中没中
三步:
- 看版本:后台「仪表盘 → 更新」或者首页右下角的「概览」能看到当前版本。在 6.8.0-6.8.5、6.9.0-6.9.4、7.0.0-7.0.1、7.1 beta1 范围内的,全中。
- 用官方检测工具:研究团队放了个在线检测站点 wp2shell.com,输自己的域名就能扫。
- 查日志:翻 Nginx access log,找路径含
/wp-json/batch/v1或?rest_route=/batch/v1的异常批量请求。短时间内大量这种请求,基本就是被探测了。
修复:能升级就别拖
官方 7 月 17 日发了强制自动更新,受影响版本的站点大部分应该已经自动升上去了。手动升级的话:
- 7.0 分支 → 升到 7.0.2
- 6.9 分支 → 升到 6.9.5
- 6.8 分支 → 升到 6.8.6
- 7.1 测试分支 → 升到 7.1 beta2
后台「更新」页面点「立即更新」,或去 WordPress.org 下载 7.0.2 手动覆盖。升级前备份数据库和文件,别偷懒。
临时缓解:暂时升不了怎么办
如果暂时没法升级(比如改过核心代码、插件兼容性没测完),先做应急:
- WAF 拦截:在 Nginx 或 WAF 层拦掉
/wp-json/batch/v1和?rest_route=/batch/v1两条路径。我是直接在 Nginx 加了几行:
# 拦掉匿名访问的 batch API
location ~ ^/wp-json/batch/v1 {
if ($http_authorization = "") {
return 403;
}
}
# 拦掉 rest_route 查询参数形式
if ($arg_rest_route ~* "^/batch/v1") {
return 403;
}
- 插件禁用:装个 Disable WP REST API 之类的插件,直接禁掉匿名用户的 REST API 访问。风险是可能影响部分依赖 REST API 的功能(比如区块编辑器、某些插件的回调)。
- Searchlight Cyber 的应急插件:研究团队放了个自定义插件
disable-batch-api-for-unauth.php,放到wp-content/plugins/下启用,强制 REST Batch API 需身份验证。比全局禁用 REST API 影响面小。
这几个都是临时措施,可能影响合法业务,升级到安全版本后记得撤掉。
小结
这次 wp2shell 漏洞几个关键点记一下:
- 是两个 CVE 的组合链,不是单点。光看安恒通告只提了 63030,容易漏掉 60137。
- 6.8 分支也受影响(只中 60137),别只盯着 6.9/7.0。
- 从路由混淆 → SQL 注入 → 读密码哈希 → 上传插件 → RCE,整条链零前置条件,开箱即用就能打。
- 官方已强制自动更新,先确认自己站是不是已经升上去了。没升的赶紧手动升。
- 暂时升不了的,WAF 拦
/batch/v1是最简单的应急。
安全这事儿,没有「小站不会被盯上」这一说。扫描器是无差别扫的,你的站只要暴露在公网,就在候选名单里。该升就升,别拖。
「摸鱼小窝」 (blog.aistu.cn)版权所有,引用、转载时必须标明原文出处!







加载中