[漏洞分析]thinkcmf 1.6.0版本從sql注入到任意程式碼執行
0x00 前言
該漏洞源於某真實案例,雖然攻擊沒有用到該漏洞,但在分析攻擊之後對該版本的cmf審計之後發現了,也算是有點機遇巧合的味道,我沒去找漏洞,漏洞找上了我XD
thinkcmf 已經非常久遠了,該版本看github上的更新時間已經是4年前了,也就是2014年的時候,那時候我沒學安全呢。。。
0x01 前臺sql注入
前臺在登入方法中存在注入,thinkcmf是基於thinkphp3.2寫的,直接看
檔案application\User\Controller\LoginController.class.php 方法 dologin
很明顯的注入,通過extract我們可以註冊$where陣列,而後直接傳入where方法,沒有經過I方法過濾的引入引數是會引發表示式注入的。
比如這樣子:
這裡由於有驗證碼,無法輕易的編寫批量指令碼。當然引入打碼工具另說。
注入之後,我們想到的一定是登入後臺了。
那麼先了解一下thinkcmf的管理員密碼是怎麼加密的。
看到 install\index.php 檔案的 sp_password 方法
解釋一下,$pre就是表字首,$pw是密碼,意思是
儲存在資料庫的密碼 = 表字首md5的前12位+密碼md5+表字首md5的後四位
比如值為c535018ee946e10adc3949ba59abbe56e057f20f883e89af 儲存在資料庫的密碼。
那麼拆分一下就是
c535018ee946(表字首md5的前12位)
e10adc3949ba59abbe56e057f20f883e(密碼md5)
89af(表字首md5的後四位)
知道所謂的加密演算法之後,我們就可以輕易獲取到管理員密碼的md5值,通過碰撞md5值的形式獲取到管理員的真實密碼。
現在我們可以登入上後臺了,可登入後臺之後要怎麼getshell呢?
仔細分析了一下thinkcmf的後臺,似乎沒有可以getshell的地方。
0x02 許可權驗證處的任意程式碼執行
認真看了看程式碼,發現後臺的一些操作會有許可權驗證,而跟蹤許可權驗證程式碼的時候發現了一個eval的程式碼塊。
看到許可權驗證處application\Common\Lib\iAuth.class.php check 方法
使用了eval來引入變數,那麼這個$command是否可控呢?
經分析其來源於sp_auth_rule表中的condition欄位,備註為規則附加條件
而這些資料在安裝的時候就早已經寫入到資料庫中了,除非我們有辦法可以來修改這裡的值?
是的,前面的sql注入排上用場了。
thinkphp 自 3系列開始就使用pdo作為連線資料庫的驅動,而這裡這個注入不涉及到引數繫結等問題,那麼我們就可以利用它來執行多語句,插入資料或者修改資料了。
簡單測試一下,比如修改一下後臺管理員的user_email欄位。
檢視資料庫,成功修改
多語句執行可以為我們省下很多事,比如密碼過於複雜無法猜解出明文時,我們可以直接修改密碼的hash值為我們想要的。
分析一下許可權驗證的程式碼,它是怎麼觸發的?
隨便找了個需要登入後臺的檔案比如 application\Portal\Controller\AdminPageController.class.php
該controller繼承於AdminbaseController,跟蹤下去
而在AdminbaseController初始化的函式中,發現了檢測許可權的程式碼,跟進
發現如果$uid是1的話就直接返回了,這個$uid其實就是資料庫裡面的id欄位值,也就是說要觸發許可權驗證就必須是一個低許可權的使用者。
繼續走,如果訪問的不是url為admin/index/index 就會進行鑑權,跟進sp_auth_check方法
最終來到了我們的check方法。
具體意思都寫在解釋裡面了,看到eval程式碼塊,我們只要閉合掉左括號,即可引入我們的惡意程式碼。
那麼整個利用過程就是登入一個低許可權的使用者,通過sql注入寫入程式碼到我們可以訪問的url的condition欄位中。
比如我填加了一個低許可權的使用者hack,他擁有內容管理的許可權
對應他能夠訪問的url有
那麼我們只要在sp_auth_rule表中對應的url的condition欄位插入程式碼,然後登陸該使用者訪問該url即可觸發程式碼執行。
比如我們通過sql注入插入一段執行phpinfo的程式碼
payload:
where[id][0]=exp&where[id][1]=in (1);update sp_auth_rules set `condition`='1);phpinfo();die();//' where id=30#
請求
檢視一下表sp_auth_rule,成功插入
那麼後臺登陸使用者hack之後,訪問url
http://127.0.0.1/index.php?g=Portal&m=AdminPage&a=add
即可看到phpinfo執行了
而在之後的研究中,我發現此處許可權驗證的程式碼來自於thinkphp 自身。
看到檔案simplewind\Core\Library\Think\Auth.class.php getAuthList方法的程式碼
是不是有種似曾相識的感覺,是的就是thinkcmf根據tp的改寫的。
那麼這裡就引申出來一個審計點:
tp3框架中如果使用了auth類來驗證許可權,且有注入點,那麼是可以嘗試去審計一下任意程式碼執行。
類似的例子,暫時沒看到,以後看到了更新上來。
0x03 總結
總結一下利用:
通過前臺的sql注入,獲取到後臺許可權(獲取管理員密碼,或者修改管理員hash值),登陸進後臺,新增低許可權使用者,再通過sql注入來注入程式碼。登陸低許可權使用者,訪問注入了程式碼的url,即可觸發任意程式碼執行。
而在實際中,往往是已經有了低許可權的使用者,我們只需要觀察使用者能夠訪問的URL,直接注入程式碼即可,免去了新增低許可權使用者的步驟。
整個利用構造下來還是比較有趣的,不完美的是還是需要登入後臺,因為很多網站或許會把後臺隱藏掉,但是也有可能會因為不理解tp支援的url模式而導致繞過 ,這裡就不細說了,懂的人自然懂。
打完收工~