PHP 的安全模式是為了試圖解決共享伺服器(shared-server)安全問題而設立的。在結構上,試圖在 PHP 層上解決這個問題是不合理的,但修改 web 伺服器層和作業系統層顯得非常不切實際。因此許多人,特別是 ISP,目前使用安全模式。
以下是php.ini中關於安全模式的設定:
safe_mode boolean
是否啟用 PHP 的安全模式。
safe_mode_gid boolean
預設情況下,安全模式在開啟檔案時會做 UID 比較檢查。如果想將其放寬到 GID 比較,則開啟 safe_mode_gid。是否在文件存取時使用 UID(FALSE)或 GID(TRUE)來做檢查。
safe_mode_include_dir string
當從此目錄及其子目錄(目錄必須在 include_path 中或以完整路徑來包含)包含檔案時越過 UID/GID 檢查。
從 PHP 4.2.0 開始,本指令可以接受和 include_path 指令類似的風格用冒號(Windows 中是分號)隔開的路徑,而不只是一個目錄。 指定的限制其實是一個前綴,而非一個目錄名。這也就是說“safe_mode_include_dir = /dir/incl”將允許存取“/dir/include”和“/dir/incls”,如果它們存在的話。如果希望將存取控制在指定的目錄,那麼請在結尾加上一個斜線,例如:「safe_mode_include_dir = /dir/incl/」。 如果本指令的值為空,在 PHP 4.2.3 中以及 PHP 4.3.3 起具有不同 UID/GID 的檔案將無法包含。在較早版本中,所有文件都能被包含。
safe_mode_exec_dir string
如果 PHP 使用了安全模式, system() 和其它程式執行函數將拒絕啟動不在此目錄中的程式。必須使用 / 作為目錄分隔符,包括 Windows 中。
safe_mode_allowed_env_vars string
設定某些環境變數可能是潛在的安全缺口。本指令包含一個逗號分隔的前綴清單。在安全模式下,使用者只能改變那些名字具有在這裡提供的前綴的環境變數。預設情況下,使用者只能設定以 PHP_ 開頭的環境變數(例如 PHP_FOO = BAR)。
注意:
如果本指令為空,PHP 將使使用者可以修改任何環境變數!
safe_mode_protected_env_vars string
本指令包含有一個逗號分隔的環境變數的列表,最終使用者不能用 putenv() 來改變這些環境變數。甚至在 safe_mode_allowed_env_vars 中設定了允許修改時也不能改變這些變數。
當 safe_mode 設定為 on,PHP 將透過檔案函數或其目錄檢查目前腳本的擁有者是否和將被操作的檔案的擁有者相符。例如:
-rw-rw-r-- 1 rasmus rasmus 33 Jul 1 19:20 script.php -rw-r--r-- 1 root root 1116 May 26 18:01 /etc/passwd
運行 script.php
<?php readfile('/etc/passwd'); ?>
如果安全模式被激活,則將會導致以下錯誤:
Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not allowed to access /etc/passwd owned by uid 0 in /docroot/script.php on line 2
同時,或許會存在這樣的環境,在該環境下,寬鬆的 GID 檢查已經足夠,但或許會存在這樣的環境,在該環境下,寬鬆的 GID 檢查已經足夠,但可能會存在這樣的環境,在該環境下,寬鬆的 GID 檢查已經足夠,但可能會存在這樣的環境,在該環境下,寬鬆的 GID 檢查已經足夠,但可能會存在這樣的環境,在該環境下,寬鬆的 GID 檢查已經足夠,但可能會存在這樣的環境,在該環境下,寬鬆的 GID 檢查已經足夠,但也許會存在這樣的環境,在該環境下,寬鬆的 GID 檢查已經足夠,但可能會存在這樣嚴格的 UID 檢查反而是不適合的。可以用 safe_mode_gid選項來控制這種檢查。若設定為 On 則進行寬鬆的 GID 檢查;設定為 Off(預設值)則進行 UID 檢查。
除了 safe_mode 以外,如果設定了 open_basedir 選項,則所有的檔案作業將被限制在指定的目錄下。例如:
<Directory /docroot> php_admin_value open_basedir /docroot </Directory>
如果在設定了 open_basedir 選項後執行相同的 script.php,則其結果會是:
Warning: open_basedir restriction in effect. File is in wrong directory in /docroot/script.php on line 2
也可以單獨地屏蔽某些函數。請注意 disable_functions 選項不能在 php.ini 檔案外部使用,也就是說無法在 httpd.conf 檔案的以不同虛擬主機或不同目錄的方式來屏蔽函數。如果將以下內容加入 php.ini 檔案:
disable_functions readfile,system
則會得到以下的輸出:
Warning: readfile() has been disabled for security reasons in /docroot/script.php on line 2
警告
當然,這些 PHP 限制不適用於執行檔。