Mysql报错注入原理分析count、rand、groupby
字数 1424 2025-08-29 08:31:47

MySQL报错注入原理分析:count、rand、group by

0x00 基本概念

MySQL报错注入是一种利用数据库错误信息泄露数据的SQL注入技术。其中,count()rand()group by的组合使用可以产生特定的报错,攻击者可以利用这些报错信息获取数据库中的敏感数据。

0x01 核心报错语句

最常见的报错注入语句:

select count(*), (floor(rand(0)*2))x from information_schema.tables group by x;

0x02 报错条件分析

必要条件

  1. 必须使用count(*)函数
  2. 必须使用rand()函数(特别是rand(0)
  3. 必须使用group by子句
  4. 表中记录数必须≥3条(对于rand(0)

记录数量影响

  • 使用rand(0)时:

    • 记录数<3:不会报错
    • 记录数≥3:必定报错
  • 使用rand()(无参数)时:

    • 记录数≥2:可能随机报错
    • 报错与否取决于虚表是否已存在0和1键值

0x03 随机因子分析

rand() vs rand(0)

  • rand():真正的随机函数,每次调用产生不同的随机序列
  • rand(0):伪随机函数,给定相同种子(0)时产生确定性的序列(011011...)

确定性影响

  • floor(rand(0)*2):产生固定的011011...序列,导致可预测的报错
  • floor(rand()*2):产生随机序列,报错不可预测

0x04 虚拟表工作原理

当执行select count(*) from table group by x时,MySQL会:

  1. 建立一个虚拟表,包含:

    • key:group by的列(主键,不可重复)
    • count(*):计数
  2. 查询流程:

    • 取数据库记录
    • 计算group by表达式
    • 检查虚表是否存在该key:
      • 存在:对应count(*)加1
      • 不存在:插入新记录(key=表达式值,count(*)=1)

0x05 报错原理详解

select count(*) from T-Safe group by floor(rand(0)*2);为例:

  1. 初始空虚拟表:

    key | count(*)
    
  2. 查询第一条记录:

    • 计算floor(rand(0)*2)=0(第一次计算)
    • 虚表无0键,需插入:
      • 再次计算floor(rand(0)*2)=1(第二次计算)
      • 插入虚表:
        key | count(*)
        1   | 1
        
  3. 查询第二条记录:

    • 计算floor(rand(0)*2)=1(第三次计算)
    • 虚表存在1键,直接count(*)加1:
      key | count(*)
      1   | 2
      
  4. 查询第三条记录:

    • 计算floor(rand(0)*2)=0(第四次计算)
    • 虚表无0键,需插入:
      • 再次计算floor(rand(0)*2)=1(第五次计算)
      • 尝试插入虚表:
        key | count(*)
        1   | 2
        
      • 但1键已存在,主键冲突导致报错

0x06 关键点总结

  1. 计算次数

    • floor(rand(0)*2)在查询过程中被计算多次
    • 3条记录时共计算5次(查询3次+插入2次)
  2. 确定性序列

    • rand(0)产生固定序列011011...
    • 第4次计算=0,第5次计算=1,导致主键冲突
  3. 记录数要求

    • 需要≥3条记录才能确保floor(rand(0)*2)在插入时产生冲突
  4. 无参数rand()

    • 随机性导致报错不可预测
    • 当虚表未同时包含0和1键时可能报错

0x07 实际应用

在SQL注入中,可以利用此报错机制获取数据:

select count(*), concat((select version()), floor(rand(0)*2))x from information_schema.tables group by x;

这将把数据库版本信息包含在错误消息中返回。

0x08 防御措施

  1. 使用参数化查询
  2. 对用户输入进行严格过滤
  3. 避免直接拼接SQL语句
  4. 设置数据库错误信息不对外显示
MySQL报错注入原理分析:count、rand、group by 0x00 基本概念 MySQL报错注入是一种利用数据库错误信息泄露数据的SQL注入技术。其中, count() 、 rand() 和 group by 的组合使用可以产生特定的报错,攻击者可以利用这些报错信息获取数据库中的敏感数据。 0x01 核心报错语句 最常见的报错注入语句: 0x02 报错条件分析 必要条件 必须使用 count(*) 函数 必须使用 rand() 函数(特别是 rand(0) ) 必须使用 group by 子句 表中记录数必须≥3条(对于 rand(0) ) 记录数量影响 使用 rand(0) 时: 记录数 <3:不会报错 记录数≥3:必定报错 使用 rand() (无参数)时: 记录数≥2:可能随机报错 报错与否取决于虚表是否已存在0和1键值 0x03 随机因子分析 rand() vs rand(0) rand() :真正的随机函数,每次调用产生不同的随机序列 rand(0) :伪随机函数,给定相同种子(0)时产生确定性的序列(011011...) 确定性影响 floor(rand(0)*2) :产生固定的011011...序列,导致可预测的报错 floor(rand()*2) :产生随机序列,报错不可预测 0x04 虚拟表工作原理 当执行 select count(*) from table group by x 时,MySQL会: 建立一个虚拟表,包含: key:group by的列(主键,不可重复) count(* ):计数 查询流程: 取数据库记录 计算group by表达式 检查虚表是否存在该key: 存在:对应count(* )加1 不存在:插入新记录(key=表达式值,count(* )=1) 0x05 报错原理详解 以 select count(*) from T-Safe group by floor(rand(0)*2); 为例: 初始空虚拟表: 查询第一条记录: 计算 floor(rand(0)*2) =0(第一次计算) 虚表无0键,需插入: 再次计算 floor(rand(0)*2) =1(第二次计算) 插入虚表: 查询第二条记录: 计算 floor(rand(0)*2) =1(第三次计算) 虚表存在1键,直接count(* )加1: 查询第三条记录: 计算 floor(rand(0)*2) =0(第四次计算) 虚表无0键,需插入: 再次计算 floor(rand(0)*2) =1(第五次计算) 尝试插入虚表: 但1键已存在,主键冲突导致报错 0x06 关键点总结 计算次数 : floor(rand(0)*2) 在查询过程中被计算多次 3条记录时共计算5次(查询3次+插入2次) 确定性序列 : rand(0) 产生固定序列011011... 第4次计算=0,第5次计算=1,导致主键冲突 记录数要求 : 需要≥3条记录才能确保 floor(rand(0)*2) 在插入时产生冲突 无参数rand() : 随机性导致报错不可预测 当虚表未同时包含0和1键时可能报错 0x07 实际应用 在SQL注入中,可以利用此报错机制获取数据: 这将把数据库版本信息包含在错误消息中返回。 0x08 防御措施 使用参数化查询 对用户输入进行严格过滤 避免直接拼接SQL语句 设置数据库错误信息不对外显示