国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

PHP 安全:如何防范用戶上傳 PHP 可執(zhí)行文件

wangxinarhat / 1667人閱讀

摘要:每個專業(yè)的開發(fā)者都知道用戶上傳的文件都是極其危險的。如何防止引入用戶上傳的文件重命名文件名可以嗎不,辦不到解析器不關(guān)心文件的后綴名。服務(wù)器通常被設(shè)置成執(zhí)行文件并將執(zhí)行結(jié)果回復(fù)輸出。如何進(jìn)行檢查這很簡單。用戶可以上傳文件到該站點。

每個專業(yè)的 PHP 開發(fā)者都知道用戶上傳的文件都是極其危險的。不論是后端和前端的黑客都可以利用它們搞事情。

大約在一個月前,我在 reddit 上看了一篇?PHP 上傳漏洞檢測 ,因此, 我決定寫一篇文章。用戶?darpernter 問了一個棘手的問題:

盡管我將其重命名為 "helloworld.txt", 攻擊者是否仍然能夠運行他的php 腳本?

置頂?shù)拇饛?fù)是:

如果文件后綴修改為?.txt ,那么它不會被當(dāng)做php文件執(zhí)行,這樣你安心了吧,不過再三確保不是 .php.txt 的后綴上傳。

不好意思,問題的正確答案并非如此 . 雖然上面的答復(fù)并非全部錯誤,但顯然不全面。讓人驚訝的是,大多數(shù)的答案都非常相似。

我想解釋清楚這個問題。所以我要討論的東西變得有點大,我決定讓它變得更大。

問題

人們允許用戶上傳文件,但是擔(dān)心用戶上傳的文件在服務(wù)器上被執(zhí)行。

從 php 文件如何被執(zhí)行開始看。假設(shè)一個有 php 環(huán)境的服務(wù)器,那么它通常有兩種方法在外部執(zhí)行 php 文件。一是直接用 URL 請求文件,像 http://example.com/somefile.php 。第二種是 php 現(xiàn)在常用的,將所有請求轉(zhuǎn)發(fā)到 index.php ,并在這個文件中以某種方式引入其他文件。所以,從 php 文件中運行代碼有兩種方式:執(zhí)行文件或用 include/include_once/require/require_once 的方法引入其他需要運行的文件。

其實還有第三種方法:eval() 函數(shù)。它能將傳入的字符串當(dāng)做 php 代碼執(zhí)行。這個函數(shù)在大多數(shù) CMS 系統(tǒng)中被用來執(zhí)行存儲在數(shù)據(jù)庫里的代碼。eval()?函數(shù)非常危險,但如果你用了它,通常就意味著你確認(rèn)自己在做危險的操作,并確認(rèn)你已經(jīng)沒有其他選擇。實際上, eval() 有它的用途,并且在某些情況下非常有用。但如果你是新手的話,我不推薦你使用它。請看 這篇在 OWASP 的文章。我在上面寫了很多。

所以,有兩種方法執(zhí)行文件里的代碼:直接執(zhí)行或者在被執(zhí)行的文件中引入它。那么如何避免這種事情發(fā)生呢?

解決方法?

我們怎樣才能知道一個文件包含 php 代碼呢?看拓展名,如果以 .php 結(jié)尾的,像 somefile.php 我們就認(rèn)為它里面有 php 代碼。

如果在網(wǎng)站根目錄下有一個 somefile.php 文件,那么在瀏覽器訪問 http://example.com/somefile.php ,這個文件就會被執(zhí)行并且輸出內(nèi)容到瀏覽器上。

但是如果我重命名這個文件會怎樣?如果我把它重命名為 somefile.txt 或者是 somefile.jpg 呢?我會得到什么?我會得到它的內(nèi)容。它不會被執(zhí)行。它會從硬盤(或者緩存)直接被發(fā)送過來。

