一、SQL注入分类
按数据类型分
数字类型
后台语句可能为:
$id=$_POST['id']
select user,password from users where id=$id
字符类型
$id=$_POST['id']
后台语句可能为:select user,password from users where id='$id'
总结:
- 数字类型直接将后台接收到用户输入的内容带入到数据库中执行;而字符型将接收到的内容添加到引号内然后进行执行。
- 字符型注入需要考虑语句的闭合问题,而数字类型则不存在
MySQL手工测试字符型闭合语句
select user,password from users where id='$id'
select user,password from users where id="$id"
select user,password from users where id=($id)
select user,password from users where id=('$id') 括号可以无限叠加
select user,password from users where id=("$id") 括号可以无限叠加
select user,password from users where id=(($id)) 括号可以无限叠加
可参考sqli-labs靶机进行测试学习
按注入位置分
GET方式注入
注入参数以GET方式进行提交
POST方式注入
注入参数以POST方式进行提交
基于cookie的注入
后台接收cookie内的参数,在http的cookie字段中存在注入漏洞
基于http头部的注入
后台会接收referer或user-agent字段中的参数,http头部中的referer、user-agent字段中存在注入漏洞
盲注
基于布尔的盲注
特点:网站页面在输入条件为true和false的情况下会显示不同,但页面中没有输出。此时需要在SQL语句之后添加条件判断。
猜解思路:
- 猜解数据库:先构造条件判断当前数据库的名字长度,然后逐字猜解数据库名。
- 猜解数据表:先构造条件判断数据表的数量,然后逐个进行猜解,先猜解表名长度然后逐字猜解表名。
- 猜解数据列:指定数据库中的指定表进行猜解字段,首先猜解字段的数目,然后逐个猜解字段
- 猜解内容:指定数据列,先查询数据的条数,然后逐条猜解其中的内容
基于时间的盲注
特点:网站页面在输入条件为真和为假返回的页面相同,但通过延时函数构造语句,可通过页面响应时间的不同判断是否存在注入
猜解思路:
类似基于布尔的盲注,只是将条件为真转换为延时响应
常用函数
if(condition,A,B)
:若condition返回真则执行A,假则执行Bsubstr(str,A,B)
:字符串截取函数,截取str字符串从A位置开始,截取B个字符left(str,A)
:类似字符串截取函数,返回str字符串从左往右数的A个字符count(A)
:计算A的数目,常用与查询数据表、数据列、数据内容的条数len(A)
:计算A的长度,常用于返回数据库名、数据表名、数据列名的长度ascii(A)
:返回A的ascii码,当逐字猜解限制单引号的输入时,可以通过查询ascii码来绕过
基于UNION的注入
首先通过order by 进行判断查询参数的数目,然后构造union查询,查看回显。有时需要将前面参数名修改为假的参数。如id=-10’ union select 1,2,查找页面中1和2的位置,在页面中显示的数字的地方构造查询的内容。
若页面无回显但报错可以尝试报错注入
基于报错的注入
常用函数:
updatexml(1,concat('~',SQL语句,'~'),1)
extractvalue(1,concat('~',(SQL语句)))
宽字节注入
宽字节注入的原理即为数据库的编码与后台程序的编码不一致,数据库中一个字符占两个字节,而后台程序为一个字符占一个字节,当后台程序对输入的单引号的字符进行转义时,通过在这些转义的字符前输入%bf然后将%bf’带入后台程序时会转义为%bf’,此时带入数据库中,数据库将%bf\看作是一个中文字符从而使用单引号将SQL语句进行闭合。
基于base64加解密注入
后台程序在接收用户输入的参数后先进行base64解码然后带入到SQL语句中执行。所以这种类型的注入首先需要将payload进行base64加密
搜索型注入
当搜索关键字时,后台SQL语句可能为:select username from users where id='%$id%'
,此时构造闭合语句时需要考虑%的闭合
二、防御
代码层面
- 对用户输入的内容进行转义(PHP中addslashes()、mysql_real_escape()函数)。
- 限制关键字的输入(PHP中preg_replace()函数正则替换关键字),限制输入的长度 。
- 使用SQL语句预处理,对SQL语句首先进行预编译,然后进行参数绑定,最后传入参数。
网络层面
部署防火墙