你的WEB伺服器必須要能夠讀取你的來源確並執行它,這意味著任意人所寫的程式碼被伺服器運行時,它同樣可以讀取你的原始碼。在一個共享主機上,最大的風險是由於WEB伺服器是共享的,因此其它開發者所寫的PHP程式碼可以讀取任意檔案。
<?php header('Content-Type: text/plain'); readfile($_GET['file']); ?>
透過在你的原始碼所在的主機上執行上面腳本,攻擊者可以透過把file的值指定為完整的路徑和檔案名稱來使WEB伺服器讀取並顯示任何檔案。例如,假定腳本命名為file.php,位於主機example.org上,只要透過造訪下面連結即可使檔案/path/to/source.php的內容暴露:
http://www.php .cn/
當然,要使這段簡單的程式碼起作用,攻擊者必須確切地知道你的原始碼的位置,但是攻擊者可以寫出更複雜的腳本,透過它可以方便地在瀏覽整個檔案系統。關於這類腳本,請看本章後面部分的範例。
對該問題沒有完美的解決方案。正如第五章所述,你必須考慮所有你的原始碼都是公開的,甚至是保存在WEB主目錄之外的程式碼也是如此。
最好的方法是把所有敏感資料保存在資料庫中。雖然這使一些程式碼的編寫多了一層複雜性,但這是防止你的敏感資料暴露的最佳方法。很不幸的是,還有一個問題。如何保存你的資料庫存取密碼?
請看保存在網站主目錄之外一個名為db.inc的檔案:
<?php $db_user = 'myuser'; $db_pass = 'mypass'; $db_host = 'localhost'; $db = mysql_connect($db_host, $db_user, $db_pass); ?>
如果該檔案的路徑是已知的(或被猜中),就存在著你的伺服器上的另外一個使用者存取該檔案的可能,就會取得資料庫存取權限,這樣你儲存在資料庫中的所有資料就會暴露。
解決該問題的最好方案是把你的數據庫訪問權限以下面的格式保存在一個只有系統管理員權限才能讀取的文件中:
SetEnv DB_USER "myuser" SetEnv DB_PASS "mypass"
SetEnv是一個Apache的指令,上面檔案的意思是建立兩個分別代表你的資料庫使用者名稱及密碼的Apache環境變數。當然,該技巧的關鍵是只有系統管理員才能讀取該檔案。如果你無法登入成為系統管理員,你就可以限制該檔案只能由你自已進行讀取,這樣的保護方式與上面的方式類似。
$ chmod 600 db.conf $ ls db.conf -rw------- 1 chris chris 48 May 21 12:34 db.conf
這有效地防止了惡意腳本存取你的資料中權限,因此對於資料庫中保存的敏感資料來說,不會有危及安全的重大風險。
為使該文件生效,你就需要能夠透過PHP存取其中的資料。要達到這個目的,需要在httpd.conf中寫上如下的包含句:
Include "/path/to/db.conf"
語就能取得對應的內容。
由於Apache的父進程以系統管理員身份運行(需要綁定在80端口),它能夠讀取該配置文件,但處理伺服器請求的子進程(運行PHP腳本)不能讀取該文件。
你可以透過$_SERVER超級全域數組去存取這兩個變量,這樣在db.inc中,只要引用$_SERVER變數即可,而不是在其中寫明資料庫的權限:
<?php $db_user = $_SERVER['DB_USER']; $db_pass = $_SERVER['DB_PASS']; $db_host = 'localhost'; $db = mysql_connect($db_host, $db_user, $db_pass); ?>
rrreee
如果該文件被揭露,資料庫存取權也不會洩露。這對於共享主機來說是一大安全性改進,同時對於獨立主機也是一種深度防範。
注意在使用上述技巧時,資料庫存取權限就位於$_SERVER超級公用陣列中。這就需要同時限制一般訪客執行phpinfo()察看或其它任何導致$_SERVER內容暴露的原因。
當然,你可以使用本技巧保護任何資訊(不只是資料庫存取權限),但我發現把大多數資料保存在資料庫更為方便,特別是由於該技巧需要得到你的主機提供者的協助。 以上是PHP安全-源碼暴露(二)的內容,更多相關內容請關注PHP中文網(www.php.cn)!