最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

执行CGI脚本的安全上下代码

IT圈 admin 21浏览 0评论

2024年7月17日发(作者:长初)

执行CGI脚本的安全上下代码

一、注意对变量的处理

1、用户的输入是不可信任的,当谈到安全编程的时候,比尔盖茨先生对他的员

工说了一句非常经典的话:All input is invalid.(所有的用户输入都是有害

的,具体是不是他第一个说的,有待考察)

一切用户输入的地方都是我们应当注意的地方。来看一段代码吧:

-----------Code Start------------

#

01 $filepath="f://myhome//bbs//"

......

......

13 $filename=$query -> param(''page'');

14 if ($filename eq "")

15 { $filename="";

16 die("对不起,文件名不能为空!");

17 }

18 else{

19 $filename="$filepath/".$filename;

20 open(FILE,$filename);

21 while()

22 {

23 print $_;

24 }

25 close(FILE)

......

-----------Code Ends-------------

这段代码基本上没有作太多改动,因为我演示是在自己的机子上,所以把

路径改了一下,我们在这里回放一下曾经的过程。

这里的$filename用param提取page中用户输入的内容,$filename其

实是用户间接输入的内容,而代码对$filename并没有做严格的审查只是检查

是否为空,如果恶意用户直接在浏览器中指定其他文件,如cgi,asp或者任何

文件,则返回的是文件的源代码,如:看到的源代码了,通过

简单的浏览其他的页面,我们可以基本上可以得到所有文件的源代码。我们也

可以通过"../"来切换到其他的目录下。

这还不是最糟糕的,如果你的系统是Linux或者UNIX,那么更过分的在这里

呢! bin/?page=/../../../../../../ect/passwd。结果显而易见,

可以看到了主机的用户名和密码文档。

这也不是最遭的,如果利用open函数加管道符执行任意命令的后果会怎么

样?利用open函数执行命令的技术很老了,我就不废笔墨了。

后来有人对代码进行加固,将第19行改成

$filename="$filepath/".$filename.".html" 他限定后面4位为html,但是这

样的加固似乎起不到什么作用,因为它忽略了NULL字符。提交如下请求依然

可以绕过他的限定:

/myhome/bbs/?page=%

还是这个问题,还有人这么加固代码,它在将19行改了之后,又将第14行改

成:

if (($filename eq "") || (-e $filename))

他在这里检查文件是否存在,如果不存在就不去进行后面的操作,我们这么依

然提交:

/myhome/bbs/?page=%

你会发现我们依然可以成功。

他还是忽略了什么,他忽略了什么呢?他忽略了null字符是可以绕开-e的检

查,也就是说(-e $filename)将会认为文件是存在的,因为%00后面的东西在-

e中会被忽略。

ok,这里我们停一下,我们应该能注意到刚才是什么改变了程序本来的流

程。就是那个null字符(),想想还有什么我们可以用来改成程序的流程呢?

t,r,x0B,n,空格。这些字符都很有用,大家记住它并要学会如何自由运用这

些东西。大家是否还记得前不久的dvbbs论坛漏洞,就是由于上传中的null

字符所引起的。很多时候你会发现技术突破不过就是你的技术积累沉淀后的爆

发。

##关键词:用户输入的变量

##检查:是否做过有效过滤

2、隐式输入的危害

用户的输入分为两种,显示输入和隐式输入。上面的例子没有注意到用户

的输入导致问题的出现。因为那是用户直接输入的,算是显示输入吧。现在很

多程序员都会下意识的去保护自己程序的安全性或者他们本身就了解一些安全

的重要性,都会加一些有用或者没用的限制,用户直接输入可利用的部分越来

越少,于是隐式输入就开始受到关注。这里说的并不仅仅是perl cgi,包括现

在一大帮人玩的asp注入攻击,还有本来是n年前的技术现在才浮出水面的

php注入还有一些其他的攻击手段。仔细回顾一下你就会发现很多都是隐式输

入所引起。隐式输入都是不被程序员注意或者容易被忽略的地方。

cookie应该算是隐式输入中比较典型的例子,我们就用cookie来说事儿

吧......

-----------Code Start------------

#

......

18 $filename=$query->cookie("namecookie");#**********#

19 $filename="$filepath/".$filename;

20 open(FILE,$filename);

21 while()

22 {

23 print $_;

24 }

25 close(FILE)

-----------Code Ends------------

注意打星号的那一行,这只是提取cookie而已,这的确不是用户的直接

输入,但这却是用户可以间接控制的。如果恶意用户通过nc提交如下东东,

后果是什么呢?

GET /myhome/ HTTP/1.1

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,

application/x-shockwave-flash, */*

Accept-Language: zh-cn

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)

Host: 127.0.0.1

Connection: Keep-Alive

Cookie: namecookie=/../../../../../ect/passwd

我们看到这行中

Cookie: namecookie=/../../../../../ect/passwd

一般隐式输入都不容易被注意。

这里攻击者可以通过构造cookie来控制网站,结果就是和上面的一样。说到

这里其实都是一句话:All input is invalid。作为代码的编写者要注意所有用户

可以直接或间接控制的地方。

这里你可能觉得你似乎明白了,但我敢说其实你并没有真的明白,cookie

的控制是里面最简单的一个例子。隐式输入很多时候,不要说写代码的人了,

就连很多WEB安全的高手都不见得能够非常容易的找到,他们更多的是凭自

己的经验和直觉。你可能觉得我言过其实了,其实并没有,简单的连傻瓜都能

看出来的隐式输入,当然容易找到。但是许多的危害更大的,并不那么容易发

现,所以这个时候多是凭借自己的经验和对漏洞"味道"灵敏的嗅觉。

##关键词:没有

##检查:是否做过有效过滤

解决方法其实很简单,就是严格控制用户的输入。所谓严格控制并不只是

过滤,因为过滤难免有漏网之鱼。限定要比过滤来得轻巧和严格。把用户的输

入控制在你规定的范围内,可以用一个正则表达式来给用户划一个范围,指定

用户可以输入的字符或者数字,如果用户输入与你的规定的不匹配,则不与通

过。

至于如何做限定,用正则表达式会很简单。我用email的例子说明:

if (email !~/^[w.-]+@[w.-]+$))#如果不和里面的规定字符匹配则报错

{

&error"输入不正确,难道您就是传说中的黑客?"

}

else

{

#输入正确,继续操作。

......我们只希望用户输入字符、数字、@、"."、“-”、“_”这些东东。永远不

要幻想用户会按照你所希望的输入,除非你给他们划定范围。在这里用以一个

简单的正则表达式。在这个正则表达式中,要求用户只能输入英文大小写字

符,数字和“@”,"-","_""."这几个字符,如果输入其他的,则报错。

二、注意几个危险函数在代码中的使用和特殊字符过滤。

1、有几个危险函数在程序中用得越少越安全(这么说好像有点不严格,呵

呵)。因为很多都是黑客的突破口。这些函数是:system(),open(),exec()。

system()和exec都可以执行系统命令,如system("del

f:myhome$filname"),如果$filename也是通过表单从用户那里得到的,如

果我们在$filename处输入;del f:myhome。我们就删除了整个目录。我

们现在可以删除任意文件。如果你用管道操作符的话也可以。

其实system()函数可以执行系统命令,如果对其中变量缺少严格限制容易引起

安全问题,程序员们或多或少的知道一些,但是由于快速开发或者项目给的时

间紧,为了应付差事,往往不会理会。

##关键词:system()、exec()

##检查:函数中是否有可控制的变量,是否可利用

open()函数也是我们应当留意的地方,大家不要误会,open函数本身是

没有什么的,而是里面的用户输入的数据导致的问题集中到了open()函数

上。open()函数本来是用来打开一些文件,我们看到我们的第一个程序就是因

为open函数引起的泄漏源代码。我们还可以通过“>”,"<"这样的符号来控制

是否向文件写入或者读出。如果加上">"则可以向文件中写入,如果对那些向

cgi文件中写入的字符不加以控制或者过滤不完全,那么写入任意的语句就很

危险了。其实安全漏洞只不过是代码编写者没有考虑到而恶意用户却想到了的

地方。一切我们还是让代码自己说吧:

------------Code Start---------------

......

my $file = "$lbdir" . "forum$inforum/$";

......

if (open(FILE, ">$file"))

{

flock(FILE, 2) if ($OS_USED eq "Unix");

print FILE "$intopict$topictitletempt$topicdescriptiont$threadstate

t$threadpostst$threadviewst$startedbyt$startedpostdate

t$inmembernamet$currenttimet$posticont$inposttempt";

close(FILE);

}

------------Code Ends------------------

呵呵,这段代码大家眼熟吧,不错,这就是LB5K论坛中的一段代

码,我觉得这段代码应该最能说明问题(其实是我手懒,懒的自己写了),大家

注意这里的

open(FILE, ">$file");

打开文件准备向里面写入。后面的print就是向指定的文件中写入。论坛的本

意是将用户的贴子标题简单的保存在一个.pl文件中作为保存,但是编写者没有

注意到贴子的标题其实是用户可以任意控制的,如果恶意用户输入system函

数执行任意指令,如果标题是system @ARGV那么所保存的.pl记录文件中的

第一行也是system @ARGV,这样如果去调用那个.pl文件就形成了一个

webshell。

别急,我还没说完。前面说过利用open()+管道符同样可以执行命令。

##关键字: open()和后面相关联的变量

##检查:open打开的文件是否可写,可写变量是否可以控制。变量是否可控

制。

2、特殊字符

大部分情况下在用户输入的附近,程序员为了保护程序会过滤掉一大批特殊字

符。然后用户输入的恶意语句无法执行。这个部分其实要说的东西很多,但是

总觉得自己有点啰里啰唆的感觉,为了节省版面简言之吧。

看看下面的字符你是不是都过滤掉了:

反引号(``)

反引号我们平时使用的不多,但在perl应用中功能却很大,它象system一样

可以执行系统命令,如:

System(''dir c:'')

$a=`dir c:`;print $a;

上下两条语句执行的结果是一样的,就算过滤掉system,用反引号可以起到相

同的作用。

逗号

逗号可能是因为个头小的缘故,并没有受到太大的重视,不象他的兄弟分号长

得那么高总受到人家关注,但其实逗号很多时候可以做许多事情,下面两句话意

思是一样的:

$a=`dir C:`;print $a;

$a=`dir C:`,print $a#

分号

分号就不用说了吧,可以截断程序的流程,比如:

system("del ./path/$file");

假设$file可控,那么直接加入;del ./path

然后整个path目录就消失了......

反斜杠

反斜杆的应用很巧妙,正常的过滤下如果用户输入/../会被过滤成/../,但是如

果用户输入/../呢?则被过滤成了/../,看到了么?巧妙的输入,巧妙地逃避了

规则限制。

管道符

知道这句语句在ls后面加上管道符(|)会起到什么作用么?

open(FILE, "/bin/ls")

知道的话我就不废话了。

尖括号(<>)

跨站脚本是怎么实现的你不会忘记吧?^_*

美元符($)

这个放在perl中的字符串前面是什么意思?如果用户用这个字符构造语句输

入,又会产生什么效果?你不会不知道吧:p

换行符等

t,r,x0B,n,还记得第一个例程我们是怎么改变程序的流程的么?

其实这只是一部分,限于篇幅不多说了。

三、验证的不完全

验证不完全和上下文逻辑错误是程序员最容易犯的错误。作WEB安全如果能

有一个严谨的思维那就再好不过了,因为一个严谨的思维来去对付那些逻辑错

误应该是能很容易发现(个人认为)。如果你不幸和我一样没有一个成熟而又

严谨的思维,那么就多练习多总结来增长自己的经验值吧。勤能补捉阿!最容

易忽略的往往危害是最大的。几个大的cgi论坛都曾经有过这个问题。其实所

谓验证不完全就是一种逻辑思维能力的不完善。建议去学一下离散数学:-D。

举例说明:

------------Code Start---------------

#

#这是一段管理员检验认证的入口程序

......

$membername=cookie("inputname"); #从cookie中得到名字和密码

$memberpassword = cookie("inputpassword");

$filetoopen="$filepath/"."$";#提取保存在

$中的用户名和密码

if (-e "$filetoopen") #检查这个用户文件是否存在

{

open(FILE,"$filetoopen");

$line=;

close(FILE);

($name,$password,$vip)=split(/t/,$line);

}

if((lc($supername) eq lc($name)) && ($superpassword eq $password)

&& ($vip eq "super"))

#$vip值来自param提交

{ #如果管理员名字、密码和头衔(vip)都正确则可以进入。。。。

------------Code Ends------------------

这里暂不讨论将密码和管理员名称保存在$下是否安全,我

这里只是简单的举个例子。程序首先从cookie中提取了用户名和密码,还有

用户头衔。然后打开以这个用户为名的文件,提取保存在里面的admin的用户

名,密码和头衔,分别给$name,$password,$code。然后对这三者和输入的进

行比对,都一样才可进入管理页面。好像没什么错误,但不知道你是否发现其

实那个if语句根本就是形同虚设,为什么这么说呢?如果cookie中用户名和

密码都为空,那么if这段语句根本不会被执行,更不要说打开用户文件了。这

里最主要的是那个头衔的值,如果用户名和密码都为空,这时因为文件不存在

所以if不会执行,也就是不会去提取用户的用户名、密码、头衔着三个值,用

户名和密码都为空,空肯定等于空,这个不用说了。那么就剩下一个头衔

(vip)没有解决,因为头衔(vip)是用户提交的,所以我们可以在浏览器中

直接指定vip=super,这样就成功了绕过了对管理员的检验认证。这就是我们

所说的验证不完全,也是比较难避免的错误。

也许你会说这样的危害只能影响到那些开源的源代码,那你就错了,通过不同

页面不同参数的比较,发现类似如这种校验参数的利用并不是什么难事。这就

是WEB入侵中的小技巧。

这里一路说下来,我们应该注意到:思维的拓展性很多时候是来自于经验。如

果你老是感叹为什么别人想得出来的方法自己想不出来,然后认为自己的思维

太不开阔了,那我可以很负责告诉你,那不是你的思维不开阔,那绝对是你的

经验不够,而经验是哪里来的?他来自于实践:)

##关键字:没有

##检查:对管理员的认证检验的入口,和相关函数。

四、未检验用户输入长度

对于攻击者很多时候并不都是象我这样的好心人,(呵呵,别用砖头丢我)有

时候他们只是为了攻击而攻击,这个时候D.O.S(拒绝服务攻击)就成了他们的首

选。对用户的输入长度的检验就尤为重要了,如$ENV。如果你没有对用户输

入作一个限定,那么当用户输入一堆垃圾信息时,就会产生拒绝服务攻击。更

有甚者,用垃圾文件添塞硬盘,直到把硬盘写满为止,可怕不?别认为别人不

会用这么笨的方法,前不久就有人写程序模仿IE正常访问,去刷新不断调用数

据库,导致数据库瘫痪。

五、服务器的权限设置

不要让你的WEB以管理员权限运行,IIS的默认设置是GUEST的,这种权限

很低,就算攻击者得到了一个Webshell,也不会对你有太大的威胁,如果你

的目录设置和服务器的配置好的话,攻击者很难有大的作为。如IIS默认配置

是GUEST,Apeach的默认配置是uid=99;nobody的权限。如果都是这样的

话,这条就是废话了,但是我在给很多网站做测试的时候发现不少服务器给

WEB一个root权限,那基本上这个服务器如果被黑客攻击就算是OVER了。

攻击者连提升权限都不用,就可以从容的控制整个服务器。到时候你想哭都找

不到调儿。

六、服务器的目录设置

其实上面已经谈到过了目录设置,这里细说一下,不要把所有的目录均设置为

有脚本执行权限的。

注意用户可以控制的目录区域,比如上传头像或者文件的目录

恶意用户向服务器写入的shell如果写入了没有脚本执行权的目录中,那个

shell也就执行不了了。

2024年7月17日发(作者:长初)

执行CGI脚本的安全上下代码

一、注意对变量的处理

1、用户的输入是不可信任的,当谈到安全编程的时候,比尔盖茨先生对他的员

工说了一句非常经典的话:All input is invalid.(所有的用户输入都是有害

的,具体是不是他第一个说的,有待考察)

一切用户输入的地方都是我们应当注意的地方。来看一段代码吧:

-----------Code Start------------

#

01 $filepath="f://myhome//bbs//"

......

......

13 $filename=$query -> param(''page'');

14 if ($filename eq "")

15 { $filename="";

16 die("对不起,文件名不能为空!");

17 }

18 else{

19 $filename="$filepath/".$filename;

20 open(FILE,$filename);

21 while()

22 {

23 print $_;

24 }

25 close(FILE)

......

-----------Code Ends-------------

这段代码基本上没有作太多改动,因为我演示是在自己的机子上,所以把

路径改了一下,我们在这里回放一下曾经的过程。

这里的$filename用param提取page中用户输入的内容,$filename其

实是用户间接输入的内容,而代码对$filename并没有做严格的审查只是检查

是否为空,如果恶意用户直接在浏览器中指定其他文件,如cgi,asp或者任何

文件,则返回的是文件的源代码,如:看到的源代码了,通过

简单的浏览其他的页面,我们可以基本上可以得到所有文件的源代码。我们也

可以通过"../"来切换到其他的目录下。

这还不是最糟糕的,如果你的系统是Linux或者UNIX,那么更过分的在这里

呢! bin/?page=/../../../../../../ect/passwd。结果显而易见,

可以看到了主机的用户名和密码文档。

这也不是最遭的,如果利用open函数加管道符执行任意命令的后果会怎么

样?利用open函数执行命令的技术很老了,我就不废笔墨了。

后来有人对代码进行加固,将第19行改成

$filename="$filepath/".$filename.".html" 他限定后面4位为html,但是这

样的加固似乎起不到什么作用,因为它忽略了NULL字符。提交如下请求依然

可以绕过他的限定:

/myhome/bbs/?page=%

还是这个问题,还有人这么加固代码,它在将19行改了之后,又将第14行改

成:

if (($filename eq "") || (-e $filename))

他在这里检查文件是否存在,如果不存在就不去进行后面的操作,我们这么依

然提交:

/myhome/bbs/?page=%

你会发现我们依然可以成功。

他还是忽略了什么,他忽略了什么呢?他忽略了null字符是可以绕开-e的检

查,也就是说(-e $filename)将会认为文件是存在的,因为%00后面的东西在-

e中会被忽略。

ok,这里我们停一下,我们应该能注意到刚才是什么改变了程序本来的流

程。就是那个null字符(),想想还有什么我们可以用来改成程序的流程呢?

t,r,x0B,n,空格。这些字符都很有用,大家记住它并要学会如何自由运用这

些东西。大家是否还记得前不久的dvbbs论坛漏洞,就是由于上传中的null

字符所引起的。很多时候你会发现技术突破不过就是你的技术积累沉淀后的爆

发。

##关键词:用户输入的变量

##检查:是否做过有效过滤

2、隐式输入的危害

用户的输入分为两种,显示输入和隐式输入。上面的例子没有注意到用户

的输入导致问题的出现。因为那是用户直接输入的,算是显示输入吧。现在很

多程序员都会下意识的去保护自己程序的安全性或者他们本身就了解一些安全

的重要性,都会加一些有用或者没用的限制,用户直接输入可利用的部分越来

越少,于是隐式输入就开始受到关注。这里说的并不仅仅是perl cgi,包括现

在一大帮人玩的asp注入攻击,还有本来是n年前的技术现在才浮出水面的

php注入还有一些其他的攻击手段。仔细回顾一下你就会发现很多都是隐式输

入所引起。隐式输入都是不被程序员注意或者容易被忽略的地方。

cookie应该算是隐式输入中比较典型的例子,我们就用cookie来说事儿

吧......

-----------Code Start------------

#

......

18 $filename=$query->cookie("namecookie");#**********#

19 $filename="$filepath/".$filename;

20 open(FILE,$filename);

21 while()

22 {

23 print $_;

24 }

25 close(FILE)

-----------Code Ends------------

注意打星号的那一行,这只是提取cookie而已,这的确不是用户的直接

输入,但这却是用户可以间接控制的。如果恶意用户通过nc提交如下东东,

后果是什么呢?

GET /myhome/ HTTP/1.1

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,

application/x-shockwave-flash, */*

Accept-Language: zh-cn

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)

