770
Php編程
php.ini安全配置最佳實踐
之前有一段時間,我在本網站撰寫了一篇有關於使用php.ini配置文件的一些與安全相關的最佳實踐的文章。對於那些不知道的php.ini文件的人(如果你使用過PHP,你就應該知道這個文件),我要說的是,php.ini文件是你在安裝PHP後的“主設置”文件。這是PHP解釋器(在Web和命令行方麵)尋找如何設置自己和一些選項打開/關閉的地方。
由於它是全局的配置文件,因此可以包括許多不同類型的設置:
· 輸出緩衝限製
· 禁用PHP函數
· 最大執行時間/內存使用量
· 錯誤處理和顯示首選項
· 允許include或打開訪問遠程的資源
…當然還有更多的設置選項。這也是你可以加載外部擴展並配置更多特定字段的設置,如會話處理,正則表達式,郵件服務器配置和各種數據庫擴展。現在你可以很明顯的明白此文件的重要性,並且內部選項的錯誤設置可能會在你的應用程序的安全性上留下 “裂縫” 。
在這有一點需要指出 - 有一個選項(with-config-file-scan-dir)你可以編譯成指向另一個安裝了PHP的目錄,並將其中的*.ini文件進行加載,尋找PHP設置。這個操作是在php.ini生成之後做的,所以在這裏總是有機會可以覆蓋掉一些主要的設置。
不要誤會我的解釋,在應用程序代碼級別上可以做很多事情,可以幫助你提高應用程序的安全性以及一些通過配置設置無法輕鬆完成的事情。當你談論php.ini安全性的時候,你其實正在看的是一些非常基本的東西。即使在PHP附帶的默認配置文件中也有很多地方你可以進行潛在的濫用行為,甚至你不需要了解這些選項。有很多文章提出了一些關於某些設置要禁用的建議,以及其他選項的應該設置的合理級別,但似乎沒有哪篇文章是保持了最新的信息。
我不得不向Ed Finkler提出需求,在他原來編寫的概念驗證工具—— PHPSecInfo中打破了這一點。他的工具是一個PHP實用程序,你可以放入你的Web應用程序,這個工具可以可視化地指出你的應用程序的痛點在哪裏。工具會根據通過/失敗狀態對HTML進行著色,並提供有關該問題的更多信息以及設置選項值的良好建議。不幸的是,它已經有很長一段時間沒有更新了,但它仍然是一個有用的工具。如果你使用它,請注意一點——它可以為訪問你的站點的用戶提供大量的信息披露。它不建議在生產經常使用,但可能是在你初始的配置和安裝過程中非常有用的一個工具。
正如我所提到的,我收集了我可以找到的所有與php.ini相關的安全信息,並決定對這些信息進行分析能有一些實際的意義。而不是隻是寫一篇文章這麼簡單,我決定讓這些信息對普通用戶更加有用,這些用戶將在任何框架或應用程序平台之外吸取有關安全的PHP服務器端配置的教訓。所以,我創建了Iniscan工具 —— 一個命令行實用程序,你可以針對你的php.ini文件運行安全掃描,並在建議你在此基礎級別上保護應用程序時提供一些最佳做法。
Iniscan - 概述
Iniscan項目背後的目標是聚集各種最佳做法來保證配置文件的安全性。這包括更普通的PHP大眾以及那些正在尋找他們所運行的特定版本的PHP的內容的用戶。掃描器會使用給定的選項值(默認或從命令行選項中指定)掃描php.ini文件,並將php.ini的一些設置與其自己的規則集進行比較,來尋找安全問題。
要在自己的係統上進行嚐試,可以使用Composer輕鬆安裝它:
{ "require": { "psecio/iniscan": "dev-master" } }
一旦下載完成,你可以通過命令行針對你自己的php.ini來啟動執行:
bin/iniscan scan --path=/path/to/php.ini
這將產生類似於下麵這樣的掃描結果:
== Executing INI Scan [12.05.2013 17:59:40] ==
Results for php.ini:
============
Status | Severity | Key | Description
----------------------------------------------------------------------
PASS | ERROR | session.use_cookies | Accepts cookies to manage sessions
PASS | ERROR | session.use_only_cookies | Must use cookies to manage sessions, don t accept session-ids in a link
FAIL | WARNING | session.cookie_domain | It is recommended that you set the default domain for cookies.
PASS | ERROR | session.cookie_httponly | Setting session cookies to http only makes them only readable by the browser
掃描的結果輸出提供了這幾個事情:
· 檢查通過或失敗的狀態
· 問題的嚴重程度
· php.ini中進行檢查的“key”
· 對檢查出的問題和原因的總結描述
如果你對實際的檢查過程很感興趣,請查看src/Psecio/Iniscan/rules.json文件中的定義和工具將會檢查的一些值。
當報告出任何檢查失敗的情況時,命令將以非零狀態退出,使你更容易以編程的方式檢查整體的通過或失敗的狀態。
還有一組可以提供的命令行選項,這些選項可以使掃描更加靈活:
· --path定義要檢查的php.ini文件的路徑。如果沒有給出,它會嚐試從PHP的內部設置中尋找。
· --fail-only 告訴Iniscan隻顯示檢查失敗的選項,而不需要顯示檢查通過的內容。
· --format 允許你以各種格式輸出掃描結果(目前支持默認的CLI輸出以及JSON和XML)
· --threshold 定義你想要看到的最低失敗值(例如--threshold = ERROR將顯示錯誤而不是警告)
· --php指定你要用於評估的PHP版本。如果沒有指定這個值,Iniscan則會從中PHP_VERSION 中讀取
· --output 定義要將掃描結果輸出寫入的目錄(如使用JSON和XML的輸出格式)
因此,如果你隻想查看安全問題並將結果輸出到JSON數據集,則可以使用下麵的命令:
bin/iniscan scan --path=/path/to/php.ini --fail-only --format=json --output=/path/to/output-dir
還包括兩個“列表”命令,以便你了解該工具執行的檢查:
bin/iniscan list-tests
以及你當前正在處理的php.ini設置文件:
bin/iniscan show
PHP.ini安全性一瞥
接下來,我會嚐試通過規則列表中的每個條目,並討論這些條目為什麼需要被檢查,我會將其分解成幾個部分,並描述一些基本的可能會因為糟糕的設置而出現的安全問題。其中一些已經在另一篇文章中提及。
一般的PHP設置選項
有幾個設置與任何特定的PHP功能無關,這些功能更加通用一些。其中有些是有爭議的,盡管它們可能導致一些問題(如expose_php),但其中幾個可以產生真正的影響。例如,如果你知道你的應用程序永遠不會通過任何類似於include / require或fopen打開遠程位置的文件,那麼你可以關閉allow_url_fopen和allow_url_include設置。這可以防止意外的遠程文件包含問題所導致的代碼執行,例如將用戶上傳的“.php”文件放在可公開訪問的目錄中,然後包含執行。
還有一些涉及到與最終用戶共享什麼樣的信息有關的錯誤處理。如果啟用error_reporting和display_errors,那麼在開發過程中輸出的錯誤值是絕對有助於調試腳本並跟蹤錯誤的。然而,在生產和麵向公眾的環境中,相同的信息可能會泄露你的應用程序的某些敏感信息,你可能不希望存在潛在的攻擊。例如,假設生產中沒有關閉錯誤開關,最終用戶正在嚐試通過一些SQL注入測試來實施入侵。如果由於這些請求而出現錯誤,那麼該攻擊者將獲得有關應用程序內部的一些信息,並且由於PHP本身傾向於在某些錯誤上提供堆棧跟蹤,因此有關組成應用程序的實際文件的信息也會泄露。
會話設置選項
Session是使用PHP有用性方麵的重要組成部分。在其他語言可能需要引入單獨的會話處理程序的情況下,PHP包括了其默認的功能(並且已有很長時間)。正如你所料,這意味著配置就在這個文件裏,一般來說PHP都在php.ini裏進行配置。這個文件裏已經定義了很多有關會話的設置,但這並不意味著它們是最安全的選項。當前默認的設置更多的是“這些將在大多數係統上工作”為目的的。
那麼我們需要注意哪些呢?最初的幾個選項是有關於處理會話處理程序的cookie。默認情況下,PHP會話使用帶有PHPSESSID哈希值的cookie 作為值。Iniscan工具會檢查以確保你的session.use_cookies和session.use_only_cookies設置被啟用,以防止會話被以任何其他方式注入。還有三個其他設置選項,更多的是保護實際的Cookie本身:session.cookie_domain限製可以訪問它們的域,cookie_httponly防止從Web環境以外的來源進行訪問,cookie_secure設置以及阻止訪問HTTPS / SSL連接之外的Cookie 。
除此之外,還有一些更多的自定義檢查工作,一個是處理腳本將其會話寫入的路徑,另一個處理熵文件的路徑。第一個設置選項——session.save_path告訴PHP在哪裏寫會話文件。默認情況是寫入/tmp也就是本地文件係統上的臨時目錄。這有一個明顯的問題,它與該目錄的默認權限有關。原來的意圖/tmp是要有一個任何應用程序可以讀寫的地方,包括運行PHP的Web服務器。所以,想象一下如果有人通過另一種方法來破壞服務器,並且能夠讀取到這些會話文件的內容時會發生什麼呢。默認情況下,PHP隻需要在會話中使用數據,使用base64將其編碼並將其寫入文件。Iniscan會檢查你設置的路徑——save_path並確保它不是對任何人都是可讀/寫的。
第二個自定義會話檢查可以幫助增強PHPSESSID——PHP會話cookie值使用的哈希值的隨機性。雖然默認散列生成的結果是可以接受的,但PHP開發組希望允許用戶可以幫助它更隨機。而不是試圖將更多的功能引入到你的代碼中,他們在一個較低的級別定義了session.entropy_file設置選項。默認情況下,此設置未定義,但在PHP 5.4.0及更高版本中,它使用/dev/urandom或/dev/arandom,作為值,如果可用的話。
這些都是隨機數據的良好來源,但如果你的版本低於PHP 5.4.0呢?你可以分配任何你想要的設置的entropy_file文件,PHP將會在該會話ID的隨機生成過程中使用該文件的內容。過去有一些問題,PHP的會話ID生成是可預測的,因為它的實現是“隨機的”(注意那裏的引號),並且可以預測其他請求的結果,並允許進行會話固定攻擊。
自定義安全檢查
還有一些是Iniscan的定製檢查,這些檢查不僅僅隻是檢查“某個選項的值設置了沒?”或“某個選項確認是否關閉了”。一個與通過disable_functions設置選項禁用函數有關的設置,允許你阻止PHP執行某些函數,並可以關閉諸如exec,passthru或其他文件係統執行功能之類的函數。這可以防止未經授權的代碼進行係統調用,並且可能(取決於執行用戶的訪問級別)對本地文件進行更改。
另一個更為具體的檢查,是在特定版本的PHP上檢查一個安全問題。CVE-2013-1635引用的問題影響了PHP 5.3.22和5.4.13+版本,並且與SOAP擴展的WSDL緩存目錄的問題相關soap.wsdl_cache_dir-可以在open_basedir限製之外設置為啟用。雖然本身並不完全是“最佳實踐”,但這是值得注意的事情。自定義檢查允許Iniscan使用更複雜的邏輯來查看是否有風險(例如檢測當前的PHP版本)。
開源!
最後的一個提醒,在寫這篇文章之前 - Iniscan項目是開放源代碼的,並托管在Github上,並且始終保持開放貢獻的態度。它不一定是代碼,總是會有一些事情沒有想到或特定於你的配置,可能會讓它失敗。如果你遇到這些問題,請提交一個有關該問題的issue,這將有助於你解決遇到的問題。該項目已經受到Github和Packagist的大量安裝的關注,但它總是可以使用input或pull請求來幫助它更加好用。
希望這個工具能夠幫助PHP社區以簡單而有效的方式加強服務器端的安全。該項目一直在尋找好的想法和“下一步”要做的事情,所以如果你有一些好的建議,甚至隻是一般的反饋,請讓我知道!
資源
Iniscan 開源項目
PHP 手冊中關於php.ini 的介紹
在你的 php.ini 保持安全
最後更新:2017-10-08 23:36:35