標題:文件上傳漏洞相關

taibeihacker

Moderator

文件上传漏洞​

1 前言​

靶場環境:https://github.com/c0ny1/upload-labs
環境搭建:
1
2
docker pull c0ny1/upload-labs
docker run -d -p 80:80 upload-labs
判斷上傳漏洞的類型:
20210113094518.png-water_print

文件上傳漏洞主要存在以下幾個方面:
可解析的後綴,也就是該語言有多個可解析的後綴,比如php 語言可解析的後綴為php,php2,php3 等等
大小寫混合,如果系統過濾不嚴,可能大小寫可以繞過。
中間件,每款中間件基本都解析漏洞,比如iis 就可以把xxx.asp;jpg 當asp 來執行。
系統特性,特別是Windows 的後綴加點,加空格,加:$DATA 可以繞過目標系統。
語言漏洞,流行的三種腳本語言基本都存在00 截斷漏洞。
雙后綴,這個與系統和中間件無關,偶爾會存在於代碼邏輯之中。

1.1 可解析的后缀​

很多語言都有多個可以解析後綴。當目標站點採用黑名單時,往往包含不全。
语言可解析后缀asp/aspx
asp、aspx、asa、asax、ascx、ashx、asmx、cer
php
php、php5、php4、php3、php2、phtml、pht
jsp
jsp、jspa、jspx、jsw、jsv、jspf、jhtml

1.2 中间件漏洞​

1.2.1 IIS​

IIS 一共有三個解析漏洞:
IIS 6.0 文件解析xx.asp;jpg
IIS 6.0 目錄解析xx.asp/1.jpg
IIS 7.5 畸形解析xxx.jpg/x.php

1.2.2 Apahce​

apache 相關的解析漏洞有兩個:
%0a (CVE-2017-15715)
未知後綴test.php.xxx

1.2.3 nginx​

nginx 解析漏洞有三個:
訪問鏈接加/xxx.php,即test.jpg/xxx.php
畸形解析漏洞test.jpg%00xxx.php
CVE-2013-4547 test.jpg(非編碼空格)\0x.php

1.2.4 tomcat​

tomcat 用於上傳繞過的有三種,部分限制在windows 操作系統下。
xxx.jsp/
xxx.jsp%20
xxx.jsp:$DATA

1.3 系统特性​

經過查資料,目前發現在系統層面,有以下特性可以被上傳漏洞所利用。
Windows 下文件名不區分大小寫,Linux下文件名區分大寫
Windows 下ADS 流特性,導致上傳文件xxx.php:$DATA=xxx.php
Windows 下文件名結尾加入.空格、0x81-0xff等字符,最終生成的文件均被windows 忽略。

2 WriteUP​

2.1 PASS - 01​

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
script type='text/javascript'
function checkFile() {
var file=document.getElementsByName('upload_file')[0].value;
if (file==null || file=='') {
alert('請選擇要上傳的文件!');
return false;
}
//定義允許上傳的文件類型
var allow_ext='.jpg|.png|.gif';
//提取上傳文件的類型
var ext_name=file.substring(file.lastIndexOf('.'));
//判斷上傳文件類型是否允許上傳
if (allow_ext.indexOf(ext_name)==-1) {
var errMsg='該文件不允許上傳,請上傳' + allow_ext + '類型的文件,當前文件類型為:' + ext_name;
alert(errMsg);
return false;
}
}
/script
前端禁用JS,直接上傳Webshell

2.2 PASS - 02​

繞過MIME 檢測,通過BurpSuite 修改Content-Type 即可
20210113095128.png-water_print

2.3 PASS - 03​

1
2
3
4
5
6
7
$deny_ext=array('.asp','.aspx','.php','.jsp');
$file_name=trim($_FILES['upload_file']['name']);
$file_name=deldot($file_name);//刪除文件名末尾的點
$file_ext=strrchr($file_name, '.');
$file_ext=strtolower($file_ext); //轉換為小寫
$file_ext=str_ireplace(':$DATA', '', $file_ext);//去除字符串:$DATA
$file_ext=trim($file_ext); //收尾去空
後端過濾了.php,通過使用.php3、php5、php7、phtml、pht 等後綴繞過檢測
20210113095554.png-water_print

2.4 PASS - 04​

