Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->编程语言 ->CGI ->正文

CGI的安全(二)

来源:Linuxdby.com 作者:Webmaster 时间:2007-04-28 点击: [收藏] [投稿]

  这被称为buffer overflow,聪明的hacker就会利用这个来远程执行命令。这个缓冲溢出的bug存在于NCSA httpd v1.3中。这是为什么一个网络(或CGI)程序员需要更细心地编程的很好的例子。在一个单用户的机器里,缓冲溢出只能造成系统崩溃。在崩溃的单用户计算机中没有必要利用缓冲溢出来执行程序,因为大概你已经执行了你需要的任何程序(除了公共终端)。然而,在网络系统中,一个崩溃的CGI程序远不是这么简单,它会成为未经授权的用户进入的后门。 



  程序2中的代码解决了两个问题。首先,它动态的分配了存储字符串的足够的空间。其次,注意我将信息的长度加了1。这样,我实际上分配了比字符串长度多1字节的内存。这就保证字符串不会是0。因为目标字符总是会为额外的字符留有空间,strcpy()函数在目标字符串的最后添加了空字符,strcpy()放置了空字符。没有理由认为传送给CGI脚本的字符串会是空字符,因此,为了以防万一,我在最后留了1字节的空间。 

  倘若你的C程序避免了像缓冲溢出这样的问题,那么你就可以写出安全的CGI程序。然而,这是艰苦的工作,特别是当你的CGI很大更复杂的时候。这些问题将迫使你花费比一般的CGI任务更多的时间来思索低级语言的设计工作。基于这个原因,你可能更喜欢高级一点的编程语言(如Perl)。 

  然而,具有高级特点的Perl有着冒失的一面。尽管你能假设Perl会正确地处理字符串的存储,但当Perl使用你并不注意的高级一点的语法做一些事情时,很可能会有危险。在下一节中你会更清楚的了解到。 

2-2.shell危险性 

  很多的CGI任务都可以使用其他的程序很容易的实现。例如,你要写一个CGI的邮件网关,完全使用CGI程序来完成执行邮件的发送代理是很愚蠢的行为。更实用的方法是将数据通过管道传送到一个存在的邮件传送代理程序,比如sendmail,然后让sendmail来完成剩下的工作。这种习惯很好并值得鼓励。 

  安全风险依赖于你怎样调用这些外部的程序。完成这项工作在Perl和C中有很多函数可以实现。它们中很多函数通过调用shell,然后让shell来执行这个命令。这些命令被列在表1中,如果你使用了它们中的一个,那么你就使得Unix hells在攻击下显得很脆弱。 

  表1. C和Perl中可以调用shell的函数. 
  Perl 函数 C 函数 
  system(’...’) system() 
  open(’| ...’) popen() 
  exec(’...’) 

  eval(’...’) 

 `...` 

  为什么shell很危险呢?有很多的非数字的字符可以通过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是怎样利用这个作为他(她)的优势的?观察以下程序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编写的,不会有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) 


 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<



上一篇:CGI的安全(一)   下一篇:关于CGI读写COOKIE的编程

文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
更多相关文章
Power by linux-cn.com 粤ICP备05006655号