PHP 安全----以 CGI 模式安裝時

來源:http://www.php.net/manual/zh/security.intro.php

簡介

PHP 作爲一種強大的語言,無論是以模塊還是 CGI 的方式安裝,它的解釋器都可以在服務器上訪問文件、運行命令以及創建網絡連接等。這些功能也許會給服務器添加很多不安全因素,但是隻要正確地安裝和配置 PHP,以及編寫安全的代碼,那麼 PHP 相對於 Perl 和 C 來說,是能創建出更安全的 CGI 程序的。而且,也可以在可用性和安全性之間找到一個很好的平衡點。

PHP 可能會被用在很多不同的方面,因此,PHP 內置的選項以方便用戶對其進行配置。雖然衆多的選項可以使 PHP 完成很多工作,但是對這些選項的設定以及對服務器的配置很可能會產生安全問題。

PHP 的選項與其語法一樣,具有很高的靈活性。使用 PHP,可以在只有 shell 用戶權限的環境下創建完善的服務器端程序,或者在被嚴格限制環境下使用它來完成服務器端包含(Server-Side Includes)而無需承但太大的風險。如何建立這樣一種環境,其安全性如何,很大程度上取決於 PHP 的開發者。

本章以一些常規的安全建議作開頭,講述如何在不同的環境下儘可能地提高安全性,以及介紹對於不同安全級別的一些編程原則。

總則

絕對安全的系統是不存在的,因此安全業界常用的方法有助於平衡可用性和風險。對用戶提交的每一個變量都進行雙重驗證可能是一個很負責任的行爲,但會導致用戶必須花很多時間去填寫一張複雜無比的表格,從而迫使某些用戶嘗試繞過安全機制。

最好的安全機制應該能在不防礙用戶,並且不過多地增加開發難度的情況下做到能滿足需求。實際上,一些安全問題往往會發生在這種過度強化安全機制的系統上。

不要忘記著名的等強原則:一個系統的的強度是由它最薄弱的環節決定的(譯者注:相當於木桶原理)。如果所有的事務都基於時間、地點、事務種類進行詳細的記錄,而用戶驗證卻只依靠一個 cookie,那麼用戶所對應的事務記錄的可信度就被大大剝弱了。

調試代碼的時候一定要記住,就算是一個簡單的頁面也很難對所有可能發生的情況進行檢測:對你不滿的僱員不一定會輸入如你所願的東西,黑客也有足夠的時間研究你的系統,當然,你的寵物貓也會跳到你的鍵盤上。這就是爲什麼必須檢查所有的代碼,去發現哪裏可以引入不正當的數據,然後對代碼改進、簡化或者增強。

互聯網上充滿了爲了成名而破壞你的代碼、攻擊你的網站並輸入不正當數據的人,總之他們會使你的生活充滿樂趣。無論是大網站還是小網站,只要能和互聯網連接,就會成爲一個目標。很多黑客程序並不理會網站的大小,只會機械地掃描 IP 地址並找尋受害者。我們希望那個不要是你。


以 CGI 模式安裝時

Table of Contents

  • 可能受到的攻擊
  • 情形一:只運行公開的文件
  • 情形二:使用 --enable-force-cgi-redirect 選項
  • 情形三:設置 doc_root 或 user_dir
  • 情形四:PHP 解釋器放在 web 目錄以外

可能受到的攻擊

如果不想把 PHP 嵌入到服務器端軟件(如 Apache)作爲一個模塊安裝的話,可以選擇以 CGI 的模式安裝。或者把 PHP 用於不同的 CGI 封裝以便爲代碼創建安全的 chroot 和 setuid 環境。這種安裝方式通常會把 PHP 的可執行文件安裝到 web 服務器的 cgi-bin 目錄。CERT 建議書» CA-96.11 建議不要把任何的解釋器放到 cgi-bin 目錄。儘管 PHP 可以作爲一個獨立的解釋器,但是它的設計使它可以防止下面類型的攻擊:

  • 訪問系統文件:http://my.host/cgi-bin/php?/etc/passwd在 URL 請求的問號(?)後面的信息會傳給 CGI 接口作爲命名行的參數。其它的解釋器會在命令行中打開並執行第一個參數所指定的文件。但是,以 CGI 模式安裝的 PHP 解釋器被調用時,它會拒絕解釋這些參數。
  • 訪問服務器上的任意目錄:http://my.host/cgi-bin/php/secret/doc.html好像上面這種情況,PHP 解釋器所在目錄後面的 URL 信息/secret/doc.html 將會例行地傳給CGI 程序並進行解釋。通常一些 web 服務器的會將它重定向到頁面,如http://my.host/secret/script.php。如果是這樣的話,某些服務器會先檢查用戶訪問/secret 目錄的權限,然後纔會創建http://my.host/cgi-bin/php/secret/script.php 上的頁面重定向。不幸的是,很多服務器並沒有檢查用戶訪問 /secret/script.php 的權限,只檢查了/cgi-bin/php 的權限,這樣任何能訪問/cgi-bin/php 的用戶就可以訪問 web 目錄下的任意文件了。在 PHP 裏,編譯時配置選項--enable-force-cgi-redirect 以及運行時配置指令 doc_root user_dir 都可以爲服務器上的文件和目錄添加限制,用於防止這類攻擊。下面將對各個選項的設置進行詳細講解。

