本人新手,在《PHP安全编码》中提到“不要直接使用$_GET”,同时又提到“可以尝试在php.ini中开启magic_quotes_gpc,这样对于所有由用户GET、POST、COOKIE中传入的特殊字符都会转义”,我很纠结,是否开启magic_quotes_gpc就可以直接使用$_GET?
如下面例子中的代码本人感觉很不安全,因为没有做验证,但又不知道如何改进,希望大神能帮忙,谢谢。
<?php
$name = $_GET["name"];
$user = $_GET["user"];
mysql_query("SELECT $name FROM $user");
你是想要filter_input函数,多看手册:
http://www.w3school.com.cn/php/func_filter_input.asp
我一般都对$_POST $_GET都使用zaddslashes,然后整数的参数值进行取整,防止XSS和SQL注入
HTTP头信息:IP、浏览器信息、等也进行转义过滤防止HTTP头注入
magic_quotes_gpc开启后会影响图片上传等,自动将内容引号转义
注意PHP5.5包括之后已经将magic_quotes_gpc配置废弃
除此之外,最好在服务器方面也做关键词过滤,Mysql为业务使用到的库创建用户和赋权
可以把自己应用放服务器上,装个sqlmap注入下自己试试,以上几点做到一般情况下不会被搞,至少不会被getshell
乌云白帽子路过...
1. 像用户名这种有格式的东西,应该取到之后马上用正则表达式验证,比如
preg_match('/\A\w{6,14}\z/', $user)
就验证了它是不是6~14位的数字字母下划线。不要使用系统自带的filter,那个管不了什么用。2. 不要使用
mysql
开头的函数,要使用mysqli
,而且最好进行参数化查询而不是addslashes
,后者会有编码问题。3. 输出html的时候,默认使用
htmlspecialchars
,这个函数可以指定编码。或者你可以用现成的模板引擎。4. 比较字符串的时候,强制使用
strcmp
,不要使用双等号。5. 不要使用
$_REQUEST
。这样可以防掉95%。至于
magic_quotes_gpc
,应该早就废了吧。现在市面上这些书真的害人不浅,随便下结论或者是楼主没有仔细读。为什么直接使用 $_GET $_POST 不安全?
看了楼主的例子,应该是直接将$_GET 用在拼接SQL上,这样肯定是不安全的,所以核心信息应该是:直接将 $_GET/$_POST等用户输入的内容用于SQL拼接是不安全的,如何避免?
例如:
如果用户提交的username 为
那么就会变成这样:
那么会返回所有的用户记录。当然这里只是粗暴的举了一个例子。实际上要做XSS要熟知代码或者猜测到运行的逻辑等了解很多东西。
最简单的过滤方法是使用 mysql_real_escape_string 函数
至于 magic_quotes,是php最失败的一个改进,现已废弃,就算是低版本的PHP也一定要关闭它。
如果 $_GET
首先判断是否为空
然后对值进行判断
举个例子:
只接受数字 那就使用 php自带函数 is_numeric
一般 GET 也只是传递某个标识
总之在数据库或其他操作之前 先验证 传过来的变量 是否为自己预期的值
可以先对post或者get请求过滤,php有内置函数进行过滤,然后在使用
同意二楼的要有一个过滤,不过只是系统自带的肯定不行,最好自己再根据情况做一个过滤等之类的处理。
防止XSS攻击,最简单粗暴的做法就是用htmlspecialchars把特殊字符(
&,",',<,>
)转换为HTML实体(&"'<>
)后输出.防止XSS攻击,最复杂的就是自己写正则过滤,不过还好有HTMLPurifier库,除了能过滤XSS代码,还能把不完整的标签补全或者去掉.Yii框架也用到了这个XSS过滤库.
http://htmlpurifier.org/download
上面说的是防御XSS,下面说防御SQL注入:
PDO和MySQLi等都提供有绑定参数查询的功能,而绑定参数的目的就是防止SQL注入.
http://php.net/manual/zh/pdo.prepared-statements.php
预处理语句如此有用,以至于它们唯一的特性是在驱动程序不支持的时候,PDO将模拟处理.
这样可以确保不管数据库是否具有这样的功能,都可以确保应用程序可以用相同的数据访问模式.
上面参与查询的变量$calories被绑定为整型,$colour被绑定为长度为12个字符的字符串型.
MySQLi里同样提供有像PDO bindParam一样的bind_param,这时就不需要用addslashes,mysqli_real_escape_string之类的函数了,也不需要依赖magic_quotes_gpc配置了(该配置从PHP5.4开始已经被移除).
用PDO操作MySQL时注意禁用模拟预处理,这样才会使用真正的预处理,这样才能确保程序先发送SQL模板给MySQL编译,然后再传参数过去执行,这样可以确保这些参数不被SQL注入.MySQLi扩展的预处理默认就是真正的预处理.
这些都可以通过MySQL的general_log日志或者WireShark观察到.
对于一些要求是整型的参数,其实还可以直接用
intval($calories)
拿到整型值.如果你要验证和过滤一些用户输入的数据,又不想自己写正则表达式,那就可以用filter_input/filter_var函数,比如验证邮箱,IP等:
http://php.net/manual/zh/filter.filters.php
我来回答个无关的:
Are PDO prepared statements sufficient to prevent SQL injection?
PDO是否可以防住SQL注入。
建议你先看看
joomla-framework的input类库,地址在这里
或者先把joomla-framework的input类库在你的代码中使用(前期就不要考虑性能之类的问题),先搞明白对于$_GET(包括$_POST、$_FILES、$_COOKIE等)要进行怎样的处理,然后在以后的使用过程中自己选择是否实现简单版本。