把尽可能多的服务隔离运行可以部分地解决这个问题,例如用apache suexec程序的sbox让所有的cgi在隔离的环境以客户的用户id而不是web服务器的用户id运行。另外,许多服务器上运行着ftp服务,例如wu-ftpd,该服务的所有文件传输都是隔离进行的,同样也保护了善意客户的资料避免被其他人偷看。
然而,恶意的客户仍旧能够用cgi程序创建符号链接指向其他用户的存储区域,然后通过它自己的web服务器查看其他人的文件,这是因为在一个运行多个网站的环境中,web服务器无法简单地以隔离方式以及用它为之应答请求的客户的用户id运行。管理员应该配置web服务器以及其他文件传输程序使其不再使用符号链接。在apache上,这可以通过关闭最顶层的“followsymlinks”选项实现(不要在较低的层次上把它重新打开),配置代码示例如下:
< directory / >options -followsymlinks< /directory >
|
数据源的可靠性
第三类常见的安全问题是cgi程序或php脚本的质量低下,它们信任了来源不可靠的参数,未经严格的检查就立即使用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值,所有其他值都必须进行检查。[page]
伪造web请求(一)
下面这个简单的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.0host: valiant.koehntopp.dereferer: http://www.attacker.com/die_sucker_die.html
|
下面是完整的会话过程:
kris@valiant:~/www < telnet valiant 80trying 193.102.57.3...connected to valiant.koehntopp.de.escape character is '^]'.get /~kris/test.php?b=this+is+a+test http/1.0host: valiant.koehntopp.dereferer: http://www.attacker.com/die_sucker_die.htmlhttp/1.1 200 okdate: sat, 08 apr 2000 06:44:02 gmtserver: apache/1.3.9 (unix) (suse/linux) php/4.0rc2-dev mod_ssl/2.4.7 openssl/0.9.4x-powered-by: php/4.0rc2-devconnection: closecontent-type: text/htmlthe value of b is this is a testthe value of http_referer is http://www.attacker.com/die_sucker_die.htmlconnection closed by foreign host.
|