在這點上 reddit 社區(qū)上的答案是對的。重命名能防止一個文件被非預(yù)期的執(zhí)行,那么為什么我認(rèn)為這種解決方法是錯的呢?

我相信你注意到我在 “解決方法” 后面加的問號。這個問號是有意義的?,F(xiàn)在大多數(shù)網(wǎng)站的 URL 上幾乎看不到多帶帶的 php 文件。并且就算有,也是人為故意偽造的,因為 URL 上需要有 .php 來實現(xiàn)對老版本 URL 的向后兼容。

現(xiàn)在絕大部分 php 代碼是在運行中被引入的,因為所有請求都被發(fā)送到了網(wǎng)站根目錄的 index.php。這個文件會根據(jù)特定的規(guī)則引入其他 php 文件。這種規(guī)則可能(或者在將來會)被惡意使用。如果你應(yīng)用的規(guī)則允許引入用戶的文件,那么應(yīng)用會容易遭到攻擊,你應(yīng)該立即采取措施防止用戶的文件被執(zhí)行。

如何防止引入用戶上傳的文件?

重命名文件名可以嗎??---?不,辦不到!

PHP解析器不關(guān)心文件的后綴名。事實上,所有程序都不關(guān)心。雙擊文件,文件會被對應(yīng)的程序打開。文件后綴名只是幫助操作系統(tǒng)識別用什么程序打開文件。只要程序有讀取文件的能力,程序就可以打開任何文件。有時程序拒絕打開和操作文件。但那并不是因為后綴名,是文件內(nèi)容所致。

服務(wù)器通常被設(shè)置成執(zhí)行 .php? 文件并將執(zhí)行結(jié)果回復(fù)輸出。如果你請求圖片 .jpg ?---?將從磁盤上原樣的返回。如果你要求服務(wù)器以某種方式運行一張 jpeg 圖片,會發(fā)生?服務(wù)器會執(zhí)行還是不呢?

圖片來源:?Echo / Cultura / Getty?Images

程序不關(guān)心文件名。甚至不關(guān)心文件是否有名字,也不關(guān)心它究竟是不是文件。

從文件執(zhí)行PHP代碼需要什么?

有至少兩個情況可以讓PHP執(zhí)行代碼:

代碼介于??和??>?標(biāo)記之間

代碼介于??和??>?標(biāo)記之間

即使文件中填充了一些奇怪的二進(jìn)制數(shù)據(jù)或一些奇怪的保護名稱,該標(biāo)記中的代碼仍然會被執(zhí)行。

這里有一個圖片給您:

該圖片沒有問題

它現(xiàn)在很純凈。但是您可能知道 JPEG 格式允許在文件中添加一些注釋。比如,拍攝照片的相機型號或坐標(biāo)地址。如果我們試圖在里面放一些PHP代碼并嘗試?include?或?require?呢?讓我們來看看吧!

問題! 1

下載這個圖片到你的硬盤上?;蛘吣阕约喝ヅ粡?JPEG 圖片也行。你隨便用什么格式的文件都無所謂。我建議用一個 JPEG 文件來演示,主要是因為它是一張圖片且易于在其中進(jìn)行文本編輯。我用的是一個 Windows的筆記本,目前我手頭上沒有 Apple 或 Linux(或其他UNIX系的系統(tǒng))的筆記本。所以一會我會發(fā)一個這個 OS 下的屏幕快照。但是我確信你肯定也能做這個事。

用以下這段 PHP 代碼建個文件:

Problem?

保存一個圖片命名為troll-face.jpg

把圖片和 php 腳本文件都放在同一個文件夾下

打開瀏覽器請求這個 php 文件

如果你把你的 php 文件命名為?index.php,然后把它放在文件根目錄或者放在你網(wǎng)站目錄下的任何一個文件目錄中。

如果你準(zhǔn)確完成了上述步驟,你就可以看到這個畫面:

到此這都沒毛病。沒 PHP 代碼展示,也沒有 PHP 代碼被執(zhí)行。

