任意文件上傳
一、概述
大多數網站都有文件上傳的接口,但如果在后台開發時並沒有對上傳的文件進行安全考慮或采用了有缺陷的措施,導致攻擊者可以通過一些手段繞過安全措施從而上傳一些惡意文件,從而通過該惡意文件的訪問來控制整個后台
二、測試流程:參考Word流程圖
三、實戰測試
1、客戶端檢測繞過(javascript 檢測)
首先觀察到提示只允許上傳圖片文件,那么前端的查看代碼,當頁面發生改變時,會調用這個checkFileExt函數來檢查上傳的是不是圖片,我們只需要在前端將checkFileExt函數刪除,就能上傳一個一個非圖片文件。
2、服務端驗證繞過(MIME 類型檢測)
MIME(Multipurpose Internet Mail Extensions)多用途互聯網郵件擴展類型。是設定某種擴展名的文件用一種應用程序來打開的方式類型,當該擴展名文件被訪問的時候,瀏覽器會自動使用指定應用程序來打開。多用於指定一些客戶端自定義的文件名,以及一些媒體文件打開方式。
每個MIME類型由兩部分組成,前面是數據的大類別,例如聲音audio、圖象image等,后面定義具體的種類。
常見的MIME類型(通用型):
超文本標記語言文本 .html text/html
xml文檔 .xml text/xml
XHTML文檔 .xhtml application/xhtml+xml
普通文本 .txt text/plain
RTF文本 .rtf application/rtf
PDF文檔 .pdf application/pdf
Microsoft Word文件 .word application/msword
PNG圖像 .png image/png
GIF圖形 .gif image/gif
JPEG圖形 .jpeg,.jpg image/jpeg
au聲音文件 .au audio/basic
MIDI音樂文件 mid,.midi audio/midi,audio/x-midi
RealAudio音樂文件 .ra, .ram audio/x-pn-realaudio
MPEG文件 .mpg,.mpeg video/mpeg
AVI文件 .avi video/x-msvideo
GZIP文件 .gz application/x-gzip
TAR文件 .tar application/x-tar
任意的二進制數據 application/octet-stream
通過使用 PHP 的全局數組 $_FILES,你可以從客戶計算機向遠程服務器上傳文件。
第一個參數是表單的 input name,第二個下標可以是 "name", "type", "size", "tmp_name" 或 "error"。就像這樣:
$_FILES["file"]["name"] - 被上傳文件的名稱
$_FILES["file"]["type"] - 被上傳文件的類型
$_FILES["file"]["size"] - 被上傳文件的大小,以字節計
$_FILES["file"]["tmp_name"] - 存儲在服務器的文件的臨時副本的名稱
$_FILES["file"]["error"] - 由文件上傳導致的錯誤代碼
詳細可參考:http://www.w3school.com.cn/php/php_file_upload.asp
分析代碼邏輯:首先會獲取到前端的提交請求,然后定義了一個數組(定義圖片上傳指定類型),然后通過upload_sick函數對上傳的文件進行一定的檢查。
分析upload_sick函數存在漏洞的的原因是因為 $ _FILES() 這個全局的方法是通過瀏覽器http頭去獲取的content-type,content-type是前端用戶可以控制的。容易被繞過。
上傳一張正常的符合標准的圖片,對其content-type進行抓包操作。可見正常上傳符合要求的圖片中數據包中content-type為image/png對比符合條件,而php文件則不符合條件返回文件類型錯誤。
三、代碼注入繞過--getimagesize()
getimagesize() 函數用於獲取圖像大小及相關信息,成功返回一個數組,失敗則返回 FALSE 並產生一條 E_WARNING 級的錯誤信息,如果用這個涵數來獲取類型,從而判斷是否是圖片的話,會存在問題。
語法格式:
array getimagesize ( string $filename [, array &$imageinfo ] )
getimagesize() 函數將測定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 圖像文件的大小並返回圖像的尺寸以及文件類型及圖片高度與寬度。
2、文件包含漏洞之文件上傳漏洞利用
方法一:直接偽造頭部GIF89A
方法二:CMD方法,copy /b test.png+1.php muma.png
方法三:直接使用工具增加備注寫入一句話木馬。
四、路徑/擴展名繞過
1、白名單
0x00截斷或test.asp%00.jpg
MIME繞過
2、黑名單
(1)文件名大小寫繞過
(2)名單繞過
用黑名單里沒有的名單進行攻擊,比如黑名單里沒有.php|.php5|.php4|.php3|.php2|php1|.html|.htm|.phtml|.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|.htaccess后綴文件之類
(3)特殊文件名或文件夾繞過(windows)
還有比如發送的http 包里把文件名改成test.asp. 或test.asp_(下划線為空格),這種命名方式在windows 系統里是不被允許的,所以需要在burp 之類里進行修改,然后繞過驗證后,會被windows 系統自動去掉后面的點和空格,但要注意Unix/Linux 系統沒有這個特性。
(4)0x00截斷
name = getname(http request) //假如這時候獲取到的文件名是test.asp .jpg(asp 后面為0x00)
type = gettype(name) //而在gettype()函數里處理方式是從后往前掃描擴展名,所以判斷為jpg
if (type == jpg)
SaveFileToPath(UploadPath.name, name) //但在這里卻是以0x00 作為文件名截斷
//最后以test.asp 存入路徑里
(5)把文件名改成test.asp. 或test.asp_(下划線為空格),這種命名方式在windows 系統里是不被允許的,所以需要在burp 之類里進行修改,然后繞過驗證后,會被windows 系統自動去掉后面的點和空格,但要注意Unix/Linux 系統沒有這個特性。
(6)雙后綴名繞過
(7)::$DATA繞過
是Windows下NTFS文件系統的一個特性,即NTFS文件系統的存儲數據流的一個屬性 DATA 時,就是請求 a.asp 本身的數據,如果a.asp 還包含了其他的數據流,比如 a.asp:lake2.asp,請求 a.asp:lake2.asp::$DATA,則是請求a.asp中的流數據lake2.asp的流數據內容。
五、中間件解析漏洞繞過(參考文檔)
IIS解析漏洞
Apache解析漏洞
.htaccess
配置文件LoadModule rewrite_module modules/mod_rewrite.so前的注釋去掉,尋找關鍵詞:AllowOverride,並把后面的參數從None全部改成All
Nginx解析漏洞
.htaccess文件解析
本地文件包含解析
六、安全防范
針對文件上傳漏洞的特點和必須具備的三個條件,我們阻斷任何一個條件就可以達到組織文件上傳攻擊的目的:
1、最有效的,將文件上傳目錄直接設置為不可執行,對於Linux而言,撤銷其目錄的'x'權限;實際中很多大型網站的上傳應用都會放置在獨立的存儲上作為靜態文件處理,一是方便使用緩存加速降低能耗,二是杜絕了腳本執行的可能性;
2、文件類型檢查:強烈推薦白名單方式,結合MIME Type、后綴檢查等方式(即只允許允許的文件類型進行上傳);此外對於圖片的處理可以使用壓縮函數或resize函數,處理圖片的同時破壞其包含的HTML代碼;
3、使用隨機數改寫文件名和文件路徑,使得用戶不能輕易訪問自己上傳的文件;
4、單獨設置文件服務器的域名;
任意文件下載
一、漏洞介紹
一些網站由於業務需求,往往需要提供文件查看或文件下載功能,但若對用戶查看或下載的文件不做限制,則惡意用戶就能夠查看或下載任意敏感文件,這就是文件查看與下載漏洞。
二、利用方式
一般鏈接形式:
download.php?path=
down.php?file=
data.php?file=
或者包含參數:
&Src=
&Inputfile=
&Filepath=
&Path=
&Data=
當遇到一個任意文件下載時,我們的一般利用思路:
(1)下載常規的配置文件,例如: ssh,weblogic,ftp,mysql等相關配置
(2)下載各種.log文件,從中尋找一些后台地址,文件上傳點之類的地方,如果運氣好的話會獲得一些前輩們的后門。
(3)下載web業務文件進行白盒審計,利用漏洞進一步攻入服務器。
嘗試讀取/root/.bash_history看自己是否具有root權限。如果沒有的話。我們只能按部就班的利用../來回跳轉讀取一些.ssh下的配置信息文件,讀取mysql下的.bash_history文件。來查看是否記錄了一些可以利用的相關信息。然后逐個下載我們需要審計的代碼文件,但是下載的時候變得很繁瑣,我們只能嘗試去猜解目錄,然后下載一些中間件的記錄日志進行分析。
如果我們遇到的是java+oracle環境
可以先下載/WEB-INF/classes/applicationContext.xml 文件,這里面記載的是web服務器的相應配置,然后下載/WEB-INF/classes/xxx/xxx/ccc.class對文件進行反編譯,然后搜索文件中的upload關鍵字看是否存在一些api接口,如果存在的話我們可以本地構造上傳頁面用api接口將我們的文件傳輸進服務器
如果具有root權限
在linux中有這樣一個命令 locate 是用來查找文件或目錄的,它不搜索具體目錄,而是搜索一個數據庫/var/lib/mlocate/mlocate.db。這個數據庫中含有本地所有文件信息。Linux系統自動創建這個數據庫,並且每天自動更新一次。當我們不知道路徑是什么的情況下,這個可以說是一個核武器了,我們利用任意文件下載漏洞mlocate.db文件下載下來,利用locate命令將數據輸出成文件,這里面包含了全部的文件路徑信息。
locate 讀取方法: locate mlocate.db admin //可以將mlocate.db中包含admin文件名的內容全部輸出來
(4)常見利用文件
/root/.ssh/authorized_keys
/root/.ssh/id_rsa
/root/.ssh/id_ras.keystore
/root/.ssh/known_hosts //記錄每個訪問計算機用戶的公鑰
/etc/passwd
/etc/shadow
/etc/my.cnf //mysql配置文件
/etc/httpd/conf/httpd.conf //apache配置文件
/root/.bash_history //用戶歷史命令記錄文件
/root/.mysql_history //mysql歷史命令記錄文件
/proc/mounts //記錄系統掛載設備
/porc/config.gz //內核配置文件
/var/lib/mlocate/mlocate.db //全文件路徑
/porc/self/cmdline //當前進程的cmdline參數
三、漏洞修復
(1)過濾".",使用戶在url中不能回溯上級目錄
(2)正則嚴格判斷用戶輸入參數的格式
(3)php.ini配置open_basedir限定文件訪問范圍
中間件解析漏洞
0x00 總覽說明
服務器解析漏洞算是歷史比較悠久了,但如今依然廣泛存在。在此記錄匯總一些常見服務器(WEB server)的解析漏洞,比如IIS6.0、IIS7.5、apache、nginx等方便以后回顧溫習。
0x01 歸納總結
(一)IIS5.x-6.x解析漏洞
使用iis5.x-6.x版本的服務器,大多為windows server 2003,網站比較古老,開發語句一般為asp;該解析漏洞也只能解析asp文件,而不能解析aspx文件。
目錄解析(6.0)
形式:www.xxx.com/xx.asp/xx.jpg
原理: 服務器默認會把.asp,.asa目錄下的文件都解析成asp文件。
文件解析
形式:www.xxx.com/xx.asp;.jpg
原理:服務器默認不解析;號后面的內容,因此xx.asp;.jpg便被解析成asp文件了。
解析文件類型
IIS6.0 默認的可執行文件除了asp還包含這三種 :
/test.asa
/test.cer
/test.cdx
修復方案
1.目前尚無微軟官方的補丁,可以通過自己編寫正則,阻止上傳xx.asp;.jpg類型的文件名。
2.做好權限設置,限制用戶創建文件夾。
(二)apache解析漏洞
Apache 解析文件的規則是從右到左開始判斷解析,如果后綴名為不可識別文件解析,就再往左判斷。比如 test.php.owf.rar “.owf”和”.rar” 這兩種后綴是apache不可識別解析,apache就會把oldboy.php.owf.rar解析成php。
漏洞形式
www.xxxx.xxx.com/test.php.php123
其余配置問題導致漏洞
(1)如果在 Apache 的 conf 里有這樣一行配置 AddHandler php5-script .php 這時只要文件名里包含.php 即使文件名是 test2.php.jpg 也會以 php 來執行。
(2)如果在 Apache 的 conf 里有這樣一行配置 AddType application/x-httpd-php .jpg 即使擴展名是 jpg,一樣能以 php 方式執行。
修復方案
1.apache配置文件,禁止.php.這樣的文件執行,配置文件里面加入
<Files ~ “.(php.|php3.)”>
Order Allow,Deny
Deny from all </Files>
2.用偽靜態能解決這個問題,重寫類似.php.*這類文件,打開apache的httpd.conf找到LoadModule rewrite_module modules/mod_rewrite.so把#號去掉,重啟apache,在網站根目錄下建立.htaccess文件,代碼如下:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .(php.|php3.) /index.php
RewriteRule .(pHp.|pHp3.) /index.php
RewriteRule .(phP.|phP3.) /index.php
RewriteRule .(Php.|Php3.) /index.php
RewriteRule .(PHp.|PHp3.) /index.php
RewriteRule .(PhP.|PhP3.) /index.php
RewriteRule .(pHP.|pHP3.) /index.php
RewriteRule .(PHP.|PHP3.) /index.php
</IfModule>
(三)nginx解析漏洞
漏洞原理
Nginx默認是以CGI的方式支持PHP解析的,普遍的做法是在Nginx配置文件中通過正則匹配設置SCRIPT_FILENAME。當訪問www.xx.com/phpinfo.jpg/1.php這個URL時,$fastcgi_script_name會被設置為“phpinfo.jpg/1.php”,然后構造成SCRIPT_FILENAME傳遞給PHP CGI,但是PHP為什么會接受這樣的參數,並將phpinfo.jpg作為PHP文件解析呢?這就要說到fix_pathinfo這個選項了。 如果開啟了這個選項,那么就會觸發在PHP中的如下邏輯:
PHP會認為SCRIPT_FILENAME是phpinfo.jpg,而1.php是PATH_INFO,所以就會將phpinfo.jpg作為PHP文件來解析了
漏洞形式
www.xxxx.com/UploadFiles/image/1.jpg/1.php
www.xxxx.com/UploadFiles/image/1.jpg%00.php
www.xxxx.com/UploadFiles/image/1.jpg/%20\0.php
xxx.jpg%00.php (Nginx <8.03 空字節代碼執行漏洞)
另外一種手法:上傳一個名字為test.jpg,以下內容的文件。
<?PHP fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd])?>');?>
然后訪問test.jpg/.php,在這個目錄下就會生成一句話木馬shell.php。
修復方案
1.修改php.ini文件,將cgi.fix_pathinfo的值設置為0;
2.在Nginx配置文件中添加以下代碼:
if ( $fastcgi_script_name ~ ..*/.*php ) { return 403; }
這行代碼的意思是當匹配到類似test.jpg/a.php的URL時,將返回403錯誤代碼。
(四)IIS7.5解析漏洞
IIS7.5的漏洞與nginx的類似,都是由於php配置文件中,開啟了cgi.fix_pathinfo,而這並不是nginx或者iis7.5本身的漏洞。
https://www.xp.cn/a.php/182.html
當安裝完成后, php.ini里默認cgi.fix_pathinfo=1,對其進行訪問的時候,在URL路徑后添加.php后綴名會當做php文件進行解析,漏洞由此產生
注:在進行實際的測試的時候,發現漏洞並沒有產生,后來發現要設置FastCGI為關閉,該項好像是用來處理數據文件
如此,就可以來點高級玩法 創建cmd.txt文件,內容為
<?php fputs(fopen('shell.php','w'),'<?php phpinfo();?>');
//創建新的文件
?>
保存后,重命名為cmd.jpg 文件 再次進行訪問
ctf考題
upload-labs
一個幫你總結所有類型的上傳漏洞的靶場
文件上傳靶機下載地址:https://github.com/c0ny1/upload-labs
運行環境
操作系統:推薦windows(除了Pass-19必須在linux下,其余Pass都可以在windows上運行) php版本:推薦5.2.17(其他版本可能會導致部分Pass無法突破) php組件:php_gd2,php_exif(部分Pass需要開啟這兩個組件) apache:以moudel方式連接
PS:為了節省時間,可下載Windows下集成環境,解壓即可運行靶機環境。
https://github.com/c0ny1/upload-labs/releases
總結
實驗用小馬
繞過方法
Pass-01
源代碼:
1.前端禁用JS,直接上傳Webshell
2.把以.php結尾的小馬改為以.jpg|.png|.gif結尾,用burpsuite抓包,在把.jpg|.png|.gif改回.php即可上傳成功
Pass-02
源代碼:
由代碼可知,對文件MIME類型進行了驗證判斷
截斷上傳數據包,修改Content-Type為image/gif,然后放行數據包
Pass-03
源代碼:
1.這里是黑名單驗證(‘.asp‘,‘.aspx‘,‘.php‘,‘.jsp‘),我們可上傳php3,php5...等這樣可以被服務器解析的后綴名
Pass-04
源代碼:
分析代碼發現,這里對上傳的后綴名的判斷增加了,php3.php5....已經不允許上傳,但是沒有限制.htaccess文件的上傳,所以我們依然可以使用
另外一種方法就是利用PHP 和 Windows環境的疊加特性,以下符號在正則匹配時的相等性:
利用PHP 和 Windows環境的疊加特性,以下符號在正則匹配時的相等性:
先上傳一個名為4.php:.jpg的文件,上傳成功后會生成4.php的空文件,大小為0KB.
然后將文件名改為4.<或4.<<<或4.>>>或4.>><后再次上傳,重寫4.php文件內容,Webshell代碼就會寫入原來的4.php空文件中。
Pass-05
源代碼:
分析代碼,發現以.htaccess為后綴的文件已經不允許上傳,但是 $file_ext = strtolower($file_ext); //轉換為小寫 這一句沒有了,我們就可以使用文件名后綴大小寫混合繞過,把1.php改為1.phP...來上傳
Pass-06
源代碼:
利用Windows系統的文件名特性。文件名最后增加空格和點,寫成1.php .,這個需要用burpsuite抓包修改,上傳后保存在Windows系統上的文件名最后的一個.會被去掉,實際上保存的文件名就是1.php
果然上傳成功
Pass-07
源代碼:
原理同Pass-06,文件名后加點和空格,改成1.php.
Pass-08
源代碼:
分析代碼,少了 $file_ext = str_ireplace(‘::$DATA‘, ‘‘, $file_ext);//去除字符串::$DATA 這一句,我們可以采用Windows文件流特性繞過,文件名改成
1.php::$DATA , 上傳成功后保存的文件名其實是1.php
Pass-09
源代碼:
原理同Pass-06,上傳文件名后加上點+空格+點,改為1.php. .
Pass-10
源代碼:
分析代碼,由於 $file_name = str_ireplace($deny_ext,"", $file_name); 只對文件后綴名進行一次過濾,這樣的話,雙寫文件名繞過,文件名改成1.pphphp
Pass-11
源代碼:
分析代碼,這是以時間戳的方式對上傳文件進行命名,使用上傳路徑名%00截斷繞過,不過這需要對文件有足夠的權限,比如說創建文件夾,上傳的文件名寫成1.jpg, save_path改成../upload/1.php%00 (1.php%00.jpg經過url轉碼后會變為1.php\000.jpg),最后保存下來的文件就是1.php
修復建設: php版本要小於5.3.4,5.3.4及以上已經修復該問題;magic_quotes_gpc需要為OFF狀態
Pass-12
源代碼:
原理同Pass-11,上傳路徑0x00繞過。利用Burpsuite的Hex功能將save_path改成../upload/1.php【二進制00】形式
Pass-13
源代碼:
繞過文件頭檢查,添加GIF圖片的文件頭GIF89a,繞過GIF圖片檢查。
或者我們使用命令copy 1.jpg /b + shell.php /a webshell.jpg,將php一句話追加到jpg圖片末尾,代碼不全的話,人工補充完整。形成一個包含Webshell代碼的新jpg圖片,然后直接上傳即可。但是我們沒有辦法拿到shell,應為我們上傳的圖片馬無法被解析成php形式,通常圖片馬配合%00或者0x00截斷上傳,或者配合解析漏洞
Pass-14
源代碼:
getimagesize() 函數用於獲取圖像尺寸 ,索引 2 給出的是圖像的類型,返回的是數字,其中1 = GIF,2 = JPG,3 = PNG,4 = SWF,5 = PSD,6 = BMP,7 = TIFF(intel byte order),8 = TIFF(motorola byte order),9 = JPC,10 = JP2,11 = JPX,12 = JB2,13 = SWC,14 = IFF,15 = WBMP,16 = XBM
這里有詳解:https://blog.csdn.net/sanbingyutuoniao123/article/details/52166617
image_type_to_extension() 函數用於獲取圖片后綴
Pass-15
源代碼:
Pass-16
源代碼:
原理:將一個正常顯示的圖片,上傳到服務器。尋找圖片被渲染后與原始圖片部分對比仍然相同的數據塊部分,將Webshell代碼插在該部分,然后上傳。具體實現需要自己編寫Python程序,人工嘗試基本是不可能構造出能繞過渲染函數的圖片webshell的。
這里提供一個包含一句話webshell代碼並可以繞過PHP的imagecreatefromgif函數的GIF圖片示例。
php圖像二次渲染:
https://blog.csdn.net/hitwangpeng/article/details/48661433
https://blog.csdn.net/hitwangpeng/article/details/46548849
https://xz.aliyun.com/t/2657
這兩個講的還可以
打開被渲染后的圖片,Webshell代碼仍然存在
提供一個jpg格式圖片繞過imagecreatefromjpeg函數渲染的一個示例文件。 直接上傳示例文件會觸發Warning警告,並提示文件不是jpg格式的圖片。但是實際上已經上傳成功,而且示例文件名沒有改變。
從上面上傳jpg圖片可以看到我們想復雜了,程序沒有對渲染異常進行處理,直接在正常png圖片內插入webshell代碼,然后上傳示例文件即可,並不需要圖片是正常的圖片。
程序依然沒有對文件重命名,攜帶webshell的無效損壞png圖片直接被上傳成功。
Pass-17
源代碼:
利用條件競爭刪除文件時間差繞過。使用命令pip install hackhttp安裝hackhttp模塊,運行下面的Python代碼即可。如果還是刪除太快,可以適當調整線程並發數。
在腳本運行的時候,訪問Webshell
也可以使用burp來完成: 這關利用的是競爭條件,服務器先允許你上傳文件,然后檢測是否合法,不合法再刪除,我們要利用的就是在服務器刪除前,訪問到我們上傳的php。 例如這里我准備一個tj.php,內容為
<?php
$myfile = fopen("qing.php", "w");
$txt = "<?php phpinfo();?>";
fwrite($myfile, $txt);
fclose($myfile);
?>
條件競爭中burp需要線程設置偏大
這里我上傳我的tj.php,然后不停的訪問test.php上傳后的地址,即http://www.hack_upload.com/upload/test.php
這里使用兩個發包器,一個包是上傳我們test.php的包,一個是訪問我們上傳test.php后的地址
利用條件競爭,訪問tj.php成功,所以新建了一個qing.php
Pass-18
源代碼:
剛開始沒有找到繞過方法,最后下載作者Github提供的打包環境,利用上傳重命名競爭+Apache解析漏洞,成功繞過。
上傳名字為18.php.7Z的文件,快速重復提交該數據包,會提示文件已經被上傳,但沒有被重命名。
快速提交上面的數據包,可以讓文件名字不被重命名上傳成功。
然后利用Apache的解析漏洞,即可獲得shell
Pass-19
源代碼:
原理同Pass-11,上傳的文件名用0x00繞過。改成19.php【二進制00】.1.jpg
Pass-20
源代碼:
解題思路
文件命名規則:$file_name = reset($file) . '.' . $file[count($file) - 1];
reset():將內部指針指向數組中的第一個元素,並輸出。
end():將內部指針指向數組中的最后一個元素,並輸出。
$file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];如果save_name不為空則file為save_name,否則file為filename
if (!is_array($file))判斷如果file不是數組則以’.’分組
文件名命名規則$file_name = reset($file) . '.' . $file[count($file) - 1];
我們POST傳入一個save_name列表:['info20.php', '', 'jpg'],此時empty($_POST['save_name']) 為假則file為save_name,所以由$ext = end($file);為jpg可以通過后綴名判斷(判斷結束后最后一個元素jpg彈出),並且最終文件名組裝為upload20.php.
解題步驟