渗透测试之SQL注入(四)
字数 1568 2025-08-15 21:32:20

SQL注入之报错注入技术详解

一、报错注入概述

报错注入(Error-based SQL Injection)是一种通过故意构造错误的SQL语句,利用数据库返回的错误信息来获取数据库数据的注入技术。与布尔盲注不同,报错注入可以直接从错误信息中提取数据,效率更高。

二、报错注入产生条件

  1. 数据库报错函数未关闭:应用系统未关闭数据库报错函数,导致SQL语句错误直接回显在页面上
  2. 输入未充分过滤:后台未对MySQL报错函数进行有效过滤
  3. 错误信息暴露:部分错误信息甚至直接泄露数据库名和表名等敏感信息

三、常用报错函数

MySQL中常用的报错函数包括:

  1. updatexml()
  2. floor()
  3. extractvalue()
  4. exp()

其中updatexml()floor()是最常用的报错函数。

四、updatexml()函数详解

4.1 函数语法

UPDATEXML(XML_document, XPath_string, new_value)

参数说明:

  • XML_document:String格式,XML文档对象名称
  • XPath_string:Xpath格式的字符串
  • new_value:String格式,替换查找到的符合条件的数据

4.2 报错原理

updatexml()函数找不到相应的xpath路径时,会报出错误信息。我们可以利用这个特性,在xpath路径中插入我们想要查询的数据。

4.3 辅助函数

  1. concat():用于连接字符串
  2. concat_ws():语法为concat_ws(分隔符,字符串1,字符串2,...),例如concat_ws(0x7e,database(),user())会把查出来的库名和用户通过~连接起来完成报错

五、floor()函数报错注入

5.1 关键函数说明

  1. rand()

    • 产生0到1之间的随机数
    • 当提供种子参数(如0)后,产生的值是伪随机的(可预知的)
  2. floor()

    • 返回小于等于该值的最大整数
    • floor(rand(0)*2)可以产生确定的两个数:0和1

5.2 报错原理分析

利用group bycount(*)结合使用时MySQL内部创建虚拟表的机制:

  1. MySQL会建立一个虚拟表,包含两个字段:

    • 分组的key
    • 计数值count(*)
  2. 查询数据时:

    • 先检查虚拟表中是否存在该分组
    • 存在则计数值加1
    • 不存在则新建该分组
  3. 关键点:

    • rand()的特殊性:如果使用rand(),该值会被计算多次
    • group by进行分组时,floor(rand(0)*2)执行两次:
      • 第一次:查看分组是否存在
      • 第二次:插入新分组时再次计算

5.3 具体报错过程

floor(rand(0)*2)产生的序列是固定的:0,1,1,0,1,...

  1. 遇到第一个值0:不存在,准备插入分组

    • 插入时floor(rand(0)*2)再次计算,得到1
    • 实际插入分组1
  2. 遇到第二个值1:已存在分组1,计数加1

  3. 遇到第三个值1:已存在分组1,计数加1

  4. 遇到第四个值0:不存在,准备插入分组

    • 插入时floor(rand(0)*2)再次计算,得到1
    • 尝试插入分组1,但分组1已存在
    • 报错产生

六、实际注入示例

6.1 获取数据库名

?id=-1' union select count(*),count(*), concat('~',(select database()),'~',floor(rand()*2)) as a from information_schema.tables group by a--+

6.2 获取表名

?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1)--+

6.3 获取列名

?id=1' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1),0x7e),1)--+

6.4 获取数据

?id=1' and updatexml(1,concat(0x7e,(select username from users limit 0,1),0x7e),1)--+

七、防御措施

  1. 关闭错误回显:生产环境应关闭数据库错误回显
  2. 参数化查询:使用预处理语句和参数化查询
  3. 输入验证:对用户输入进行严格过滤和验证
  4. 最小权限原则:数据库用户应仅具有必要的最小权限
  5. WAF防护:部署Web应用防火墙拦截注入攻击

八、总结

报错注入是一种高效的SQL注入技术,利用数据库的错误回显机制直接获取数据。理解其原理不仅有助于渗透测试,也能帮助开发人员更好地防御此类攻击。在实际测试中,应根据目标环境选择合适的报错函数和技术。

SQL注入之报错注入技术详解 一、报错注入概述 报错注入(Error-based SQL Injection)是一种通过故意构造错误的SQL语句,利用数据库返回的错误信息来获取数据库数据的注入技术。与布尔盲注不同,报错注入可以直接从错误信息中提取数据,效率更高。 二、报错注入产生条件 数据库报错函数未关闭 :应用系统未关闭数据库报错函数,导致SQL语句错误直接回显在页面上 输入未充分过滤 :后台未对MySQL报错函数进行有效过滤 错误信息暴露 :部分错误信息甚至直接泄露数据库名和表名等敏感信息 三、常用报错函数 MySQL中常用的报错函数包括: updatexml() floor() extractvalue() exp() 其中 updatexml() 和 floor() 是最常用的报错函数。 四、updatexml()函数详解 4.1 函数语法 参数说明: XML_ document :String格式,XML文档对象名称 XPath_ string :Xpath格式的字符串 new_ value :String格式,替换查找到的符合条件的数据 4.2 报错原理 当 updatexml() 函数找不到相应的xpath路径时,会报出错误信息。我们可以利用这个特性,在xpath路径中插入我们想要查询的数据。 4.3 辅助函数 concat() :用于连接字符串 concat_ ws() :语法为 concat_ws(分隔符,字符串1,字符串2,...) ,例如 concat_ws(0x7e,database(),user()) 会把查出来的库名和用户通过 ~ 连接起来完成报错 五、floor()函数报错注入 5.1 关键函数说明 rand() : 产生0到1之间的随机数 当提供种子参数(如0)后,产生的值是伪随机的(可预知的) floor() : 返回小于等于该值的最大整数 floor(rand(0)*2) 可以产生确定的两个数:0和1 5.2 报错原理分析 利用 group by 与 count(*) 结合使用时MySQL内部创建虚拟表的机制: MySQL会建立一个虚拟表,包含两个字段: 分组的key 计数值count(* ) 查询数据时: 先检查虚拟表中是否存在该分组 存在则计数值加1 不存在则新建该分组 关键点: rand() 的特殊性:如果使用 rand() ,该值会被计算多次 group by 进行分组时, floor(rand(0)*2) 执行两次: 第一次:查看分组是否存在 第二次:插入新分组时再次计算 5.3 具体报错过程 floor(rand(0)*2) 产生的序列是固定的:0,1,1,0,1,... 遇到第一个值0:不存在,准备插入分组 插入时 floor(rand(0)*2) 再次计算,得到1 实际插入分组1 遇到第二个值1:已存在分组1,计数加1 遇到第三个值1:已存在分组1,计数加1 遇到第四个值0:不存在,准备插入分组 插入时 floor(rand(0)*2) 再次计算,得到1 尝试插入分组1,但分组1已存在 报错产生 六、实际注入示例 6.1 获取数据库名 6.2 获取表名 6.3 获取列名 6.4 获取数据 七、防御措施 关闭错误回显 :生产环境应关闭数据库错误回显 参数化查询 :使用预处理语句和参数化查询 输入验证 :对用户输入进行严格过滤和验证 最小权限原则 :数据库用户应仅具有必要的最小权限 WAF防护 :部署Web应用防火墙拦截注入攻击 八、总结 报错注入是一种高效的SQL注入技术,利用数据库的错误回显机制直接获取数据。理解其原理不仅有助于渗透测试,也能帮助开发人员更好地防御此类攻击。在实际测试中,应根据目标环境选择合适的报错函数和技术。