把盡可能多的服務隔離運行可以部分地解決這個問題,例如用Apache suexec程序的sbox讓所有的CGI在隔離的環境以客戶的用戶ID而不是Web服務器的用戶ID運行。另外,許多服務器上運行著FTP服務,例如wu-ftpd,該服務的所有文件傳輸都是隔離進行的,同樣也保護了善意客戶的資料避免被其他人偷看。
然而,惡意的客戶仍舊能夠用CGI程序創建符號鏈接指向其他用戶的存儲區域,然后通過它自己的Web服務器查看其他人的文件,這是因為在一個運行多個網站的環境中,Web服務器無法簡單地以隔離方式以及用它為之應答請求的客戶的用戶ID運行。管理員應該配置Web服務器以及其他文件傳輸程序使其不再使用符號鏈接。在Apache上,這可以通過關閉最頂層的“FollowSymLinks”選項實現(不要在較低的層次上把它重新打開),配置代碼示例如下:
< directory / >Options -FollowSymLinks< /directory >
|
數據源的可靠性
第三類常見的安全問題是CGI程序或PHP腳本的質量低下,它們信任了來源不可靠的參數,未經嚴格的檢查就立即使用CGI參數。
Web應用一般包含位于防火墻之內的和防火墻之外的兩部分,防火墻之內的如本地的腳本程序、數據庫、Web服務器以及本地數據文件等。由于這些部件都由管理員直接管理和控制,因此可以認為它們都是可以信任的。Web應用的其他組成部分位于防火墻之外,是不可信任的。這主要是指用戶的瀏覽器——如果用戶使用瀏覽器,而且沒有為了更方便地控制輸入Web應用的數據和發現Web應用中可能存在的問題而直接在telnet會話中輸入Web請求。
防火墻是可信任的Intranet和不可信任的Internet之間的分界線。
所有來自信任分界線之外的數據未經檢查就不應該進入Web應用,這包括所有傳遞給CGI腳本的參數,比如:GET、POST和COOKIE變量,HTTP_REFERER、HTTP_USER_AGENT和所有HTTP_*變量,以及所有其他遠程生成的變量值。在CGI腳本使用所有這些變量之前,都必須對它們進行合法性檢查,這種檢查可以確保變量的值確實在預期的范圍內。
例如,有些腳本在請求的HTTP_REFERER正確時就接受表單輸入,這是一種常見但錯誤的編程習慣。腳本用這種機制來防范偽造的請求是徒勞的。毫無疑問,對于攻擊者來說,掌握必需的HTTP_REFERER并將它并入請求的其余部分一起發送是輕而易舉的,因此這種保護是沒有用的。這種腳本的錯誤在于:在這類調用中必須檢查的不僅僅是HTTP_REFERER值,所有其他值都必須進行檢查。[page]
偽造Web請求(一)
下面這個簡單的PHP程序將輸出CGI參數b的值以及HTTP_REFERER的值:
kris@valiant:~/www < cat test.php< ?php print "The value of b is $bn"; print "The value of HTTP_REFERER is $HTTP_REFERERn";? >
|
用telnet連接到80端口,我們能夠向上述腳本提供任意的參數值b,同時還可以任意提供HTTP_REFERER值。我們把下面的幾行發送到服務器:
GET /~kris/test.php?b=this+is+a+test HTTP/1.0Host: valiant.koehntopp.deReferer: http://www.attacker.com/die_sucker_die.html
|
下面是完整的會話過程:
kris@valiant:~/www < telnet valiant 80Trying 193.102.57.3...Connected to valiant.koehntopp.de.Escape character is '^]'.GET /~kris/test.php?b=this+is+a+test HTTP/1.0Host: valiant.koehntopp.deReferer: http://www.attacker.com/die_sucker_die.htmlHTTP/1.1 200 OKDate: Sat, 08 Apr 2000 06:44:02 GMTServer: Apache/1.3.9 (Unix) (SuSE/Linux) PHP/4.0RC2-dev mod_ssl/2.4.7 OpenSSL/0.9.4X-Powered-By: PHP/4.0RC2-devConnection: closeContent-Type: text/htmlThe value of b is this is a testThe value of HTTP_REFERER is http://www.attacker.com/die_sucker_die.htmlConnection closed by foreign host.
|