CGI 安全问题

CGI脚本的安全问题主要源于与用户的交互和外部数据的处理。文章强调了不要盲目信任表单数据和路径信息,因为用户可以以多种方式篡改输入,可能导致系统漏洞。编写安全的CGI脚本需要限制接收数据的长度,验证输入格式,避免执行意外的外部程序,并确保文件和脚本的权限设置恰当。此外,使用CGI Wrap等工具可以提高安全性,而使用他人CGI脚本时应追根溯源,确保代码来源可靠。
摘要由CSDN通过智能技术生成

在计算机领域——尤其在Internet上——尽管大部分Web服务器所编的程序都尽可能保护自己的内容不受侵害,但只要CGI脚本中有一点安全方面的失误--口令文件、私有数据、以及任何东西,就能使入侵者能访问计算机。遵循一些简单的规则并保持警惕能使自己的CGI脚本免受侵害,从而可以保护自己的权益。 

1. 脚本和程序 

在开始决定采用何种语言编写CGI脚本时应考虑几个因素,其中之一应是安全性。Shell 脚本,Perl程序和C可执行程序是CGI脚本最常采用的形式,从安全性角度来说每种都备有优缺。尽管没有哪一种是最好的--基于其他方面的考虑,如速度和可重用性--每种都有实用的领域。 

Shell脚本一般用于小的、快速的甚至可以用完就不要的CGI程序,因此,编写它们时常常不考虑安全性。这种疏忽可以导致一些缺陷,使得仅对系统具有一般知识的人也能进入系统任意走动。 

尽管Shell CGI 程序最容易写,甚至只需拼凑一下即可,但控制它们却很困难,因为它们一般是通过执行外部的其他程序来完成工作的。这就导致一些可能的隐患,CGI 程序会继承任何它使用的程序的安全问题。 

例如,常用UNIX实用程序 awk对于它能处理的数据的数量有一些相当严格限制。如果在CGI脚本中使用awk,那么该程序也就有了同样的限制。Perl比Shell脚本更进一步。Perl用于CGI编程有很多优点,并且相当安全。但Perl能给CGI 作者提供足够的灵活性从而导致对安全性的错误感觉。例如,Perl是解释型的。这意味着它实际在调用时是先编译,然后每次执行一步。这就很容易使得不正确的用户数据被包括进来作为代码的一部分,从而错误地进行解释,形成程序中止原因。 

最后谈谈C。C迅速成为标准应用开发语言,几乎所有的UNIX和windows NT系统都是用它开发的。从安全性的角度来看C 似乎是很不错,但由于它的流行性,它的好几种安全性问题已广为人知,而这些问题也能很容易地被人利用。 

例如,C 对串处理非常差。它不做任何自动的定位或清理而让编程者自己处理所有事情。在处理串时,大部分C 程序员都是简单地建立一个预定义的空间并希望它足够大以便处理用户输入的任何内容。 

当然,Shell脚本、Perl和C 不是仅有的编写CGI脚本语言。实际上,任何可以按预定义的方式与Web服务器进行交互的计算机语言都可以用于编写CGI程序。在UNIX和Windows NT服务器上,数据是通过环境变量和标准输入(stdin) 传给脚本的,所以任何能从这两种数据源读取并写入标准输出(sidout)的语言都能用于创建CGI:awk、FORTRAN、C++、Basic和COBOL,等。windows的程序员可以使用流行的Visual Basic,这意味着有经验的VB程序员不必去学一门新语言。Macintosh使用AppleEvents、和AppleScript与CGI程序进行通信,所以任何可以读写这两者的语言都可使用。 

不过,Shell脚本(不管使用那种Shell)、Perl和C仍是最流行为的编写CGI脚本的语言。这并不是说必须使用它们了;只是说大部程序的库——即大部分经过测试的安全的库——都是用这三种语言编写的。如果自己来选择CGI编程语言,最好是借鉴前人的经验。 

2. 谁也不信 

几乎所有的CGI 安全问题都来自与用户的交互。接收来自外部数据源的输入之后一个简单的、可预见的CGI程序突然向多方向伸展,每个方面都可能有最小的缝隙使得“黑客”可以溜进来。正是与用户的这种交互——通过表单或文件路径——才给予了CGI 脚本这种能力,但同时也使得它们成了运行在Web服务器上的最潜在的危险部分。 

编写安全的CGI 脚本很大程度上是创造性和妄想的结合。编写者必须有足够的创造性才能想到用户使用的,不管是无意地还是别的所有的可能隐含导致问题的发送数据的方式。而且必须有点妄想,因为有可能不知道什么时候、什么地方、他们将会一一加以试验。 

2.1 两种导致问题的方式 

当用户登录进入Web 站点并开始进行交互访问时,他们能以两种方式惹麻烦。一种是不遵守规则,歪曲或违反页面中建立的每个限制或约束;另一种方式是按要求去做。 

大部分CGI 脚本是作为HTML表单的后台运行的,负责处理由用户输入的信息并提供某种定制的输出。因为在这种情况下,大部分CGI 脚本编写时都等待某种特殊格式的数据。它们期望用户的输入能匹配收集并发送信息的表单。不过事情并不总是这样。用户可以有许多种办法绕过这些预定义的格式而给脚本发送一些看起来是随机的数据。CGI 程序必须对此有所准备。 