情形一:只運行公開的文件

如果 web 服務器中所有內容都受到密碼或 IP 地址的訪問限制,就不需要設置這些選項。如果 web 服務器不支持重定向,或者 web 服務器不能和 PHP 通信而使訪問請求變得更爲安全,可以在 configure 腳本中指定--enable-force-cgi-redirect 選項。除此之外,還要確認 PHP 程序不依賴其它方式調用,比如通過直接的 http://my.host/cgi-bin/php/dir/script.php 訪問或通過重定向訪問http://my.host/dir/script.php

在Apache中,重定向可以使用 AddHandler 和 Action 語句來設置,請看下一節。

情形二:使用 --enable-force-cgi-redirect 選項

此編譯選項可以防止任何人通過如 http://my.host/cgi-bin/php/secretdir/script.php 這樣的 URL 直接調用 PHP。PHP 在此模式下只會解析已經通過了 web 服務器的重定向規則的 URL。

通常 Apache 中的重定向設置可以通過以下指令完成:

Action php-script /cgi-bin/php
AddHandler php-script .php

此選項只在 Apache 下進行過測試,並且要依賴於 Apache 在重定向操作中所設置的非標準 CGI 環境變量 REDIRECT_STATUS。如果 web 服務器不支持任何方式能夠判斷請求是直接的還是重定向的,就不能使用這個選項,而應該用其它方法。請看下一節。

情形三:設置 doc_root 或 user_dir

在 web 服務器的主文檔目錄中包含動態內容如腳本和可執行程序有時被認爲是一種不安全的實踐。如果因爲配置上的錯誤而未能執行腳本而作爲普通 HTML 文檔顯示,那就可能導致知識產權或密碼資料的泄露。所以很多系統管理員都會專門設置一個只能通過 PHP CGI 來訪問的目錄,這樣該目錄中的內容只會被解析而不會原樣顯示出來。

對於前面所說無法判斷是否重定向的情況,很有必要在主文檔目錄之外建立一個專用於腳本的 doc_root 目錄。

可以通過配置文件內的doc_root 或設置環境變量PHP_DOCUMENT_ROOT 來定義 PHP 腳本主目錄。如果設置了該項,那麼 PHP 就只會解釋 doc_root 目錄下的文件,並確保目錄外的腳本不會被 PHP 解釋器執行(下面所說的user_dir 除外)。

另一個可用的選項就是 user_dir。當 user_dir 沒有設置的時候,doc_root 就是唯一能控制在哪裏打開文件的選項。訪問如http://my.host/~user/doc.php 這個 URL 時,並不會打開用戶主目錄下文件,而只會執行 doc_root 目錄下的~user/doc.php(這個子目錄以 [~] 作開頭)。

如果設置了 user_dir,例如 public_php,那麼像 http://my.host/~user/doc.php 這樣的請求將會執行用戶主目錄下的 public_php 子目錄下的doc.php 文件。假設用戶主目錄的絕對路徑是/home/user,那麼被執行文件將會是/home/user/public_php/doc.php

user_dir 的設置與 doc_root 無關,所以可以分別控制 PHP 腳本的主目錄和用戶目錄。

情形四:PHP 解釋器放在 web 目錄以外

一個非常安全的做法就是把 PHP 解釋器放在 web 目錄外的地方,比如說 /usr/local/bin。這樣做唯一不便的地方就是必須在每一個包含 PHP 代碼的文件的第一行加入如下語句:

#!/usr/local/bin/php
還要將這些文件的屬性改成可執行。也就是說,要像處理用 Perl 或 sh 或其它任何腳本語言寫的 CGI 腳本一樣,使用以 #! 開頭的 shell-escape 機制來啓動它們。

在這種情況下,要使 PHP 能正確處理 PATH_INFO PATH_TRANSLATED 等變量的話,在編譯 PHP 解釋器時必須加入 --enable-discard-path 參數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章