綜述
2018年01月09日,Dedecms官方更新了DedeCMS V5.7
SP2正式版,後續在10日有網友爆出其存在任意使用者密碼重置漏洞。
攻擊難度:低。
危害程度:高。
官方修復情況如下:目前暫未釋出升級補丁
什麼是DedeCMS?
織夢內容管理系統(DeDeCMS)
以簡單、實用、開源而聞名,是國內最知名的PHP開源網站管理系統,也是使用使用者最多的PHP類CMS系統,在經歷多年的發展,目前的版本無論在功能,還是在易用性方面,都有了長足的發展和進步。廣泛應用於中小型企業入口網站,個人網站,企業和學習網站建設,在中國,DedeCMS應該屬於最受人們喜愛的CMS系統。
影響的版本
2018年01月09日之前的所有版本。
技術分析
此漏洞點出現在忘記密碼功能處.檔案/member/resetpassword.php:
在找回密碼時,當\$dopost =
safequestion時,通過傳入的member_id查詢出對應id使用者的安全問題和答案資訊,當我們傳入的問題和答案不為空,而且等於之前設定的問題和答案是就進入sn()函式。
這裡如果使用者設定了問題和答案,我們並不知道問題和答案是什麼,就無法進入sn()函式。但是如我此使用者沒有設定問題和答案呢?此時系統預設問題是”0”,答案是空。
那麼我們傳入答案$safeanswer = “”
時:
$row['safeanswer'] == $safeanswer;
成立。
但是傳入問題$safequestion = “0”
時:
if(empty($safequestion)) $safequestion = '',而$row[safequestion] = “0”
此時$row[safequestion] == $safequestion;
不成立。
所以要讓\$row[safequestion] ==
\$safequestion;成立必須繞過if判斷,此時如果屬性PHP的話,會想到PHP的弱型別問題,所以在型別轉換的時候往往會發生意料之外的情況。
下面我們來看看如何繞過if empty的判斷:
可以看到使用”0.0”
,”0.”
,”0e1”
都可以繞過前面的判斷,最後進入sn()函式,繼續跟進。
sn()函式在檔案/member/inc/inc_pwd_functions.php:
這裡當第一次進行忘記密碼操作時,\$row應該時空,所以進入第一個if條件傳送郵件insert一條記錄到dede_pwd_tmp表裡;如果之前進行過忘記密碼操作,但是時間已經超過10分鐘,那麼繼續進行傳送新驗證碼的操作update
dede_pwd_tmp表裡面的資料,跟進當前檔案的newmail()函式。
例如這裡第一次進行insert操作(update操作是一樣的)時,將8為的隨機字串\$randval加密後下乳dede_pwd_tmp表中,然後當\$send
= N時(上面預設傳入N),將隨機字串\$randval拼接到url中返回,返回的url為:
http://www.attack.com/member/resetpassword.php?dopost=getpasswd&id=$mid&key=$randval
\$mid就是可控的引數member_id,既然這列已經返回了重置密碼的驗證碼key那麼就可以直接重置對應id的使用者密碼了,跟進一下重置密碼的過程。
首先在重置密碼時,判斷輸入的id對應使用者是否進行過密碼重置操作,如果沒有就退出了。
然後判斷傳入的key的md5是否等於資料庫中的pwd內容,如果相等就直接修改了dede_member表中對應使用者的密碼了。
漏洞驗證
直接傳送如下請求即可獲取重置密碼的連結:
http://localhost/DedeCMS-V5.7-UTF8-SP2/member/resetpassword.php?dopost=safequestion&safequestion=0e1&safeanwser=&id=1
然後獲取的重置面連結為:
http://localhost/DedeCMS-V5.7-UTF8-SP2/member/resetpassword.php?dopost=getpasswd&id=1&key=D2kIQomh
然後就可以直接重置密碼了。
這裡修改id的值即可修改對應的使用者的密碼。
但是這個漏洞存在一個缺陷,因為通過分析可以看出來只有沒有設定安全問題的使用者才會受此漏洞的影響;而且只能修改前臺使用者的密碼。
防護方案
臨時方案可以暫時關閉會員功能,等待官方釋出升級補丁然後升級。