computer 版 (精华区)

发信人: Aug (如风), 信区: network
标  题: CGI的安全<转载> (8)
发信站: 听涛站 (Tue Mar 14 16:02:20 2000), 转信

2-1.语言的风险性

  不同的语言有其与生俱来的安全风险。任何语言都可以编写安全的CGI程序,
但是你必须注意每个语言的怪癖(急转)。这里,我只讨论C和Perl,但是它
们的有些特性并不适用于其它语言。想得到其他语言的指定信息,请参照适当
的文件。

  在前面的章节我们学到,一般来说,编译CGI程序比解释脚本更可取。编译
程序有两个优势:首先,你不需要有服务器可理解的解释器;其次,程序的
源文件是不可访问的。注意,像Perl一样的传统的解释型语言可以被编译成
二进制形式。(关于如何在Perl中实现,请参阅Larry Wall和Randall Schwartz
的《Perl编程》)从安全立场来说,编译的Perl程序和编译的C程序一样好用。

  像C这样比较低级的语言会出现被称为buffer overflow的问题。C语言并没
有处理字符串的好的内置的方法。通常的方法或者是声明一个字符数组或者
指向字符的指针。很多人倾向于前一种方法,因为它编程比较简单。思考一
下下面两个功能等价的程序代码。

程序1. 在C语言中使用数组定义字符串.

#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简单得多,而且在这个特定的例子里,两者都可以很好的工
作。我们假设有这样一个例子:我已经知道了我处理的字符串的长度,因此,
我可以定义一个适当的数组长度。但是,在CGI程序里,你不知道输入的字符
串会有多长。举个例子,如果信息的长度大于80 char,那么程序1会崩溃(即
我们通常说的"溢出")。

  这被称为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使用你并不注意的高级一点的语法做一些事情时,
很可能会有危险。在下一节中你会更清楚的了解到。

--
※ 修改:.Aug 于 Mar 14 16:02:45 修改本文.[FROM: 匿名天使的家]
※ 来源:.听涛站 cces.net.[FROM: 匿名天使的家]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:1.477毫秒