目錄
1.Pass-01 前端繞過
分析
解題
2.Pass-02 服務器端檢測--修改IMME
分析
解題
3.Pass-03 黑名單繞過
分析
解題
4.Pass-04?.htaccess繞過
分析
?解題
5.Pass-05 . .繞過和.user.ini繞過
分析
解題
6.Pass-06 大小寫繞過
分析
解題
7.Pass-07 空格繞過
分析
解題
8.Pass-08 .繞過
分析
解題
9.Pass-09 ::$DATA繞過
分析
解題
10.Pass-10?. . 繞過
分析
解題
11.Pass-11 雙寫繞過
分析
解題
12.Pass-12 %00截斷(GET)
分析
解題
13.Pass-13 %00截斷(POST)
分析
解題
14.Pass-14 圖片馬1
分析
解題?
15.Pass-15 圖片馬2
分析?
解題
16.Pass-16 圖片馬3
分析
解題
17.Pass-17 二次渲染繞過
分析
解題
18.Pass-18 條件競爭
分析
解題
19.Pass-19? 條件競爭2
分析
?解題
20.Pass-20 move_uploaded_file繞過
分析
解題
21.Pass-21 數組繞過
分析
解題
1.Pass-01 前端繞過
分析
選擇一個php文件上傳,頁面立即彈出錯誤提示,且?沒有向服務器發送請求?(通過瀏覽器開發者工具查看網絡請求可確認)。
這種即時反饋表明驗證邏輯是在客戶端完成的,而非服務端
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;}
}
分析源碼也可以發現,這里的關鍵是驗證羅德由JS函數(checkFile())實現,且驗證失敗時會直接組織扁擔提交到服務器
解題
- 方法1
直接禁用js就可以上傳了,以Google Chrome為例,設置-->隱私與安全-->網站設置-->javaScript-->不允許網站使用JS
上傳成功。
- 方法2
使用Burpsuit抓包修改后綴繞過
上傳jpg文件-->點擊上傳Burpsuit抓包-->修改jpg后綴為php
上傳成功
2.Pass-02 服務器端檢測--修改IMME
分析
$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.'文件夾不存在,請手工創建!';}
}
它是用file_exists()函數檢查文件存在,并判斷文件的類型是否為image/jpeg,image/gif,image/png,如果是,就會拼接文件路徑
解題
上傳php文件-->點擊上傳Burpsuit抓包-->修改Content-Type為代碼允許的三個類型
上傳成功
3.Pass-03 黑名單繞過
分析
?$deny_ext = array('.asp','.aspx','.php','.jsp');
其設置的后綴為黑名單,我們選擇這四種后綴之外的文件就可以成功上傳,比如php5
解題
上傳成功
4.Pass-04?.htaccess繞過
分析
$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");
?該題代碼與第三關幾乎相同,僅僅在黑名單中多添加了一些后綴,但是它卻少了.htaccess。如果Web應用允許上傳.htaccess文件,并且.htaccess文件可以啟用,那就意味著攻擊者可以更改Apache的配置,對于受害者來說這種情況是十分危險的。
.htaccess文件攻擊有三種方式:
1. 如果黑名單過濾了所有的能執行的后綴名,如果允許上傳.htaccess。當.htaccess文件的內容如下,會將內容符合php語法規則的文件當作php文件解析
SetHandler application/x-httpd-php
2.? 該文件還會匹配文件名中的關鍵字,如:[1.php.jpg]中包含.php,并且.htaccess文件的內容如下,[1.php.jpg]中的代碼就會被執行
AddHandler php5-script .php
3.? 匹配文件名,當.htaccess文件內容如下,它可以將匹配到的文件名的文件中的代碼執行
<FilesMatch "sxc">SetHandler application/x-httpd-php
</FilesMatch>
?解題
直接編寫htaccess文件
<FilesMatch "web.jpg">SetHandler application/x-httpd-php
</FilesMatch>
然后上傳一個web.jpg文件,然后上傳這個.htaccess,再訪問web.jpg,即可通關。
5.Pass-05 . .繞過和.user.ini繞過
分析
$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");
源碼里把所有可以解析的后綴名都給寫死了,包括大小寫,轉換,空格,還有點號,正常的php類文件上傳不了了,并且拒絕上傳 .htaccess 文件。但是沒有被限制的后綴名還有.php7和.ini
php.ini 是 php的配置文件,.user.ini 中的字段也會被 php 視為配置文件來處理,從而導致 php 的文件解析漏洞。
但是想要引發 .user.ini 解析漏洞需要三個前提條件
服務器腳本語言為PHP 服務器使用CGI/FastCGI模式 上傳目錄下要有可執行的php文件
? 什么是 CGI
? ? ? ?CGI 的全稱為“通用網關接口”(Common Gateway Interface),為 HTTP 服務器與其他機器上的程序服務通信交流的一種工具, CGI 程序須運行在網絡服務器上。
? ?
? ? ? ?傳統 CGI 接口方式的主要缺點是性能較差,因為每次 HTTP 服務器遇到動態程序時都需要重新啟動解析器來執行解析,之后結果才會被返回給 HTTP
? ? ? ?服務器。這在處理高并發訪問時幾乎是不可用的,因此就誕生了 FastCGI。另外,傳統的 CGI 接口方式安全性也很差,故而現在已經很少被使用了。
? ?
? ? ? ?什么是 FastCGI
? ? ? ?FastCGI 是一個可伸縮地、高速地在 HTTP 服務器和動態服務腳本語言間通信的接口(在 Linux 下, FastCGI 接口即為 socket,這個socket 可以是文件 socket,也可以是IP socket),主要優點是把動態語言和 HTTP
? ?服務器分離開來。多數流行的 HTTP 服務器都支持 FastCGI,包括 Apache 、 Nginx 和 Lighttpd 等。
解題
- 方法1 .user.ini繞過
創建一個文件名為 .user.ini? 內容為
auto_prepend_file=web.jpg
?上傳web.jpg文件和.user.ini文件到upload目錄下之后訪問readme.php就可以執行web.jpg中的php代碼
- 方法2 . .繞過
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;
如果我們上傳web.php. .,可以看見$file_name處理后值為web.php. (這里有一個空格),而$file_ext值為.
最終的文件路徑拼接的時候應該是web.php. 最后的空格和.會因為windows系統的特性自動過濾掉,成為web.php
繞過成功
6.Pass-06 大小寫繞過
分析
$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); //首尾去空
可以發現,這里黑名單過濾了極多的部分,包括.htaccess .ini以及之前用到的php5等。仔細查看源碼發現,其沒有進行大小寫的過濾。所以可以通過大小寫進行繞過。
解題
直接上傳web.PHP即可
上傳成功
7.Pass-07 空格繞過
分析
$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
?仔細觀察代碼中部可以發現,其忽略了空格存在的情況,所以我們可以使用空格繞過的方式
解題
上傳web.php進行抓包,然后在其后綴處加上一個空格
上傳成功
8.Pass-08 .繞過
分析
$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); //首尾去空
?觀察源代碼,發現其沒有刪除文件名中小數點的函數
解題
上傳web.php進行抓包,然后在其后綴處加上一個.
上傳成功
9.Pass-09 ::$DATA繞過
分析
$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); //首尾去空
??觀察源代碼,發現其沒有過濾::$DATA
解題
上傳web.php進行抓包,然后在其后綴處加上一個::$DATA
上傳成功
10.Pass-10?. . 繞過
分析
這關跟第五關是一樣的,通過代碼分析可以推斷,我們可以使用. .繞過的方法達到上傳php文件的目的。
解題
上傳成功
11.Pass-11 雙寫繞過
分析
$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;
先使用trim函數去除其兩邊的空白字符以及轉義字符,再使用str_ireplace,將$file_name的字符串與$deny_ext中的黑名單對比,如果有相同的,則從$file_name中刪除對應部分,通常這種情況的過濾,可以使用雙寫對應的字符,使其刪除一次后恢復為正確的文件后綴進行繞過。
解題
上傳web.pphphp文件
上傳成功
12.Pass-12 %00截斷(GET)
分析
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;
通過觀察函數可以發現,我們的上傳路徑是可控的(通過GET方式傳參),所以我們想到可以使用%00截斷的方法 ?
%00是字符串的結束標識符,攻擊者可以利用手動添加字符串標識符的方式來將后面的內容進行截斷
只有數據包中必須含有上傳路徑的情況下才可以用,那么攻擊者可以通過修改path的值來構造paylod,并且php<5.3.29并且magic_quotes_gpc是關閉的
解題
上傳info.jpg,然后抓包截斷。路徑處加上info.php%00
上傳成功
13.Pass-13 %00截斷(POST)
分析
這里和上一關區別只是一個為POST一個為GET方法,在GET請求中會對輸入的內容進行URL解碼。但POST請求有不同, 需要我們將POST中的%00解碼后傳入。
解題
上傳info.jpg,然后抓包截斷。路徑處加上web (這里有個空格),選中空格,改變他的16進制為00
上傳成功
14.Pass-14 圖片馬1
分析
function getReailFileType($filename){$file = fopen($filename, "rb");$bin = fread($file, 2); //只讀2字節fclose($file);$strInfo = @unpack("C2chars", $bin); $typeCode = intval($strInfo['chars1'].$strInfo['chars2']); $fileType = '';
?getReailFileType這個函數是用于檢測文件頭部兩個字節的信息(前兩個字節是文件格式的標識),并且通過二進制碼判斷其文件的類型,然后控制文件的上傳。
由于其要檢測前兩個字節的信息,所以不能簡單的通過直接修改后綴進行上傳。需要制作圖片馬,采用圖片與木馬合并的方法
windows下通過cmd命令進行制作
copy 1.jpg /b + 2.php /a 3.php
解題?
首先制作一張圖片馬web.php,我們將其上傳。但是由于圖片不能解析為php代碼來執行。若有文件包含漏洞,則可以通過文件包含漏洞進行解析。好由于題目說了存在文件包含漏洞,我們通過文件包含漏洞進行。 我們復制圖片地址,鏈接到文件包含界面,然后訪問。
上傳成功
15.Pass-15 圖片馬2
分析?
本關與上一關類似,只是判斷文件的函數方法略有區別,也可以通過圖片馬進行訪問。
解題
上傳成功
16.Pass-16 圖片馬3
分析
根據要求首先開啟php_exif模塊, 這關和之前兩個也類似,僅僅是使用函數變化,原理相同
解題
上傳成功
17.Pass-17 二次渲染繞過
分析
if(($fileext == "jpg") && ($filetype=="image/jpeg")){if(move_uploaded_file($tmpname,$target_path)){//使用上傳的圖片生成新的圖片$im = imagecreatefromjpeg($target_path);if($im == false){$msg = "該文件不是jpg格式的圖片!";@unlink($target_path);}else{//給新圖片指定文件名srand(time());$newfilename = strval(rand()).".jpg";//顯示二次渲染后的圖片(使用用戶上傳圖片生成的新圖片)$img_path = UPLOAD_PATH.'/'.$newfilename;imagejpeg($im,$img_path);@unlink($target_path);$is_upload = true;}} else {$msg = "上傳出錯!";}
以jpg的函數為例,代碼先通過檢查上傳文件的后綴,然后用$im = imagecreatefromjpeg語句將上傳的圖片傳給$im作為一個圖片標志符,再經過srand函數重新命名后,利用imagejpeg函數將$im的圖像保存到指定路徑處。相當于對文件的圖像部分進行了重新生成,并且使用unlink函數將原圖片刪除。
所以說如果我們上傳一個圖片馬的話,經過這個函數的重新生成得到的圖片會是一堆亂碼,不在包含我們的php語句。
但是jpg、png、gif文件在重新生成后與原圖片相比是否存在不變的部分呢?下面以gif圖片為例解題,這里使用gif文件比jpg和png文件更加簡單。
解題
先生成一個gif的圖片馬
將web.gif上傳,把重新生成的圖片保存下來,利用010editor將渲染前后的圖片對比,將web.gif未改變的部分加入php語句
上傳成功
18.Pass-18 條件競爭
分析
$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 = '上傳出錯!';}
}
?這個代碼的文件處理流程是:移動文件到指定路徑-->判斷后綴名是否符合-->符合則重命名-->不符合則刪除文件。
這里存在邏輯的問題那就是先上傳后刪除,服務器處理代碼時總會存在一定的時間差,當我們在上傳文件后就多次快速嘗試訪問目標文件,那么是不是有機會在刪除前成功訪問文件。 而如果文件的代碼是重新創建一個木馬文件,新木馬文件則永遠不會被刪除了!
解題
創建一個木馬文件demo.php
<?php fputs(fopen('web.php','w'),'<?php phpinfo(); ?>');?>
上傳這個demo.php并抓包,然后發送到intruder模塊,設置pyload和不間斷發包
設置好后開始attack 并訪問127.0.0.1/upload/demo.php 我等待上幾秒就成功了
19.Pass-19? 條件競爭2
分析
這關我們通過對源碼斷點調試來分析源碼,在index.php中,首先new了一個MyUpload類,傳入了上傳的文件名,臨時名,文件大小,隨機time名(這個隨機time和文件最終名字有關)。然后傳入UPLOAD_PATH給upload函數(也就是把../upload傳入)。
然后我們看看MyUpload函數,對類初始化的時候調用Myupload函數,傳入對應參數賦值,進入里面看看,在upload函數中,是先進行文件路徑、后綴、大小判斷,然后文件移動、重命名。
這就出現了邏輯問題,先移動后重命名
$ret = $this->move();if( $ret != 1 ){return $this->resultUpload( $ret ); }// check if we need to rename the fileif( $this->cls_rename_file == 1 ){$ret = $this->renameFile();if( $ret != 1 ){return $this->resultUpload( $ret ); }}
?解題
還是一樣,先做圖片馬web.jpg
copy 1.jpg /b + demo.php /a web.jpg<?php fputs(fopen('web.php','w'),'<?php phpinfo(); ?>');?>
上傳,復制圖片地址并訪問
然后訪問?
http://127.0.0.1/upload/web.php
?上傳成功
20.Pass-20 move_uploaded_file繞過
分析
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 = '禁止保存為該類型文件!';}
move_uploaded_file()還有這么一個特性,會忽略掉文件末尾的 /.
解題
方法一
上傳一個jpg圖片,里面內容為php語句,然后抓包修改,在save_name處的內容上加上/.
方法二
?同樣可以使用大小寫繞過,修改位置跟方法一的位置相同
上傳成功
21.Pass-21 數組繞過
分析
$is_upload = false;
$msg = null;
if(!empty($_FILES['upload_file'])){//檢查MIME$allow_type = array('image/jpeg','image/png','image/gif');if(!in_array($_FILES['upload_file']['type'],$allow_type)){$msg = "禁止上傳該類型文件!";}else{//檢查文件名$file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];if (!is_array($file)) {$file = explode('.', strtolower($file));}$ext = end($file); //文件后綴$allow_suffix = array('jpg','png','gif');if (!in_array($ext, $allow_suffix)) {$msg = "禁止上傳該后綴文件!";}else{$file_name = reset($file) . '.' . $file[count($file) - 1];$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH . '/' .$file_name;if (move_uploaded_file($temp_file, $img_path)) {$msg = "文件上傳成功!";$is_upload = true;} else {$msg = "文件上傳失敗!";}}}
}else{$msg = "請選擇要上傳的文件!";
}
首先檢查upload_file如果不為空,則繼續檢查MIME類型是否是白名單里的
然后如果save_name為空,則把$_FILES['upload_file']['name']的值給$file,不為空則把$_POST['save_name']的值給$file
接下來如果$file不是數組,explode函數則將其處理為數組,用.分割
然后繼續通過end函數獲得$file中的最后一個元素,賦值給$ext,并進行后綴校驗。如果后綴符合,則拼接文件名為首元素.尾元素。reset函數來獲取首元素
解題
上傳web.php,抓包
要修改三個部分?
- MIME類型
- save_name后加上數組,保存名稱改為php后綴
- 再加入一個save_name[2]繞過尾元素
上傳成功