文章总结: WordPress7.0.0-7.0.1及6.9.0-6.9.4版本存在严重RCE漏洞链wp2shell,由CVE-2026-63030(RESTAPI路由混淆,CVSS9.8)与CVE-2026-60137(SQL注入,CVSS5.9)串联组成,无需认证即可在默认配置下实现远程代码执行。已有野外利用报告和公开PoC。建议立即升级至7.0.2/6.9.5/6.8.6等修复版本,并检查日志和数据库IOC确认是否已被利用。 综合评分: 87 文章分类: 漏洞预警,漏洞分析,应急响应,渗透测试,红队
【漏洞预警】WordPress wp2shell 紧急漏洞预警:CVE-2026-63030 / CVE-2026-60137 未授权 RCE 链
猎户攻防实验室
2026年7月19日 09:32 北京
在小说阅读器读本章
去阅读
2026 年 7 月 17 日,WordPress 发布 7.0.2 / 6.9.5 / 6.8.6 与 7.1 beta 2 安全版本,修复由两个核心漏洞串联而成的 wp2shell 攻击链:
- • CVE-2026-63030 — REST API
batch/v1批处理路由混淆,CNA CVSS 9.8 Critical - • CVE-2026-60137 —
WP_Query的author__not_inSQL 注入,CNA CVSS 5.9 Medium
两者串联后,在默认配置、无需认证、无需任何插件的情况下,可对开箱即用的 WordPress 实现远程代码执行。Patchstack 已将 CVE-2026-63030 标记为”Known to be exploited”(2026-07-17 晚 7 点 ET 前已有野外利用报告),公开 PoC 已在 GitHub 流通。
一、影响版本
必须按分支判断,不要用”版本号 ≥ 某值即安全”的跨分支比较(7.0.0 数值上大于 6.9.5,但仍受影响)。
| WordPress 版本 | CVE-2026-60137 | CVE-2026-63030 | 风险 |
| — | — | — | — |
| < 6.8 | — | — | 不受影响 |
| 6.8.0 – 6.8.5 | ✅ | — | 仅 SQLi |
| 6.9.0 – 6.9.4 | ✅ | ✅ | 完整 wp2shell RCE 链 |
| 7.0.0 – 7.0.1 | ✅ | ✅ | 完整 wp2shell RCE 链 |
| 7.1 beta 1 | ✅ | ✅ | 必须更新 |
| 6.8.6 / 6.9.5 / 7.0.2 / 7.1 beta 2 | — | — | 已修复 |
二、攻击链与实测证据
入口:WordPress REST API 支持两种等价访问形式,防护必须同时覆盖:
POST /wp-json/batch/v1 # path 形式
POST /?rest_route=/batch/v1 # query 形式 ← PoC 实测默认走这个
攻击链:
- 1. 向
batch/v1发送构造的批处理请求,触发 REST API 子请求匹配与调度之间的路由混淆; - 2. 被错误调度的子请求把请求参数
author_exclude映射到WP_Query的author__not_in,因未做完整整数化处理 → SQL 注入; - 3. 通过 UNION 假文章原语拖取
wp_users表(实测:3 个请求拿到管理员 bcrypt 哈希$wp$2y$10$...); - 4. 利用 SQLi 在
wp_posts伪造 customizer changeset / nav menu item → 自动创建名为wp2_<16hex>的管理员账号; - 5. 用该管理员身份上传插件 webshell → RCE。
实测(隔离 Docker 环境,WordPress 7.0.1 默认配置):
完整链路(check → read → shell)在受影响版本上稳定复现;在 7.0.2 上 UNION 原语即不可用,桥接在第一步失败。
三、紧急排查
第 1 步:版本确认
wp core version
# 或无 WP-CLI 时
grep '\$wp_version[[:space:]]*=' /var/www/html/wp-includes/version.php
判读:
| 实际版本 | 处置 |
| — | — |
| 6.9.0 – 6.9.4 / 7.0.0 – 7.0.1 / 7.1 beta 1 | 完整链路暴露,按 P0 立即处置 |
| 6.8.0 – 6.8.5 | 仅 SQLi,检查插件/主题是否暴露该参数,升级到 6.8.6 |
| 6.8.6 / 6.9.5 / 7.0.2 / 7.1 beta 2 | 已修复 |
⚠️ 不要用”版本 ≥ 6.9.5″判断安全。7.0.0 数值上大于 6.9.5 但仍受影响。
第 2 步:检查 batch 入口是否可达
用空 batch 请求探测(不含任何 payload,只判断路由是否暴露):
for url in \
'https://YOUR_SITE/wp-json/batch/v1' \
'https://YOUR_SITE/?rest_route=/batch/v1'
do
curl -ksS --connect-timeout 10 -o /dev/null \
-w "$url -> HTTP %{http_code}\n" \
-H 'Content-Type: application/json' --data '{"requests":[]}' "$url"
done
判读:
| path 形式 | query 形式 | 含义 |
| — | — | — |
| 200 | 207 | 受影响版本的典型表现 (实测:受影响的 WP 7.0.1 上 path 形式 200、query 形式 207) |
| 200 / 207 / 明确 REST 参数错误 | 同左 | 入口可达,需结合版本判断风险 |
| 401 / 403 | 同左 | 已被认证策略或安全设备阻断(缓解已生效) |
| 404 | 同左 | 路由不可达,或被 WAF/重写规则隐藏 —— 不能单独据此判定安全 |
⚠️ 不要用
curl -I(HEAD 请求)测 batch/v1。实测 HEAD 会被 pretty-permalink 重写规则返回 301/404/405,即使 POST 实际可达。
第 3 步:访问日志找入口请求
⚠️ 必须同时匹配 path 形式和 query 形式,只匹配 path 形式会漏报(PoC 默认走 query 形式):
# 覆盖两种形式的入口请求
zgrep -hEi '"POST [^"]*(/wp-json/batch/v1/?|[?&]rest_route=(%2f|/)?batch(%2f|/)v1)' \
/var/log/nginx/access.log* /var/log/apache2/access.log* 2>/dev/null
# PoC 默认 User-Agent 是字面值 "wp2shell",可作为附加筛选
zgrep -hE '"wp2shell"$' /var/log/nginx/access.log* /var/log/apache2/access.log* 2>/dev/null
命中后进一步提取:源 IP、User-Agent、状态码、请求大小、同源频率、CDN/源站日志是否能对应。
单次 batch POST 也可能是正常功能调用,不能仅凭路径判定入侵。但受影响版本上出现来源不明、频率异常或体积超大的 batch POST,应立即升级为高优先级调查。
第 4 步:数据库 IOC 检查(实测高可靠)
⚠️ 关于 PoC 清理行为(实测结论):
- • PoC 预认证桥接建的临时管理员和 webshell 插件正常退出时会清理(实测从干净基线跑一次后,
wp_users和plugins/都恢复原状) - • 但 PoC 客户端(urllib)在网络不稳时会出现
IncompleteRead异常中断,中断时不会执行清理逻辑,会留下wp2_<16hex>管理员账号和wp2shell_<8hex>webshell 目录 - • PoC 完全不清理
wp_posts伪造记录,每次跑都新增 2 条 —— 这是最可靠的入侵 IOC,比wp_users检查更稳
下面两条 SQL 都建议执行,互为补充:
先拿实际表前缀:
wp db prefix # 通常返回 wp_,但很多站点做过硬化
-- 实测 IOC 1:PoC 桥接创建的临时管理员(残留)
SELECT ID, user_login, user_email, user_registered
FROM <prefix>users
WHERE user_login LIKE 'wp2\_%'
OR user_registered > '2026-07-10'
ORDER BY user_registered DESC;
-- 实测 IOC 2:PoC 伪造的 wp_posts
-- 特征:post_type IN ('customize_changeset','nav_menu_item','request')
-- 且 post_date 硬编码为 '2020-01-01 00:00:00'
SELECT ID, post_type, post_status, post_date, LEFT(post_title, 50)
FROM <prefix>posts
WHERE (post_type IN ('customize_changeset','nav_menu_item','request')
AND post_date = '2020-01-01 00:00:00')
OR post_title LIKE 'wp2\_%';
判读:任一查询有结果 → 基本确认已被 PoC 利用。
补充检查管理员角色(用于发现已存在账号被提权):
SELECT u.ID, u.user_login, u.user_email, u.user_registered
FROM <prefix>users u
JOIN <prefix>usermeta um ON um.user_id = u.ID
WHERE um.meta_key = '<prefix>capabilities'
AND um.meta_value LIKE '%administrator%'
ORDER BY u.user_registered DESC;
PHP/Apache 错误日志取证:UNION 注入触发时,WordPress 的 wpdb::print_error() 会把完整 SQL 写入 PHP error log。具体位置取决于部署方式:
- • Apache + mod_php:
/var/log/apache2/error.log或/var/log/httpd/error_log - • Nginx + PHP-FPM:
/var/log/php-fpm.log或/var/log/php/error.log - • Docker 容器:PHP
error_log通常指向 stderr,通过docker logs <container>查看 - •
wp-content/debug.log:仅当wp-config.php同时设置define('WP_DEBUG', true)和define('WP_DEBUG_LOG', true)时才会生成(默认 WordPress 镜像不会自动开启,所以这个文件大概率不存在,不要直接 grep 它)
# Apache 部署
grep -hE 'UNION ALL SELECT|post_author NOT IN' /var/log/apache2/error.log* 2>/dev/null
# Nginx + PHP-FPM 部署
grep -hE 'UNION ALL SELECT|post_author NOT IN' /var/log/php*/error*.log 2>/dev/null
# Docker 部署
docker logs <wordpress-container> 2>&1 | grep -E 'UNION ALL SELECT|post_author NOT IN'
# 仅当显式开启 WP_DEBUG_LOG=true 时才存在
grep -hE 'UNION ALL SELECT|post_author NOT IN' /var/www/html/wp-content/debug.log* 2>/dev/null
命中即强烈表明已遭 PoC 利用 —— payload 中可见伪造的 customize_changeset / nav_menu_item / request 等 post_type 字符串。
第 5 步:文件 IOC 检查
实测 PoC webshell 落在 wp-content/plugins/ 目录(通过管理员插件上传功能写入,另外会自动清理,不作为唯一排查证据)。下面第 1 条是 wp2shell 专属 IOC,第 2-4 条是通用 webshell 排查:
# 1. wp2shell 专属 IOC:实测 webshell 路径模式
# PoC 通过插件上传能力写到 plugins/wp2shell_<8hex>/wp2shell_<8hex>.php
find /var/www/html/wp-content/plugins -type d -name 'wp2shell_*' 2>/dev/null
find /var/www/html/wp-content/plugins -type f -path '*/wp2shell_*/*.php' 2>/dev/null
# 2. 通用排查:事件窗口内新增/修改的可疑 PHP 文件(含危险函数)
# 排除 wp-config.php / wp-config-docker.php(容器构建产物,含 base64 是 wp_salt 用,属误报)
find /var/www/html -type f -name '*.php' -newermt '2026-07-10' \
-not -name 'wp-config.php' -not -name 'wp-config-docker.php' \
-print0 2>/dev/null \
| xargs -0 -r grep -lE 'eval[[:space:]]*\(|base64_decode[[:space:]]*\(|shell_exec[[:space:]]*\(' 2>/dev/null
# 3. 通用排查:uploads 目录原则上不应有可执行 PHP
# (wp2shell 实测不会写这里,但其它攻击向量常滥用 uploads)
find /var/www/html/wp-content/uploads -type f \
\( -iname '*.php' -o -iname '*.phtml' -o -iname '*.phar' \) 2>/dev/null
# 4. 核心 checksum 校验
wp core verify-checksums
wp plugin verify-checksums --all
判读:
- • 命中第 1 条
find wp2shell_*→ 几乎确定是 PoC webshell(PoC 正常退出会清理,异常退出时残留) - • 命中第 2 条 → 通用 webshell 嫌疑,需结合文件来源、修改时间、checksum 综合判断
- • 命中第 3 条 → 非本次 PoC 特征,但应立即调查(其它攻击向量)
- •
wp plugin verify-checksums报Couldn't fetch response ... 404→ 该插件不在 WordPress.org checksum 库,这本身是 IOC(实测:PoC 上传的wp2shell_<8hex>会触发此警告) - •
wp core verify-checksums报File should not exist: wp-config-docker.php→ Docker 镜像特例,非入侵痕迹
四、修复
4.1 首选方案:升级到对应分支安全版本
升级前先备份(数据库 + wp-content + wp-config.php):
# 默认升级到最新稳定版(当前 7.0.2)
wp core update
wp core verify-checksums
wp core version # 确认精确版本,不是"大于某值"
# 需要保留当前分支时显式指定(按实际分支选其一,不要全跑)
wp core update --version=7.0.2 # 7.x 分支
wp core update --version=6.9.5 # 6.9 分支
wp core update --version=6.8.6 # 6.8 分支
4.2 Docker 部署升级陷阱
只跑 docker pull 不够 —— Compose 不会自动用新镜像,必须 --force-recreate:
# 1. 先改 compose 文件里的 image: 标签为安全版本
# image: wordpress:7.0.2-apache
# 2. 重新拉取 + 强制重建
docker compose pull
docker compose up -d --force-recreate
# 3. 验证容器内实际 WP 版本(不能只看镜像 tag)
docker compose exec wordpress php -r \
'include "/var/www/html/wp-includes/version.php"; echo $wp_version, PHP_EOL;'
⚠️ 升级前确认数据库、
wp-content、uploads都在持久化卷中,且有可恢复备份。⚠️ 截至 2026-07-19,Docker Hub 上
wordpress:7.0.2尚未发布(wordpress:7.0.1-php8.2-apache有 arm64 变体)。Docker 部署的站点建议改用容器内wp core update升级,等官方镜像或自行构建。
4.3 发行版包管理器部署(apt)
如果 WordPress 由 Debian/Ubuntu 包管理,应优先遵循发行版安全公告:
apt update && apt install --only-upgrade wordpress
发行版可能用回补补丁而非升级版本号,不能只看版本字符串判断是否修复,需对照发行版 changelog。
4.4 升级后验证
升级完成不等于安全,必须复测:
# 1. 版本精确落在安全分支
wp core version # 应输出 6.8.6 / 6.9.5 / 7.0.2
# 2. checksum 通过
wp core verify-checksums # 应输出 "Success: WordPress installation verifies against official checksums."
# 3. 用第 2 步的探测确认 batch 入口行为符合预期(已升级版本上 POST 仍可达但 SQLi 失败)
五、无法立即升级时的临时缓解
临时措施必须同时覆盖两种入口:
/wp-json/batch/v1
/?rest_route=/batch/v1
5.1 MU 插件兜底(最稳,所有部署方式通用)
wp-content/mu-plugins/block-wp2shell.php:
<?php
/**
* wp2shell emergency mitigation.
* Remove after upgrading to 6.8.6 / 6.9.5 / 7.0.2.
*
* 实测:rest_pre_dispatch 在 REST 路由规范化之后触发,
* 因此同时覆盖 path 和 query 两种入口。
*/
add_filter('rest_pre_dispatch', static function ($result, $server, $request) {
if ('/batch/v1' === untrailingslashit($request->get_route())) {
return new WP_Error('wp2shell_blocked',
'REST batch endpoint temporarily disabled.', array('status' => 403));
}
return $result;
}, 10, 3);
部署后从站点外部复测两个入口都应返回 403:
for url in \
'http://localhost:8083/wp-json/batch/v1' \
'http://localhost:8083/?rest_route=/batch/v1'
do
curl -ksS -o /dev/null -w "$url -> HTTP %{http_code}\n" \
-H 'Content-Type: application/json' --data '{"requests":[]}' "$url"
done
5.2 Nginx 边缘层加固(与 MU 插件叠加,推荐)
# Pretty permalink 形式
location ~* ^/(?:index\.php/)?wp-json/batch/v1/?$ {
return 403;
}
# Query 形式(PoC 实测真实流量,必须保留这条)
if ($args ~* "(^|&)rest_route=(%2f|/)batch(%2f|/)v1/?(&|$)") {
return 403;
}
⚠️ 不要把阻断
/wp-json/wp/v2/users当作修复。漏洞利用的子请求由 WordPress 内部 REST 服务器调度,不会作为新的外部 HTTP 请求再次经过 Nginx,所以这条规则对 wp2shell 无效。
5.3 Apache .htaccess 加固(适用 Apache + mod_rewrite)
⚠️ 实测注意事项:
- •
.htaccess仅在 Apache 主配置对/var/www/html设了AllowOverride All(或FileInfo)时才生效。WordPress 官方 Docker 镜像在docker-php.conf里启用了AllowOverride All,但部分定制镜像可能没启用 —— 不确定时优先用 MU 插件方案。 - • path 形式的 RewriteRule 在
.htaccess里容易被 WordPress 标准RewriteRule . /index.php [L]抢先匹配而失效(实测命中此问题)。建议把 wp2shell 拦截规则放在# BEGIN WordPress块之前,或干脆只依赖 query 形式拦截 + MU 插件。
# 放在 # BEGIN WordPress 之前,确保优先匹配
RewriteEngine On
# Query 形式(PoC 实测真实流量,实测可拦)
RewriteCond %{QUERY_STRING} (^|&)rest_route=(%2F|/)batch(%2F|/)v1/?(&|$) [NC]
RewriteRule ^ - [F,L]
# Path 形式(注意:必须放在 WP 标准 index.php 重写之前才生效)
RewriteCond %{REQUEST_URI} ^/(?:index\.php/)?wp-json/batch/v1/?$ [NC]
RewriteRule ^ - [F,L]
5.4 三层防御实测对比
| 测试场景 | Nginx | MU 插件 | .htaccess | PoC check 结果 | | — | — | — | — | — | | 三层全启用 | ✅ | ✅ | ✅ | HTTP 403,被 Nginx 拦 | | 仅禁用 Nginx(保留反代) | ❌ | ✅ | ✅ | HTTP 403,被 MU 插件拦 | | 禁用 Nginx + MU 插件 | ❌ | ❌ | ✅(query 形式) | HTTP 403,被 .htaccess 拦 query 形式 |
实测细节:
- • Nginx 和 MU 插件两层对 path 和 query 两种形式都完全有效
- •
.htaccess层实测对 query 形式有效,对 path 形式(/wp-json/batch/v1)容易被 WP 标准重写规则抢先而失效,所以建议把.htaccess作为第三道兜底,不要单独依赖 - • 生产建议:Nginx(边缘)+ MU 插件(应用)两层叠加即可,无需依赖 .htaccess
结论:Nginx 和 MU 插件任一层独立即可阻断整条攻击链;.htaccess 不可靠,仅作兜底。
六、发现失陷后的处置
如果第 4、5 步发现 IOC,不能只升级 WordPress:
- 1. 隔离站点 + 取证:切换维护页或断公网,保留磁盘、容器、数据库、日志快照;
- 2. 从可信镜像/干净安装包重建核心、插件、主题,不要只删可疑文件(无法保证后门清理干净);
- 3. 重置所有管理员密码,撤销可疑的 Application Password;
- 4. 更新
wp-config.php的 Authentication Keys and Salts(使所有现有登录会话失效):
wp config shuffle-salts # 注意是 shuffle-salts(带 s),不是 shuffle-salt
# Docker 部署:因 wp-config.php 用 getenv_docker() 包装,还需改容器的 SALT 环境变量
- 5. 轮换关联凭据:数据库、SMTP、CDN、对象存储、第三方 API key;
- 6. 检查持久化:计划任务、MU 插件、额外主题/插件、系统 cron、Web 服务账号的 SSH 密钥;
- 7. 评估通报义务:根据日志确认最早攻击时间,评估数据库/用户数据是否泄露,按本地合规要求履行通报。
参考
- • WordPress 7.0.2 Security Release(官方公告) https://wordpress.org/news/2026/07/wordpress-7-0-2-release/
- • CVE-2026-63030(CVE.org,CVSS 9.8) / CVE-2026-60137(CVSS 5.9) https://www.cve.org/CVERecord?id=CVE-2026-60137
- • Searchlight Cyber — wp2shell 原始研究 https://slcyber.io/research-center/wp2shell-pre-authentication-rce-in-wordpress-core/
- • Rapid7 ETR — CVE-2026-63030 https://www.rapid7.com/blog/post/etr-cve-2026-63030-wp2shell-a-critical-remote-code-execution-vulnerability-in-wordpress-core/
#
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:猎户攻防实验室 《【漏洞预警】WordPress wp2shell 紧急漏洞预警:CVE-2026-63030 / CVE-2026-60137 未授权 RCE 链》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论