現(xiàn)在,我們來添加一個問題:

打開文件屬性對話框或運行一些允許編輯 EXIF 信息的應(yīng)用程序

切換到 Details 選項卡或以其他方式編輯該信息

向下滾動到 camera 參數(shù)

將下面代碼復(fù)制到 “camera maker” 字段后面:

Yep, a problem!"; phpinfo(); ?>

刷新頁面!

很明顯出現(xiàn)了一點問題!

您在頁面上看到了該圖片。相同的圖片還存在頁面的 PHP 代碼中。圖片的代碼也被執(zhí)行了。

我們該怎么做?!!1

長話短說:?如果我們不在程序種引入這些不安全的文件,文件中的腳本就不會執(zhí)行。

仔細(xì)看下面的例子。

最終答案?

如果有人在某處看到我錯了 - 請糾正我,這是一個嚴(yán)重的問題。

PHP是一種腳本語言。您總是需要引用一些動態(tài)組合路徑的文件。因此,為了保護服務(wù)器,您必須檢查路徑并防止混淆您的站點文件和用戶上傳或創(chuàng)建的文件。如果用戶的文件與應(yīng)用程序文件分開,則可以在使用上傳或創(chuàng)建文件之前檢查文件的路徑。如果它位于您的應(yīng)用程序腳本允許的文件夾中 - 那么它可以使用 include_once 或 require 或 require_once 引入這個文件。如果不是--那么就不引入它。

如何進(jìn)行檢查?這很簡單。你只需要將 $folder (文件)路徑與一個允許程序引入文件 ( $file ) 的路徑文件夾進(jìn)行比較。

// 不好的例子,不要用!
if (substr($file, 0, strlen($folder)) === $folder) {
  include $file;
}

如果 ?$folder 的存放路徑是 /path/to/folder ?而且 ?$file? 的存放路徑是? /path/to/folder/and/file , 然后我們在代碼中使用 substr()?函數(shù)把他們的路徑都變成字負(fù)串進(jìn)行判斷,如果文件位于不同的文件夾中---這個字符串將不相等。反之則反。

上面的代碼有兩個重要的問題。如果 file 路徑是 /path/to/folderABC/and/file,很明顯,該文件也不在允許引入的文件夾中。通過向兩個路徑添加斜杠可以防止這種情況。我們在這里向文件路徑添加斜杠并不重要,因為我們只需要比較兩個字符串。

舉個例子: 如果 folder 路徑是 ?/path/to/folder? 并且 file 路徑是?/path/to/folder/and/file ,那么從 file 提取和 folder 具有相同數(shù)量的字符,那么 $ folder 將是 /path/to/folder 。

再比如 folder 路徑是?/path/to/folder 并且 file 路徑是?/path/to/folderABC/and/file, 那么從 file 中提取 folder 具有相同數(shù)量的字符,和 $folder一樣,并且將再次成為/path/to/folder,這種都是錯誤的,這不是我們期望的結(jié)果。

因此,在 /path/to/folder/ 添加斜杠后,與 /path/to/folder/and/file 的提取部分 /path/to/folder/ 相同就是安全的。

如果將 /path/to/folder//path/to/folderABC/and/file 的提取部分 / path/to/folderA ,很明顯二個字符串不一樣。

這就是我們期望得到的。但還有另一個問題。這并不明顯。我敢肯定,如果我問你,你看到這里有一個災(zāi)難性的漏洞 - 你不會猜到它在哪里。你也許已經(jīng)在經(jīng)驗中使用過這個東西,甚至可能就在今天。現(xiàn)在,您將看到漏洞是如何隱晦和顯而易見。往下看。

/../

假想一個很常見的場景。

有這么一個網(wǎng)站。用戶可以上傳文件到該站點。所有的文件都位于一個特定的目錄下。有一個包含用戶文件的腳本。腳本自上而下進(jìn)行查找是否包含用戶的輸入(直接或間接)路徑---那這個腳本可以通過如下方式進(jìn)行路徑偽造:

