章 29. 使用 Register Globals可能 PHP 中最具爭議的變化就是從 PHP 4.2.0 版開始配置檔中 register_globals 的預設值從 on 改為 off 了。對此選項的依賴是如此普遍以至於很多人根本不知道它的存在而以為 PHP 本來就是這麼工作的。本節會解釋用這個指令如何寫出不安全的代碼,但要知道這個指令本身沒有不安全的地方,誤用才會。 當 register_globals 開啟以後,各種變量都被注入代碼,例如來自 HTML 表單的請求變量。再加上 PHP 在使用變量之前是無需進行起始化的,這就使得更容易寫出不安全的代碼。這是個很艱難的抉擇,但 PHP 社區還是決定預設關閉此選項。當開啟時,人們使用變量時確實不知道變量是哪裡來的,只能想當然。但是 register_globals 的關閉改變了這種代碼內定變量和用戶端傳送的變量混雜在一起的糟糕情況。下面舉一個錯誤使用 register_globals 的例子:
當 register_globals = on 的時候,上面的代碼就會有危險了。若果是 off,$authorized 就不能通過如 URL 請求等模式來改變,這樣就好多了,儘管起始化變量是一個良好的寫程式習慣。比如說,若果在上面的代碼執行之前加入 $authorized = false 的話,無論 register_globals 是 on 還是 off 都可以,因為會員狀態被起始化為未經認證。 另一個例子是關於會話的。當 register_globals = on 的時候,$username 也可以用在下面的代碼中,但要意識到 $username 也可能會從其它途徑進來,比如說通過 URL 的 GET。
採取相應的預防措施以便在偽造變量輸入的時候給予警示是完全有可能的。若果事先確切知道變量是哪裡來的,就可以檢查所送出的資料是否是永遠不正當的表單送出而來。不過這不能保證變量未被偽造,這需要攻擊者去猜測應該怎樣去偽造。若果不在乎請求資料來源的話,可以使用 $_REQUEST 陣列,它內含了 GET、POST 和 COOKIE 的所有資料。明細可參見本手冊的來自 PHP 之外的變量。
當然,單純地關閉 register_globals 並不代表所有的代碼都安全了。對於每一段送出上來的資料,都要對其進行具體的檢查。永遠要驗證會員資料和對變量進行起始化!把 error_reporting() 設為 E_NOTICE 層級可以檢查未起始化的變量。 更多關於模擬 register_globals 為 on 或 off 的訊息,請見此 FAQ。
| |||||