Host: 127.0.0.1

Connection: Keep-Alive

Cookie: namecookie=/../../../../../ect/passwd

我们看到这行中

Cookie: namecookie=/../../../../../ect/passwd

一般隐式输入都不容易被注意。

这里攻击者可以通过构造cookie来控制网站,结果就是和上面的一样。说到

这里其实都是一句话:All input is invalid。作为代码的编写者要注意所有用户

可以直接或间接控制的地方。

这里你可能觉得你似乎明白了,但我敢说其实你并没有真的明白,cookie

的控制是里面最简单的一个例子。隐式输入很多时候,不要说写代码的人了,

就连很多WEB安全的高手都不见得能够非常容易的找到,他们更多的是凭自

己的经验和直觉。你可能觉得我言过其实了,其实并没有,简单的连傻瓜都能

看出来的隐式输入,当然容易找到。但是许多的危害更大的,并不那么容易发

现,所以这个时候多是凭借自己的经验和对漏洞"味道"灵敏的嗅觉。

##关键词:没有

##检查:是否做过有效过滤

解决方法其实很简单,就是严格控制用户的输入。所谓严格控制并不只是

过滤,因为过滤难免有漏网之鱼。限定要比过滤来得轻巧和严格。把用户的输

入控制在你规定的范围内,可以用一个正则表达式来给用户划一个范围,指定

