原文:Kevin Yank 轉自:www.linuxforum.net (恭喜再此開通)
在很長一段時間內,PHP作為伺服器端腳本語言的最大賣點之一就是會為從表單提交的值自動建立一個全域變數。在PHP 4.1中,PHP的製作者們推薦了一個存取提交資料的替代手段。在PHP 4.2中,他們取消了那種老舊的做法!正如我將在這篇文章中解釋的那樣,作出這樣的變化的目的是出於安全性的考慮。我們將研究PHP在處理表單提交及其它資料時的新的做法,並說明為什麼這樣做會提高程式碼的安全性。
這裡有什麼錯誤?
看看下面的這段PHP腳本,它用來在輸入的用戶名及口令正確時授權訪問一個Web頁:
// 檢查用戶名及口令
if ($username == 'kevin' and $password == 'secret')
$authorized = true;
?>
?>
Please enter your username and password:
OK,我相信大約半數的讀者會不屑的說「太愚蠢了-- 我不會犯這樣的錯誤的!」但是我保證有很多的讀者會想「嗨,沒什麼問題啊,我也會這麼寫的!」當然還會有少數人會對這個問題感到困惑(“什麼是PHP?”)。 PHP被設計為一個「好的、容易的」腳本語言,初學者可以在很短的時間內學會使用它;它也應該能夠避免初學者犯下上面的錯誤。
再回到剛才的問題,上面的程式碼中存在的問題是你可以輕易地獲得存取的權力,而不需要提供正確的使用者名稱和口令。只在要你的瀏覽器的網址列的最後加上?authorized=1。因為PHP會自動地為每一個提交的值創建一個變數 -- 不論是來自動一個提交的表單、URL查詢字串還是一個cookie -- 這會將$authorized設定為1,這樣一個未授權的使用者也可以突破安全限制。
那麼,怎麼簡單地解決這個問題呢?只要在程式的開頭將$authorized預設為false。這個問題就不存在了! $authorized是一個完全在程式碼中建立的變數;但是為什麼開發者得為每個惡意的使用者提交的變數擔心呢?
PHP 4.2作了什麼改變?
在PHP 4.2中,新安裝的PHP中的register_globals選項預設為關閉,因此EGPCS值(EGPCS是Environment、Get、Post、Cookies、Server的縮寫 -- 這是PHP中外部變數來源的全部範圍)不會被當作全域變數來創建。當然,這個選項還可以透過手動來開啟,但PHP的開發者推薦你將其關閉。要貫徹他們的意圖,你需要使用其它的方法來取得這些值。
從PHP 4.1開始,EGPCS值就可以從一組指定的陣列中獲得:
$_ENV -- 包含系統環境變數
$_GET -- 包含查詢方法中的變量,以及提交方法字串為GET的表單中的變數
$_POST -- 包含提交方式為POST的表單中的變數
$_COOKIE -- 包含所有cookie變數
$_SERVER --@包含變數,例如所有cookie變數
$_SERVER ---包含變數,例如>$_REQUEST -- 包含$_GET、$_POST和$_COOKIE的全部內容
$_SESSION -- 包含所有已註冊的session變數 在PHP 4.1之前,當開發者關閉register_globals選項(這也被考慮在提高PHP性能的一種方法)後,必須使用諸如$HTTP_GET_VARS這樣的令人討厭的名字來獲取這些變數。這些新的變數名稱不僅短,而且它們還有其他優點。
首先,讓我們在PHP 4.2中(也就是說關閉register_globals 選項)重寫上面提到的程式碼:
$username = $_REQUEST['username'];
$username = $_REQUEST['username'];
$password = $_REQUEST['password'];
// 檢查使用者名稱及口令
if ($username == 'kevin and $password == 'secret')>
?>
Please enter username and password: