
所有 PoC 都利用了相同的两个缺陷 - REST 批量路由混淆(CVE-2026-63030)和
author__not_in SQL 注入(CVE-2026-60137)- 并采用相同的双重嵌套批次结构。
它们之间的区别在于所选择的远程代码执行(RCE)路径、环境前置条件,
以及安全默认设置。本文档具体说明了本仓库中的实现在这一格局中所处的位置。
check 不发送任何 SQL 载荷;
所有流量都可以携带归因标记;shell 命令写入目标的一切内容事后都会自动移除。
参见 §3。[1] 仅将时间盲注/盲注作为读取通道;UNION 伪造文章原语存在于桥接内部,但未作为提取预言机(extraction oracle)暴露。
[2] 朴素的可用性探测(0) UNION SELECT …)在对象缓存的水合过程中被静默丢弃,available() 返回 false,整个预认证桥接中止 - 见 §1。
[3] 该项目自己的 README 在前置条件中列出了“无持久化对象缓存(Redis/Memcached)”。
[4] 在 Sploitus 上镜像的公开变体(链接见下文):盲读加上 INTO OUTFILE 投放器作为 RCE 步骤,使用 per_page=-1 分类载体。
[5] OUTFILE RCE 路径不依赖伪造文章渲染,因此对象缓存无法阻止它 - 真正构成阻碍的是 MySQL FILE 权限和共享的可写目录。托管主机几乎从不向 WordPress 数据库用户授予 FILE 权限,而且通常会设置 secure_file_priv。
UNION 伪造文章原语取决于 WP_Query 返回行的方式:
wp_posts 行;通过 UNION 注入的行直接成为
WP_Post。伪造的文章得以渲染。在具有持久化对象缓存的主机上,已填充的基结果集会迫使 WP_Query 进入拆分模式。公开 PoC 使用的标准探测 -
0) UNION SELECT <forged row> -- -
post_author NOT IN (0) 匹配每一行),因此在对象缓存之后,伪造行会蒸发消失:可用性探测出现假阴性,available() 返回 false,整个预认证桥接在一个实际上完全可利用的主机上被报告为“已失效”。公开的统一工具通过将*“无持久化对象缓存”*列为硬性前置条件来记录相同的边界。本仓库则改为清空基集:
1) AND 1=0 UNION ALL SELECT <forged row> -- -
基集为零行时,伪造行是唯一的行;查询保持整行模式;永远不会执行水合查找。在对象缓存主机上 - 这是大多数托管 WordPress 生产环境 - 一个注入的关键字(AND 1=0)就是“UNION 通道失效”与“完整预认证 RCE”之间的全部差别。诊断、探测矩阵(per_page × 注入形式)。
范围说明:盲注/时间盲注读取通道不受对象缓存影响(在 SQL 中计数行不涉及伪造文章的水合),因此每个 PoC 的盲注读取在任何地方都有效。对象缓存对其他 PoC 造成的破坏仅限于依赖 UNION 的部分:带内提取和 SQLi 到管理员桥接。
案例研究中记录的第二条相关经验:当两个通道都可用时,以带内 UNION 读取为准 - 生产环境中的时间盲注预言机在抖动下对一个值产生了位翻转,而带内读取则明确无误地确定了该值。
公开 PoC 中存在三条预认证 RCE 路径:
本仓库实现了该桥接:它不需要 WordPress 已拥有之外的任何数据库权限,在数据库层和 Web 层之间无任何共享时也能正常工作,并且不会留下任何可供 FILE 权限路径依赖的文件。代价是复杂性 - 该桥接是一个七行的投毒文章图(poisoned post graph)- 而这正是 §1 中对象缓存假阴性曾经隐藏该路径的地方。
专为在授权下对生产系统运行而构建,而不仅仅是实验室:
check 默认非破坏性 - 被动指纹探测加上良性的标记批次;除非给出 --confirm-sqli,否则不发送任何 SQL 载荷。修补之后,消失的标记三元组兼作修复验证。--user-agent,使所有漏洞利用流量在日志中可识别(公开工具默认不具备这一经验法则)。author_exclude → author__not_in 汇聚点、伪造 WP_Post 的 UNION 原语以及自定义器桥接(customizer-bridge)概念都是公开的技术(来源已在下方注明)。INTO OUTFILE 投放器),镜像于 Sploitus -
https://sploitus.com/exploit?id=7CD079AD-E27B-5C54-A696-60635BFDB241| 能力 | 本仓库 | Icex0/wp2shell-poc | sergiointel/wp2shell-poc | 0xsha/wp2shell | OUTFILE 变体 [4] |
|---|
| 预认证盲注/时间盲注 SQLi 读取 | 是 | 是 | 是(时间盲注) | 是 | 是 |
| 带内 UNION 读取(1 个请求/值) | 是 | 是 | - [1] | - [1] | - |
| 基于报错的读取(EXTRACTVALUE) | 是 | 是 | - | - | - |
| UNION 通道在持久化对象缓存下依然可用 | 是(清空基集) | 否 - 探测出现假阴性 [2] | 未记录 | 否 - 已记录的前置条件 [3] | 不适用 [5] |
| 免破解的预认证 RCE | 是(SQLi 到管理员桥接) | 是(相同的桥接) | 是(桥接起源) | 是(相同的桥接) | 是,通过 INTO OUTFILE [5] |
| RCE 的额外前置条件 | 除默认安装外无其他要求 | 无(在非对象缓存主机上) | 无(同上) | 无(同上) | MySQL FILE 权限 + 与 mysqld 共享的 Web 可写路径 |
| 非破坏性检查 / 补丁验证 | 是(标记三元组;默认无载荷) | 是 | 否 | 是(block_cannot_read) | 是(标记批次) |
| 归因 / User-Agent 标记 | 是,所有命令均支持 | 否 | 否 | 传输标志 | 否 |
| 自动清理(Webshell + 生成的管理员) | 是 | 是 | 未记录 | 仅令牌门控的 Webshell | 投放器已移除 [5] |
| 蓝队检测指南 | 是,基于生产环境运行 | 否 | 否 | 改为实验室矩阵 | 缓解措施说明 |
| 依赖 | 仅标准库 | 仅标准库 | 单文件 | 仅标准库,单文件 | Python ≥3.10 包 |
| 路径 | 使用者 | 额外前置条件 |
|---|
SQLi 到管理员桥接(伪造 oEmbed/changeset/nav 行 → POST /wp/v2/users → 登录 → 上传插件) | 本仓库、sergiointel(起源)、Icex0、0xsha | 除默认安装外无其他要求 |
INTO OUTFILE 投放器(通过 SQLi 写入 PHP 文件,再获取它以获得 Shell) | OUTFILE 变体 [4] | MySQL FILE 权限、允许该权限的 secure_file_priv,以及一个 mysqld 可写且由 Web 服务器提供服务的目录 |
哈希恢复 → 破解 → 登录(导出 user_pass,离线破解,然后上传插件) | 全部(作为后备方案) | bcrypt 哈希必须真的能被破解($wp$2y$,hashcat -m 35500)- 缓慢,往往永远无法破解 |