文件上傳__常用bypass小結

文件上傳是常用getshell的路徑之一,因爲可以通過上傳一句話木馬實現控制主機

這裏從uploads-lab靶場的實驗下,用文字總結並講述一些常用的上傳及bypass。順便拓展一丟丟東西

這裏借用uploads-lab的圖片一用
在這裏插入圖片描述

首先針對前端 (也就是客戶端) 的繞過

js繞過

在F12下,在js添加文件後綴刪除方法
在這裏插入圖片描述

抓包修改文件後綴繞過

可以將要上傳的php文件改後綴名爲jpg|png|gif上傳,繞過js驗證後,再用burp抓包修改文件後綴
 

首先針對後端 (也就是服務端) 的繞過

檢查後綴

一、黑名單
  1. 上傳特殊可解析後綴
    服務器端做了一個黑名單過濾,過濾了 asp、aspx、php、jsp
    但是可以其他後綴名上傳,例如phps、php3、phtml、php5等等
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $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); //收尾去空

        if(!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;            
            if (move_uploaded_file($temp_file,$img_path)) {
                 $is_upload = true;
            } else {
                $msg = '上傳出錯!';
            }
        } else {
            $msg = '不允許上傳.asp,.aspx,.php,.jsp後綴文件!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夾不存在,請手工創建!';
    }
}
  1. 上傳.htaccess
    黑名單裏php、php5等奇葩後綴全部不允許上傳時。可嘗試上傳.htaccsess文件繞過
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf");
        $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); //收尾去空

        if (!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.$file_name;
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上傳出錯!';
            }
        } else {
            $msg = '此文件不允許上傳!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夾不存在,請手工創建!';
    }
}

首先上傳一個.htaccess內容如下的文件:
類似於把文件名包含 1 的解析成php
<FilesMatch "1"> SetHandler application/x-httpd-php </FilesMatch>

htaccess文件是Apache服務器中的一個配置文件,它負責相關目錄下的網頁配置。在這裏,可以通過htaccess文件,可以幫我們將所有文件都會以php進行解析,包括上傳的圖片馬等…
 
3. 後綴大小寫繞過
用burp將後綴改爲大寫PHP即可
 
4. 空格、點後綴繞過
可以利用windows系統的命名規則進行繞過
Windows下xx.jpg[空格]xx.jpg. 這兩類文件都是不允許存在的,若這樣命名,windows會默認除去空格或點
此處會刪除末尾的點,但是沒有去掉末尾的空格,因此上傳一個.php[空格]或者.php.文件即可
 
5. 雙寫後綴繞過

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");

        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = str_ireplace($deny_ext,"", $file_name);
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = UPLOAD_PATH.'/'.$file_name;        
        if (move_uploaded_file($temp_file, $img_path)) {
            $is_upload = true;
        } else {
            $msg = '上傳出錯!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夾不存在,請手工創建!';
    }
}

利用str_ireplace對黑名單裏的文件後綴名進行了替換,換成空字符,使用了str_ireplace函數,即不區分大小寫,故大小寫繞過不適用。但是這裏替換是替換成了空字符,於是我們可以雙寫後綴名,如xxx.pphphp,使得替換後的後綴名爲php。
 
6. ::$DATA繞過
這裏還是利用windows的一個特性。
NTFS文件系統包括對備用數據流的支持。這不是衆所周知的功能,主要包括提供與Macintosh文件系統中的文件的兼容性。備用數據流允許文件包含多個數據流。每個文件至少有一個數據流。在Windows中,此默認數據流稱爲:$ DATA

簡單講就是在php+windows的情況下:如果文件名+"::$DATA"會把::$DATA之後的數據當成文件流處理,不會檢測後綴名,且保持"::$DATA"之前的文件名。例如:xx.php::$DATA
 
7. 配合解析漏洞

(一)IIS 6.0解析漏洞
IIS 6.0解析利用方法有兩種
1.目錄解析
將木馬圖片上傳至asp文件夾下,其目錄內的任何擴展名的文件都被IIS當作asp文件來解析並執行
/xx.asp/xx.jpg

2.文件解析
分號後面的不被解析,也就是說xxx.asp;.jpg會被服務器看成是xxx.asp
xxx.asp;.jpg

