檔案上傳常見驗證
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.'資料夾不存在,請手工建立!';
}
}
通過程式碼分析,此關是判斷上傳的檔案型別是否在白名單中,在就上傳,否則上傳失敗。
繞過方法為修改上傳檔案型別為白名單中的任意一個即可。
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格式的檔案。
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檔案,
先將此檔案上傳至伺服器。目的是在.htaccess檔案所在的目錄中所有格式檔案按.htaccess檔案規定的方式執行。
再上傳一個名為shana.jpg的馬即可。
訪問http://127.0.0.1/upload-labs/upload/shana.jpg
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. ."繞過
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"可繞過
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 . '資料夾不存在,請手工建立!';
}
}
原始碼中沒有刪除字尾名末尾空格,可增加空格進行繞過。
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 . '資料夾不存在,請手工建立!';
}
}
分析得缺少刪除末尾的點的操作。
抓包加點進行過濾。
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即可繞過。
9. upload-labs第10關(一次驗證繞過)
方法同第5關
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 . '資料夾不存在,請手工建立!';
}
}
分析得,若上傳是黑名單中的字尾則刪除字尾名。
只需複寫字尾名即可繞過。
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截斷。繞過