数,未经严格的检查就立即使用CGI参数。 Web应用一般包含位于防火墙之内的和防火墙之外的两部分,防火墙之内的如本地的脚本程序、数据库、Web服务器以及本地数据文件等。由于这些部件都由管理员直接管理和控制,因此可以认为它们都是可以信任的。Web应用的其他组成部分位于防火墙之外,是不可信任的。这主要是指用户的浏览器——如果用户使用浏览器,而且没有为了更方便地控制输入Web应用的数据和发现Web应用中可能存在的问题而直接在telnet会话中输入Web请求。
防火墙是可信任的Intranet和不可信任的Internet之间的分界线。
所有来自信任分界线之外的数据未经检查就不应该进入Web应用,这包括所有传递给CGI脚本的参数,比如:GET、POST和COOKIE变量,HTTP_REFERER、HTTP_USER_AGENT和所有HTTP_*变量,以及所有其他远程生成的变量值。在CGI脚本使用所有这些变量之前,都必须对它们进行合法性检查,这种检查可以确保变量的值确实在预期的范围内。
例如,有些脚本在请求的HTTP_REFERER正确时就接受表单输入,这是一种常见但错误的编程习惯。脚本用这种机制来防范伪造的请求是徒劳的。毫无疑问,对于攻击者来说,掌握必需的HTTP_REFERER并将它并入请求的其余部分一起发送是轻而易举的,因此这种保护是没有用的。这种脚本的错误在于:在这类调用中必须检查的不仅仅是HTTP_REFERER值,所有其他值都必须进行检查。
下面这个简单的PHP程序将输出CGI参数b的值以及HTTP_REFERER的值:
kris@valiant:~/www < cat test.php
< ?php
print "The value of b is $bn";
print "The value of HTTP_REFERER is $HTTP_REFERERn";
? >
用telnet连接到80端口,我们能够向上述脚本提供任意的参数值b,同时还可以任意提供HTTP_REFERER值。我们把下面的几行发送到服务器:
GET /~kris/test.php?b=this+is+a+test HTTP/1.0
Host: valiant.koehntopp.de
Referer: http://www.attacker.com/die_sucker_die.html
下面是完整的会话过程:
kris@valiant:~/www < telnet valiant 80
Trying 193.102.57.3...
Connected to valiant.koehntopp.de.
Escape character is '^]'.
GET /~kris/test.php?b=this+is+a+test HTTP/1.0
Host: valiant.koehntopp.de
Referer: http://www.attacker.com/die_sucker_die.html
HTTP/1.1 200 OK
Date: Sat, 08 Apr 2000 06:44:02 GMT
Server: Apache/1.3.9 (Unix) (SuSE/Linux) PHP/4.0RC2-dev mod_ssl/2.4.7 OpenSSL/0.9.4
X-Powered-By: PHP/4.0RC2-dev
Connection: close
Content-Type: text/html
The value of b is this is a test
The value of HTTP_REFERER is http://www.attacker.com/die_sucker_die.html
Connection closed by foreign host.
注意b的值必须以URL编码格式输入。要将字符串进行URL编码,可以使用一个简单的PHP程序,例如:
kris@valiant:~/www < cat urlencode.php
#! /home/kris/bin/php -q
< ?php
print urlencode($argv[1])."n";
? >
kris@valiant:~/www < ./urlencode.php "this is a test"
this+is+a+test
发送HTTP POST请求只是稍微复杂一点:现在应该在这个请求中包含一个合法的Content-Type头以及正确的内容长度字节数。下面是具体过程:
kris@valiant:~/www < telnet valiant 80
Trying 193.102.57.3...
Connected to valiant.koehntopp.de.
Escape character is '^]'.
POST /~kris/test.php HTTP/1.0
Host: valiant.koehntopp.de
Referer: http://www.attacker.com/die_sucker_die.html
Content-Type: application/x-www-form-urlencoded
Content-Length: 16
b=this+is+a+test
HTTP/1.1 200 OK
Date: Sat, 08 Apr 2000 06:55:11 GMT
Server: Apache/1.3.9 (Unix) (SuSE/Linux) PHP/4.0RC2-dev
mod_ssl/2.4.7 OpenSSL/0.9.4
X-Powered-By: PHP/4.0RC2-dev
Connection: close
Content-Type: text/html
The value of b is this is a test
The value of HTTP_REFERER is
http://www.attacker.com/die_sucker_die.html
Connection closed by foreign host.
另外一种常见的错误是把内部应用的状态数据通过< INPUT TYPE="HIDDEN" >标记从一个页面传递到另一个页面。把内部应用的状态放到信任界限之外就如把应用的心脏挖出来放到了攻击者的面前。对于如此缺乏安全保障的应用,任何想要摧毁它的攻击者都可以轻易地引导该应用并得到任何想要的效果。应用的状态应该通过会话变量保存在服务器上,永远不应该跨越信任界限。所有的Web应用开发平台都有这种机制。例如在PHP3中,PHPLIB可用于保存会话数据,PHP4使用的是session_*()调用,ASP提供Session对象,Cold Fusion提供几种不同的会话变量。
Web应用不应该把任何来自信任界线之外的数据直接保存为会话变量:会话变量是可信任的变量,不应该用来保存不可信任的数据。通常,来自外面的数据(比如表单变量的数据)应该先传入检验其合法性的函数。只有当检验函数表示表单提供的数据是安全的,才可以把表单数据复制到会话变量。Web应用应该把这种检查集中到一起进行,应用的所有其余部分永远不应该直接接触表单变量,而是应该使用经过检查且确认安全的会话数据。
参考:
http://www.koehntopp.de/kris/artikel/webtune/
"Webserver verstehen und tunen" (德语)
http://www.koehntopp.de/php/
"de.comp.lang.php - H‰ufig gestellte Fragen" (德语)
http://www.insecure.org/nmap/
"NMAP Port Scanner" (英语)
http://ethereal.zing.org/
"Ethereal Network Monitor" (英语)
http://www.marko.net/cheops
"Ceops Network Mapper" (英语)
http://freshmeat.net/appindex/1998/04/06/891857252.html
"lsof - list open files" (英语)
"TCP/IP Illustrated, Volume 1: The Protocols" (英语)
W. Richard Stevens
Addison-Wesley
"Hacking Exposed - Network Security Secrets & Solutions" (英语)
McClure, Scambray and Kurtz
http://phplib.netuse.de/
"A library for PHP application development" (英语)
上一页 [1] [2]