出去玩了一周,然后 WordPress 圈就炸了。
WordPress 官方 近日紧急发布了 7.0.2 安全版本,修复了一个代号为 wp2shell 的极危漏洞链(由 CVE-2026-63030 与 CVE-2026-60137 组合而成)。
该漏洞链允许未授权的匿名攻击者在默认安装的 WordPress 网站上直接执行任意代码(Pre-Auth RCE)。鉴于漏洞的严重性,WordPress.org 官方已启动强制自动更新机制推送补丁。
wp2shell 漏洞原理与详细利用过程
wp2shell 的核心威力在于将两个中高危级别的漏洞完美串联,形成了一个无需任何前置条件的“未授权远程代码执行”攻击链:
WP_Query中的 SQL 注入
CVE-2026-60137
漏洞源头:自 WordPress 6.8 引入。
技术机制:WP_Query类在处理 author__not_in参数时存在 PHP 类型混淆(Type Juggling)缺陷。程序原本预期接收一个整数数组,但如果攻击者传入一个精心构造的字符串,系统将绕过数组过滤逻辑,直接将原始字符串拼接进 SQL 查询语句的 WHERE条件中。
受限条件:该 SQL 注入本身虽然危害大,但在正常情况下暴露该参数的 REST 路由需要管理员身份验证,因此单独存在时属于“受限注入”。
REST API 批量路由混淆
CVE-2026-63030
漏洞源头:自 WordPress 6.9 引入。
技术机制:WordPress REST API 的批量处理接口(/wp-json/batch/v1)允许在单个 HTTP 请求里组合多个子请求。系统内部使用两个并行数组分别进行“权限检查”和“请求执行”。攻击者通过构造嵌套的恶意批量请求(Double Batch),利用错误触发两个数组的对齐偏移(Desync),使得高权限敏感接口在无权限的公开接口上下文下被盲目执行,实现了免认证绕过。
完整利用链
从注入到取得 Webshell

绕过认证
攻击者向 /wp-json/batch/v1发送嵌套的异常请求,利用路由混淆(CVE-2026-63030)绕过身份验证,盲目调用原本需要受保护的敏感 REST 路由。触发注入
攻击者通过上述路由将恶意参数输入给 author__not_in接口,触发 SQL 注入(CVE-2026-60137)。构造缓存与伪造记录
攻击者利用 SQL 注入在数据库的 wp_posts和wp_options表中插入包含等标记的伪造记录,触发 oEmbed 缓存与瞬态(Transients)生成。提升权限与创建用户
利用伪造的 customize_changeset记录及parse_request逻辑,在管理员上下文下执行操作,并通过 POST /wp/v2/users 接口在后台直接新增一个具有管理员权限的账号。代码执行(RCE)
管理员账号创建完成后,攻击者上传恶意插件或直接部署 Webshell 脚本,获取服务器终端控制权。
影响范围与补丁版本对照
| WordPress 分支 | 受影响状态 | 官方安全补丁 |
| < 6.8 | ||
| 6.8.0 ~ 6.8.5 | 6.8.6 | |
| 6.9.0 ~ 6.9.4 | 受完整 wp2shell RCE 漏洞链影响 | 6.9.5 |
| 7.0.0 ~ 7.0.1 | 受完整 wp2shell RCE 漏洞链影响 | 7.0.2 |
| 7.1 Beta | 7.1 Beta 2 |
应急响应与防护措施
立即升级(最根本的修复方案)
登录 WordPress 后台,点击 仪表盘 -> 更新 -> 立即更新,将系统升级至 7.0.2、6.9.5或 6.8.6。也可以手动更新可前往 WordPress.org 官网下载安装包 进行覆盖。 在防火墙或 Web 服务器层临时阻断
若暂时无法升级,必须在防火墙(WAF)或 Web 服务器配置中切断以下两个批处理 REST 路由的访问(注意防范 URL 参数变体): /wp-json/batch/v1/?rest_route=/batch/v1检查网站入侵痕跡
检查 Web 访问日志中是否存在针对 /batch/v1的异常 POST 请求。检查后台用户列表中是否存在未经授权新建的管理员账号。 检查 wp_posts和wp_options表中是否存在可疑的缓存记录或未知代码片段。
如果你的 WordPress 暂时无法升级,那么你可以在你当前主题的 functions.php文件中添加如下代码禁用 Batch API:
add_filter('rest_pre_dispatch', function( $result, $server, $request){
if('/batch/v1' !== strtolower(untrailingslashit($request->get_route()))){
return $result;
}return new WP_Error('rest_batch_disabled', '批量 API 已禁用', ['status'=>401]);
}, -1000, 3 );
