SQL注入漏洞的产生原因:
1.前端的传参点可控(这个原因一般无法避免)
2.用户的传参到达后端后,没有经过严格的校验,而被直接带入sql语句中执行(SQL防御一般从这里入手)
SQL注入的注入点分类:数字型 和 字符型
- 数字型过滤:
$id = $_GET['id'];
if(!is_numeric($id)){ //可以判断传参是否是数字
die('参数异常,请重新输入');
}
在PHP5版本中,is_numeric函数是无法过滤16进制数的,如果攻击者将字符串转换成16进制,将无法被过滤
此时建议版本切换到PHP7,在PHP7中,可过滤16进制。
如果在PHP5中要过滤16进制,怎么实现?
elseif (substr($id,0,2)=='0x'){
die('参数又异常了,请重新输入');
}
- 字符型过滤:
字符型过滤主要采用黑名单方法来实现
1、将非法的字符串替换成空
$id = $_GET['id'];
$id = preg_replace('/union|and|or|order|select|delete|update/i','',$id);
var_dump($id)
这种方法有缺陷,如果攻击者在传参时,进行了双写,即可绕过此限制
比如:id=1 anandd 1=1
过滤后:id = 1 and 1=1
2、使用正则匹配关键字,若匹配到直接中止用户的行为
if(preg_match('/union|and|or|order|select|delete|update/i',$id)){
die('参数异常,请重新输入');
}
var_dump($id);
- 预处理
每个代码的段的执行都要经历:词法分析——语法分析——编译——执行
预处理:预编译一次,可以多次执行。用来解决一条SQL语句频繁执行的问题。
预处理语句:
1 预处理语句:prepare 预处理名字 from ‘sql语句’
2 执行预处理:execute 预处理名字 [using 变量]
-- 创建带有位置占位符的预处理语句
mysql> prepare stmt from 'select * from stuinfo where stuno=?';
mysql> set @id='s25301'; #定义变量
mysql> execute stmt using @id #给变量赋值