萬盛學電腦網

 萬盛學電腦網 >> 應用技巧 >> Web服務器的安全和攻擊防范(二)

Web服務器的安全和攻擊防范(二)

可以看到,www.example.server的sunrpc服務開放了對外部機器的連接。這是沒有必要的,我們可以安裝帶有訪問控制的rpcbind程序或者配置防火牆阻斷它。   
由於NFS默認值極不合理,把文件系統完全不受保護地以可讀寫方式顯露給外界就成了一種極為常見的錯誤。下面是一個實例:
# /usr/sbin/kshowmount -e center2.sample-university.net
Export list for center2.sample-university.net:
/usr/lib/cobol (everyone)
/usr/sys/inst.images (everyone)
/stadtinf (everyone)
/var/spool/mail (everyone)
/usr/lpp/info (everyone)
/usr/local (everyone)
/pd-software (everyone)
/u1 (everyone)
/user (everyone)
/fix (everyone)
/u (everyone)
/ora rzws01
/install (everyone)
/ora-client 192.168.15.20

所有注明了“everyone”的目錄都是向公眾開放的,其中包括:保存了數百個用戶郵件的“/var/spool/mail”目錄,以及用戶的主目錄“/u”和“/u1”。另外“/usr/local”和“/usr/lib/cobol”也是允許寫入的,這使得它很容易被安裝上特洛伊木馬。任何人都可以進入這個系統,且不會遇到什麼值得一提的阻力。 我們要討論的第二類安全問題涉及到服務器公用目錄下的私有數據。許多Web空間提供商提供的只有“Web空間”,它們會把用戶FTP目錄的根映射到Web服務器的根。也就是說,用戶可以通過FTP以“/”訪問服務器目錄“/home/www/servers/www.customer.com/”,同時任何人可以通過URL“http://www.customer.com/”訪問它,用FTP方式保存的“/password”文件可以通過URL“http://www.customer.com/password”訪問。如果用戶Web應用需要保存一些私有的、不能從Web訪問的數據,則根本無法找到滿足要求的位置。

許多Web商店把訂單日志和調試輸出寫入一個或多個日志文件,或者用配置文件來保存密碼和商品數據。如果這些數據保存到頁面文檔根目錄之下,那麼它們就有相應的URL而且可以通過Web訪問。此時攻擊者所要做的只是猜出這些文件的名字。只要了解了20種主流在線商店系統的默認設置並正確地識別出目標網站所用的系統,要猜出這些文件名字是相當簡單的。   

如果Web服務器既提供私有數據存儲又提供公用頁面目錄,上述問題就不會再出現。例如在這些方案中,FTP根目錄“/”映射到“/home/www/servers/www.customer.com/”,但頁面文檔的根目錄卻在它的下一級目錄“/home/www/servers/www.customer.com/pages”,可以通過FTP以“/pages”形式訪問。在這種目錄配置下,用戶可以另外創建和頁面文檔根目錄平行的目錄,然後把敏感數據放到這些目錄中。由於這些目錄可以通過FTP訪問,但不能通過HTTP訪問,所以它們是無法通過Web訪問的。   

如果系統沒有采用上述根目錄分離的目錄結構,我們還有一種解決問題的辦法,即在頁面文檔根目錄下創建專用的私有數據存儲目錄,如“/shop”,然後在這個目錄中創建.htaccess文件,通過.htaccess文件拒絕所有HTTP訪問(適用於Apache服務器):
$ cat /shop/.htaccess order deny, allow deny from all

該目錄中的文件只能通過FTP傳輸,因為FTP傳輸忽略.htaccess文件。但與前面采用頁面文檔根目錄之外獨立目錄的方法相比,這種方法的風險更多一點,因為如果服務器管理員在服務器主配置文件中意外地關閉了該目錄必不可少的“AllowOverride Limit”優先權,這種保護將不再有效。

上述問題還有各種變化形式。如果一台機器上運行著多個客戶網站,那麼客戶就能夠欺騙機器,訪問在其自己目錄層次之外的路徑,例如“/home/www/servers/www.customer.com”目錄之外的文件。通常,只需創建各種符號鏈接(指向保存在用戶虛擬服務器之外的文件)就有可能實現這一點。最有可能成為鏈接目標的是包含文件和私有密匙,這是為了獲取數據庫密碼和其他必須保密的信息(為了讓應用能夠正常運行這些信息往往以明文形式保存在這類文件中)。其他可能的攻擊目標還包括保存在非公用目錄中的訂單記錄和其他有用數據。

把盡可能多的服務隔離運行可以部分地解決這個問題,例如用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值,所有其他值都必須進行檢查。

下面這個簡單的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.0
Host: valiant.koehntopp.de
Referer: http://www.attacker.com/die_sucker_die.html
下面是完整的會話過程:
kris@valiant:~/www < telnet valiant 80
Trying 193.102.57.3...
Connected to valiant.koehntopp.de.
Escape character is '^]'.
GET /~kris/test.php?b=this+is+a+test HTTP/1.0
Host: valiant.koehntopp.de
Referer: http://www.attacker.com/die_sucker_die.html
HTTP/1.1 200 OK
Date: Sat, 08 Apr 2000 06:44:02 GMT
Server: Apache/1.3.9 (Unix) (SuSE/Linux) PHP/4.0RC2-dev mod_ssl/2.4.7 OpenSSL/0.9.4
X-Powered-By: PHP/4.0RC2-dev
Connection: close
Content-Type: text/html
The value of b is this is a test
The value of HTTP_REFERER is http://www.attacker.com/die_sucker_die.html
Connection closed by foreign host.   
注意b的值必須以URL編碼格式輸入。要將字符串進行URL編碼,可使用一個簡單的PHP程序,例如:
kris@valiant:~/www < cat urlencode.php
#! /home/kris/bin/php -q
< ?php
print urlencode($argv[1])."n";
? >
kris@valiant:~/www < ./urlencode.php "this is a test"
this+is+a+test
發送HTTP POST請求只是稍微復雜一點:現在應該在這個請求中包含一個合法的Content-Type頭以及正確的內容長度字節數。下面是具體過程:
kris@valiant:~/www < telnet valiant 80
Trying 193.102.57.3...
Connected to valiant.koehntopp.de.
Escape character is '^]'.
POST /~kris/test.php HTTP/1.0
Host: valiant.koehntopp.de
Referer: http://www.attacker.com/die_sucker_die.html
Content-Type: application/x-www-form-urlencoded
Content-Length: 16
b=this+is+a+test
HTTP/1.1 200 OK
Date: Sat, 08 Apr 2000 06:55:11 GMT
Server: Apache/1.3.9 (Unix) (SuSE/Linux) PHP/4.0RC2-dev
mod_ssl/2.4.7 OpenSSL/0.9.4
X-Powered-By: PHP/4.0RC2-dev
Connection: close
Content-Type: text/html
The value of b is this is a test
The value of HTTP_REFERER is
http://www.attacker.com/die_sucker_die.html
Connection closed by foreign host.
另外一種常見的錯誤是把內部應用的狀態數據通過< INPUT TYPE="HIDDEN" >標記從一個頁面傳遞到另一個頁面。把內部應用的狀態放到信任界限之外就如把應用的心髒挖出來放到了攻擊者的面前。對於如此缺乏安全保障的應用,任何想要摧毀它的攻擊者都可以輕易地引導該應用並得到任何想要的效果。應用的狀態應該通過會話變量保存在服務器上,永遠不應該跨越信任界限。所有的We
copyright © 萬盛學電腦網 all rights reserved