1. 程式人生 > >[漏洞分析]thinkcmf 1.6.0版本從sql注入到任意程式碼執行

[漏洞分析]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模式而導致繞過 ,這裡就不細說了,懂的人自然懂。

打完收工~