“SQL注入”这是有关程序安全的一节内容。学习编程一要学会写代码实现功能,二就是程序中无处不在的隐患要做好安全防护。现在大家都普遍用框架开发程序,基础的安全防范框架都已帮助做好,程序员只注重于逻辑功能的开发就好。“SQL注入”框架都会做各种安全防护,程序员只需要配置下。虽然框架带来了便捷,但作为程序员必须要懂什么是“SQL注入”。
所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
比如一个网站的用户登录功能用了如下的select语句:
$sql = "SELECT * FROM `user` WHERE name='{$name}' and pass=md5('{$pass}')"
当$name变量和$pass变量输入的是正常数据:
$name = " 'admin' ";
$pass = " '1234abcd' ";
在mysql执行的SQL语句
SELECT * FROM `user` WHERE name='admin' and pass=md5('1234abcd')
这样的SQL语句不会造成安全影响。
可当$name变量和$pass变量输入的是非正常数据,而程序又没有对用户输入的数据做安全处理时:
$name = " 'or 1#' ";
$pass = " '1234abcd' ";
在mysql执行的SQL语句
SELECT * FROM `user` WHERE name='' or 1#' and pass=md5('1234abcd')
首先说明下:在SQL语句中“#”是注释符号。
上面的那个SQL语句就是有问题的,它的where条件永远为真,这样会造成程序出错。如果网站后台是这样写的,不法分子就可能会获取管理权限。
类似的还有这样 ' or 1 or '
SELECT * FROM `user` WHERE name=' ' or 1 or ' ' and pass=md5('')
说明:
不只是这两个“字符”可以造成SQL注入,任何对原SQL语句造成改变的字符都有可能会SQL注入。
不仅仅在登录时,可以被注入,任何用户数据参与执行,都可以被注入。
怎么去预防呢?
1)验证:一定要对用户输入的数据做好验证,重要的input字段不能为空,限定数据类型。比如:
ID需要整型的数据,将用户传递的请求数据强制转换成整型。
$_GET[‘m_id’] = " '0 or 1# ' ";
Delete from `user` where id= {intval($_GET[‘m_id’])};
用户名仅仅由字母、数字和特定的字符组成,使用正则做好验证,如果检测不满足要求,则不执行SQL。
2)过滤:使用PHP的过滤函数对用户输入的数据做安全处理。比如我们前面讲过的addslashes函数(第六章第2节),PDO对象prepare方法也能起到过滤作用,后续操作详情查看手册。
楠神在这章的项目写得很简单,必要的安全代码都没有写,通过以上两点,大家可以在我代码基础上做下安全防护。
3)业务逻辑:不一样的业务逻辑有时也能起到安全的作用。就比如上面的select语句把name和pass都当成where条件,这样写代码变简单了,安全却变差了,不如楠神项目中写的那样好。先通过name获取用户的pass,再与用户输入的pass做比对。
说明:写代码有很多细节会影响程序的安全,等到后面写大项目时,楠神还会介绍一些细节的安全问题。
附:
“SQL注入”的危害不只是暴库获取数据,获取后台登录权限,对数据库做增删改操作,它还可以获取服务器的webshell,具体原理:
黑客可以通过SQL注入漏洞,先把木马代码写入mysql,然后执行select..in To outfile 查询输出php文件,这个PHP文件就是一个PHP木马文件,利用PHP木马文件即可拿到整台服务器的webshell。