檔案上傳之後端黑白名單繞過

朝朝_暮暮發表於2021-08-07

檔案上傳常見驗證

1. 字尾名

  • 黑名單:後端程式碼中明確不讓上傳的檔案字尾名。
    比如:asp、php、jsp、aspx、cgi、war等
  • 白名單:後端程式碼中明確可以上傳檔案的型別
    比如:jpg、png、zip、rar、gif····

php5、phtml等格式未出現在黑名單中可以繞過,此型別與搭建平臺的設定有關。

2. 檔案型別

檔案型別在http頭資訊中又稱MIME資訊。
具體表現在http頭中的content-type資訊中。

3. 檔案頭資訊

檔案頭是位於檔案開頭的一段承擔一定任務的資料,一般都在開頭的部分。
常見檔案的檔案頭:
JPEG (jpg), 檔案頭:FFD8FF
PNG (png),  檔案頭:89504E47 檔案尾:0000000049454E44AE426082
GIF (gif), 檔案頭:47494638
ZIP Archive (zip), 檔案頭:504B0304 檔案尾:00000000
TIFF (tif), 檔案頭:49492A00
Windows Bitmap (bmp),   檔案頭:424D
CAD (dwg), 檔案頭:41433130
Adobe Photoshop (psd), 檔案頭:38425053
Rich Text Format (rtf), 檔案頭:7B5C727466
XML (xml), 檔案頭:3C3F786D6C
HTML (html), 檔案頭:68746D6C3E
Email [thorough only] (eml), 檔案頭:44656C69766572792D646174653A
Outlook Express (dbx), 檔案頭:CFAD12FEC5FD746F
Outlook (pst), 檔案頭:2142444E
MS Word/Excel (xls.or.doc), 檔案頭:D0CF11E0
MS Access (mdb), 檔案頭:5374616E64617264204A
WordPerfect (wpd), 檔案頭:FF575043
Adobe Acrobat (pdf), 檔案頭:255044462D312E
Quicken (qdf), 檔案頭:AC9EBD8F
Windows Password (pwl), 檔案頭:E3828596
RAR Archive (rar), 檔案頭:52617221
Wave (wav), 檔案頭:57415645
AVI (avi), 檔案頭:41564920
Real Audio (ram), 檔案頭:2E7261FD
Real Media (rm), 檔案頭:2E524D46
MPEG (mpg), 檔案頭:000001BA
MPEG (mpg), 檔案頭:000001B3
Quicktime (mov), 檔案頭:6D6F6F76
Windows Media (asf), 檔案頭:3026B2758E66CF11
MIDI (mid), 檔案頭:4D546864


相關靶場分析

1. upload-labs第2關(MIME繞過)

檢視原始碼:

$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.'資料夾不存在,請手工建立!';
    }
}

通過程式碼分析,此關是判斷上傳的檔案型別是否在白名單中,在就上傳,否則上傳失敗。
繞過方法為修改上傳檔案型別為白名單中的任意一個即可。
image

2. upload-labs第3關(特殊解析字尾繞過)

檢視原始碼:

$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 . '資料夾不存在,請手工建立!';
    }
}

過濾條件為:

  • 過濾字尾名asp,aspx,php,jsp
  • 去除接收過來的檔名中的空格
  • 刪除檔名末尾的點
  • 將“.”前面的內容截斷
  • 字尾名轉換為小寫
  • 去除檔案字尾含有::$DATA字串變為空
  • 收尾去掉空格
    繞過方法為:使用特殊的字尾名,php5,phml等
    原因是apache伺服器可以解析php5、php3、phtml格式的檔案為php格式的檔案。
    image

3. upload-labs第4關(.htaccess上傳漏洞)

原始碼分析:

$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",".ini");
        $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檔案,
image
先將此檔案上傳至伺服器。目的是在.htaccess檔案所在的目錄中所有格式檔案按.htaccess檔案規定的方式執行。
再上傳一個名為shana.jpg的馬即可。
訪問http://127.0.0.1/upload-labs/upload/shana.jpg
image

4. upload-labs第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 = 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也過濾掉了。
只進行了一次過濾檢驗,可以使用".php. ."繞過
image
image

5. upload-labs第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",".ini");
        $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 . '資料夾不存在,請手工建立!';
    }
}

原始碼中沒有大小寫過濾。
上傳".PHp"可繞過
image

6. upload-labs第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",".ini");
        $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 . '資料夾不存在,請手工建立!';
    }
}

原始碼中沒有刪除字尾名末尾空格,可增加空格進行繞過。
image
image

7. upload-labs第8關(字尾名加點繞過)

原始碼:

$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",".ini");
        $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 . '資料夾不存在,請手工建立!';
    }
}

分析得缺少刪除末尾的點的操作。
抓包加點進行過濾。
image
image

8. upload-labs第9關(::$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",".ini");
        $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 . '資料夾不存在,請手工建立!';
    }
}

分析得,少了去除檔名中的::$DATA字串。
字尾名加::$DATA即可繞過。
image
image

9. upload-labs第10關(一次驗證繞過)

方法同第5關
image
image

10. upload-labs第11關(字尾名重寫繞過)

原始碼:

$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","ini");

        $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 . '資料夾不存在,請手工建立!';
    }
}

分析得,若上傳是黑名單中的字尾則刪除字尾名。
只需複寫字尾名即可繞過。
image
image

11. upload-labs第12關(%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型別檔案!";
    }
}

分析是取最後一個點後面的格式與白名單進行對比。
使用get傳參,可用%00截斷。繞過
image
image

相關文章