原文地址:https://xz.aliyun.com/t/6357
1. 文件上傳漏洞
1.1 漏洞簡介
? 文件上傳,顧名思義就是上傳文件的功能行為,之所以會被發展為危害嚴重的漏洞,是程序沒有對訪客提交的數據進行檢驗或者過濾不嚴,可以直接提交修改過的數據繞過擴展名的檢驗。文件上傳漏洞是漏洞中最為簡單猖獗的利用形式,一般只要能上傳獲取地址,可執行文件被解析就可以獲取系統WebShell。
1.2 漏洞原理
? 網站WEB應用都有一些文件上傳功能,比如文檔、圖片、頭像、視頻上傳,當上傳功能的實現代碼沒有嚴格校驗上傳文件的后綴和文件類型時,就可以上傳任意文件甚至是可執行文件后門。
1.3 漏洞危害
? 惡意文件傳遞給解釋器去執行,之后就可以在服務器上執行惡意代碼,進行數據庫執行、服務器文件管理,服務器命令執行等惡意操作。根據網站使用及可解析的程序腳本不同,可以上傳的惡意腳本可以是PHP、ASP、JSP、ASPX文件等。
2. 上傳點和繞過形式
2.1 文件上傳常見點
上傳頭像
上傳相冊
上傳附件
添加文章圖片
前臺留言資料上傳
編輯器文件上傳
......
例如如下編輯器上傳點:
文件管理處文件上傳:
前臺用戶發表文章處文件上傳:
個人頭像處文件上傳:
2.2 后綴繞過
PHP:
php2、php3、php5、phtml、pht(是否解析需要根據配置文件中設置類型來決定)
ASP:
asa、cer、cdx
ASPX:
ascx、ashx、asac
JSP:
jsp、jspx、jspf
2.3 繞過類型
Content-Type繞過
前端繞過
文件解析規則繞過
Windows環境特性繞過
文件名大小寫繞過
雙寫繞過
點空格繞過
文件頭繞過
條件競爭繞過
......
在以下的文章介紹中,將采取其中的幾種常見的繞過形式做演示。
3. 漏洞在系統中的差異
? 上傳文件漏洞在不同的系統、架構以及行為中,利用形式也是各不相同。常用的web容器有IIS、Tomcat、Nginx、Apache等。以下主要以比較經典的解析漏洞做解釋。
3.1 IIS 5.x/6.0解析漏洞
1、當創建.asp的文件目錄的時候,在此目錄下的任意文件,服務器都解析為asp文件。例如如下:
漏洞目錄利用形式:www.xxx.com/xx.asp/xx.jpg。
xx.jpg的內容可以為一段合法的asp腳本文件。
2、服務器默認不解析”;“以后的內容,導致xx.asp;.jpg被解析成xx.asp
漏洞文件利用形式:www.xxx.com/xx.asp;.jpg
xx.jpg的內容可以為一段合法的asp腳本文件。
漏洞產生的原因參考詳細文章內容:https://www.cnblogs.com/l1pe1/p/9210094.html
通過對IIS6的核心文件類型解析相關文件的逆向后,整理出下面的核心處理代碼。
//reverse code by golds7n with ida
int __thiscall Url(void *this, char *UrlStruct)
{
void *pW3_URL_INFO; // esi@1
int bSuccess; // eax@1
const wchar_t *i; // eax@2
wchar_t *wcsSlashTemp; // ebx@6
int wcsTemp; // eax@6
int wcs_Exten; // eax@6
int v8; // esi@9
int v10; // eax@11
int v11; // ST04_4@13
int v12; // eax@13
int ExtenDll; // eax@19
int Extenisa; // eax@20
int ExtenExe; // eax@21
int ExtenCgi; // eax@22
int ExtenCom; // eax@23
int ExtenMap; // eax@24
int Entry; // [sp+Ch] [bp-148h]@6
wchar_t *wcsMaohaoTemp; // [sp+10h] [bp-144h]@6
unsigned int dotCount; // [sp+14h] [bp-140h]@1
wchar_t *Str; // [sp+18h] [bp-13Ch]@3
char *url_FileName; // [sp+1Ch] [bp-138h]@1
char Url_FileExtenName; // [sp+20h] [bp-134h]@1
char v25; // [sp+50h] [bp-104h]@1
dotCount = 0;
pW3_URL_INFO = this;
STRU::STRU(&Url_FileExtenName, &v25, 0x100u);
url_FileName = (char *)pW3_URL_INFO + 228;
bSuccess = STRU::Copy((char *)pW3_URL_INFO + 228, UrlStruct);
if ( bSuccess < 0 )
goto SubEnd;
for ( i = (const wchar_t *)STRU::QueryStr((char *)pW3_URL_INFO + 228); ; i = Str + 1 )
{
Str = _wcschr(i, '.'); ***********N1************
if ( !Str )
break;
++dotCount;
if ( dotCount > W3_URL_INFO::sm_cMaxDots )
break;
bSuccess = STRU::Copy(&Url_FileExtenName, Str);
if ( bSuccess < 0 )
goto SubEnd;
wcsSlashTemp = _wcschr(Str, '/'); ***********N2************
JUMPOUT(wcsSlashTemp, 0, loc_5A63FD37);
wcsTemp = STRU::QueryStr(&Url_FileExtenName);
wcsMaohaoTemp = _wcschr((const wchar_t *)wcsTemp, ':'); ***********N3************
JUMPOUT(wcsMaohaoTemp, 0, loc_5A63FD51);
wcs_Exten = STRU::QueryStr(&Url_FileExtenName);
__wcslwr((wchar_t *)wcs_Exten);
if ( META_SCRIPT_MAP::FindEntry(&Url_FileExtenName, &Entry) )
{
*((_DWORD *)pW3_URL_INFO + 201) = Entry;
JUMPOUT(wcsSlashTemp, 0, loc_5A63FDAD);
STRU::Reset((char *)pW3_URL_INFO + 404);
break;
}
if ( STRU::QueryCCH(&Url_FileExtenName) == 4 )
{
ExtenDll = STRU::QueryStr(&Url_FileExtenName);
if ( !_wcscmp(L".dll", (const wchar_t *)ExtenDll)
|| (Extenisa = STRU::QueryStr(&Url_FileExtenName), !_wcscmp(L".isa", (const wchar_t *)Extenisa)) )
JUMPOUT(loc_5A63FD89);
ExtenExe = STRU::QueryStr(&Url_FileExtenName);
if ( !_wcscmp(L".exe", (const wchar_t *)ExtenExe)
|| (ExtenCgi = STRU::QueryStr(&Url_FileExtenName), !_wcscmp(L".cgi", (const wchar_t *)ExtenCgi))
|| (ExtenCom = STRU::QueryStr(&Url_FileExtenName), !_wcscmp(L".com", (const wchar_t *)ExtenCom)) )
JUMPOUT(loc_5A63FD89);
ExtenMap = STRU::QueryStr(&Url_FileExtenName);
JUMPOUT(_wcscmp(L".map", (const wchar_t *)ExtenMap), 0, loc_5A63FD7B);
}
}
if ( *((_DWORD *)pW3_URL_INFO + 201)
|| (v10 = *((_DWORD *)pW3_URL_INFO + 202), v10 == 3)
|| v10 == 2
|| (v11 = *(_DWORD *)(*((_DWORD *)pW3_URL_INFO + 204) + 0xC4C),
v12 = STRU::QueryStr(url_FileName),
bSuccess = SelectMimeMappingForFileExt(v12, v11, (char *)pW3_URL_INFO + 756, (char *)pW3_URL_INFO + 1012),
bSuccess >= 0) )
v8 = 0;
else
SubEnd:
v8 = bSuccess;
STRU::_STRU(&Url_FileExtenName);
return v8;
}
以上有三處被標記的位置,這三處是用來檢測點號、反斜杠、分號。、
可以理解為的檢測流程為:
www.xxx.com/xxx.asp;xxx.jpg
N1:從頭部查找查找"."號,獲得".asp;xxxx.jpg"
N2:查找";"號,如果有則內存截斷
N3:查找"/",如果有則內存截斷
因此,.asp將最終被保存下來,IIS6只簡單地根據擴展名來識別,所以從腳本映射表中里查找腳本與擴展名對比,并利用asp.dll來解析。導致最終的問題產生。
對于此問題,微軟并不認為這是一個漏洞,同樣也沒推出IIS6.0解析漏洞的補丁。因此在IIS6.0的網站下,此問題仍然可以嘗試是否存在。
3.2 Nginx 解析漏洞
? Nginx是一個高性能的HTTP和反向代理web服務器,同時也提供了IMAP/POP3/SMTP服務。Nginx是由伊戈爾·賽索耶夫為俄羅斯訪問量第二的Rambler.ru站點開發的。
? 在低版本Nginx中存在一個由PHP-CGI導致的文件解析漏洞。為什么是由于PHP-CGI的原因呢,因為在PHP的配置文件中有一個關鍵的選項cgi.fix_pathinfo在本機中位于php.ini配置文件中,默認是開啟的,當URL中有不存在的文件時,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文件來解析了
? 在默認Fast-CGI開啟狀況下上傳名字為xx.jpg,內容為:
<?PHP fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd])?>');?>
然后訪問xx.jpg/.php,在這個目錄下就會生成一句話木馬shell.php。同樣利用phpstudy說明,上傳1.jpg格式的文件,內容為訪問phpinfo,如下即可觸發:
3.3 Apache 解析漏洞
? Apache是世界使用排名第一的Web服務器軟件。它可以運行在幾乎所有廣泛使用的計算機平臺上,由于其跨平臺和安全性被廣泛使用,是最流行的Web服務器端軟件之一。它快速、可靠并且可通過簡單的API擴充,將Perl/Python等解釋器編譯到服務器中。
? Apache 在1.x和2.x版本中存在解析漏洞,例如如下地址格式:
www.xxxx.com/apache.php.bbb.aaa
Apache從右至左開始判斷后綴,若aaa非可識別后綴,再判斷bbb,直到找到可識別后綴為止,然后將該可識別后綴進解析,因此如上地址解析為訪問apache.php文件。
? 那么為什么會產生此問題原因,在Apache的官方網站上,有一句這么關于“extension”的解釋:
地址:http://httpd.apache.org/docs/current/mod/directive-dict.html
extension
In general, this is the part of the filename which follows the last dot. However, Apache recognizes multiple filename extensions, so if a filename contains more than one dot, each dot-separated part of the filename following the first dot is an extension. For example, the filename file.html.en contains two extensions: .html and .en. For Apache directives, you may specify extensions with or without the leading dot. In addition, extensions are not case sensitive.
? 通過這個解釋可以看出來,Apache允許文件有多個后綴名,并會按照第一個點來分析文件后綴,例如file.html.en。Apache按照每個點來分割后綴名,因此此文件名為.html、.en。由于en后綴不被識別,便繼續向前解析。
? 另外對于Apache解析漏洞的正確說法應該是,使用module模式與php結合的所有版本 apache存在未知擴展名解析漏洞,使用fastcgi模式與php結合的所有版本apache不存在此漏洞。而是否解析的后綴名在文件mime.types中查找是否出現。
? 此處使用phpstudy測試,利用dvwa的文件上傳功能,上傳1.php.wwe。結果解析如下:
4. 測試
以下采用手工測試和工具測試兩種方法來進行文件上傳測試。
4.1 手工測試
對于文件上傳漏洞方式和舉例此處采用一個文件靶場,地址:https://github.com/c0ny1/upload-labs
以下將利用靶場其中的一部分內容來舉例說明文件上傳漏洞的產生和效果。
環境:Ubuntu 18、Windows phpStudy (采用不一樣的系統,為了在不同系統的差異做演示)
WEB容器:Apache 2.0
語言:PHP
抓包工具:Burp Suite Pro
驗證工具:Hackbar插件
4.1.1 前端驗證
此種驗證形式在很多網站、CMS都有使用,只在前端利用JS來做效驗,采用禁用JS上傳、抓包上傳都可以繞過此處限制。此處采用抓包演示。
點擊上傳文件,選擇已經改成“.jpg”后綴的后門文件。修改burp中的文件后綴信息。
訪問已經上傳的文件,利用Hackbar訪問phpinfo()。可以看到后門已經得到執行。
4.1.2 .htaccess
規則文件繞過
? 在利用.htaccess文件之前,我們先來了解一下什么是.htaccess規則文件。.htaccess文件(或者"分布式配置文件"),全稱是Hypertext Access(超文本入口)。提供了針對目錄改變配置的方法, 即,在一個特定的文檔目錄中放置一個包含一個或多個指令的文件, 以作用于此目錄及其所有子目錄。作為用戶,所能使用的命令受到限制。
? 概述來說,.htaccess文件是Apache服務器中的一個配置文件,它負責相關目錄下的網頁配置。通過htaccess文件,可以幫我們實現:網頁301重定向、自定義404錯誤頁面、改變文件擴展名、允許/阻止特定的用戶或者目錄的訪問、禁止目錄列表、配置默認文檔等功能。
? 在一些啟用了.htaccess文件的網站上就可以使用此文件類型來繞過限制較全面的黑名單過濾。
? 先上傳一個.htaccess文件,內容為:AddType application/x-httpd-php .aaa
。如下:
? 然后再上傳文件后綴為.aaa的文件,讓其解析為php類型文件。
? 上傳成功后訪問此上傳文件,訪問如下:
4.1.3 文件名后綴大小寫混合繞過
? 在對后綴的判斷中,如果只是對字符串進行單獨的比較來判斷是不是限制文件,可以采用后綴名大小寫繞過形式。如下形式:
? 訪問上傳成功的文件:
4.1.4 Windows文件流特性繞過
? 在討論這種特性之前,我們先來認識一下Windows文件流。流文件,即NTFS交換數據流(alternate data streams,簡稱ADS),是NTFS磁盤格式的一個特性,在NTFS文件系統下,每個文件都可以存在多個數據流,就是說除了主文件流之外還可以有許多非主文件流寄宿在主文件流中,它使用資源派生來維持與文件相關的信息。創建一個數據交換流文件的方法很簡單,命令為“宿主文件:準備與宿主文件關聯的數據流文件”。
? 詳細相關介紹和內容可以查看文章:https://www.freebuf.com/column/143101.html。此處不做深入解釋。
上傳文件為xxx.php::data。
我們訪問的時候就可以直接訪問xxx.php文件。
4.1.5 %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 = $_POST['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類型文件!";
}
}
可以看出代碼采用的白名單校驗,只允許上傳圖片格式,理論上這個上傳是不好繞過的。但是后面采用保存文件的時候,是路徑拼接的形式,而路徑又是從前端獲取,所以我們可以采用在路徑上截斷。如下上傳,顯示文件路徑中有個空格,這并不是真正意義上的空格,而是%00截斷后顯示成的空格。
訪問上傳地址路徑:
4.1.6 文件頭檢測繞過
? 提到文件頭檢測,我們就先來認識一下常見文件的文件頭格式。我們先打開一個正常的JPG圖片格式文件,查看文件的文件頭十六進制。采用010Editor。
? 右邊欄中有明顯的JFIF存儲格式字樣,文件頭前十個字節為FF D8 FF E0 00 10 4A 46 49 46
,其中開頭標紅的為標記碼,FF D8代表SOI標記,意思是圖像文件開始值。4A 46 49 46
代表字符串JFIF標記。
關于JPEG文件格式介紹可以閱讀:https://www.cnblogs.com/sddai/p/5666924.html
? 然后我們再打開一份PNG文件格式的圖片,同樣采用010Editor來查看其十六進制。
? 對于的開頭4字節為右欄中‰PNG
字樣,PNG的8字節文件署名域用來識別該文件是不是PNG文件。也就是89 50 4E 47 0D 0A 1A 0A
。
關于PNG文件格式可以閱讀:https://blog.csdn.net/qq_21950929/article/details/79198814
? 同樣打開一份GIF文件格式圖片,用010Editor來打開查看文件。
? 文件十六進制中可以看到,其中47 49 46 38 39 61
,代表了右欄中的GIF89a,這六個字節作為了GIF文件格式頭的開頭文件。而在其后的繞過中就采用了GIF89a這個字符串。
關于GIF文件格式可以閱讀:http://www.lxweimin.com/p/df52f1511cf8
了解過文件格式后,我們來看這個文件格式檢測繞過形式,首先查看代碼,為了方便演示修改了源代碼對文件格式的獲取,此處只讀取文件的前兩個字節值:
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 = '';
switch($typeCode){
case 255216:
$fileType = 'jpg';
break;
case 13780:
$fileType = 'png';
break;
case 7173:
$fileType = 'gif';
break;
default:
$fileType = 'unknown';
}
return $fileType;
}
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_type = getReailFileType($temp_file);
if($file_type == 'unknown'){
$msg = "文件未知,上傳失敗!";
}else{
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1); //此處為了方便演示添加了file_ext 變量
$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_ext;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上傳出錯!";
}
}
}
然后上傳php文件,修改文件內容,添加文件頭GIF89a:
這種添加形式類似于在hex中修改添加:
然后在訪問以上傳的文件:
4.2 利用工具進行FUZZ
? 很多網站對上傳進行攔截的時候采取的是黑名單校驗,當我們看到黑名單的時候就可以考慮采取修改后綴、截斷等方式嘗試繞過。
? 我們采用一個工具:https://github.com/c0ny1/upload-fuzz-dic-builder 來生成fuzz的字典。執行命令:
python upload-fuzz-dic-builder.py -n test -a jpg -l php -m apache --os win -o upload_file.txt
? 把生成的字典導入burp中,同時取消payload-encoding的選中狀態。執行后可以看到有些php文件上傳成功。然后訪問其中上傳成功的文件,查看是否執行。
訪問如圖中的地址文件,可以看到上傳成功:
5. 實戰演示
演示漏洞為:CVE-2018-2894
漏洞環境:Linux Weblogic 12.2
漏洞下載地址:https://github.com/vulhub/vulhub/tree/master/weblogic/CVE-2018-2894
漏洞介紹:WebLogic管理端未授權的兩個頁面存在任意上傳getshell漏洞,可直接獲取權限。兩個頁面分別為/ws_utc/begin.do,/ws_utc/config.do。
影響范圍為:Oracle WebLogic Server,版本10.3.6.0,12.1.3.0,12.2.1.2,12.2.1.3。
下載好vulhub后,進入相應的CVE目錄,執行如下命令:
docker-compose up -d
等到docker構建結束,會在7001端口開放一個服務,如下所示:
此處需要登陸賬號和密碼,正常情況下是嘗試弱口令進后臺上傳文件,此處方便演示,從構建日志中查看密碼:
docker-compose logs | grep password
查看結果:
weblogic_1 | ----> 'weblogic' admin password: oZUcqr8j
weblogic_1 | admin password : [oZUcqr8j]
weblogic_1 | * password assigned to an admin-level user. For *
登陸后界面如下:
點擊左側中的base_domain選項,再點擊下面的高級選項,從高級中啟用web測試頁,保存。
然后訪問http://192.168.120.132:7001/ws_utc/config.do頁面,設置Work Home Dir,可以看到其中已經填寫一個目錄,此目錄訪問需要登陸,修改為P牛的建議路徑:
/u01/oracle/user_projects/domains/base_domain/servers/AdminServer/tmp/_WL_internal/com.oracle.webservices.wls.ws-testclient-app-wls/4mcj4y/war/css
原路徑為:
/u01/oracle/user_projects/domains/base_domain/tmp/WSTestPageWorkDir
在當前頁面中選擇安全->添加,上傳webshell
然后從放回頁面中查看id項時間戳,訪問路徑/ws_utc/css/config/keystore/時間戳_文件名
然后執行命令whoami:
6. CMS實戰演示
6.1 PHPOK 任意文件上傳
演示漏洞為:phpok 任意文件上傳
漏洞環境:Windows phpStudy
漏洞環境下載:https://download.phpok.com/4.8.338.zip
漏洞介紹:phpok 4.8.338版本管理后臺存在任意文件上傳漏洞,攻擊者可利用漏洞上傳任意文件,獲取網站權限。
下載文件后,把解壓的文件放入phpstudy中的www目錄中,此處修改了版本號目錄為phpok。然后訪問本地地址:http://localhost/phpok,會自動進入安裝頁面,填寫數據庫密碼,創建賬號后自動進入安裝頁面,安裝完成后顯示如下:
使用一開始創建的賬號密碼登陸,登陸成功后在后側的選擇欄處選擇工具->附件分類管理。
點擊右側上方的創建資源分類,然后在支持的附件類型中創建php文件類型。
選擇左側的內容管理->資訊中心->行業管理
點擊頁面中的選擇圖片->上傳附近選擇添加的附件類型->選擇php文件上傳,上傳成功后點擊上傳的圖片,選擇預覽就可以看到文件目錄的地址
訪問地址文件后門,可以看到執行代碼成功
漏洞修復:此問題在高版本修復,及時升級到高版本處理,目前最新版本為5.2.116。
6.2 FCKeditor 2.4.3 文件上傳
演示漏洞為:FCKeditor 2.4.3 文件上傳
漏洞環境:Windows phpStudy
漏洞環境下載:https://github.com/treadmillian/fckeditor.git
漏洞介紹:FCKeditor /fckeditor/editor/filemanager/upload/php/upload.php 文件上傳漏洞。
首先從GitHub下載文件,放到phpStudy的www目錄中,同時修改config.php文件,修改UserFilesPath參數為fck目錄下的地址,可以修改為網站根目錄下的任意目錄中,此處修改如下:
文件地址: \fckeditor\editor\filemanager\browser\default\connectors\php\config.php
訪問地址:http://localhost/fckeditor/editor/filemanager/browser/default/connectors/test.html#
選擇文件上傳,由于2.4.3在文件配置已經進行了后綴的限制,默認限制為:
array('html','htm','php','php2','php3','php4','php5','phtml','pwml','inc','asp','aspx','ascx','jsp','cfm','cfc','pl','bat','exe','com','dll','vbs','js','reg','cgi','htaccess','asis','sh','shtml','shtm','phtm')
對于此處漏洞我們采用空格繞過,先上傳一個JPG的圖片,抓包修改后綴,添加空格如下:
訪問上傳產生的路徑文件,路徑會顯示在頁面中:
http://localhost/fckeditor/editor/filemanager/browser/default/connectors/uploads/file/05091707156.php
執行一句話木馬文件:
漏洞修復:由于此處使用黑名單校驗,可以根據需要的類型修改為白名單參數。
7. 漏洞修復
關于文件上傳漏洞的產生和修改此處討論兩種文件上傳漏洞的情況和修復:
7.1 代碼未判斷文件類型或者文件類型限制不完全,一般這種是黑名單或者沒有限制,建議添加白名單限制參數數組,固定為圖片或文本格式文件。例如如下:
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 = UPLOAD_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類型文件!";
}
}
7.2 如果是使用WEB中間件存在上傳,或者是CMS存在文件上傳漏洞,根據官方建議安裝補丁升級版本,或者使用官方推薦的臨時修改策略來限制問題的產生和利用。