PHP程式碼審計——檔案操作漏洞

2022-09-03 12:08:51

夢想CMS(lmxcms)任意檔案刪除

1. 漏洞詳情——CNVD-2020-59469
 

2. 漏洞描述稱後臺Ba***.cl***.php檔案存在任意檔案刪除,檢視cms原始碼,只有BackdbAction.class.php和BasicAction.class.php這兩個類檔案符合名字要求
 

3. 檢視原始碼,程式碼中的註釋顯示只有BackdbAction.class.php有檔案刪除功能。php中的檔案刪除函數是unlink(),搜尋一下該函數,發現BackdbAction.class.php檔案存在該函數,且有變數傳入,那麼應該就是這個檔案存在檔案刪除漏洞了
 

 

4. 類檔案最下方的delOne()方法中傳入了filename的變數,並且與`file/back`進行拼接組成檔案路徑,也就是說只能刪除file/back這個目錄下的檔案,但只要能繞過路徑,就能實現任意檔案刪除
 

5. 可以看到檔案中的delbackdb()和delmorebackdb()都呼叫了delOne()方法,delbackdb()中支隊檔名進行了首尾兩端的空格去除,而且只校驗了檔名。
 

6. 使用../../即可繞過目錄限制,在根目錄下新建一個test.txt檔案,嘗試刪除test.txt檔案,如下所示,檔案被成功刪除
http://localhost:8081/admin.php?m=backdb&a=delbackdb&filename=../../test.txt

 


7. 若網站的install目錄在完成安裝後沒有刪除,則利用該檔案刪除漏洞刪除install目錄下的install_ok.txt檔案,則可實現對網站的重新覆蓋安裝

夢想CMS(lmxcms)任意檔案讀取

1. php檔案讀取的函數
fread()
fgets()
fgetss()
file()
readfile()
file_get_contents()
fpassthru()

2. 漏洞詳情————CNVD-2020-51412
 

3. 漏洞詳情中沒有給出任何提示,但是隻給了低危,說明漏洞在後臺,在專案中搜尋file_get_contents


4. 只有file.class.php檔案中的file_get_contents存在變數傳入,該函數被getcon函數呼叫,檢視getcon函數被哪些方法呼叫了,雙擊進入該檔案,選擇getcon右鍵查詢使用,如下,可以看到getcon被TemplateAction.class.php檔案的TemplateAction類的editfile方法呼叫了,並且傳入了dir變數

5. dir變數傳入editfile方法後,與$this->config['template']進行拼接,echo輸出一下$this->config['template'].$dir,存取一下看拼接的是什麼
admin.php?m=template&a=editfile&dir=1
 

6. 如下所示,拼接的是E:/phpstudy/phpstudy_pro/WWW/localhost/lmxcms1.4/template/,也就是模板檔案所在的目錄
 

7. 嘗試一下讀取網站組態檔,如下所示,成功讀取到組態檔
 http://localhost:8081/admin.php?m=Template&a=editfile&dir=../inc/db.inc.php

 


夢想CMS(lmxcms)任意檔案檔案寫入

1. 如上所示,成功讀取到檔案後,可以直接編輯讀取到的檔案並提交,我們可以直接在讀取到的檔案中寫入webshell,這樣就能直接上線了

2. 既然可以修改檔案,說明一定還有修改檔案的方法,檢視原始碼,發現還是在editfile方法中,存在一個file::put(),先判斷POST資料裡面是否設定了settemcontent,然後再進行寫入操作

3. 搜尋fileput,方法介紹如下,有兩個引數,file引數規定要寫入資料的檔案,檔案不存在則建立新檔案,data引數規定要寫入的資料

4. 嘗試寫入一個webshell,可以看到成功在template目錄下寫入了shell.php,也可以加上../寫入到根目錄下

5. 使用蟻劍連線成功
 

earmusicCMS任意檔案下載

1. 檔案下載沒有關鍵函數,只能從功能點入手,對檔案下載的功能點進行抓包,從抓包資料中找到對應的功能點檔案。
   
2. 這裡我們選擇earmusicCMS進行審計,搭建好環境後先登入,上傳一個test,然後開啟這個test,可以看到頁面中有一個下載選項

 


3. 點選下載選項,使用BurpSuite進行抓包,可以看到下載功能點指向的地址是/template/default/source/auth.php。

4. 轉到該檔案,檢視程式碼,發現有一個SafeRequest(),轉到該函數宣告,是一個設定請求方式的函數,函數過濾了一些魔術符號
 

5. auth.php檔案的下方存在header設定,將請求回顯的資料轉化成下載,最後使用readfile()讀取file檔案內容
 

6. 在檔案內查詢file的第一次出現,發現是在header的上面,通過geturl的值來確定file的值,轉到geturl()宣告,geturl()定義了兩個引數file和type,type引數預設為空,也就是沒有設定型別,file引數使用了正規表示式進行過濾,然後將file與網站地址組合成一個url並返回

7. geturl的file引數為$row['in_audio'],這個就是file的地址,查詢row第一次出現的位置,發現出現在auth.php檔案的前面,有一個sql執行語句,id變數被傳入sql語句,sql語句被傳入了getrow()函數,查詢該函數的宣告,發現有兩處宣告

8. 分別轉到兩處宣告看一下,都是返回sql執行結果的
 

 


9.  getrow()將id變數的sql語句執行結果賦值給row,然後從row中取出in_audio,查詢誰能夠控制in_audio,發現在source\user\music\add.php中可以控制in_audio,轉到該檔案檢視,像是上傳音樂的地方,開啟瀏覽器看一下

 


10. 如下圖所示,對比一下,確實是網站上傳音樂的功能點,這個地方的音訊地址可以控制in_audio,控制下載的檔案

11. 在template\default\source\1.php\目錄下新建一個1.php檔案,檔案內容寫入phpinfo(),嘗試一下能不能下載該檔案

 

 


12. 成功下載到1.php檔案。嘗試下載`source/system/config.inc.php`檔案。將音訊地址改為`../../../source/system/config.inc.php`,結果發現被過濾了

 

 

 


13. 再次提交,抓包,看一下提交的時候被傳遞給了誰,如下所示,傳遞到了source/user/music/ajax.php,有兩個重要的引數ac=edit audio=Sfaty filter,

14. 轉到這個檔案,找到ac=edit,逐個檢視audio的方法,發現checkname()中對file進行了過濾,過濾了./,一旦匹配到關鍵詞直接變為Safety filter

 

 


15. 沒有過濾`/`,使用絕對路徑嘗試繞過

16. 如圖所示,成功讀取到組態檔