為什么文件上傳表單是主要的安全威脅
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
為了讓最終用戶(hù)將文件上傳到您的網(wǎng)站,就像是給危及您的服務(wù)器的惡意用戶(hù)打開(kāi)了另一扇門(mén)。即便如此,在今天的現(xiàn)代互聯(lián)網(wǎng)的Web應(yīng)用程序,它是一種常見(jiàn)的要求,因?yàn)?/SPAN>它有助于提高您的業(yè)務(wù)效率。在Facebook和Twitter等社交網(wǎng)絡(luò)的Web應(yīng)用程序,允許文件上傳。也讓他們在博客,論壇,電子銀行網(wǎng)站,YouTube和企業(yè)支持門(mén)戶(hù),給機(jī)會(huì)給最終用戶(hù)與企業(yè)員工有效地共享文件。允許用戶(hù)上傳圖片,視頻,頭像和許多其他類(lèi)型的文件。 向最終用戶(hù)提供的功能越多,Web應(yīng)用受到攻擊的風(fēng)險(xiǎn)和機(jī)會(huì)就越大,這種功能會(huì)被惡意用戶(hù)利用,獲得到一個(gè)特定網(wǎng)站的權(quán)限,或危及服務(wù)器的可能性是非常高的。 案例1:沒(méi)有任何驗(yàn)證的簡(jiǎn)單文件上傳表單 一個(gè)簡(jiǎn)單的文件上傳表單通常包含一個(gè)HTML表單和PHP腳本。 HTML表單的形式呈現(xiàn)給用戶(hù),而需要文件上傳功能的PHP腳本中包含的代碼。這種形式和PHP腳本下面是一個(gè)例子: HTML Form:
PHP Code:
當(dāng)PHP接收POST請(qǐng)求且編碼類(lèi)型是multipart/form-data,它會(huì)創(chuàng)建一個(gè)臨時(shí)文件名隨機(jī)的臨時(shí)目錄中(例如/ var/tmp/php6yXOVs)。 PHP也將填充全局?jǐn)?shù)組$_FILES上傳的文件的信息: PHP函數(shù)move_uploaded_file將用戶(hù)提供的臨時(shí)文件移動(dòng)到一個(gè)位置。在這種情況下,目的地是服務(wù)器根目錄以下。因此,文件可以使用的URL,如:http://www.domain.tld/uploads/uploadedfile.ext訪(fǎng)問(wèn)。在這個(gè)簡(jiǎn)單的例子中,有允許上傳的文件類(lèi)型沒(méi)有限制,因此攻擊者可以上傳一個(gè)PHP或NET帶有惡意代碼的文件,可導(dǎo)致服務(wù)器妥協(xié)。 案例2:Mime類(lèi)型驗(yàn)證 另一個(gè)常見(jiàn)的錯(cuò)誤Web開(kāi)發(fā)人員確保文件上傳表單時(shí),只檢查從PHP返回mime類(lèi)型。當(dāng)一個(gè)文件被上傳到服務(wù)器,PHP將設(shè)置變量$_FILES['UploadedFile']['type']所提供的Web瀏覽器客戶(hù)端使用的MIME類(lèi)型。然而,文件上傳表單驗(yàn)證不能依賴(lài)于這個(gè)值。惡意用戶(hù)可以輕松地使用腳本或其他一些自動(dòng)化的應(yīng)用程序,允許發(fā)送HTTP POST請(qǐng)求,這讓他送一個(gè)假的mime類(lèi)型的文件上傳。 案例3:限制危險(xiǎn)的拓展 在另一個(gè)例子里,我們遇到了文件上傳使用黑名單的做法,作為一項(xiàng)安全措施。從開(kāi)發(fā)者收集制定的危險(xiǎn)列表,如果正在上傳的文件包含在列表中,訪(fǎng)問(wèn)會(huì)被拒絕。 惡意用戶(hù)可以很容易地繞過(guò)該檢查上傳一個(gè)文件名為“.htaccess”,其中包含類(lèi)似于下面的一行代碼: 上面的代碼行,指示Apache Web服務(wù)器執(zhí)行jpg圖片,好像他們是PHP腳本。攻擊者現(xiàn)在可以上傳一個(gè)jpg擴(kuò)展名的文件,其中包含PHP代碼。正如下面的截圖,通過(guò)web瀏覽器請(qǐng)求一個(gè)jpg文件,其中包含PHP的命令phpinfo()函數(shù),它仍然是從Web服務(wù)器執(zhí)行: 案例4: 雙擴(kuò)展名 (第1部分) 本案例中使用的安全策略和案例3中所使用的非常相近. 盡管方式換成了簡(jiǎn)單的檢查文件名具有的擴(kuò)展名, 開(kāi)發(fā)者通過(guò)在文件名中查找 ‘.’ 字符并提取點(diǎn)號(hào)之后的字符串來(lái)得到文件擴(kuò)展名. 繞過(guò)該途徑的方法有點(diǎn)兒復(fù)雜, 但是仍然是現(xiàn)實(shí)的. 首先, 讓我們看看 Apache 是怎么處理具有多重?cái)U(kuò)展名的文件的. Apache 手冊(cè)中有如下一段陳述: “文件可以有多個(gè)擴(kuò)展名, 這些擴(kuò)展名的順序一般情況下是無(wú)關(guān)緊要的. 例如: 如果文件 welcome.html.fr 被映射為內(nèi)容類(lèi)型是 text/html , 語(yǔ)言是法語(yǔ)的話(huà), 文件welcome.fr.html 將被映射為完全相同的內(nèi)容. 如果一個(gè)以上的擴(kuò)展名映射到同種類(lèi)型的元信息上, 那么將使用最右邊的那個(gè), 除了語(yǔ)言和內(nèi)容編碼. 比如: .gif 的 MIME 類(lèi)型是 image/gif , .html 的 MIME 類(lèi)型是 text/html , 那么 welcome.gif.html 的 MIME 類(lèi)型將是text/html ." 因此一個(gè)名為 ‘filename.php.123’ 的文件將會(huì)被解釋為一個(gè) PHP 文件并被執(zhí)行. 這僅限于最后的那個(gè)擴(kuò)展名(本例中是 .123)沒(méi)有在 web 服務(wù)器的 mime-types 列表中被指定. web開(kāi)發(fā)者通常不會(huì)意識(shí)到 Apache 還存在這么一個(gè) ‘特性’, 出于某些原因來(lái)說(shuō)這可能非常危險(xiǎn). 知道了這個(gè)以后, 一個(gè)攻擊者可以上傳一個(gè)名為 shell.php.123 的文件并繞過(guò)文件上傳保護(hù)機(jī)制. 后臺(tái)腳本將會(huì)計(jì)算出最后的擴(kuò)展名 (.123)并作出該擴(kuò)展名并不在危險(xiǎn)的擴(kuò)展名列表內(nèi)的結(jié)論. 話(huà)雖如此, 想要預(yù)防某惡意用戶(hù)可能會(huì)使用的所有隨機(jī)擴(kuò)展名來(lái)上傳一個(gè)文件到你的 web 服務(wù)器上是不可能的. 案例5: 雙擴(kuò)展名 (第2部分) 一個(gè)更好的增強(qiáng)文件上傳表單的安全性的途徑就是白名單機(jī)制. 在本例中, 開(kāi)發(fā)者定義了一個(gè) 已知/可接受 的擴(kuò)展名列表并且不允許使用未在名單中指定的擴(kuò)展名. 然而, 在某些情況下該途徑不會(huì)像期待的方式那樣工作. 當(dāng) Apache 被配置為執(zhí)行 PHP 代碼的時(shí)候, 存在兩種方式來(lái)實(shí)現(xiàn)該機(jī)制: 使用 AddHandler 指令, 或者使用 AddType 指令. 如果 AddHandler 指令被使用, 所有包含 ‘.php’ 擴(kuò)展名的文件名(例如: ‘.php’ , ‘.php.jpg’)均被作為 PHP 腳本來(lái)執(zhí)行. 因此, 如果你的 Apache 配置文件包含如下一行的話(huà), 你可能很容易受到攻擊: AddHandler php5-script .php 一個(gè)攻擊者可以上傳名為 ‘filename.php.jpg’ 的文件并繞過(guò)保護(hù)機(jī)制, 然后執(zhí)行其中的代碼. 案例 6: 檢查圖片頭部 當(dāng)僅允許上傳圖片的時(shí)候, 開(kāi)發(fā)者通常使用 PHP 的 getimagesize 函數(shù)來(lái)檢測(cè)圖片的頭部信息. 該函數(shù)在被調(diào)用時(shí)將會(huì)返回圖片的尺寸, 如果圖片經(jīng)驗(yàn)證為無(wú)效的, 也就是說(shuō)圖片頭部信息不正確, 則會(huì)返回 false 值. 因此一個(gè)開(kāi)發(fā)者一般會(huì)檢查該函數(shù)是否返回 true 或 false, 并且通過(guò)該信息來(lái)驗(yàn)證上傳的文件. 所以, 如果一個(gè)惡意用戶(hù)試著上傳一個(gè)內(nèi)嵌有簡(jiǎn)單 PHP shell 的 jpg 文件的話(huà), 該函數(shù)會(huì)返回 false 然后他將不允許上傳此文件. 然而, 即使這種方式也能被很容易的繞過(guò). 如果一個(gè)圖片在一個(gè)圖片編輯器內(nèi)打開(kāi), 就如 Gimp, 用戶(hù)就可以編輯圖片的注釋區(qū), 那兒就能插入 PHP 代碼, 就如下圖所示. 該圖片仍然有一個(gè)有效的頭部; 因此就繞過(guò)了 getimagesize 函數(shù)的檢查. 從下面截圖中可以看到, 當(dāng)一個(gè)普通的 web 瀏覽器請(qǐng)求該圖的時(shí)候, 插入到圖片注釋區(qū)的 PHP 代碼仍然被執(zhí)行了: 案例七:通過(guò).htaccess保護(hù)上傳文件夾 另一種流行的穿件安全的文件上傳表單的方法是適用.htaccess保護(hù)好上傳文件存放的文件夾。辦法是限制這個(gè)文件夾里的腳本文件的執(zhí)行。這種情形一下,一個(gè).htaccess文件一般包含下面的代碼: AddHandler cgi-script .php .php3 .php4 .phtml .pl .py .jsp .asp .htm .shtml .sh .cgi 上面的是另一種形式的黑名單,本身并不是很安全。在PHP手冊(cè)中,move_uploaded_file一章中,有一個(gè)warning:若目標(biāo)文件已經(jīng)存在,則會(huì)覆蓋原文件。 因?yàn)樯蟼鞯奈募軌蚨視?huì)覆蓋已經(jīng)存在的同名文件,一個(gè)惡意用戶(hù)很輕易就能用他自己修改過(guò)的.htaccess替換掉原來(lái)的。這使得他可以執(zhí)行特定的將會(huì)幫助他危害服務(wù)器的腳本。 案例八:客戶(hù)端驗(yàn)證 另一種在文件上傳表單中常用的安全技術(shù)是在客戶(hù)端驗(yàn)證上傳的文件。一般而言,該技術(shù)在A(yíng)SP.NET應(yīng)用中更通用一些,因?yàn)锳SP.NET提供了易用的驗(yàn)證控件。 這些驗(yàn)證控件允許開(kāi)發(fā)者對(duì)要上傳的文件做正則檢查,以查出待上傳的文件擴(kuò)展名是否在允許列表中。下面是一段來(lái)自微軟網(wǎng)站的示例代碼:
這段ASP.NET代碼使用了驗(yàn)證控件,所以最終用戶(hù)只被允許上傳.mp3,.mpeg,或者.m3u文件到服務(wù)器。若文件類(lèi)型和這三個(gè)指定的文件類(lèi)型不一致,驗(yàn)證控件將跑出異常,文件也就不會(huì)被上傳。 由于這種文件驗(yàn)證是在客戶(hù)端完成的,惡意用戶(hù)很容易就能繞過(guò)這一檢查。寫(xiě)一段客戶(hù)端腳本來(lái)替換web應(yīng)用的驗(yàn)證腳本做驗(yàn)證并非不可能。不用web瀏覽器,入侵者可以使用可以發(fā)送HTTP POST請(qǐng)求的程序來(lái)實(shí)現(xiàn)上傳文件。 推薦的解決方案 在允許上傳文件的網(wǎng)站和web應(yīng)用中,應(yīng)當(dāng)應(yīng)用下面的一系列最佳實(shí)踐方法。這些實(shí)踐方法將有助于你保證web應(yīng)用的上傳文件的安全性。
總結(jié) 如上所述,惡意用戶(hù)有很多手段繞過(guò)文件上傳表單安全驗(yàn)證。因此,在web應(yīng)用中實(shí)現(xiàn)文件上傳表單時(shí),應(yīng)當(dāng)尊徐正確的安全指導(dǎo),并且做恰當(dāng)?shù)臏y(cè)試。不幸的是要做足夠的測(cè)試將會(huì)需要很多時(shí)間和更多的安全專(zhuān)家。 還好有了Acunetix WVS,不需要安全專(zhuān)家就可以自動(dòng)完成上傳表單脆弱性檢查,Acunetix WVS用最少的時(shí)間為開(kāi)發(fā)者提供了足夠多的能夠追蹤并修復(fù)問(wèn)題的信息。 該文章在 2013/9/20 16:06:43 編輯過(guò) |
關(guān)鍵字查詢(xún)
相關(guān)文章
正在查詢(xún)... |