(二)IIS 7.0解析漏洞
在php.ini裏設置cgi.fix_pathinfo=1
使得訪問任意文件URL時,在URL後面添加“/x.php”等字符時,該文件被iis當php文件代碼解析
默認Fast-CGI開啓狀況下,上傳一個木馬文件爲xxx.jpg,然後訪問xxx.jpg/x.php,這個文件將以php進行解析

(三)Nginx <8.03畸形解析漏洞
默認Fast-CGI開啓狀況下,上傳一個木馬文件爲xxx.jpg,然後訪問xxx.jpg/x.php,這個文件將以php進行解析

(四)Nginx 空字節代碼執行漏洞
影響版本0.5.,0.6, 0.7 <= 0.7.65, 0.8 <= 0.8.37
Ngnix在遇到%00空字節時與後端FastCGI處理不一致,導致可以在圖片中嵌入PHP代碼然後通過訪問xxx.jpg%00.php來執行其中的代碼

(五)Apache解析漏洞(只能是黑名單)
上傳的文件命名爲:xxx.php.x1.x2.x3,Apache是從右往左判斷後綴,直到遇到可解析後綴爲止

 

二、白名單
  1. MIME繞過

後端只對Content-Type進行了檢查。在burp中更改Content-Type進行繞過即可
以白名單方式更換:image/jpg
更多content-type格式

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']            
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上傳出錯!';
            }
        } else {
            $msg = '文件類型不正確,請重新上傳!';
        }
    } else {
        $msg = UPLOAD_PATH.'文件夾不存在,請手工創建!';
    }
}

 
2. 00截斷

Get路徑傳入

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');
    $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
    if(in_array($file_ext,$ext_arr)){
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = '上傳出錯!';
        }
    } else{
        $msg = "只允許上傳.jpg|.png|.gif類型文件!";
    }
}
截斷條件:
1、php版本小於5.3.4
2、php.ini的magic_quotes_gpc爲OFF狀態

可在get請求路徑構造sava_path=/upload/xxx.php%00繞過

Post路徑傳入

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');
    $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
    if(in_array($file_ext,$ext_arr)){
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = "上傳失敗";
        }
    } else {
        $msg = "只允許上傳.jpg|.png|.gif類型文件!";
    }
}

點擊上傳抓包後
對路徑:sava_path=/upload/xxx.php%00
或者
對文件:xxx.php%00.jpg
我們需要對%00做一個URL編碼,也就是URL-decode

爲什麼兩者用法不同?
這是因爲 %00 截斷在 GET 中被 url 解碼之後是空字符。但是在 POST 中 %00 不會被 url 解碼,所以只能通過 burpsuite 修改成 hex 值爲 0x00 (URL decode)進行截斷。
 

檢查內容

一、圖片馬

利用windows的cmd命令製作copy製作圖片馬。製作完圖片馬後直接上傳,然後利用文件包含即可

copy /b 11.jpg + yijuhua.php yijuhua.jpg
在這裏插入圖片描述
 

二、二次渲染

過程有點複雜。等實際場景用到了再細細研究
參考這個?

條件競爭(代碼邏輯問題)

(這種方式還是不建議的,容易被管理員發現,還是算了)

$is_upload = false;
$msg = null;

if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');
    $file_name = $_FILES['upload_file']['name'];
    $temp_file = $_FILES['upload_file']['tmp_name'];
    $file_ext = substr($file_name,strrpos($file_name,".")+1);
    $upload_file = UPLOAD_PATH . '/' . $file_name;

    if(move_uploaded_file($temp_file, $upload_file)){
        if(in_array($file_ext,$ext_arr)){
             $img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;
             rename($upload_file, $img_path);
             $is_upload = true;
        }else{
            $msg = "只允許上傳.jpg|.png|.gif類型文件!";
            unlink($upload_file);
        }
    }else{
        $msg = '上傳出錯!';
    }
}

這裏是先move_uploaded_file函數將上傳文件臨時保存,再進行判斷,如果不在白名單裏則unlink刪除,在的話就rename重命名,所以這裏存在條件競爭

先用burp開啓兩個intruder模塊,一個用於重複上傳,另一個用於重複訪問。設置上傳請求,記住此處的文件名,等下要用來拼接訪問請求的url

因爲此處沒有什麼參數需要爆破,只是需要重複發起請求
 

總結

總結就是,慢慢測試,根據測試選擇適合的路線

 
GOT IT!

 
******************************************************
小實驗小結,具體測試利用方式需根據具體實踐場景~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章