0x01 簡介
PHP檔案包含漏洞中,如果找不到可以包含的檔案,我們可以通過包含臨時檔案的方法來getshell。因為臨時檔名是隨機的,如果目標網站上存在phpinfo,則可以通過phpinfo來獲取臨時檔名,進而進行包含。
0x02 漏洞利用原理
在給PHP傳送POST資料包時,如果資料包裡包含檔案區塊,無論你訪問的程式碼中有沒有處理檔案上傳的邏輯,PHP都會將這個檔案儲存成一個臨時檔案(通常是/tmp/php[6個隨機字元]),檔名可以在$_FILES變數中找到。這個臨時檔案,在請求結束後就會被刪除。
同時,因為phpinfo頁面會將當前請求上下文中所有變數都列印出來,所以我們如果向phpinfo頁面傳送包含檔案區塊的資料包,則即可在返回包裡找到$_FILES變數的內容,自然也包含臨時檔名。
在檔案包含漏洞找不到可利用的檔案時,即可利用這個方法,找到臨時檔名,然後包含之。
但檔案包含漏洞和phpinfo頁面通常是兩個頁面,理論上我們需要先傳送資料包給phpinfo頁面,然後從返回頁面中匹配出臨時檔名,再將這個檔名傳送給檔案包含漏洞頁面,進行getshell。在第一個請求結束時,臨時檔案就被刪除了,第二個請求自然也就無法進行包含。
這個時候就需要用到條件競爭,具體流程如下:
- 傳送包含了webshell的上傳資料包給phpinfo頁面,這個資料包的header、get等位置需要塞滿垃圾資料
- 因為phpinfo頁面會將所有資料都列印出來,1中的垃圾資料會將整個phpinfo頁面撐得非常大
- php預設的輸出緩衝區大小為4096,可以理解為php每次返回4096個位元組給socket連線
- 所以,我們直接操作原生socket,每次讀取4096個位元組。只要讀取到的字元裡包含臨時檔名,就立即傳送第二個資料包
- 此時,第一個資料包的socket連線實際上還沒結束,因為php還在繼續每次輸出4096個位元組,所以臨時檔案此時還沒有刪除
- 利用這個時間差,第二個資料包,也就是檔案包含漏洞的利用,即可成功包含臨時檔案,最終getshell
0x03 漏洞復現
漏洞環境在vulhub上可以獲取
https://github.com/vulhub/vulhub/tree/master/php/inclusion
直接在docker上拉取環境
環境啟動後,訪問http://ip:8080/phpinfo.php即可看到一個PHPINFO頁面,訪問http://ip:8080/lfi.php?file=/etc/passwd,可見的確存在檔案包含漏洞。
用exp.py指令碼來不斷的上傳資料,利用條件競爭實現包含檔案。
成功包含臨時檔案後,會執行')?>,寫入一個新的檔案g到/tmp/目錄。
用python2執行:python exp.py your-ip 8080 100
看到只用了100個資料包的時候就寫入成功了,之後就可以配合lfi.php執行任意命令,然後配合之前存在檔案包含漏洞的php檔案,就可以任意命令執行。
檢視檔案
?php>
0x04 參考文章
https://github.com/vulhub/vulhub/tree/master/php/inclusion
https://dl.packetstormsecurity.net/papers/general/LFI_With_PHPInfo_Assitance.pdf