14.1文件包含漏洞
曾经提到过“代码注入漏洞”这种攻击,其原理就是注入一段用户能控制的脚本或代码,并让服务器执行。“代码注入”的典型代表就是文件包含。
在互联网的安全历史中,PHP的文件包含漏洞已经臭名昭著。
文件包含是php常用用法,主要由4个函数完成:include、require、include_once、require_once。当使用这4个函数包含一个新的文件时,该文件将作为PHP代码执行,PHP内核并不会在意该文件是什么类型。
要想成功利用这个漏洞,需要满足以下2个条件:
1.include等函数通过动态变量的方式引入需要包含的文件;
2.用户能够控制该动态变量。
14.1.1 本地文件包含
<?php $file = $_GET['file'] ; // "../../etc/password\0' if(file_exists('/home/wwwrun/'.$file.'.php')){ //file_exists will return true as the file /home/wwwrun/../../etc/password exist include '/home/wwwrun/'.$file.'.php'; //the file /etc/password will be included }
这段代码中,用户控制了参数file,PHP将访问/etc/password文件。(使用\0隔断了.php标识)
在一般的web应用中,0字节用户其实是不需要的,因此完全可以禁用0字节:
if (is_string($value)) { $value = str_replace("\0",'',$value); }
但是这样并不能解决问题,由于操作系统对目录最大长度的限制,可以不需要0字节达到隔断的目的。
目录字符串在windows下是256字节,在Linux下是4096字节。最大长度之后的字符床将被丢弃,可以通过'./'的形式构造出这么长的字符串。
除了inluce等4个函数外,fopen、fread也十分危险。
解决方法:
1.URLEncode
2.设置php.ini的open_basedir限制项目的访问目录。
注意:
open_basedir的值是目录前缀.如果要限定一个目录,需要加上‘/’
windows下多个目录应当使用分号隔开,linux下使用冒号隔开。
14.2 变量覆盖漏洞
变量如果未被初始化,且能被用户所空至,那么很可能导致安全问题。而在PHP中,这种情况在register_globals为ON时尤为严重。
(register_globals为ON,代表参数变量可以直接注入到全局变量中)
<?php if($auth){ echo "private!"; } ?>
在register_globals=ON的情况下,如果存在auth=1类似的参数,那么if语句的语句体将被执行。
类似的,通过$GLOBALS获取的变量,也可能导致变量覆盖。
如下是一段常见的禁用register_globals的代码:
if (int_get('register_globals')) foreach($_REQUEST as $k=>$v) unset(${$k});
这样会禁止参数注入到变量中,但是尝试使用GLOBAL[a]覆盖全局变量的时候,却成功覆盖了$a.
这是因为unset默认只会销毁局部变量。
产生变量覆盖的其他场景:
extract(),从数组中导出变量。
遍历初始化变量。
import_request_variables ,将GET、POST、Cookie中的变量导出到全局。
parse_str(),解析URL中的query string
14.4 定制安全的PHP环境
php.ini 安全参数配置
1.register_globals=OFF,否则容易出现变量覆盖。
2.open_basedir ,用于对抗文件包含、目录遍历等攻击。
3.allow_url_include=off、allow_url_fopen=off,用于对抗远程文件包含。
4.display_errors=off,开发模式下可为on,否则会暴露很多蜜柑信息。
5.log_errors=on,正式环境下使用即可,把错误信息记录在日志中。
6.magic_quotes_gpc,推荐关闭,他并不只得依赖,一直有若干中方法可以绕过他,甚至由于它的存在衍生新的安全问题。
7.cgi.fix_pathinfo,如果php以cgi方式安装,则需要关闭,避免出现文件解析问题。
8.session.cookie_httponly,开启HttpOnly
9.safe_mode,PHP的安全模式是否开启的争议一直很大。一方面,他会影响很多函数;另一方面,他又不停的被黑客们绕过,因此很难去设。
共享环境下:建议开启,可以和disable_functions配合使用
单独应用环境下:考虑关闭它,更多的依赖于disable_functions控制环境安全。
10.disable_functions,能够在PHP中禁用函数。这是把双刃剑,禁用函数增加开发困难,禁用的太少有可能增加开发写出不安全代码的几率。