PHP檔案包含與phpinfo
0x00 漏洞概述
當遇到PHP檔案包含漏洞時,如果找不到可以包含的檔案,可以通過包含臨時檔案來GetShell。由於臨時檔案的檔名是隨機的,如果目標網站存在phpinfo,則可以通過phpinfo來獲取臨時檔名,進而完成包含。
0x01 漏洞原理
在給PHP伺服器POST資料包時,如果資料包含有檔案區塊,無論訪問路徑的程式碼是否具有處理檔案上傳的邏輯,PHP都會將這個區塊(檔案)儲存為一個臨時檔案,通常位於/tmp/php[6個隨機字元]。檔名可以在$_FILES
變數中找到。該臨時檔案會在請求結束後被刪除。
因為phpinfo會將當前請求的上下文全部打印出來,所以如果向phpinfo頁面傳送包含檔案區塊的資料包,則可以在返回包找到$_FILES
實際情況下,檔案包含漏洞和phpinfo通常來自於兩個頁面,理論上需要先發送給phpinfo頁面,然後從返回包得到臨時檔名,再將這個檔名傳送給檔案包含漏洞頁面,進行GetShell。在第一個請求結束時,臨時檔案就被刪除了,第二個請求自然無法完成檔案包含。
此時需要用到條件競爭:
- 傳送包含webshell的上傳資料到phpinfo頁面,這個資料包的header、get等位置充滿了垃圾資料。
- 因為phpinfo頁面會將所有資料打印出來,垃圾資料會將整個phpinfo頁面過分填充。
- PHP預設的輸出緩衝區大小為4096,可理解為PHP每次返回4096個位元組給socket連線。直接操作原生socket,每次讀取4096個位元組,只要讀取到的字元裡包含臨時檔名,就立即傳送第二個資料包。
- 此時第一個資料包的socket連線還未結束,因為PHP還在繼續每次輸出4096個位元組,所以臨時檔案此時還未被刪除。
- 利用時間差完成包含臨時檔案,最終GetShell。
0x02 環境搭建
建立一個Docker專案,Apache部分直接依靠拉取,只需要編寫三個檔案。
執行
docker-compose up -d
等待完成即可。
~/docker-compose.yml
version: '2'
services:
php:
image: php:7.2-apache
volumes:
- ./www:/var/www/html
ports:
- "8080:80"
~/www/lfi.php
即檔案包含漏洞所在地。
<?php
include $_GET['file'];
~/www/phpinfo.php
<?php
phpinfo();
0x03 利用流程
訪問靶機
根目錄為403。通過目錄掃描等途徑可得/phpinfo.php和/lfi.php。
訪問/lfi.php,從報錯資訊可知服務端系統Linux、網站路徑、include
函式。
由於不知道lfi.php所接受的引數名稱,需要爆破一下。
得到引數名為file
。
EXP
使用優質EXP,需要Python2。
因為已知網站路徑/var/www/html/,所以可以在Payload處做一點自定義(同時注意檔案包含路徑和phpinfo路徑是否正確):
執行:
python exp.py 192.168.31.39 8080 100
連線
剛才自定了Payload中的檔案路徑,所以訪問網站根目錄的cmd.php即可。
大功告成!