/path/to/folder/../../../../../../../another/path/from/root/

舉例。用戶發(fā)起請求,你的腳本中包含了一個基于類似如下用戶輸入路徑的文件:

include $folder . "/" . $_GET["some"]; // or $_POST, or whatever

你麻煩大了。有天用戶發(fā)送一個?../../../../../../etc/.passwd?這種或其他請求,你就哭吧。

再不然。假如有人讓你的腳本加載一個他想要的文件,你就廢了。它不一定就只是出現(xiàn)在用戶文件中。它可能是你的CMS或你自己文件的一些插件(別相信任何人),甚至是應(yīng)用程序邏輯中的錯誤等。

或者

用戶可能會上傳一個名為 file.php 的文件,你會把它和其他的用戶文件一樣放在一個特定的文件夾里面:

move_uploaded_file($filename, $folder . "/" . $filename);

用戶的文件就存放在那里,你必須常常檢查從來沒有包含該文件夾中的文件,目前來看,所有的東西都挺正常的。通常,用戶發(fā)給你的文件不會包含斜杠或者其他特殊字符,因為這是被系統(tǒng)文件系統(tǒng)禁止的。之所以這樣,是因為通常情況下瀏覽器發(fā)給你的文件是在真實文件系統(tǒng)中創(chuàng)建的,同時它的名字是一些真實存在的文件的名字。

但是 http 請求允許用戶發(fā)送任何字符。所以如果某人偽造請求創(chuàng)建名為 ../../../../../../var/www/yoursite.com/index.php 的文件---這行代碼會覆蓋你的 index.php 文件,如果 index.php 處于在上述路徑的話。

所有的初學(xué)者都希望通過過濾 「..」或者斜杠來解決這個問題,但是這種做法是錯誤的,由于你在安全方面還缺乏經(jīng)驗。同時你必須(是的,必須)明白一個簡單的事情:你永遠(yuǎn)無法在安全和密碼學(xué)方面的獲得足夠的知識。這句話的意思是,如果你懂得了「兩個點和斜杠」的漏洞,但這不代表你知道所有其他的缺陷、攻擊和其他特殊字符,你也不知道在文件寫入文件系統(tǒng)或數(shù)據(jù)庫時可能發(fā)生的代碼轉(zhuǎn)換。

解決方案和答案

為了解決這個問題,PHP中內(nèi)置了一些特殊函數(shù)方法,只是為了在這種情況下使用。

basename()

第一個解決方案?---?basename()?它從路徑結(jié)束時提取路徑的一部分,直到它遇到第一個斜杠,但忽略字符串末尾的斜杠,參見示例。無論如何,你會收到一個安全的文件名。如果你覺得安全 - 那么是的這很安全。如果它被不法上傳利用 - 你可以使用它來校驗文件名是否安全。

realpath()

另一個解決方案?---?realpath()它將上傳文件路徑轉(zhuǎn)換規(guī)范化的絕對路徑名,從根開始,并且根本不包含任何不安全因素。它甚至?xí)⒎栨溄愚D(zhuǎn)換為此符號鏈接指向的路徑。

因此,您可以使用這兩個函數(shù)來檢查上傳文件的路徑。要檢查這個文件路徑到底是否真正屬于此文件夾路徑。

我的代碼

我編寫了一個函數(shù)來提供如上的檢查。我并不是專家,所以風(fēng)險請自行承擔(dān)。代碼如下。


結(jié)語。

必須過濾用戶輸入,文件名也屬于用戶輸入,所以一定要檢查文件名。記得使用 basename() 。

必須檢查你想存放用戶文件的路徑,永遠(yuǎn)不要將這個路徑和應(yīng)用目錄混合在一起。文件路徑必須由某個文件夾的字符串路徑,以及 basename($filename) 組成。文件被寫入之前,一定要檢查最終組成的文件路徑。

