摘要:每個專業的開發者都知道用戶上傳的文件都是極其危險的。如何防止引入用戶上傳的文件重命名文件名可以嗎不,辦不到解析器不關心文件的后綴名。服務器通常被設置成執行文件并將執行結果回復輸出。如何進行檢查這很簡單。用戶可以上傳文件到該站點。
每個專業的 PHP 開發者都知道用戶上傳的文件都是極其危險的。不論是后端和前端的黑客都可以利用它們搞事情。
大約在一個月前,我在 reddit 上看了一篇?PHP 上傳漏洞檢測 ,因此, 我決定寫一篇文章。用戶?darpernter 問了一個棘手的問題:
盡管我將其重命名為 "helloworld.txt", 攻擊者是否仍然能夠運行他的php 腳本?
置頂的答復是:
如果文件后綴修改為?.txt ,那么它不會被當做php文件執行,這樣你安心了吧,不過再三確保不是 .php.txt 的后綴上傳。
不好意思,問題的正確答案并非如此 . 雖然上面的答復并非全部錯誤,但顯然不全面。讓人驚訝的是,大多數的答案都非常相似。
我想解釋清楚這個問題。所以我要討論的東西變得有點大,我決定讓它變得更大。
問題人們允許用戶上傳文件,但是擔心用戶上傳的文件在服務器上被執行。
從 php 文件如何被執行開始看。假設一個有 php 環境的服務器,那么它通常有兩種方法在外部執行 php 文件。一是直接用 URL 請求文件,像 http://example.com/somefile.php 。第二種是 php 現在常用的,將所有請求轉發到 index.php ,并在這個文件中以某種方式引入其他文件。所以,從 php 文件中運行代碼有兩種方式:執行文件或用 include/include_once/require/require_once 的方法引入其他需要運行的文件。
其實還有第三種方法:eval() 函數。它能將傳入的字符串當做 php 代碼執行。這個函數在大多數 CMS 系統中被用來執行存儲在數據庫里的代碼。eval()?函數非常危險,但如果你用了它,通常就意味著你確認自己在做危險的操作,并確認你已經沒有其他選擇。實際上, eval() 有它的用途,并且在某些情況下非常有用。但如果你是新手的話,我不推薦你使用它。請看 這篇在 OWASP 的文章。我在上面寫了很多。
所以,有兩種方法執行文件里的代碼:直接執行或者在被執行的文件中引入它。那么如何避免這種事情發生呢?
解決方法?我們怎樣才能知道一個文件包含 php 代碼呢?看拓展名,如果以 .php 結尾的,像 somefile.php 我們就認為它里面有 php 代碼。
如果在網站根目錄下有一個 somefile.php 文件,那么在瀏覽器訪問 http://example.com/somefile.php ,這個文件就會被執行并且輸出內容到瀏覽器上。
但是如果我重命名這個文件會怎樣?如果我把它重命名為 somefile.txt 或者是 somefile.jpg 呢?我會得到什么?我會得到它的內容。它不會被執行。它會從硬盤(或者緩存)直接被發送過來。
在這點上 reddit 社區上的答案是對的。重命名能防止一個文件被非預期的執行,那么為什么我認為這種解決方法是錯的呢?
我相信你注意到我在 “解決方法” 后面加的問號。這個問號是有意義的。現在大多數網站的 URL 上幾乎看不到多帶帶的 php 文件。并且就算有,也是人為故意偽造的,因為 URL 上需要有 .php 來實現對老版本 URL 的向后兼容。
現在絕大部分 php 代碼是在運行中被引入的,因為所有請求都被發送到了網站根目錄的 index.php。這個文件會根據特定的規則引入其他 php 文件。這種規則可能(或者在將來會)被惡意使用。如果你應用的規則允許引入用戶的文件,那么應用會容易遭到攻擊,你應該立即采取措施防止用戶的文件被執行。
如何防止引入用戶上傳的文件?重命名文件名可以嗎??---?不,辦不到!
PHP解析器不關心文件的后綴名。事實上,所有程序都不關心。雙擊文件,文件會被對應的程序打開。文件后綴名只是幫助操作系統識別用什么程序打開文件。只要程序有讀取文件的能力,程序就可以打開任何文件。有時程序拒絕打開和操作文件。但那并不是因為后綴名,是文件內容所致。
服務器通常被設置成執行 .php? 文件并將執行結果回復輸出。如果你請求圖片 .jpg ?---?將從磁盤上原樣的返回。如果你要求服務器以某種方式運行一張 jpeg 圖片,會發生?服務器會執行還是不呢?
圖片來源:?Echo / Cultura / Getty?Images
程序不關心文件名。甚至不關心文件是否有名字,也不關心它究竟是不是文件。
從文件執行PHP代碼需要什么?有至少兩個情況可以讓PHP執行代碼:
代碼介于??和??>?標記之間
代碼介于?=?和??>?標記之間
即使文件中填充了一些奇怪的二進制數據或一些奇怪的保護名稱,該標記中的代碼仍然會被執行。
這里有一個圖片給您:
該圖片沒有問題
它現在很純凈。但是您可能知道 JPEG 格式允許在文件中添加一些注釋。比如,拍攝照片的相機型號或坐標地址。如果我們試圖在里面放一些PHP代碼并嘗試?include?或?require?呢?讓我們來看看吧!
問題! 1下載這個圖片到你的硬盤上。或者你自己去弄一張 JPEG 圖片也行。你隨便用什么格式的文件都無所謂。我建議用一個 JPEG 文件來演示,主要是因為它是一張圖片且易于在其中進行文本編輯。我用的是一個 Windows的筆記本,目前我手頭上沒有 Apple 或 Linux(或其他UNIX系的系統)的筆記本。所以一會我會發一個這個 OS 下的屏幕快照。但是我確信你肯定也能做這個事。
用以下這段 PHP 代碼建個文件:
Problem?
保存一個圖片命名為troll-face.jpg
把圖片和 php 腳本文件都放在同一個文件夾下
打開瀏覽器請求這個 php 文件
如果你把你的 php 文件命名為?index.php,然后把它放在文件根目錄或者放在你網站目錄下的任何一個文件目錄中。
如果你準確完成了上述步驟,你就可以看到這個畫面:
到此這都沒毛病。沒 PHP 代碼展示,也沒有 PHP 代碼被執行。
現在,我們來添加一個問題:
打開文件屬性對話框或運行一些允許編輯 EXIF 信息的應用程序
切換到 Details 選項卡或以其他方式編輯該信息
向下滾動到 camera 參數
將下面代碼復制到 “camera maker” 字段后面:
Yep, a problem!"; phpinfo(); ?>刷新頁面!
很明顯出現了一點問題!
您在頁面上看到了該圖片。相同的圖片還存在頁面的 PHP 代碼中。圖片的代碼也被執行了。
我們該怎么做?!!1長話短說:?如果我們不在程序種引入這些不安全的文件,文件中的腳本就不會執行。
仔細看下面的例子。
最終答案?如果有人在某處看到我錯了 - 請糾正我,這是一個嚴重的問題。
PHP是一種腳本語言。您總是需要引用一些動態組合路徑的文件。因此,為了保護服務器,您必須檢查路徑并防止混淆您的站點文件和用戶上傳或創建的文件。如果用戶的文件與應用程序文件分開,則可以在使用上傳或創建文件之前檢查文件的路徑。如果它位于您的應用程序腳本允許的文件夾中 - 那么它可以使用 include_once 或 require 或 require_once 引入這個文件。如果不是--那么就不引入它。
如何進行檢查?這很簡單。你只需要將 $folder (文件)路徑與一個允許程序引入文件 ( $file ) 的路徑文件夾進行比較。
// 不好的例子,不要用! if (substr($file, 0, strlen($folder)) === $folder) { include $file; }如果 ?$folder 的存放路徑是 /path/to/folder ?而且 ?$file? 的存放路徑是? /path/to/folder/and/file , 然后我們在代碼中使用 substr()?函數把他們的路徑都變成字負串進行判斷,如果文件位于不同的文件夾中---這個字符串將不相等。反之則反。
上面的代碼有兩個重要的問題。如果 file 路徑是 /path/to/folderABC/and/file,很明顯,該文件也不在允許引入的文件夾中。通過向兩個路徑添加斜杠可以防止這種情況。我們在這里向文件路徑添加斜杠并不重要,因為我們只需要比較兩個字符串。
舉個例子: 如果 folder 路徑是 ?/path/to/folder? 并且 file 路徑是?/path/to/folder/and/file ,那么從 file 提取和 folder 具有相同數量的字符,那么 $ folder 將是 /path/to/folder 。
再比如 folder 路徑是?/path/to/folder 并且 file 路徑是?/path/to/folderABC/and/file, 那么從 file 中提取 folder 具有相同數量的字符,和 $folder一樣,并且將再次成為/path/to/folder,這種都是錯誤的,這不是我們期望的結果。
因此,在 /path/to/folder/ 添加斜杠后,與 /path/to/folder/and/file 的提取部分 /path/to/folder/ 相同就是安全的。
如果將 /path/to/folder/ 與 /path/to/folderABC/and/file 的提取部分 / path/to/folderA ,很明顯二個字符串不一樣。
這就是我們期望得到的。但還有另一個問題。這并不明顯。我敢肯定,如果我問你,你看到這里有一個災難性的漏洞 - 你不會猜到它在哪里。你也許已經在經驗中使用過這個東西,甚至可能就在今天。現在,您將看到漏洞是如何隱晦和顯而易見。往下看。
/../假想一個很常見的場景。
有這么一個網站。用戶可以上傳文件到該站點。所有的文件都位于一個特定的目錄下。有一個包含用戶文件的腳本。腳本自上而下進行查找是否包含用戶的輸入(直接或間接)路徑---那這個腳本可以通過如下方式進行路徑偽造:
/path/to/folder/../../../../../../../another/path/from/root/舉例。用戶發起請求,你的腳本中包含了一個基于類似如下用戶輸入路徑的文件:
include $folder . "/" . $_GET["some"]; // or $_POST, or whatever你麻煩大了。有天用戶發送一個?../../../../../../etc/.passwd?這種或其他請求,你就哭吧。
再不然。假如有人讓你的腳本加載一個他想要的文件,你就廢了。它不一定就只是出現在用戶文件中。它可能是你的CMS或你自己文件的一些插件(別相信任何人),甚至是應用程序邏輯中的錯誤等。
或者用戶可能會上傳一個名為 file.php 的文件,你會把它和其他的用戶文件一樣放在一個特定的文件夾里面:
move_uploaded_file($filename, $folder . "/" . $filename);用戶的文件就存放在那里,你必須常常檢查從來沒有包含該文件夾中的文件,目前來看,所有的東西都挺正常的。通常,用戶發給你的文件不會包含斜杠或者其他特殊字符,因為這是被系統文件系統禁止的。之所以這樣,是因為通常情況下瀏覽器發給你的文件是在真實文件系統中創建的,同時它的名字是一些真實存在的文件的名字。
但是 http 請求允許用戶發送任何字符。所以如果某人偽造請求創建名為 ../../../../../../var/www/yoursite.com/index.php 的文件---這行代碼會覆蓋你的 index.php 文件,如果 index.php 處于在上述路徑的話。
所有的初學者都希望通過過濾 「..」或者斜杠來解決這個問題,但是這種做法是錯誤的,由于你在安全方面還缺乏經驗。同時你必須(是的,必須)明白一個簡單的事情:你永遠無法在安全和密碼學方面的獲得足夠的知識。這句話的意思是,如果你懂得了「兩個點和斜杠」的漏洞,但這不代表你知道所有其他的缺陷、攻擊和其他特殊字符,你也不知道在文件寫入文件系統或數據庫時可能發生的代碼轉換。
解決方案和答案為了解決這個問題,PHP中內置了一些特殊函數方法,只是為了在這種情況下使用。
basename()第一個解決方案?---?basename()?它從路徑結束時提取路徑的一部分,直到它遇到第一個斜杠,但忽略字符串末尾的斜杠,參見示例。無論如何,你會收到一個安全的文件名。如果你覺得安全 - 那么是的這很安全。如果它被不法上傳利用 - 你可以使用它來校驗文件名是否安全。
realpath()另一個解決方案?---?realpath()它將上傳文件路徑轉換規范化的絕對路徑名,從根開始,并且根本不包含任何不安全因素。它甚至會將符號鏈接轉換為此符號鏈接指向的路徑。
因此,您可以使用這兩個函數來檢查上傳文件的路徑。要檢查這個文件路徑到底是否真正屬于此文件夾路徑。
我的代碼我編寫了一個函數來提供如上的檢查。我并不是專家,所以風險請自行承擔。代碼如下。
結語。
必須過濾用戶輸入,文件名也屬于用戶輸入,所以一定要檢查文件名。記得使用 basename() 。
必須檢查你想存放用戶文件的路徑,永遠不要將這個路徑和應用目錄混合在一起。文件路徑必須由某個文件夾的字符串路徑,以及 basename($filename) 組成。文件被寫入之前,一定要檢查最終組成的文件路徑。
在你引用某個文件前,必須檢查路徑,并且是嚴格檢查。
記得使用一些特殊的函數,因為你可能并不了解某些弱點或漏洞。
并且,很明顯,這與文件后綴或 mime-type 無關。JPEG 允許字符串存在于文件內,所以一張合法的 JPEG 圖片能夠同時包含合法的 PHP 腳本。
不要信任用戶。不要信任瀏覽器。構建似乎所有人都在提交病毒的后端。
當然,也不必害怕,這其實比看起來的簡單。只要記住 “不要信任用戶” 以及 “有功能解決此問題” 便可。
轉自 PHP / Laravel 開發者社區 https://laravel-china.org/top...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/29973.html
摘要:一常見網站安全漏洞對于的漏洞,目前常見的漏洞有五種。分別是文件漏洞注入漏洞腳本命令執行漏洞全局變量漏洞和文件漏洞。這就是月行胃的注入漏洞。 一、常見PHP網站安全漏洞 對于PHP的漏洞,目前常見的漏洞有五種。分別是Session文件漏洞、SQL注入漏洞、腳本命令執行漏洞、全局變量漏洞和文件漏洞。這里分別對這些漏洞進行簡要的介紹。 1、session文件漏洞 Session攻擊是黑客最常...
摘要:保證,軟件及操作系統更新到最新維護和服務器的一項重要工作是更新安全補丁。所有的安全更新應盡快進行審查并更新。啟用審查服務用于系統審查,可審查時間,驗證事件,文件修改,賬號修改 PHP是廣泛使用的開源服務端腳本語言。通過HTTP或HTTPS協議,Apache Web服務允許用戶訪問文件或內容。服務端腳本語言的錯誤配置會導致各種問題。因此,PHP應該小心使用。以下是為系統管理員準備的,安全...
摘要:保證,軟件及操作系統更新到最新維護和服務器的一項重要工作是更新安全補丁。所有的安全更新應盡快進行審查并更新。啟用審查服務用于系統審查,可審查時間,驗證事件,文件修改,賬號修改 PHP是廣泛使用的開源服務端腳本語言。通過HTTP或HTTPS協議,Apache Web服務允許用戶訪問文件或內容。服務端腳本語言的錯誤配置會導致各種問題。因此,PHP應該小心使用。以下是為系統管理員準備的,安全...
閱讀 1391·2023-04-26 03:04
閱讀 2325·2019-08-30 15:44
閱讀 3727·2019-08-30 14:15
閱讀 3507·2019-08-27 10:56
閱讀 2702·2019-08-26 13:53
閱讀 2616·2019-08-26 13:26
閱讀 3075·2019-08-26 12:11
閱讀 3609·2019-08-23 18:21