重寫文件解析規則繞過。上傳先上傳一個名為.htaccess 文件,內容如下
1
2
3
FiileMatch '04.jpg'
SetHandler application/x-httpd-php
/FiileMatch
再上傳一個03.jpg ,訪問03.jpg,即以PHP 文件進行解析。
20210113100041.png-water_print

2.5 PASS - 05​

還是黑名單,加上了.htaccess,但是沒有將後綴進行大小寫統一,於是可以通過大小寫繞過.
20210113100129.png-water_print

2.6 PASS - 06​

利用Windows 系統的文件名特性。文件名最後增加點和空格,寫成06.php[空格] ,
上傳後保存在Windows 系統上的文件名最後的一個. 會被去掉,實際上保存的文件名就是06.php
20210113100337.png-water_print

2.7 PASS - 07​

原理同Pass-06,文件名後加點,改成07.php.
20210113100438.png-water_print

2.8 PASS - 08​

Windows 文件流特性繞過,文件名改成08.php:$DATA,上傳成功後保存的文件名其實是08.php
php 在window 環境下,如果文件名+ :$DATA 會把:$DATA 之後的數據當成文件流處理,不會檢測後綴名,且保持:$DATA 之前的文件名
20210113103212.png-water_print

2.9 PASS - 09​

原理同Pass-06,上傳文件名後加上點+ 空格+ 點,改為09.php.
20210113103319.png-water_print

2.10 PASS - 10​

雙寫文件名繞過,文件名改成10.pphphp
20210113103439.png-water_print

2.11 PASS - 11​

上傳路徑名%00 截斷繞過。上傳的文件名寫成11.jpg,save_path 改成./upload/11.php%00,最後保存下來的文件就是11.php
20210113103600.png-water_print

2.12 PASS - 12​

原理同Pass-11,上傳路徑0x00 繞過。這次的save_path 是通過post 傳進來的,還是利用00 截斷,但這次需要在二進制中進行修改,因為post 不會像get 對%00 進行自動解碼
利用Burpsuite 的Hex 功能將save_path 改成./upload/12.php[二進制00]形式
20210113103701.png-water_print

2.13 PASS - 13​

繞過文件頭檢查,添加GIF 圖片的文件頭GIF89a,繞過GIF 圖片檢查。
20210113104024.png-water_print

2.14 PASS - 14​

這裡用getimagesize 獲取文件類型,還是直接就可以利用圖片馬就可進行繞過

2.15 PASS - 15​

這裡用到php_exif 模塊來判斷文件類型,還是直接就可以利用圖片馬就可進行繞過

2.16 PASS - 16​

原理:將一個正常顯示的圖片,上傳到服務器。尋找圖片被渲染後與原始圖片部分對比仍然相同的數據塊部分,
將Webshell 代碼插在該部分,然後上傳。具體實現需要自己編寫Python 程序,人工嘗試基本是不可能構造出能繞過渲染函數的圖片webshell 的。
參考:

2.17 PASS - 17​

利用條件競爭刪除文件時間差繞過。
在腳本運行的時候,訪問Webshell

2.18 PASS - 18​

利用上傳重命名競爭+ Apache解析漏洞,成功繞過。
上傳名字為18.php.7Z 的文件,快速重複提交該數據包,會提示文件已經被上傳,但沒有被重命名。
20210113104348.png-water_print

2.19 PASS - 19​

本關考察CVE-2015-2348 move_uploaded_file() 00 截斷,原理同Pass-11,上傳的文件名用0x00 繞過。改成19.php[二進制00].1.jpg
20210113104506.png-water_print

2.20 PASS - 20​

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$file=empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
if (!is_array($file)) {
$file=explode('.', strtolower($file));
}
$ext=end($file);
$allow_suffix=array('jpg','png','gif');
if (!in_array($ext, $allow_suffix)) {
$msg='禁止上傳該後綴文件!';
}else{
$file_name=reset($file) . '.' . $file[count($file) - 1];
$temp_file=$_FILES['upload_file']['tmp_name'];
$img_path=UPLOAD_PATH . '/' .$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$msg='文件上傳成功! ';
$is_upload=true;
} else {
$msg='文件上傳失敗! ';
}
首先end 函數取所post 參數數組中的最後一個值,$file_name=reset($file) . '.' . $file[count($file) - 1]。我們可以post 一個參數名為一個[0]一個[2],然後$file[count($file) - 1] 就為空,$file_name 最終就為reset($file) 即$file[0],就可以繞過判斷
20210113105239.png-water_print
 
返回
上方