在你引用某個文件前,必須檢查路徑,并且是嚴(yán)格檢查。

記得使用一些特殊的函數(shù),因為你可能并不了解某些弱點或漏洞。

并且,很明顯,這與文件后綴或 mime-type 無關(guān)。JPEG 允許字符串存在于文件內(nèi),所以一張合法的 JPEG 圖片能夠同時包含合法的 PHP 腳本。

不要信任用戶。不要信任瀏覽器。構(gòu)建似乎所有人都在提交病毒的后端。

當(dāng)然,也不必害怕,這其實比看起來的簡單。只要記住 “不要信任用戶” 以及 “有功能解決此問題” 便可。

轉(zhuǎn)自 PHP / Laravel 開發(fā)者社區(qū) https://laravel-china.org/top...

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/29973.html

相關(guān)文章

  • PHP網(wǎng)站常見一些安全漏洞及防御方法

    摘要:一常見網(wǎng)站安全漏洞對于的漏洞,目前常見的漏洞有五種。分別是文件漏洞注入漏洞腳本命令執(zhí)行漏洞全局變量漏洞和文件漏洞。這就是月行胃的注入漏洞。 一、常見PHP網(wǎng)站安全漏洞 對于PHP的漏洞,目前常見的漏洞有五種。分別是Session文件漏洞、SQL注入漏洞、腳本命令執(zhí)行漏洞、全局變量漏洞和文件漏洞。這里分別對這些漏洞進(jìn)行簡要的介紹。 1、session文件漏洞 Session攻擊是黑客最常...

    lavor 評論0 收藏0
  • 寫給系統(tǒng)管理員的 25 個 PHP 安全實踐

    摘要:保證,軟件及操作系統(tǒng)更新到最新維護和服務(wù)器的一項重要工作是更新安全補丁。所有的安全更新應(yīng)盡快進(jìn)行審查并更新。啟用審查服務(wù)用于系統(tǒng)審查,可審查時間,驗證事件,文件修改,賬號修改 PHP是廣泛使用的開源服務(wù)端腳本語言。通過HTTP或HTTPS協(xié)議,Apache Web服務(wù)允許用戶訪問文件或內(nèi)容。服務(wù)端腳本語言的錯誤配置會導(dǎo)致各種問題。因此,PHP應(yīng)該小心使用。以下是為系統(tǒng)管理員準(zhǔn)備的,安全...

    wpw 評論0 收藏0
  • 寫給系統(tǒng)管理員的 25 個 PHP 安全實踐

    摘要:保證,軟件及操作系統(tǒng)更新到最新維護和服務(wù)器的一項重要工作是更新安全補丁。所有的安全更新應(yīng)盡快進(jìn)行審查并更新。啟用審查服務(wù)用于系統(tǒng)審查,可審查時間,驗證事件,文件修改,賬號修改 PHP是廣泛使用的開源服務(wù)端腳本語言。通過HTTP或HTTPS協(xié)議,Apache Web服務(wù)允許用戶訪問文件或內(nèi)容。服務(wù)端腳本語言的錯誤配置會導(dǎo)致各種問題。因此,PHP應(yīng)該小心使用。以下是為系統(tǒng)管理員準(zhǔn)備的,安全...

    senntyou 評論0 收藏0
  • PHP新手最佳實踐

    不要使用mysql_*系列函數(shù),查詢時盡量對sql語句進(jìn)行預(yù)處理 PHP官方目前已經(jīng)將此系列函數(shù)標(biāo)記為棄用狀態(tài),添加PHP對mysql的支持,編譯時使用下面的參數(shù) --enable-mysqlnd --with-pdo-mysql --with-mysqli --with-mysql=mysqlnd mysql_*系列函數(shù)不支持 預(yù)處理語句,事務(wù),存儲過程,異步查詢,多條...

    willin 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<