本文通過upload-labs學習檔案上傳漏洞,最後有一個檔案上傳的小結。首先看一下$_FILES[]的内容
array(1) {
["myfile"]=>
array(5) {
["name"]=>
string(7) "hhh.php"
["type"]=>
string(24) "application/octet-stream"
["tmp_name"]=>
string(22) "C:\Windows\php6109.tmp"
["error"]=>
int(0)
["size"]=>
int(156)
}
}
這些資訊也是伺服器檢測的依據來源。靶場入口
paas-1
前端javascript檢測,直接禁用JavaScript或者burpsuit抓包改名字就行了。
pass-2
Content-Type檢測
Content-Type :image/gif imag/jpg
Content-Type :application/octet-stream
pass-3
過濾.asp,.aspx,.php,.jsp檔案字尾,用php3,php4,phtml等替換。
但phpstudy因為配置原因無法解析php3等檔案字尾。
pass-4
過濾的很多檔案字尾,但可以上傳.htaccess檔案,修改解析,然後上傳.jpg。
pass-5
大小寫繞過(前提是配置檔案開啟)
pass-6
檔案名加空格繞過
pass-7
檔案名後面加.繞過(eg:hhh.php.),利用的是windows特性在儲存時會自動把點去掉。
pass-8
通過::$DATA繞過
pass-9
利用windows檔案命名特性
test.php… ------> test.php
test.php ------> test.php(前一個test.php後有空格)
test.php. … ------> test.php
構造一個.和空格組合的檔案名(test.php. .)繞過
pass-10
雙寫繞過。
pass-11
控制上傳路徑,在上傳路徑後通過%00截斷,繞過白名單
%00截斷條件:
php版本小于5.3.4
php.ini中magic_quotes_gpc為OFF狀态。
move_uploaded_file函數的底層實作類似于C語言,遇到0x00就會截斷。
pass-12
因為save_path也在上傳檔案的那個表單裡,是以就不會對其解碼,那麼要通過%00截斷,就隻有在包的二進制裡面修改才有用。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI2EzX4xSZz91ZsAzNfRHLGZkRGZkRfJ3bs92YsAjMfVmepNHL9cXVTFUNyUVQClGVF5UMR9Fd4VGdsATNfd3bkFGazxSUhxGatJGbwhFT1Y0Mk9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL5EjM4ITYwYTYhVGN1YDNihjZ4QjZjZDZ3MjMxYGM3AzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
pass-13
通過copy paint.jpg /b+shell.txt /a webshell.jpg 來構造一個圖檔馬,然後再結合檔案包含漏洞利用圖檔馬.
pass-14
通過getimagesize()會傳回圖像的尺寸大小及類型等資訊.
array(6) {
[0]=>
int(48)
[1]=>
int(48)
[2]=>
int(3)
[3]=>
string(22) "width="48" height="48""
["bits"]=>
int(8)
["mime"]=>
string(9) "image/png"
}
- 索引 0 給出的是圖像寬度的像素值
- 索引 1 給出的是圖像高度的像素值
- 索引 2 給出的是圖像的類型,傳回的是數字,其中1 = GIF,2 = JPG,3 = PNG,4 = SWF,5 = PSD,6 = BMP,7 = TIFF(intel byte order),8 = TIFF(motorola byte order),9 = JPC,10 = JP2,11 = JPX,12 = JB2,13 = SWC,14 = IFF,15 = WBMP,16 = XBM
- 索引 3 給出的是一個寬度和高度的字元串,可以直接用于 HTML 的 标簽
- 索引 bits 給出的是圖像的每種顔色的位數,二進制格式
- 索引 channels 給出的是圖像的通道值,RGB 圖像預設是 3
- 索引 mime 給出的是圖像的 MIME 資訊,此資訊可以用來在 HTTP Content-type 頭資訊中發送正确的資訊,如: header(“Content-type: image/jpeg”);
這一關主要就是通過getimagesize檢測的圖檔的類型,還是和上一關類似,上傳一個圖檔馬就可以了。
pass-15
通過exif_imagetype()讀取圖像第一個位元組并檢查簽名。傳回結果和getimagesize的索引2類似,但它更快。
還是和上面一樣上傳一個圖檔馬就行了,但要打開php_exif擴充。
pass-16
經過了二次渲染,原來加在後面的圖檔馬被删掉了,是以這個要對比前後檔案差異,然後把代碼插在未被修改的地方就行了。
參考:二次渲染繞過
pass-17
代碼審計可以看出是白名單過濾,但它是先把檔案移動到檔案夾下,然後判斷如果檔案字尾不對再删除檔案。于是就會有一小段時間是存在那個檔案夾的,所有就可以通過條件競争來繞過。同時模拟很多人上傳檔案和通路,隻要有一次通路成功就可以建立後門。
參考:條件競争
pass-18
通過代碼審計可以看出它最後是先上傳的檔案,然後改的名字,于是也可以通過條件競争上傳webshell。
pass-19
代碼審計先檢視pathinfo()函數傳回檔案字尾,當檔案名以點(.)結尾時,傳回為空。于是可以通過這一點繞過黑名單檢測。還能看出最後上傳的檔案名我們可控,于是設定檔案名為test.php即可上傳。除此之外還可以通過大小寫繞過黑名單檢測。還可以用<CVE-2015-2348 move_uploaded_file() 00截斷>
pass-20
從代碼審計可以看出首先經過了一個Content-Type檢測,然後把儲存的檔案名進行白名單過濾,最後上傳。
白名單過濾主要就是想辦法繞過in_array( e x t , ext, ext,allow_suffix),而對于in_array(string,array,[strict])的繞過,再兩個參數的情況下是弱比較。但在這題裡面似乎利用不了,因為$file初始值是上傳的檔案名或者你輸入的儲存的檔案名,然後經過了exlode函數分割變成了數組,最後通過end得到數組最後一個。
但問題就在于這個$file的初始值是我們完全可控的,然後在explode函數前它做了一個is_array()檢測,是以我們可以自己直接給她POST傳入一個數組就繞過了白名單檢測。
然後看到了儲存的檔案名是通過$file數組擷取的,reset()傳回數組的第一個元素,count()傳回數組元素的個數,這個是關鍵點它傳回的是設定過的數組元素個數。
<?php
$a = array();
var_dump($a[4]); //NULL
echo "<br>".count($a)."<br>"; //0
$a[0]='123';
$a[4]="hhh";
echo count($a)."<br>"; //2
$a[4]=null;
echo count($a)."<br>"; //2
var_dump($a[4]); //NULL
?>
于是就可以傳入一個數組save_path[0]=“demo.php”,save_path[2]=“jpg”;這樣$file[count($file)-1]就為空,就繞過了最後檔案儲存的檔案名字尾了。
總結
前端檢測
直接禁用javascript或者抓包就OK了。
檔案類型檢測(Content-Type)
也可以直接抓包修改Content-Type字段。
檔案名檢測(File_Name)
黑名單:
- 大小寫繞過(strtolower())
- 罕見字尾(eg:phtml,php5等)
- 檔案字尾加空格繞過(trim())
- 末尾加點(deldot()/strrstr())
- 末尾空格和字尾組合(deldot(),trim())
- 特殊符号::$DATA(windows系統下)
- 雙寫繞過
- 上傳.htaccess檔案(前提是配置檔案有AllowOverride All)
白名單:
- %00截斷(條件:1、PHP版本<5.3.4。2、magic_quotes_gpc關閉)。注意上傳時修改的位置。
- 在上傳路徑或者檔案名可控的條件下分析其拼接過程,通過上傳特定參數繞過白名單。
檔案内容檢測
- 讀取檔案頭部判斷檔案類型,那麼我們就可以用01editor修改檔案頭部,常見檔案頭部
- 檔案内容敏感字元檢測,可以通過一些其他方法替代
二次渲染
通過上傳的圖檔馬然後再通路對比前後的差別确定是否存在二次渲染,然後找出未改變的地方插入一句話木馬。