文件上傳之後端黑白名單繞過
文件上傳常見驗證
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的馬即可。
訪問//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截斷。繞過