CGI教學(xué):CGI安全問題(最后3)
發(fā)布時間:2008-08-06 閱讀數(shù): 次 來源:網(wǎng)樂原科技
3 內(nèi)部傷害
到目前為止,僅僅考慮了通過Web例覽站點(diǎn)的人——從幾千里之外——可能帶來的潛在的安全危險。但實(shí)際上還存在另一種離得更近的危險因素。
在CGI安全問題上常犯的一種錯誤是忘記了本地用戶。盡管通過Web瀏覽站點(diǎn)的人不影響本地安全,如文件保護(hù)和所有者,但Web服務(wù)器的本地用戶卻能這樣,必須做出更多努力防止這些入侵。大部分多用戶系統(tǒng)上,如UNIX,Web服務(wù)器是作為一個程序運(yùn)行的,而機(jī)器仍被許多人使用做著許多事情。僅僅因為為某人與自己一起工作或訪問自己的學(xué)校并不意味著他能抵制住誘惑,而不去搗鼓Web安裝從而引起問題。
3.1 CGI腳本用戶
大部分Web服務(wù)器是作為運(yùn)行CGI腳本的特殊用戶而安裝的。這是在CGI程序運(yùn)行時擁有該CGI程序的用戶,并且他所擁有的權(quán)限能限制該腳本能做什么事情。
在UNIX下,服務(wù)器自己也是作為root(系統(tǒng)的超級用戶或管理員)運(yùn)行的,并允許它使用端口80作為瀏覽器與之通信的地方(只有root能使用這些被稱為"保留的"端口0到1023;所有用戶都可以使用其余的端口)。當(dāng)服務(wù)器執(zhí)行CGI程序時,大部分Web服務(wù)器都能設(shè)置為以另外一個用戶而不是Web服務(wù)器本身來運(yùn)行該程序——盡管不是所有服務(wù)器都能這么做。
將CGI腳本作為root運(yùn)行是很危險的!服務(wù)器應(yīng)被設(shè)為利用一個普通用戶,如常用的nobody來運(yùn)行CGI腳本。用戶權(quán)限越小,運(yùn)行的CGI腳本能造成的危害就越小。
3.2 Setuid 危險
編程者還應(yīng)知道自己的UNIX CGI腳本中是否設(shè)置Setuid位。如果對某個可執(zhí)行文件允許該選項,將能使該程序與擁有該文件的用戶有同樣權(quán)限,而不是執(zhí)行它的用戶。如果自己的CGI腳本上設(shè)置setuid位,無論服務(wù)器作為什么用戶來運(yùn)行它,它的權(quán)限都等同于該文件的擁有者。這當(dāng)然有很大的隱患--可能會對以其權(quán)限運(yùn)行腳本的用戶失去控制。幸運(yùn)的是Setuid位很容易被禁止。對所有CGI腳本執(zhí)行chmod a-s即能關(guān)閉所有的setuid,程序即能以允許的權(quán)限運(yùn)行。
當(dāng)然,在某些情況下也許希望設(shè)置setuid位--例如如果腳本需要以特殊用戶身份來運(yùn)行以訪問一個數(shù)據(jù)庫。在這種情況下,必須加倍小心確保該程序的其他文件保護(hù)能將可以訪問它的用戶限制在允許范圍內(nèi)。
3.3 "Community" Web服務(wù)器
即使Web服務(wù)器以一個常用的用戶來執(zhí)行腳本,仍有一個潛在的問題,那就是一個人并不總是能控制服務(wù)器。如果許多人共同控制服務(wù)器,每個人都可以將CGI腳本安裝作為nobody用戶來運(yùn)行。這就使這些人的任何一個都可以利用CGI程序訪問他們原先不能訪問的地方,而這些地方是nobody允許進(jìn)入的。
也許潛在的安全問題的解決辦法是將CGI的控制限制為一個人。在某些情況下盡管這似乎是合理的,但對較大站點(diǎn)卻經(jīng)常不太可能。例如,一個大學(xué)有幾百個學(xué)生,每個學(xué)生都想試著去編寫并安裝CGI腳本。
3.4 使用CGI Wrap
當(dāng)有多個用戶可以訪問CGI時,對于確定腳本以什么用戶運(yùn)行的問題的一個較好的解決辦法是CGI wrap程序。CGI Wrap,可以在using CGI Web站點(diǎn)中找到,是一個簡單的包裝,它以擁有該文件的用戶而不是服務(wù)器指定的用戶來運(yùn)行CGI腳本。這種簡單的預(yù)防措施使腳本擁有者對它可能的危害負(fù)責(zé)。
因為CGI wrap使得CGI腳本的作者負(fù)責(zé)他們自己的腳本權(quán)限,所以它不僅是一個保護(hù)其他人擁有的重要文件的有力的工具,而且是促使人們編寫安全的腳本的有力的工具。只有他們自己的文件會處于危險之中,這樣的現(xiàn)實(shí)對腳本作者會是極大的促進(jìn)。
3.5 CGI腳本權(quán)限
還應(yīng)該清楚了解CGI腳本被哪個用戶擁有以及腳本自身的文件權(quán)限。包含腳本的目錄的權(quán)限也非常重要。
例如,如果Web服務(wù)器上的cgi-bin目錄是所有人可寫的,那任何本地用戶將能刪除CGI腳本并用另一個來代替。如果腳本本身是所有人可寫的話,那么任何人將能修改腳本完成任何事情。
請看下面這段無害的UNIX CGI腳本:
#!/bin/sh
#Send the header
echo"Content-type:tex/html"
echo""
#Send some HTML
echo "<HTML><HEADER><TITLE>Fortune</1TLE><HEADER>
echo "<Body>Your fortune:<HR><PRE>
forune
echo"</BODY><HIML>"
現(xiàn)在,如果腳本上設(shè)置的權(quán)限允許某個惡意的用戶將程序改變?nèi)缦?
#!/bin/sh
#Send the header
echo "content-type:text/html"
echo""
#Do some damage!
rm-rf/
echo"<HTML><TITLE>Got you! <TITLE><BODY>"
echO"<H1>Ha ha!<H1></BODY></HTML>"
那么下一個在Web上訪問該腳本的用戶即使他沒做什么壞事也會導(dǎo)致大量問題。在Web上檢查用戶輸入的完整性很重要,但更重要的是保證腳本本身未被修改且不能被修改。
3.6 本地文件安全
腳本在本地硬盤上創(chuàng)建的文件的完整性也同樣重要。在得到Web用戶輸入的一個合理的文件名之后,使用該文件名干什么也很重要。根據(jù)Web服務(wù)器運(yùn)行的操作系統(tǒng),權(quán)限和擁有者信息可以與文件中的數(shù)據(jù)一起存在文件上。
例如,UNIX系統(tǒng)能記錄文件訪問權(quán)限,包括創(chuàng)建該文件的用戶的權(quán)限、同組用戶的權(quán)限、以及系統(tǒng)其他人的權(quán)限。windows NT使用的是一個更復(fù)雜訪問控制清單系統(tǒng),但完成的功能大致相同。根據(jù)這些標(biāo)志如設(shè)置以及授予或禁止什么權(quán)限,Web服務(wù)器機(jī)器的用戶也可能引起麻煩。
例如,在創(chuàng)建一個文件時就應(yīng)知道給它設(shè)置的權(quán)限。大部分Web服務(wù)器軟件將umask或權(quán)限碼設(shè)為0000,意味著可以創(chuàng)建一個任何人可讀寫的文件。盡管文件上的權(quán)限設(shè)置對在Web上瀏覽的人可能沒什么不同,但本地訪問的用戶卻能利用不嚴(yán)格的權(quán)限設(shè)置造成危害。基于這種現(xiàn)實(shí),應(yīng)該盡可能嚴(yán)格地限制文件權(quán)限。
保證每個打開文件的調(diào)用都有一個最小限制集合的最簡單的辦法是設(shè)置腳本的umask。umask()是一個UNIX調(diào)用,它能對每個后續(xù)的文件創(chuàng)建限制權(quán)限。umask()的參數(shù)是一個數(shù)字,用于對后續(xù)的文件創(chuàng)建的權(quán)限碼進(jìn)行屏蔽。如果umask為0022,則不管在打開文件時給組用戶和其他用戶賦予了什么顯式的權(quán)限,都將導(dǎo)致創(chuàng)建的文件僅能被用戶自己寫。即使已經(jīng)設(shè)置了umask,創(chuàng)建文件時也應(yīng)該顯式指定權(quán)限。如果只有CGI腳本能訪問文件,那么只有運(yùn)行CGI程序的用戶才能訪問該文件——權(quán)限為0600。如果另一個程序需要訪問該文件,可以使該程序的擁有者成為與CGI腳本同一組的用戶,這樣只需設(shè)置組用戶權(quán)限——權(quán)限為0660。如果必須讓所有人都能訪問該文件,應(yīng)使該文件只能讀,不能寫——權(quán)限為0644。
3.7 使用顯式路徑
最后,本地用戶還可以最后一種方式攻擊Web服務(wù)器——欺騙服務(wù)器運(yùn)行他寫的一個外部程序,而不是運(yùn)行在CGI腳本中指定的程序。下面是一個簡單的程序,從UNIX的fortune命令可以看出該瀏覽者還比較聰明。
#!/bin/sh
# Send the header
echo"conten_type:text/html"
echo""
#Send the fortune
echo"<HTML><HEADER><TITLE>Fortune</TITLE></HEADER><BODY>"
echo "<You crack open the cookie and the fortune reads:<HR><PRE>"
fortune
echo "</PRE><BODY></HTML>"
該腳本看起來可一點(diǎn)沒有害處。它不接收用戶輸入,所以用戶不能籍此搞什么把戲。因為它僅由Web服務(wù)器運(yùn)行,所以腳本本身的權(quán)限設(shè)置可以非常嚴(yán)格,可以防止任何有企圖的本地用戶修改它。如果對該腳本所在的目錄也設(shè)置了正確的權(quán)限的話,看起來就沒什么地方可以出問題了,是不是?
當(dāng)然還有問題。記住得要有點(diǎn)偏激。
上述程序清單調(diào)用了外部程序,在本例中是echo和fortune。因為這些腳本沒有用顯式路徑指明它們在硬盤上的位置,該shell即使用PATH環(huán)境變量來找到它們,從變量中的每一項查找要執(zhí)行的程序。這可能很危險。例如,如果fortune程序安裝在/usr/games中,但PATH中在它之前列出了/TMP,那么任何碰巧命名為"fortune"并位于臨時目錄的程序都會被執(zhí)行,而不是真正的fortune。
該程序可以做它的創(chuàng)建者想做的任何事情,可以刪除文件,也可以登記有關(guān)請求信息并將數(shù)據(jù)傳給真正的fortune——使用戶和編程者誰也不聰明。在CGI腳本中運(yùn)行外部程序時一定要指定顯式的路徑。PATH環(huán)境變量有很大作用,但它與其他變量一樣也能被非法使用.
4 使用他人CGI腳本時的注意事項
關(guān)于CGI,可以從很多地方獲得信息——從Internet上,從學(xué)校圖書館中,從像本書這樣的書中,UseNet組中以及朋友和同事中。從這些地方不僅可以獲得信息,還可以得到實(shí)際的程序和庫。有些程序和庫如果已經(jīng)有人做過了為什么自己還要從頭再做一遍呢?但就像不能盲目聽從別人的意見一樣,關(guān)于如何理財,如何駕車或者生活中的別的方面,同樣,也不能在自己的服務(wù)器上盲目地運(yùn)行另從的代碼。從Net上得到的腳本也可能真正是很好的腳本。但也許并不是?;ㄐr間考察一下腳本的來源以及獲取它的站點(diǎn)的可靠性是值得的。
4.1 追根求源
某些Web擁有者。如果不能看到并研究源代碼的話,他們甚至都不會運(yùn)行一個公共的、免費(fèi)的或商業(yè)性的腳本。這可能有點(diǎn)偏激。如果某個聲譽(yù)很好的公司銷售一個文檔詳細(xì)且廣為使用的腳本,該腳本應(yīng)該比自己寫的腳本更安全一些。原因有二。首先,專業(yè)人才知道并能避免一些常見的安全漏洞;其次,公司是為了嫌錢而做生意,如果他們以次充好或銷售那些惡意的產(chǎn)品就不能再做生意賺錢了。
從另一方面來看,如果UseNet組中看到一個編譯好的可執(zhí)行文件出自一個從沒聽說過的人,沒有什么文檔可以看,也沒有該程序的用戶可以交流交流,那么在將它放入自己的服務(wù)器之前一定要仔細(xì)考慮。也有可能這是來自一個像自己一樣的另一個CGI編程者的完全合法的貢獻(xiàn),目的是想讓全世界共享他的編程成果。但它也可能來自某個惡意的,具有變態(tài)幽默感的,只想看到自己能使多少人清盤的人。
在評價公共的免費(fèi)軟件或商業(yè)性軟件時,應(yīng)考慮下面這些方面:
該腳本來自一個聲譽(yù)好的站點(diǎn)嗎?該站點(diǎn)存在很長一段時間了嗎?它維護(hù)得好嗎?Web擁有者在發(fā)布文件前進(jìn)行檢查嗎?
有沒有足夠的文檔說明該程序如何工作以及用戶如何使用等信息?
有多少人已經(jīng)下載了該腳本?該站點(diǎn)愿意提供顧客名單嗎?(僅在有疑問時才去詢問;Web擁有者不會整天去回答這類問題。)
有人在UseNet上討論該腳本嗎?如果有,他們說好還是不好?如果沒人提到該腳本可以進(jìn)一步請求別人的見解。一般總會有人響應(yīng)的。
提示
在評價腳本時檢查下面這些useNet組: comp.security.announce,comp.securiy.unix,以及comp.infosystem.www.authority.cgi。另外還可以訪問位于ftp.cert.org的Computer
Emergency Response Team,以了解安全問題的歷史及有關(guān)工作以及安全保護(hù)的軟件。
5)該腳本的作者有沒有一些別的好名聲的腳本?
6)源代碼能得到嗎?免費(fèi)的或有價的都行。
7)該程序是不是過份宣傳它的能力?如果是,這可能是一個編程新手。
8)該站點(diǎn)自己運(yùn)行了該腳本嗎?如果沒有,為什么?能找到別的站點(diǎn)運(yùn)行該腳本嗎?過分偏激以及時間限制
盡管游覽取自Web的所有代碼是個好主意,但要花費(fèi)很多時間,特別是當(dāng)代碼比較復(fù)雜時更是如此。
例如,NCSA HTTPd就太大了,一般用戶不可能一行行去讀,但是從它的主站點(diǎn)http://www.ncsa.uiuc.edu下載它卻能保證極好的完整性,滿足任何用戶的需要。實(shí)際上,任何從NCSA下載的東西都是有保障的。
實(shí)際上,Web上的許多著名的站點(diǎn)已經(jīng)為用戶做了大部分的幾乎偏激的代碼檢查工作。從它閃中下載代碼是可能利用的另一層另一層保護(hù)。這些站點(diǎn)包括:
ftp://ftp.ncsa.uiuc.edu/Web/httpd/Unix/ncsa_httpd/cgi(the NCSA Archive)
http://www.novia.net/~geewhiz(Virtual Webwerx Division Zero-CGI Land)
http://www.lpage.com/cgi(the World-Famous Guestbook Server)
http://sweetbay.will.uiuc.edu/cgi++(cgi++)
http://www.aee.com/wdw(the Web Developers Warehouse)
4.2 注意禮貌
最后,如果確實(shí)希望從Web上下載一些CGI代碼,或者完整地使用它,或者用作自己編寫的更大程序的一部分,還應(yīng)了解一些事情。
代碼是兔費(fèi)的并不意味著可以自由地用它作自己想做的任何事情。通常程序和庫是禁止拷貝的,如果原始作者沒有放棄這個權(quán)力,他即能限制如何使用該程序。例如,作者可能禁止拆散該腳本,及禁止用作別的腳本的一部分。
一跟來說,在使用別人的代碼之前(即使已經(jīng)確定它是安全的),最好與作者進(jìn)行聯(lián)系取得許可。至少這樣做比較有禮貌。而大部分情況下,作者會很高興他的代碼能被別人利用。當(dāng)然,如果在自己程序某個片段處注明原始作者將是很禮貌的。