php是一门极其灵活的编程语言,它是高效开发web程序的最佳选择之一。但是灵活性往往带来安全性问题,这就需要我们工程师时刻审视自己的代码安全性。下面列举一些经常容易出现安全性问题的场景极其解决方案。
对于php的安全防患,是有一些基本原则的:
1.不信任任何从客户端传入的数据,如$SERVER,$_GET,$_POST,$_COOKIE,$FILES,$ENV,$REQUEST等。
2.最小化原则,将用户输入的数据的范围限制到最小化
3.安全的代码不依赖任何安全配置,不能寄希望与php.ini的安全性配置
4.程序的错误信息对外界屏蔽,程序的错误信息会给攻击者带来极大帮助
本文列举了数据库操作场景、文件操作场景、命令执行场景下容易出现的安全问题以及应对方案。
1 数据库操作场景
1.1 字符串变量注入
比如如下php代码:。
这段代码没有对不可信输入做检查,当$_POST['user'] = "' OR '' = '"
且$_POST['password'] = "' OR '' = '"
,实际的sql为:select * from user where name = '' OR '' = '' and password = '' OR '' = ''
,这样的sql就可能将所有的数据库中用户信息泄露。
1.2 整形注入
比如如下php代码:。
这段代码没有对不可信输入做检查,当$_POST['id'] = "1 OR '' = ''"
,实际的sql为:select * from user where id = 1 OR '' = ''
,这样的sql就可能将所有的数据库中用户信息泄露。
安全编码建议:以上情况都是要使用客户端传来的参数,因此必须严格检查。对于字符串型变量最好使用mysql_real_escape_string进行过滤,而对于整形变量必须使用intval来保证类型。
2 文件操作场景
2.1 文件名安全问题
如下php代码段:
include,include_once,require,requre_once这些函数的本质是载入php文件并执行,因此使用这些函数时务必非常小心。这段代码非常不安全,比如$_GET['file']="../../../../../../../../etc/passwd%00.php"
时,将会打开敏感文件/etc/passwd,因为%00
是\0
url编码后的值,对于操作系统而言相当于字符串的结束符。
2.2 文件读写安全问题
如下php代码段:
当$conent="eval($php_code)"
时,会执行代码中的php_code,理论上攻击者可以运行任何php代码。这段代码主要问题在于用双引号
包含用户提交的文件内容。
安全编码建议:将输出到文件的数据放到单引号中而非双引号。在php中表示一个字符串的方法有三种:单引号、双引号、定界符,和其他两种语法不同,单引号字符串中出现的变量和转义序列不会被变量的值替代。无论从效率还是安全性方面,都强烈推荐使用单引号。
3 命令行操作场景
如下php代码段:
$request变量来自于用户URL的输入,最终进入到system函数里作为命令来执行,但是这段代码没有安全处理用户的输入,任意用户都可以通过如下URL来在机上执行自己的命令, php?cmd=1190&func=sync_css&uri=hi&from=;cat /etc/passwd;&to=hi&1=2
最后导致系统的沦陷。
安全编码建议我们应该尽量避免使用systemexecpopenpassthru, 反引号(``)......等直接执行系统命令的函数如果必须使用这些函数的时候我们就需要在用户的参数进入system函数之前经过过滤。Php提供两个作为命令安全输入的函数一个是escapeshellarg一个是escapeshellcmd。
4.安全配置
register_globals = Off
register_globals允许php将$_GET和$_POST,$_COOKIE等变量里的内容自动注册为全局变量,如果程序里的某些变量没有经过初始化而直接使用将导致安全问题。
isplay_errors = Off, log_errors = On
如果脚本运行时出错,错误信息将提供非常多的信息给黑客,里面可能包含了web路径,一些调试信息甚至是部分的php代码。我们应该强制在线上业务关闭错误信息对外的显示该选项。并将error_log 指定为我们自定义的错误路径。
expose_php = Off
防止php在http头输出中加入版本信息防止恶意攻击者从中获取敏感信息强制执行将此选项为off。
allow_url_include = Off
防止php将远程资源作为php源文件执行。从而从一定程度上防范文件包含漏洞。强制执行此选项为off。
max_input_vars = 1000
设置用户输入生成的最大变量值。防止利用大量无用变量造成php程序hashtable冲突导致占用大量系统资源。建议执行为默认1000个值。