1. 程式人生 > 實用技巧 >upload-labs

upload-labs

less-1(前端js繞過)

建立一個一句話木馬 上傳

在前端有checkfile()函式,就是檢測上傳的檔案是否是jpg png gif格式,在前端刪掉即可上傳成功

原始碼:

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;
    }
}

沒有進行任何過濾

Less-2(檔案型別繞過)

第二關上傳後沒有通過前端js驗證,所以上一關的方法行不通。

進行抓包發現只有在Content-Type處改變資料,所以修改Content-Type的引數即可上傳成功

less-3(其他字尾可解析繞過)

第三關Content-Type修改行不通了,試了下php3上傳成功

原始碼:

$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.原始碼中有黑名單過濾了.asp,.aspx,.php,.jsp
2.在window的時候如果檔名+"::$DATA"會把::$DATA之後的資料當成檔案流處理,不會檢測字尾名,且保持::$DATA之前的檔名,他的目的就是不檢查字尾名.
例如:"phpinfo.php::$DATA"Windows會自動去掉末尾的::$DATA變成"phpinfo.php"

Less-4(.htacess檔案繞過)

直接看原始碼

$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.'/'.date("YmdHis").rand(1000,9999).$file_ext;
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上傳出錯!';
            }
        } else {
            $msg = '此檔案不允許上傳!';
        }
    } else {
        $msg = UPLOAD_PATH . '資料夾不存在,請手工建立!';
    }
}

這個黑名單過濾的有點多,把常見的過濾方法都過濾了,::$DATA也不行

可以用.htaccess檔案上傳 (.htaccess可以用來留後門和針對黑名單繞過)
.htaccess檔案
原理大概就是:通過.htaccess檔案呼叫php解析器解析一個檔案,只要包含"cimer"這個字串的任意檔案。如果"cimer"的內容是一句話木馬,就可以通過菜刀等連線

例如:
shell.htaccess檔案中

shell.jpg是一個圖片馬,上傳後會當成php解析

上傳成功後檢視影象複製路徑菜刀連線成功

Less-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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//刪除檔名末尾的點
        $file_ext = strrchr($file_name, '.');
        $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 = '此檔案型別不允許上傳!';
        }
    } else {
        $msg = UPLOAD_PATH . '資料夾不存在,請手工建立!';
    }
}

黑名單多加了.htaccess所以不能有上一關方法
但是這關的原始碼中沒有 strtolower函式,說明可以採用大小寫繞過

Less-6(空格繞過)

原始碼:

$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess");
        $file_name = $_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
        
        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 = '此檔案不允許上傳';
        }
    } else {
        $msg = UPLOAD_PATH . '資料夾不存在,請手工建立!';
    }
}


這關原始碼裡面加上了strlower函式,但是沒有 $file_ext = trim($file_ext);去空處理,所以可以利用空格繞過。 在上傳儲存到windows系統後文件名最後一個空格會被抹掉,意味著在後綴那裡加上空格後可以繞過黑名單,最後儲存的時候還是原始檔名字尾。

Less-7(點繞過)

原始碼:

$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess");
        $file_name = trim($_FILES['upload_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 . '資料夾不存在,請手工建立!';
    }
}

這關沒有 $file_name = deldot($file_name);這個函式,意味著在檔案末尾加上點就可以繞過

less-8(::$DATA )

原始碼:

$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//刪除檔名末尾的點
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //轉換為小寫
        $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 = '此檔案型別不允許上傳!';
        }
    } else {
        $msg = UPLOAD_PATH . '資料夾不存在,請手工建立!';
    }
}

原始碼中沒有了$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字串::$DATA 所以可以用::$DATA繞過 。windows中特性檔案流繞過,在後綴後加上::$DATA,上傳成功後儲存的還是原檔案

Less-9(點+空格+點繞過)

原始碼:

• 程式碼
$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess");
        $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 . '資料夾不存在,請手工建立!';
    }
}

原始碼中刪除檔名末尾的點,刪除首尾的空格,再通過strrchr虛招檔案中的點確定檔案的字尾名,但是在最後儲存檔案的時候沒有重新賦值命名,而是直接使用file_name原始檔名導致可以利用點+空格+點繞過

Less-10(雙寫繞過)

原始碼:

$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($deny_ext,"", $file_name);將deny_ext中替換成空字元,可以嘗試雙寫繞過

經過測試,使用黑名單中的任何一個雙寫都可以繞過

Less-11(GET型%00截斷)

原始碼:

$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型別檔案!";
    }
}

十一關沒有了黑名單變成了白名單,只能有jpg,png,gif。直接拼接的img_path可以%00截斷.截斷條件:
1、php版本小於5.3.4 2、php.ini的magic_quotes_gpc為OFF狀態
知識點:這裡利用的是00截斷。move_uploaded_file函式的底層實現類似於C語言,遇到0x00會截斷。

Less-12(POST型%00截斷)

原始碼:


程式碼

$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型別檔案!";
    }
}


這關和十一關不同的是這次的save_path是通過post傳進來的,還是利用00截斷,但這次需要在二進位制中進行修改,因為post不會像get對%00進行自動解碼

Less-13(圖片馬)

copy 1.jpg /b + 1.php /a test.jpg

Less-14(圖片馬繞過 - getimagesize)

這裡用getimagesize獲取檔案型別,還是直接就可以利用圖片馬就可進行繞過

getimagesize() 函式用於獲取影象大小及相關資訊,成功返回一個數組,失敗則返回 FALSE 併產生一條 E_WARNING 級的錯誤資訊

less-15(圖片馬繞過exif_imagetype)

exif_imagetype()檢查是否為圖片檔案

less-16()

詳細分析(https://xz.aliyun.com/t/2657#toc-0)

less-17