浅谈SQL注入防御手段

sql语句预编译

例如:

1
2
3
4
String sql = "select id, no from user where id=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, id);
ps.executeQuery();

这里采用了PreparedStatement,就会将sql语句预先编译好,也就是SQL引擎会预先进行语法分析,产生语法树,生成执行计划,也就是说,后面你输入的参数,无论你输入的是什么,都不会影响该sql语句的 语法结构了,因为语法分析已经完成了,而语法分析主要是分析sql命令,比如 select ,from ,where ,and, or ,order by 等等。所以即使你后面输入了这些sql命令,也不会被当成sql命令来执行了,因为这些sql命令的执行, 必须先的通过语法分析,生成执行计划,既然语法分析已经完成,已经预编译过了,那么后面输入的参数,是绝对不可能作为sql命令来执行的,只会被当做字符串字面值参数。所以sql语句预编译可以防御sql注入

讲一下另外一个预编译,就是用PDO,这里就推荐几篇文章自己看一下,简单说一下就是原理跟上面的差不多,把执行语句和变量分开,变量分别绑定,分别传参,从而阻止了注入,只是底层不太明了,自己真菜。。
https://segmentfault.com/q/1010000000723496
http://www.cnblogs.com/zl0372/p/php_28.html
https://blog.csdn.net/theVicTory/article/details/62884352

预编译方法就最有效!!也是如今市场上最流行的方式了

检查变量数据类型和格式

例如:

1
2
3
$uid=checkuid($uid);    //检测$uid是不是数字类型,不是不继续往下运行

$sql = "SELECT uid,username FROM user WHERE uid='{$uid}‘;

这段语句是为了保证了id是数字类型,checkid是一个自定义的函数,但是千万别直接里面写一个is_numeric就结束了啊,这很容易就可以用16进制或者是科学计数法去绕过的,这个还是少用吧,毕竟自写函数就像是写黑名单,肯定会有纰漏的

过滤特殊字符

这个方法也相当于黑名单,还是少用为好,一般有纰漏就可以去绕过的了

例如:

1
2
3
4
5
6
7
8
9
10
public static boolean sql_inj(String str) 
{
String inj_str = “’|and|exec|insert|select|delete|update|
count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,”;
String inj_stra[] = split(inj_str,”|”);
for (int i=0 ; i < inj_stra.length ; i++ )
{ if (str.indexOf(inj_stra[i])>=0) { return true; }
}
return false;
}

黑名单只能追求全面去避免SQL注入了

转译特殊符号

例如:

1
2
3
$uid = isset($_GET['uid']) ? $_GET['uid'] : 0;
$uid = addslashes(uid);
$sql = "SELECT uid,username FROM user WHERE uid='{$uid}'";

这里就是利用了addslashes函数去对特殊字符进行转义,比如单引号会被转译成\’,所以无法闭合和注释。不能达到sql注入攻击的效果。一般在CTF题目里面如果我看到这个函数的话,我会预测有75%可能不是SQL注入,先去看看其他点是否存在漏洞

从中间件配置上防止SQL注入

通过启用php.ini配置文件中的magic_quote_gpc (魔术字符),就可以将大部分想利用SQL注入漏洞的骇客拒绝于门外。开启magic_quote_gpc=on之后,能实现addslshes()stripslashes()这两个函数的功能,这就从很大程度上防止了sql注入。PHP 5.4 之前 PHP 指令 magic_quotes_gpc 默认是 on, 实际上所有的 GET、POST 和 COOKIE 数据都用被 addslashes() 了。 不要对已经被 magic_quotes_gpc 转义过的字符串使用 addslashes(),因为这样会导致双层转义。 遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测
但是只开启magic_quote_gpc ,对防止sql注入是远远不够的。
例如以下代码:

1
2
3
$uid = isset($_GET['uid']) ? $_GET['uid'] : 0;
$uid = addslashes(uid);
$sql = "SELECT uid,username FROM user WHERE uid={$uid}";

在这条sql语句中并没有单引号的保护,攻击者既不需要闭合单引号也不需要注释单引号,所以gpc开启对sql注入攻击的防范并没有作用。所以说变量还是要用引号包住才好,别直接就赋值了。。。

通过安全waf去防御

过安全waf达到一定程度防御,软件层面的不多说。

小结

总的来说,现在很多网站多不会再使用字符串拼接去查找数据库里面的内容了,大多数现在使用的是预编译,除了那些荒废的网站以及CTF题目里面会使用,那是不是说以后挖洞挖SQL注入的就比较难了233333。。。我还是太年轻了


听说,打赏我的人最后都成了大佬。



文章目录
  1. 1. sql语句预编译
  2. 2. 检查变量数据类型和格式
  3. 3. 过滤特殊字符
  4. 4. 转译特殊符号
  5. 5. 从中间件配置上防止SQL注入
  6. 6. 通过安全waf去防御
  7. 7. 小结