一.基本准则
- 所有的用户输入都是有害的,对所有从客户端传入的数据都不信任, 需要做判断和过滤(类型,长度,格式,范围),否则可能会受到SQL Injection、XSS等攻击。比如:$_GET, $_POST, $_COOKIE, $_FILES, $REQUEST等。 直接使用将可能存在被注入的危险。
- 用户的相关输入涉及数据库操作时需要对输入做专门的转换。例如: 数据库操作中数字型的需要做intval转换,字符串类型的需要通过mysql_real_escape_string过滤。
- 用户上传的文件的文件名必须随机重新命名,并限制其后缀,大小,类型,并以明确的后缀结束。
- 数据库操作必须使用安全数据库操作类.不使用安全数据库操作类的,使用Intval对整数型参数过滤,使用mysql_real_escape_string对字符串型进行过滤,并要配合mysql_set_charset设置当前字符集进行使用。PHP版本小于5.0.5的,须使用SET character_set_connection=字符集, character_set_results=字符集, character_set_client=binary; 这三句语句替代mysql_set_charset进行数据库字符集设置。在能用PDO的情况下,最好用PDO的预编译功能。
- 最好别使用PHP调用shell,若实在要调用shell命令时,输入参数作为system,exec,passthru等任何命令执行函数的参数时,要使用escapeshellarg函数进行过滤。(escapeshellcmd在某些条件下会存在漏洞,因此强烈推荐使用escapeshellarg) 。
- 输入参数作为php文件内容时,要使用var_export进行数据导出。字符串尽量用’ ‘而不是” “进行引用,一个是效率问题,一个是安全问题。
- 输出到网页中的变量要用htmlspecialchars 处理转义 防止xss攻击。
- 若有输入变量带到网址跳转中去,必须校验域名地址,防止通过URL被篡改,从当前网站跳转到欺诈网站,产生钓鱼攻击。
- 一些其它数据来源:比如导入excel数据,在进入库或者查询时。必须进行转义处理。
- 对外提供API接口的,数据传输过程中建议使用rsa+aes 相结合的方式来做加密处理,防止数据传输过程中被嗅探和篡改.
- 入库中存放密码不能明文,用户密码不能用纯md5加密 应该用md5+salt等
- 在表单提交中,最好加入token机制,以防CSRF攻击。
- 若文件包含了一个用户输入变量,请校验后缀,路径等信息,过滤一些跨目录符号。如:../ .. .. 等 防止文件遍历。
二.安全配置
- magic_quotes_gpc = On 注:此配置项在php5.4中已经移除。自动把用户提交的变量进行转换,比如把 ‘ 转为 ’ 等,相当于php中的addslashes()函数的处理。这对防止sql注射有重大作用。
- register_globals=off 注:register_globals允许php将$_GET,$_POST,$_COOKIE等变量里的内容自动注册为全局变量,如果程序里的某些变量没有经过初始化而直接使用将导致安全问题。
- expose_php=off 注:避免PHP版本信息暴露。
- display_errors = Off 注:页面不显示错误显示
- Safe_mode=on 注:启用安全模式
- disable_functions=exec,passthru,popen,proc_open,shell_exec,system,phpinfo, assert 注:禁用一些危险函数,
- allow_url_fopen = Off allow_url_include = Off 注:防止远程包含漏洞。
- session.cookie_httponly = 1 注:防止在xss漏洞中暴露cookies
- 设置好合适的 open_basedir 防止一个网站被入侵,同服所有网站被沦陷风险的跨站点攻击。
三.其它容易被忽略的地方
-
注意php各版本之间的区别 比如:php5.4 php5.5中 $_REQUEST 默认只包含 $_GET $_POST 不包含$_COOKIES
public function dispose_request() { $_POST = daddslashes($_POST); $_GET = daddslashes($_GET); $_REQUEST = daddslashes($_REQUEST); } 上面的代码如果是在PHP5。3以上的环境中运行 $_COOKIES变量是没有经过转义的。
-
通用过滤转义函数在过滤数组时,别忘记对$key过滤
function daddslashes($string, $force = 0) { if (!get_magic_quotes_gpc() || $force) { if (is_array($string)) { foreach ($string as $key => $val) { $string[$key] = daddslashes($val, $force); } } else { $string = addslashes($string); } } return $string; } $test[“username’a”]=”admin’a” //只转义了数组对应的value key没有转义 $test=daddslashes($test);
-
在用preg_replace 中,慎用e 参数
function dunserialize($string) { return unserialize(preg_replace('!s:(d+):"(.*?)";!se', '"s:".strlen("$2").":"$2";"', $string)); } $str='s:123:"${phpinfo()}";'; dunserialize($str); //程序最终会执行php代码,产生代码执行漏洞 其它会产生类似代码执行漏洞的函数还有: eval create_function call_user_func call_user_func_array assert 等 在使用这些函数时务必注意参数的合法性。
-
parse_str使用过程中注意变量覆盖和注入漏洞
parse_str('a=%27'); php<=5.3 $a=’ Php>5.3 $a=’
-
在要对浏览器标识入库时,必须做转义处理。
$agent = addslashes($_SERVER['HTTP_USER_AGENT']);
- 在取客户端IP中。若取到了$_SERVER[‘HTTP_X_FORWARDED_FOR’]这段。请校验该字段的值是否为IP格式。因为这字段内容可随意伪造。