Username:
Password:
Remember Me?
CGI教学:CGI安全问题
< 上一篇
|
下一篇 >
来源:linux宝库作者:linux宝库 发布时间:2007-09-30 00:00:00
在电脑领域??尤其在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脚本送垃圾。该脚本设计得很好并且很安全,因为他忽略了不认识的输入。
Enter your name,first then last:
也许用户碰巧(或意识地)将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 }
这段代码假定因为表单仅提供了两个选项,而第一项未被选中,那么第二项就肯定被选中了。这不一定是真的。尽管前面的例子没有什么害处,但在某些情况下这样的假设可能很危险。
CGI脚本应该能预期这种情形而相应地进行处理。例如,假如出现一些非预期的或"不可能"的情形,能够打印一个错误,如下所述:
If ($form_Data{"radio_choice"} eq "button_one") {
#Button One seleted }
elsif ($form_Data{"radio_choice} eq "button_two") {
#Button Two Selected }
else {
#Error }
通过加入第二个if语句--显式检查"radio_choice"实际上是"button_two"--这样脚本更安全了;他不再做假设了。
当然,错误不一定是期望脚本在这些情形下生成的。有些脚本过于小心,验证每个字段,即使是最轻微的非预期数据都生成错误信息,这样往往很扫用户的兴。让CGI 脚本识别非预期数据然后扔掉他,并且自动选择一个缺省值也能够。
另一方面,脚本还可帮助用户纠正错误而不是简单地发一条错误消息或配置一个缺省值。假如表单需要用户输入机密文字,脚本应能在进行比较之前自动跳过输入中的空白字符。下面即是个完成此功能的Perl程式片段。
$user_input =~ s/\s//;
#Remove white space by replacing it with an empty string
if ($user_input eq $secret_Word) {
#Match! }
最后,能够更进一步,让CGI脚本能处理尽可能多的不同的输入表单。尽管不可能预期到可能发送给CGI程式的任何内容,但对某个特定方面一般经常有几种常用的方式,因而能够逐个检查。
例如,仅仅因为所写的表单使用POST方法向CGI脚本提交数据,并不意味着数据必须按那种方法进来。应该检查REQUEET_METHOD环境变量来确定是使用了GET还是POST方法并相应地读取数据,而不是假定数据都是来自预期的标准输入(stdin)。一个真正编写成功的CGI脚本能接收无论使用什么方法提交的数据并在处理过程中很安全。以下程式清单即是用Perl编写的一个例子。
程式清单 CGI_READ.PL 一个充满活力的读取格式输入的程式
#Takes the maximum length allowed as a parameter
#Returns 1 and the raw form data,or "0" and the error text
sub cgi_Read
{
local($input_Max)=1024 unless $input_Max=$_[0];
local($input_Method)=$ENV{’REOUEST_METHOO’);
#Check for each possible REQUEST_METHODS
if ($input_Method eq "GET") {
#"GET"
local($input_Size)=length($ENV{’QUERY_STRING’});
#Check the size of the input
if($input_Size>$input_Max) {
return(0,"input too big"); }
#Read the input from QUERY_STRING
return(1,$ENV{’QUERY_TRING’}); }
elsif ($input_Method eq "POST") {
#"POST"
local($input_Size)=$ENV{’CONTENT_LENGTH’};
local($input_Data);
#Check the size of the input
if ($input_Size>$input_Max) {
return(0,"Input too big"); }
#Read the input from stdin
unless (read(STDIN,$input_Data,$input_Size)) {
return(0,"Could not read STDIN"); }
return(1,$Input_Data);
}
#Unrecognized METHOD
return (0,"METHOD not GET POST");
}
总而言之,脚本应该不对接收的表单数据进行假设,应尽可能预计意料之外的情形并正确地处理不正确的或错误的输入数据。在使用数据之前应按尽可能多的方式测试他;拒绝不合理的输入并打印一条错误消息;假如某项出错或漏了应自动选择一个缺省值;甚至能够试图对输入进行编码以成为程式的合理的输入。选择哪种方式依赖于自己想花费多少时间和精力,但是记住永远也不要盲目接收传给CGI脚来的任何信息。
2.5不要相信路径数据
用户能修改的另一类型数据是PATH_INTO的服务器环境变量。该变量由CGI URL中紧跟在脚本文档名之后的任何路径信息填充的。例如,假如foobar.sh是个CGl shell脚本,那么当foobar.sh运行时,URL http://www.server.com/cgi-bin/foobar.sh/extra/path/info将导致 /extra/path/info被放进PATH_INFO环境变量中。
假如使用这个PATH_INFO环境变量,就必须小心地完全验证他的内容。就像表单数据能以许多种方式被修改相同,PATH_INFO也能够修改。盲目地根据PATH_INFO的中指定的路径文档进行操作的CGI脚本可能会让恶意的用户对服务器造成伤害。
例如,假如某个CGI脚来设计用于简单地打印出PATH_INFO中引用的文档,那么编辑该CGI URL的用户就能够读取机器上的几乎任何文档,如下所示:
#!/bin/sh
#Send the header
echo "Conext-type:text/html"
echo""
#Wrap the file in some HTML
#!/bin/sh
echo"
File
"
echo"Here is the file you requested:
\n"
cat $PATH_INFO
echo "
"
尽管在用户只单击预定义的链接(即http://www.server.com/cgi-bin/foobar.sh/public/faq.txt) 时,该脚本正常工作,但是个更有创造性的(或恶意的)用户可能会利用他接收服务器上的任何文档。假如他想进入http: //www.server.com/cgi-bin/foobar.sh/etc/passwd,前面的脚本会很高兴地返回机器的口令文档??这可是不希望发生的事。
另一种安全得多的方式是在可能时使用PATH_TRANSLATED环境变量。不是任何的服务器都支持该变量,所以脚本不能依赖于他。但是假如有的话,他能提供完全修饰的路径名,而不是像PATH_INFO提供的相对URL。
但是在某种情形下,假如在CGI脚本中使用PATH_TRANSLATED的话,则能够访问通过浏览器不能访问到的文档。应该知道这点及他的应用。
在大部分UNIX服务器上,htaccess文档能够位于文档树的每个子目录,负责控制谁能够访问该目录中的特别文档。例如他能够用于限制一组Web页面只给公司雇员看。
虽然服务器知道怎样解释.htaccess,从而知道怎样限制谁能还是不能看这些页面,CGI脚本却不知道。使用PATH_TRANSLATED访问文档树中任意文档的程式有可能碰巧覆盖了服务器提供的保护。
无论使用PATH_INFO还是PATH_TRANSLATED,另一个重要的步骤是验证路径以确保他或是个真正的相对路径或是脚本认可的几个准确的、预知的路径之一。对于预定的路径,脚本将简单地将提供的数据和认可能够使用的文档的内部清单进行比较,这就是说在增加文档或修改路径时必须重新编译脚本,但安全性却有了保障。只允计用户选择几个预定义的文档而不允许用户指定实际的路径和文档名。
下面是处理访问者提供的路径时应遵循的一些规则。
1)相对路径不以斜线开头。斜线意味着"相对于根"或绝对路径。假如有的话,CGI脚本也是很少需要访问Web根之外的数据。这样他们使用的路径就是相对于Web根目录,而不是绝对路径。应拒绝任何以斜线开始的内容。
2)在路径中单个点(.)和两个点(..)的序列也有特别含义。单点意味着对"对于当前目录",而双点意味着"相对于当前目录的父目录"。聪明的黑客能够建立象../../../etc/passwd这样的串逆向三层,然后向下进入/etc/passwd文档。应拒绝任何包含双点序列的内容。
3)基于NT服务器使用驱动器字母的概念来引用磁盘卷。包含对驱动器的引用的路径都以一个字母加上一个冒号开头。应拒绝任何以冒号为第二个字符的内容。
4)基于NT的服务器还支持Univesal Naming Conventions(UNC)引用。一个UNC文档规格指定机器名和一个共享点,其余部分和指定机器上的指定的共享点有关。UNC文档规格总是以两个反斜线开头。应拒绝任何UNC路径。
2.6一切看起来都正常,但是…
现在已知道了用户能给CGI脚本提供非预期的数据的几种方式连同怎样对付他们了,余下的更大问题是怎样验证用户提交的合法数据。
大部分情况下,正确但聪明地编写的表单提交会导致比越界数据更多的问题。忽略无意义的输入很容易,但确定合法的、正确格式的输入会不会导致问题就要困难得多。因为CGI脚本很灵活,几乎可做电脑能做的任何事情,所以安全面的一个很小失误往往能被无限制地加以利用??而这正是最危险的地方。
2.7 处理文档名
文档名是提交给CGI脚本的简单数据,但假如不小心的话,却能导致许多麻烦。假如用户输入的名字中包含路径因素,如目录斜杠和双点,尽管期望的是输入一个简单的文档名--例如file.txt--但结果却可能是/file.txt或../../../file.txt。根据Web服务器的安装连同对提交的文档名做什么操作,系统中的任何文档就有可能都暴露给了一个聪明的黑客。
进一步,假如用户输入了一个已有文档的名字或一个对系统的运行很重要的文档名,怎么办?对假如输入的名字是/etc/passwd或C:\WINNT\ SYSTEM32\KRNL32.DLL怎么办?根据在CGI脚本中对这些文档进行什么操作,他们有可能被发送给用户或被垃圾覆盖了。在Windows 95和Windows NT下,假如不检查反斜杠字符(\),可能会允许Web 浏览器通过UNC文档名访问甚至不在该Web机器上的文档。
假如用户在文档名中输入了不合法的字符怎么办?在UNIX下,任何以句点(.)开头的文档名都是不可见的。在Windows下斜杠(/)和反斜杠(\)都是目录分隔符。很可能不小心写了一个Perl程式,当文档名以管(pipe)(|)开头时,尽管自己以为仅仅是打开了一个文档,实际上却是执行了一个外部程式。假如用户知道怎么办的话,甚至能够把控制字符(例如Escape键或Return键)作为文档名的一部分送给脚本。
更坏的情况是,在shell脚本中,分号用于结束一条命令并开始另一条命令。假如脚本设计目的是cat用户输入的文档,用户可能输入file.txt;rm-rf/作为文档名,导致返回fi1e.txt,然后清除整个硬盘而不经任何确认。
2.8 输入合理,输出却不合理
为了避免任何这些问题,关闭由他们打开的任何安全缝隙,检查用户输入的每个文档名。必须确保输入正是程式预期的输入。
这样做的最好办法是将输入的文档名的每个字符和可接收字符的清单进行比较,假如不匹配就返回一个错误。这比维持一个任何合法字符的清单并比较他们要安全得多??要想让什么字符溜掉太容易了。
以下程式清单是用Perl怎样完成这种比较的例子。他允许任何字符字母(大写或小写调)、任何数字、下划线和句点。他还进行检查以确保文档名不以句点开头。这样,该段代码就不允许能够改变目录的斜杠,不允许能够将多条命令放在一行的分号,或破坏Perl的Open()调用的Pipes了。
程式清单 确保任何字符都是合法的
if (($file_Name =~ /[^a-zA-Z_\.]/) || ($file_Name =~ /^\./)) {
#File name contains an illegal characgter or starts with a period
}
警告
尽管上述程式清单中的代码清除了大部分不合法的文档名,但操作系可能更有一些限制,而该代码没有覆盖到。例如,文档名能够用数字开头吗?或以下划线开头?假如文档中包含多个句点或句点后多于三个字符怎么办?整个文档名足够短得能满足文档系统的限制吗?
必须不断向自己提出这种问题。在写CGI脚本时最危险的事是认为用户会遵守指令。其实用户是不会的。确保用户不犯错误是编程者自己的事。
2.9 处理HTML
另外一种看起来无害的但却能导致很大麻烦的输入是在请求用户输入文本信息时得到的HTML。以下的程式清单是个Perl程式片段;他向任何在$user_Name变量中输入了一个名字的人,例如John Smith,发出问候信息。
程式清单 发出定制的问候脚本
print ("
Greetings!
\n");
print ("Hello,$user_Name! It’s good to see you!\n");
print ("\n");
想像一下,假如用户不是仅仅输入一个名字,而是输入了
John Smith
或想像一下当脚本希望得到用户名时,黑客输入了
,结果是公开了本该保密的信息。允许输入HTML可能很危险。
比输入简单的HTML修改页面或访问画面更危险的是恶意的黑客可能输入一条服务器端的include指令。假如web服务器配置为听从服务器端include,用户就能够输入
而不是他的名字,以便看到秘密计划的全部文本,或用户能够输入来获取机器的口令文档。可能最坏的情况是黑客可能输入而不是他的名字。这样上述程式清单中的代码会删掉硬盘上几乎任何内容。
警告
由于经常被恶意地使用,服务器端的include经常被禁止使用以保护站点免受侵害。现在假定这些都没问题。即使关闭了服务器端的include并且不介意用户能看到自己硬盘上的任何图片或改变页面显示的外观,也仍然有问题--不但是针对编程者的,而且针对其他用户。
CGI脚本的一个通常用途是留名册(guestbook):访问站点的顾客可能签个名,让别人知道他们已在那儿了。一般情况下用户简单地输入他的名字,该名字会在访问者清单中出现。但是,假如将The last signee!
作为用户名输入怎么办?
标记将导致Web浏览器忽略位于
和一个不存在的
之间的任何内容,包括以后清单中加入的任何名字。即使有10个人签了名,仅有前3个会显示出来,因为第三个名字包含一个
和一个
标记。因为第三个签名者在他的名字中使用了 HTML标记,他后面的任何名字都不会显示出来。
对于用户输入HTML而不是普通的文本的情况有两种解决办法:
1)快速但比较粗糙的办法是不允许小于号(<)和大于号(>),因为任何HTML标记必须包含在这两个字符中,所以清除他们(或假如碰到他们就返回一个错误)是一种防止HTML被提交并返回的简单的办法。下面一行Perl代码简单地清除了这两个字符:$user_Input=~s/< >//g;
2)更精细一点的办法是将这两个字符转换成他们的HTML换码--?种特别的代码,用于表示每个字符而不使用该字符本身。下面的代码通过全部用<替换了小于符号,用>替换了大于符号,从而完成了转换:
$user_Input=~s/&1t;/g;
$user_Input=~s/>/>/g;
2.10 处理外部进程
最后,CGI脚本怎样和带有外部过程的用户输入打交道是应该警惕的另一区域。因为执行一个位于自己的CGI脚本之外的程式意味着无法控制他做什么,必须尽最大努力在执行开始前验证发送给他的输入。
例如,shell脚本经常错误地将一个命令行程式和表单输入合在一起执行。假如用户输入符合需要,一切都挺正常,但是有可能会加入其他命令并非法执行。
下面即是个产生了这种错误的脚本的例子:
FINGER_OUTPUT=’finger$USER_INPUT’
echo $FINGER_OUTPUT
假如用户很礼貌地给finger输入了某人的e-mail地址,一切都会正常工作,但是假如他输入了一个e-mail地址,后面再跟一个分号和另一条命令,那么该命令也会被执行,假如用户输入了webmaster@www.server.com;rm-rf/,那麻烦可就大了。
即使没有什么隐藏的命令被加入用户数据,无意的输入错误也可能带来麻烦。例如,下面的代码行会产生一个意料之外的结果??列出目录中的任何文档??假如用户输入是个星号的话。
echo "Your input:"$USER_INPUT
当通过shell发送用户数据时,就象前面的代码片段所做的那样,最好检查一下shell的meta-character(元字符)??这些可能会导致意外的行为。
这些字符包括分号(允许一行中有多条命令),星号和问号(完成文档匹配),感叹号(在csh下指运行的作业),单引号(执行一条包含其中的命令)等等。就像过滤文档名相同,维护一个允许的字符清单一般要比试图找出每个不允许的字符容易一些。下面的Perl代码片段验证一个e-mail地址:
if ($email_Address ~= /[^a-zA-z0-9_\-\+\@\.]) {
#lllegal character! }
else { system("finger $email_Address"); }
假如决定在输入中允许shell元字符,也有办法让他们安全一些。尽管能够简单地给未验证的用户输入加上引号以免shell按特别字符进行操作,但这实际上不起什么作用。请看下的语句:
echo"Finger information:
"
finger"$USER_INPUT
echo"
尽管$USER_INPUT上的引号能够使shell不再解释一个分号,从而不允许黑客简单地插进来一条命令,但该脚本仍有许多安全面的漏洞。例如,输入可能是’rm-rf/’,其中单引号能够导致甚至在finger不知道的情况下执行黑客的命令。
一种处理特别字符的较好的办法是对他们进行换码,这样脚本只是取他们的值而不解释他们。通过对用户输入进行换码,任何的shell元字符都被忽略并作为增加的数据传给程式。下面的Perl代码即对非字母数字字符完成这种处理。
$user_Input=~s/([^w])/\\\1/g;
现在,假如用户输入加在某条命令之后,每个字符??即便是特别字符??都会由shell传送给finger。
但是请记住,验证用户输入??不相信发送给自己的任何信息??会使自己的代码更易读并且执行起来更安全。最好不是在已执行了命令之后再去对付黑客,而应在门口就对数据进行一次性的检查。
--------------------------------------------
处理内部函数
对于解释型语言,例如Shell和Perl,假如用户输入的数据不正确的话,有可能导致程式生成本来没有的错误。假如用户数据被解释为一部分执行代码,用户输入的任何内容都必须符合语言的规则,否则就会出错。
例如,下面的Perl代码片段也许会正常工作也许会产生错误,这取决于用户输入的是什么:
if ($search_Text =~ /$user_Pattern/) {
#Match! }
假如$user_Pattern是个正确的表达式,一切都会正常,但是假如$user_Pattern不合法;Perl就会失败,导致CGI程式失败 ??这可能是一种不安全的方式。为了避免这种情况,在Perl中至少应有eval()操作符,他计算表达式的值并和执行他无关,返回一个码值表示表达式是有效的还是无效的。下面的代码即是前面代码的改进版。
if (eval{$search_Text =~ /$user_Pattern
喜欢本文,那就收藏到:
上一篇:
CGI教学:CGI常用环境变量
下一篇:
CGI教学:第一章cgilib例
相关评论
我也要评论
还没有关于此文章的相关评论!
首页
上一页
下一页
尾页
昵称:
(为空则显示guest)
评论分数:
★
★ ★
★★★
★★★★
★★★★★
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
相关推荐
xml轻松学习手册(3)xml的术语_xml教程
xml轻松学习手册(4)xml语法_xml教程
xml轻松学习手册(5)xml实例解析_xml教程
了解web页面工具语言xml(一)产生背景_xml教程
了解web页面工具语言xml(二)定义_xml教程
了解web页面工具语言xml(三)支持工具_xml教程
了解web页面工具语言xml(四)应用分类_xml教程
了解web页面工具语言xml(五)好处_xml教程
了解web页面工具语言xml(六)展望_xml教程
xml技术上传文档_xml技巧
相关资讯
各种平台下Perl模块的安装方法
Perl/TkFAQ-11.3.怎样在画布中显示图片?
Perl/TkFAQ-11.4在画布组件中能够创建哪些元件?
Perl/TkFAQ-11.5.怎样调整画布中线条的位置?
Perl/TkFAQ-12.4变量必须申明为“my”吗?
Perl/TkFAQ-12.3引号的作用怎样?
Perl/TkFAQ-12.2和符号(&)是干什么用的?
Perl/TkFAQ-12.1.符号->,=>和::分别表示什么意思?
Perl/TkFAQ-12.基本问题
Perl/TkFAQ-11.10.怎样给画布的不同区域配置不同的绑定?
点击发布文章
导航
主页
设为首页
加入收藏
联系我们
赞助商
文章类别
行业资讯
域名资讯
虚拟主机
托管租用
VPS
CDN
网站运营
技术资讯
Mac OS
网络设备
路由技术
网络技术
HTML/DHTML
源码天堂
网络编程
Java
Perl
C/C++
Shell
数据库其他
DB2
Sybase
存储备份
硬件技术
网站建设
通信技术
虚拟化技术
安全其他
安全工具
加密和破解
数据库安全
程序安全
网络安全
系统安全
防火墙
VPN
网管技术其他
Informix
Oracle
PostgreSQL
Dreamweaver教程
windows操作系统
XML编程
NET编程
JSP编程
PHP编程
ASP编程
Mssql
Mysql
Access
Coreldraw
flash
web服务器
ftp服务器
mail服务器
邮件系统
IBM-AIX
HP-UX
Sco
Solaris
FreeBSD
Linux
Proxy
CSS教程
Javascript教程
Ajax
dns服务器
Photoshop教程
站长资讯
冲浪宝典
帮助中心
首页新闻
其它相关问题
安全漏洞相关问题
网站推广相关问题
虚拟主机相关问题
网站建设相关问题
服务器相关问题
备案相关问题
支付相关问题
后台操作指南
代理相关问题
邮件相关问题
域名相关问题
vps相关问题
行业资讯
名网动态
新手指南
代理帮助
订阅
Rss Feed
主机赞助商连接:
华夏名网虚拟主机域名注册
关于我们 | 网站声明 | 联系我们 | 广告服务 IDC中文资讯站-客观公证的IDC产业权威媒体
Copyright
@
2007-2008 IDCNEWS.NET, All Rights Reserved
蜀ICP备07504800号