其次,用户可以给CGI 脚本发送所期望的数据类型,按预期的形式在表单中填入每个字段。这种类型的提交可以是想像中的来自某个与站点交互的无意的用户,也可能来自某个恶意的“黑客”,凭借他有关操作系统和Web 服务器软件的知识并利用常见的编程错误。这些入侵,表面上一切都正常,却是最危险的、最难检测出来。Web 站点安全性依赖干这种入侵的防止。 

2.2 不要相信表单数据 

在CGI 编程中最常见的安全失误就是相信从表单传到脚本的数据,用户是未知的一大堆人,他们总能找到一些编程人员从来没想到过的发送数据的方法--而且是程序员认为几乎不可能的方法。 

脚本必须对这些加以考虑。例如,下面这些情形都是可能的: 

1)从一组单单选按钮中选择的结果可能不是表单中提供的选项之一。 

2)来自某个文本字段的数据长度可能大于MAXLENGTH字段允许的长度。 

3)字段本身的名字可能与表单中指定的不相符。 

2.3 不合理数据的来源 


因—些无意的或是有意的原因,导致自己的脚本接收到不知道如何去处理的数据,有可能导致非预期的——同时很危险的——行为。 

下面的代码实现了一种表单并向某个搜索yahoo!数据库的CGI脚本送垃圾。该脚本设计得很好并且很安全,因为它忽略了不认识的输入。 

<FORM METHOD="POST" ACTION="http://search.yahoo.com/bin/search"> 
Enter your name,first then last: 
<INPUT TYPE="TEXT" NAME="first"> 
<INPUT TYPE="TEXT" NAME="last"> 
</FORM 

也许用户碰巧(或者意识地)将URL编辑为这个CGI脚本。当浏览器向CGI程序提交数据时,要简单地将输入表单中的数据连到CGI的URL上(用于GET METHODS),就像用户可以很容易地将Web页面地址输入到他的浏览器一样,用户也可以自己修改发送给这个脚本的数据。 

例如,当单击表单上的Submit按钮时,Netscape将一个长串字符放入Location字段,该串由CGI的URL后接一串数据组成,大部分看起来像表单中定义的NAMES和VALUES。如果愿意的话,可以自由地编辑Location字段的内容并按自己的意愿修改数据:增加表单中没有的字段,扩展由MAXLENGTH选项限制的文本数据,或者几乎任何对象。以下显示了某CGI脚本预期从表单中提交的URL。 

http://www.altavista.digit.com/cgi-bin?pg=q&what=web&imt=&q=%22An+Entirely+Other%22 

用户可以修改同一URL,CGI脚本仍被调用,但现在接收的是非预期的数据。为了保证安全,该脚本应该在编写时就设计为能将这种输入识别为不被要求的数据并加以拒绝。 

最后,某个有野心的"黑客"也许会写一个程序连到Web上的服务器并假装是一个Web浏览器。该程序可能做一些任何一个真正的web浏览器从未做过的事,例如给CGI脚本发送成百兆字节的数据。如果CGI脚本不限制从POST METHOD读取数据,那怎么办?它有可能会崩溃,也许允许那个崩溃了系统的人访问系统。 

2.4 拒绝不合要求的表单数据 

CGI脚本可以有几种方式拒绝接收提交给它的非预期的输入。编写CGI时应该使用其中一些技巧或所有这些技巧。 

首先,CGI 脚本应设置接收多少数据的限制,不仅限制整个提交,也限制提交中的每个NAME/VALUE对。例如,CGI脚本读取POST METHOD,检查CONTENT-LENGTH环境变量的大小来确定某输入是不是合理的预期输入。
如果CGI 脚本设计接收的唯一数据是某人的姓名,那么如果CONTENT-LENGTH大于100字节,就应该有理由返回一个错误。没有哪个合理的姓有那么长,通过设置限制,就能使脚本不再盲目地读取发送给它的内容。 

注意 

令人高兴的是,不必担心去限制通过POST方法提交的数据。GET是自限制的并且不会向脚本发送多于1KB的数据。服务器自动限制放人QUERY-STRING环境变量中的数据的大小,而这正是GET发送给CGI程序的信息。 

当然,"黑客"们可以很容易地将表单由GET改为PUT从而绕过这种内置的限制。至少,程序应该检查一下数据是否是用预期的方法提交的;最好是能正确且安全地处理两种方法。 

下一步,应保证脚本知道在接收到不能识别的数据时该怎么办,例如,如果某表单要求用户选择两个单选按钮之一,脚本就不应该假设因为一个按钮未被选择,另一个就一定被选择了。下面的Perl代码就犯了这样的错误: 

if ($form_Data{"radio_choice"} eq "button_one"){ 
# Button One has been clicked } 
else { 
# Button Two has been clicked } 

这段代码假定因为表单仅提供了两个选项,而第一项未被选中,那么第二项就肯定被选中了。这不一定是真的。尽管前面的例子没有什么害处,但在某些情况下这样的假设可能很危险。 

CG

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值