用户可以输入的字符或者数字,如果用户输入与你的规定的不匹配,则不与通

过。

至于如何做限定,用正则表达式会很简单。我用email的例子说明:

if (email !~/^[w.-]+@[w.-]+$))#如果不和里面的规定字符匹配则报错

{

&error"输入不正确,难道您就是传说中的黑客?"

}

else

{

#输入正确,继续操作。

......我们只希望用户输入字符、数字、@、"."、“-”、“_”这些东东。永远不

要幻想用户会按照你所希望的输入,除非你给他们划定范围。在这里用以一个

简单的正则表达式。在这个正则表达式中,要求用户只能输入英文大小写字

符,数字和“@”,"-","_""."这几个字符,如果输入其他的,则报错。

二、注意几个危险函数在代码中的使用和特殊字符过滤。

1、有几个危险函数在程序中用得越少越安全(这么说好像有点不严格,呵

呵)。因为很多都是黑客的突破口。这些函数是:system(),open(),exec()。

system()和exec都可以执行系统命令,如system("del

f:myhome$filname"),如果$filename也是通过表单从用户那里得到的,如

果我们在$filename处输入;del f:myhome。我们就删除了整个目录。我

们现在可以删除任意文件。如果你用管道操作符的话也可以。

其实system()函数可以执行系统命令,如果对其中变量缺少严格限制容易引起

安全问题,程序员们或多或少的知道一些,但是由于快速开发或者项目给的时

间紧,为了应付差事,往往不会理会。

##关键词:system()、exec()

##检查:函数中是否有可控制的变量,是否可利用

open()函数也是我们应当留意的地方,大家不要误会,open函数本身是

没有什么的,而是里面的用户输入的数据导致的问题集中到了open()函数

上。open()函数本来是用来打开一些文件,我们看到我们的第一个程序就是因

为open函数引起的泄漏源代码。我们还可以通过“>”,"<"这样的符号来控制

是否向文件写入或者读出。如果加上">"则可以向文件中写入,如果对那些向

cgi文件中写入的字符不加以控制或者过滤不完全,那么写入任意的语句就很

危险了。其实安全漏洞只不过是代码编写者没有考虑到而恶意用户却想到了的

地方。一切我们还是让代码自己说吧:

------------Code Start---------------

......

my $file = "$lbdir" . "forum$inforum/$";

......

if (open(FILE, ">$file"))

{

flock(FILE, 2) if ($OS_USED eq "Unix");

print FILE "$intopict$topictitletempt$topicdescriptiont$threadstate

t$threadpostst$threadviewst$startedbyt$startedpostdate

t$inmembernamet$currenttimet$posticont$inposttempt";

close(FILE);

}

------------Code Ends------------------

呵呵,这段代码大家眼熟吧,不错,这就是LB5K论坛中的一段代

码,我觉得这段代码应该最能说明问题(其实是我手懒,懒的自己写了),大家

注意这里的

open(FILE, ">$file");

打开文件准备向里面写入。后面的print就是向指定的文件中写入。论坛的本

意是将用户的贴子标题简单的保存在一个.pl文件中作为保存,但是编写者没有

注意到贴子的标题其实是用户可以任意控制的,如果恶意用户输入system函

数执行任意指令,如果标题是system @ARGV那么所保存的.pl记录文件中的

第一行也是system @ARGV,这样如果去调用那个.pl文件就形成了一个

webshell。

别急,我还没说完。前面说过利用open()+管道符同样可以执行命令。

##关键字: open()和后面相关联的变量

##检查:open打开的文件是否可写,可写变量是否可以控制。变量是否可控

制。

2、特殊字符

大部分情况下在用户输入的附近,程序员为了保护程序会过滤掉一大批特殊字

符。然后用户输入的恶意语句无法执行。这个部分其实要说的东西很多,但是

总觉得自己有点啰里啰唆的感觉,为了节省版面简言之吧。

看看下面的字符你是不是都过滤掉了:

反引号(``)

反引号我们平时使用的不多,但在perl应用中功能却很大,它象system一样

可以执行系统命令,如:

System(''dir c:'')

$a=`dir c:`;print $a;

上下两条语句执行的结果是一样的,就算过滤掉system,用反引号可以起到相

同的作用。

逗号

逗号可能是因为个头小的缘故,并没有受到太大的重视,不象他的兄弟分号长

得那么高总受到人家关注,但其实逗号很多时候可以做许多事情,下面两句话意

思是一样的:

$a=`dir C:`;print $a;

$a=`dir C:`,print $a#

分号

分号就不用说了吧,可以截断程序的流程,比如:

system("del ./path/$file");

假设$file可控,那么直接加入;del ./path

然后整个path目录就消失了......

反斜杠

反斜杆的应用很巧妙,正常的过滤下如果用户输入/../会被过滤成/../,但是如

果用户输入/../呢?则被过滤成了/../,看到了么?巧妙的输入,巧妙地逃避了

规则限制。

管道符

知道这句语句在ls后面加上管道符(|)会起到什么作用么?

open(FILE, "/bin/ls")

知道的话我就不废话了。

尖括号(<>)

跨站脚本是怎么实现的你不会忘记吧?^_*

美元符($)

这个放在perl中的字符串前面是什么意思?如果用户用这个字符构造语句输

入,又会产生什么效果?你不会不知道吧:p

换行符等

t,r,x0B,n,还记得第一个例程我们是怎么改变程序的流程的么?

其实这只是一部分,限于篇幅不多说了。

三、验证的不完全

验证不完全和上下文逻辑错误是程序员最容易犯的错误。作WEB安全如果能

有一个严谨的思维那就再好不过了,因为一个严谨的思维来去对付那些逻辑错

误应该是能很容易发现(个人认为)。如果你不幸和我一样没有一个成熟而又

严谨的思维,那么就多练习多总结来增长自己的经验值吧。勤能补捉阿!最容

易忽略的往往危害是最大的。几个大的cgi论坛都曾经有过这个问题。其实所

谓验证不完全就是一种逻辑思维能力的不完善。建议去学一下离散数学:-D。

举例说明:

------------Code Start---------------

#

#这是一段管理员检验认证的入口程序

......

$membername=cookie("inputname"); #从cookie中得到名字和密码

$memberpassword = cookie("inputpassword");

$filetoopen="$filepath/"."$";#提取保存在

$中的用户名和密码

if (-e "$filetoopen") #检查这个用户文件是否存在

{

open(FILE,"$filetoopen");

$line=;

close(FILE);

($name,$password,$vip)=split(/t/,$line);

}

if((lc($supername) eq lc($name)) && ($superpassword eq $password)

&& ($vip eq "super"))

#$vip值来自param提交

{ #如果管理员名字、密码和头衔(vip)都正确则可以进入。。。。

------------Code Ends------------------

这里暂不讨论将密码和管理员名称保存在$下是否安全,我

这里只是简单的举个例子。程序首先从cookie中提取了用户名和密码,还有

用户头衔。然后打开以这个用户为名的文件,提取保存在里面的admin的用户

名,密码和头衔,分别给$name,$password,$code。然后对这三者和输入的进

行比对,都一样才可进入管理页面。好像没什么错误,但不知道你是否发现其

实那个if语句根本就是形同虚设,为什么这么说呢?如果cookie中用户名和

密码都为空,那么if这段语句根本不会被执行,更不要说打开用户文件了。这

里最主要的是那个头衔的值,如果用户名和密码都为空,这时因为文件不存在

所以if不会执行,也就是不会去提取用户的用户名、密码、头衔着三个值,用

户名和密码都为空,空肯定等于空,这个不用说了。那么就剩下一个头衔

(vip)没有解决,因为头衔(vip)是用户提交的,所以我们可以在浏览器中

直接指定vip=super,这样就成功了绕过了对管理员的检验认证。这就是我们

所说的验证不完全,也是比较难避免的错误。

也许你会说这样的危害只能影响到那些开源的源代码,那你就错了,通过不同

页面不同参数的比较,发现类似如这种校验参数的利用并不是什么难事。这就

是WEB入侵中的小技巧。

这里一路说下来,我们应该注意到:思维的拓展性很多时候是来自于经验。如

果你老是感叹为什么别人想得出来的方法自己想不出来,然后认为自己的思维

太不开阔了,那我可以很负责告诉你,那不是你的思维不开阔,那绝对是你的

经验不够,而经验是哪里来的?他来自于实践:)

##关键字:没有

##检查:对管理员的认证检验的入口,和相关函数。

四、未检验用户输入长度

对于攻击者很多时候并不都是象我这样的好心人,(呵呵,别用砖头丢我)有

时候他们只是为了攻击而攻击,这个时候D.O.S(拒绝服务攻击)就成了他们的首

选。对用户的输入长度的检验就尤为重要了,如$ENV。如果你没有对用户输

入作一个限定,那么当用户输入一堆垃圾信息时,就会产生拒绝服务攻击。更

有甚者,用垃圾文件添塞硬盘,直到把硬盘写满为止,可怕不?别认为别人不

会用这么笨的方法,前不久就有人写程序模仿IE正常访问,去刷新不断调用数

据库,导致数据库瘫痪。

五、服务器的权限设置

不要让你的WEB以管理员权限运行,IIS的默认设置是GUEST的,这种权限

很低,就算攻击者得到了一个Webshell,也不会对你有太大的威胁,如果你

的目录设置和服务器的配置好的话,攻击者很难有大的作为。如IIS默认配置

是GUEST,Apeach的默认配置是uid=99;nobody的权限。如果都是这样的

话,这条就是废话了,但是我在给很多网站做测试的时候发现不少服务器给

WEB一个root权限,那基本上这个服务器如果被黑客攻击就算是OVER了。

攻击者连提升权限都不用,就可以从容的控制整个服务器。到时候你想哭都找

不到调儿。

六、服务器的目录设置

其实上面已经谈到过了目录设置,这里细说一下,不要把所有的目录均设置为

有脚本执行权限的。

注意用户可以控制的目录区域,比如上传头像或者文件的目录

恶意用户向服务器写入的shell如果写入了没有脚本执行权的目录中,那个

shell也就执行不了了。

发布评论

评论列表 (0)

  1. 暂无评论