🎯 CVE-2026-60137 深度技术分析:漏洞根因 · PoC/EXP · 检测指纹
CVE-2026-60137 深度技术分析
摘要:CVE-2026-60137 是 WordPress Core 中一处由 WP_Query 的 author__not_in 参数过滤不严导致的 SQL 注入漏洞,CVSS 评分为 5.9(中危)。该漏洞影响 WordPress 6.8.x(< 6.8.6)、6.9.x(< 6.9.5)及 7.0.x(< 7.0.2)。虽然单独利用需要插件或主题将不可信输入传入该参数,但根据 CISA KEV 与公开 PoC(wp2shell),该漏洞可与 CVE-2026-63030(REST API 批量路由混淆)链式利用,实现默认 WordPress 安装上的未认证远程代码执行(RCE)。本文深入分析其根因、攻击链、影响及修复方案。
📌 漏洞概述
- CVE ID:CVE-2026-60137
- CVSS 评分:5.9(中危)
- 漏洞类型:SQL 注入(CWE-89)
- 影响版本:WordPress 6.8.x 至 6.8.5、6.9.x 至 6.9.4、7.0.x 至 7.0.1;已在 6.8.6、6.9.5、7.0.2 中修复
- 触发条件:当插件或主题将不可信输入直接传递给
WP_Query的author__not_in(或author_exclude)参数时,攻击者可注入恶意 SQL 语句。
该漏洞的核心问题在于 WordPress 对查询参数 author__not_in 的清洗(sanitisation)不完整。虽然 WordPress 通常会通过 wp_parse_id_list() 将数组值转换为整数,但在特定条件下(如传入关联数组、特殊格式字符串或通过某些 REST API 参数解析路径),原始值可能会绕过清洗并直接进入 SQL 查询构建逻辑。这为攻击者提供了 SQL 注入的注入点。
🔬 漏洞根因分析
要理解该漏洞,需深入 WordPress 查询解析与 SQL 构建的底层实现。WordPress 的 WP_Query 类在处理 author__not_in 参数时,预期接收一个包含用户 ID 的数组。内部通过 wp_parse_id_list() 函数将输入转换为正整数数组,再生成 NOT IN 子句。然而,该清洗过程存在一个关键盲点:当数组结构嵌套或包含特殊键名时,wp_parse_id_list() 只处理数组的值,而不会递归清洗或验证键名。攻击者可以构造类似以下结构:
author__not_in[]=1&author__not_in[x]=0 OR SLEEP(5)-- -在 PHP 中,这种参数解析会生成数组 [0 => "1", "x" => "0 OR SLEEP(5)-- -"]。当 wp_parse_id_list() 遍历该数组时,它可能仅提取值中的整数部分(例如 (int)"0 OR SLEEP(5)" 得到 0),从而理论上会中和注入。但实际漏洞是,在某个特定版本中,WP_Query 的 parse_query() 方法并未对所有输入路径强制执行 wp_parse_id_list()。尤其是当参数名被映射为 author_exclude 别名时,可能存在直接使用原始值的分支。此外,WP_Query 支持通过 tax_query 等复合查询条件传入嵌套数组,攻击者可能利用深度嵌套来绕过顶层的清洗函数,使恶意字符串最终拼接进 SQL 的 NOT IN 列表。
进一步分析公开 PoC(wp2shell)的利用链可以发现,攻击者将 SQL 注入与 WordPress REST API 的批量路由混淆(CVE-2026-63030)结合。批量接口 /batch/v1 允许在一次请求中执行多个子请求,而路由混淆导致身份验证状态在子请求间错误共享或绕过。这使得攻击者可以在未认证的情况下将恶意 SQL 注入到 author_exclude 参数中,并通过时间盲注(SLEEP())提取数据。PoC 中展示了从获取数据库表名、管理员 ID,到构造恶意 oEmbed 缓存、劫持 Customizer changeset、创建管理员账户、上传恶意插件的完整攻击流程。这证明该 SQL 注入并非仅停留在数据库读取层面,而是可以升级为完整的站点接管。
从代码层面看,修复补丁很可能在 WP_Query::parse_query() 中增加了对 author__not_in 和 author_exclude 的严格数组处理,确保每个元素都经过 absint()(绝对值转整数)且只允许纯数字键。同时加强了参数名的白名单校验,防止通过别名或动态属性注入绕过。遗憾的是,由于官方未公开完整补丁差异,这只能基于漏洞特征进行合理推断。
💥 影响与危害
该漏洞的直接影响是 SQL 注入,可导致数据泄露、认证绕过和数据篡改。但由于 WordPress 的数据库用户通常仅具有 SELECT/INSERT/UPDATE/DELETE 权限,直接通过 SQL 注入读取敏感数据是主要威胁。攻击者可提取 wp_users 表中的密码哈希、wp_options 中的密钥以及所有文章和评论数据,进而尝试离线破解管理员密码或伪造登录会话。
更严重的是,当与 CVE-2026-63030 链式利用时,攻击流程从单纯的“读取”升级为“写入与执行”。根据 PoC 介绍,攻击者可以通过 SQL 注入向数据库写入恶意 oEmbed 缓存记录,再利用 REST API 批量路由混淆将这些记录注册为 Customizer changeset。由于 changeset 被赋予管理员作者的元数据,攻击者能够通过发布该 changeset 创建新的管理员账户。获得管理员权限后,攻击者登录后台并上传一个包含恶意 REST API 端点的插件,最终实现任意命令执行。该过程完全预认证,且不需要任何特殊配置,影响所有默认 WordPress 安装。
CISA KEV 已确认该漏洞正被积极利用,并强调可与 CVE-2026-63030 链式实现未认证 RCE。这意味着网上的 WordPress 站点若未及时升级,将面临被批量扫描和自动化的权限提升攻击风险。攻击者可能利用该漏洞植入后门、挖矿木马、勒索软件或将其作为鱼叉攻击的跳板。此外,由于攻击链的最后一步会自行销毁使用的临时文件,传统文件完整性监控可能无法及时检测到入侵痕迹。
🛡️ 修复与缓解
补丁版本:
- WordPress 6.8.x 用户需升级到 6.8.6
- WordPress 6.9.x 用户需升级到 6.9.5
- WordPress 7.0.x 用户需升级到 7.0.2
这些版本修复了 author__not_in 和 author_exclude 参数的清洗逻辑,同时对 REST API 批量路由的验证进行了加固(针对 CVE-2026-63030)。
临时缓解措施:
- 立即升级:这是最有效的方法。如果无法立即升级,应首先禁用或限制 REST API 的批量端点(例如通过插件或 Web 服务器规则拦截
/wp-json/batch/v1的未认证请求),以阻止链式攻击。 - 代码审计:检查所有使用
WP_Query且允许用户输入进入author__not_in或author_exclude的主题和插件。不要将原始请求参数直接传递给这些参数,应使用absint()强制转换。 - 数据库权限最小化:确保 WordPress 数据库用户不拥有
FILE、GRANT等高危权限,降低注入带来的影响。 - Web 应用防火墙(WAF):部署针对 SQL 注入特征的 WAF 规则,拦截包含
SLEEP()、UNION SELECT、BENCHMARK()等负载的请求。 - 监控与响应:根据 CISA 的 BOD 26-04 指引,定期评估资产互联网暴露情况,并利用日志审计 SQL 注入尝试。若已确认被攻击,应参考 CISA 的取证检测要求进行排查。
总之,该漏洞虽然单独威胁有限,但链式利用可导致完全接管站点。所有 WordPress 管理员应将其视为紧急安全更新,尽快完成升级,并在升级后检查是否存在异常管理员账户或恶意插件。
🧪 PoC 复现
从 GitHub 公开仓库抓取的实际 PoC 代码(仓库)。
📋 代码元数据语言md来源h4cd0c/wp2shell针对性✅ 已验证与漏洞相关(代码含 CVE 引用)依赖见代码注释/README用法详见代码注释中的使用说明
# wp2shell
Pre-authentication Remote Code Execution against WordPress Core.
Chains **CVE-2026-60137** (SQLi in `author__not_in` / `author_exclude` parameter of `WP_Query`) with **CVE-2026-63030** (REST API batch-route confusion) for unauthenticated RCE.
## Affected Versions
|Range |Status ||---|---||<= 6.8.5 |Not affected (no batch confusion) ||6.8.0 - 6.8.5 |SQLi only,no RCE ||
**6.9.0 - 6.9.4** |**Vulnerable** ||**7.0.0 - 7.0.1** |**Vulnerable** ||7.0.2+ / 6.9.5+ |Patched |## Usage
```
python3 poc.py -u TARGET_URL
python3 poc.py -u TARGET_URL --sql "SELECT user_pass FROM wp_users LIMIT 1"
python3 poc.py -u TARGET_URL -c "id"
```
### Modes
|Arguments |Behavior ||---|---||`-u TARGET_URL` |Check if vulnerable (timing probe) ||`-u TARGET_URL --sql "SQL"` |
Extract scalar via blind SQLi ||`-u TARGET_URL -c "CMD"` |Full RCE chain |
## How It Works
1. **Batch-route confusion** — exploits the batch API (`/batch/v1`) to desync request handling and bypass authentication
2. **Time-based blind SQLi** — injects into `author_exclude` parameter via `SLEEP()` timing oracle
3. **oEmbed cache corruption** — creates forged oEmbed cache entries via UNION injection
4. **Customizer changeset injection** — recasts cache entries as a changeset with admin authorship
5. **Admin account creation** — publishes the changeset and creates a new admin user
6. **Plugin upload** — logs in as the new admin,
uploads a plugin that registers a REST API command endpoint
7. **Command execution** — sends command via the plugin's REST endpoint,returns output,
self-destructs
## Attack Flow
```
Vulnerability check → Seed oEmbed posts → Extract table name (blind SQLi)
→ Extract admin ID (blind SQLi) → Extract cache post IDs (blind SQLi)
→ Inject poisoned changeset via batch → Create admin user
→ Login → Upload command plugin → Execute command → Cleanup
```
## Credits
- **CVE-2026-60137** — SQLi in `author__not_in`: discovered by TF1T,dtro,
haongo
- **CVE-2026-63030** — Batch-route confusion: discovered by Adam Kues (Assetnote / Searchlight Cyber)
- PoC implementation: [sergiointel/wp2shell-poc](https://github.com/sergiointel/wp2shell-poc)⚔️ EXP 利用代码
截至分析时,Exploit-DB 未收录该 CVE 的公开利用代码。可利用上述 PoC 进行验证,或关注 Exploit-DB 更新。
🕵️ 检测指纹
当前规则库未收录针对该 CVE 的专用检测规则。建议:
- 根据漏洞根因编写 Nuclei 检测模板
- 在 WAF/IDS 中配置针对漏洞特征的规则
- 关注漏洞指纹库更新
🤖 本文由漏洞情报系统自动聚合生成 · 2026-08-11 07:06 · 数据源: NVD/GitHub-Advisory/OSV/CISA-KEV/Exploit-DB/PoC-in-GitHub + 检测规则库