PHP程式碼審計——文件操作漏洞

夢想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文件,如下所示,文件被成功刪除
//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. 嘗試一下讀取網站配置文件,如下所示,成功讀取到配置文件
 //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. 如圖所示,成功讀取到配置文件