SQL 报错注入之 FLOOR() 函数报错:主键重复

报错注入(Error-based SQL Injection)是一种常见的 SQL 注入攻击方式。通过构造特殊的 SQL 语句触发数据库错误,攻击者可以借助数据库返回的错误信息获取内部数据。在此类攻击中,FLOOR() 函数常被用于制造错误,特别是通过触发主键重复错误来获取数据库的内部信息。

一、FLOOR() 函数引发主键重复报错的原理

FLOOR() 是 MySQL 的数学函数,用于返回小于或等于指定数值的最大整数。例如:

SELECT FLOOR(4.8);  -- 返回 4

在 SQL 报错注入攻击中,攻击者常利用 FLOOR() 函数制造重复键错误。例如,结合 RAND() 函数生成随机数,然后通过 FLOOR() 将结果转换为整数,从而在插入数据时触发主键冲突的错误。通过这个过程,数据库会返回包含内部信息的错误消息。

1.1 基本原理

通过生成随机数并将其转为整数,攻击者可以制造随机但有限的重复主键错误:

INSERT INTO table_name (id, column1)
VALUES (FLOOR(RAND() * X), 'value');

由于 RAND() 函数生成的随机数有限,而主键要求唯一性,这种操作在多次执行后极有可能触发主键重复错误。MySQL 会返回详细的错误信息,其中可能包含表名、列名等敏感信息。

二、FLOOR() 函数引发主键重复报错的攻击步骤

2.1 识别注入点

首先,攻击者需要识别可能存在 SQL 注入漏洞的输入点。这通常通过提交特殊字符或语句进行测试,如单引号(')、双引号(")或常见的注入测试语句(如 OR 1=1)等。

示例:

SELECT * FROM users WHERE id = 1 OR 1=1;

如果返回了意外的数据,表明存在 SQL 注入漏洞。

2.2 构造恶意查询

接下来,攻击者会构造利用 FLOOR() 函数引发主键重复的恶意查询。该查询通过生成随机数并强制转为整数,企图在插入数据时制造重复主键错误。

示例:

INSERT INTO users (id, username)
VALUES (FLOOR(RAND() * 2), 'malicious_user');

在多次执行该查询后,极有可能触发主键重复错误。MySQL 会返回错误信息,如:

ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

2.3 分析错误信息

通过分析返回的错误信息,攻击者可以获取有关数据库内部结构的线索,例如主键列的名称、表名等。这些信息可以进一步帮助攻击者精确定位数据库的弱点。

示例:

ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY' in table 'users'

攻击者通过这个错误信息得知了表名 users 以及主键列的名称为 id。

2.4 提取数据

攻击者可以进一步调整注入语句,利用报错机制逐步提取数据库中的敏感信息。例如,攻击者可以使用 UNION SELECT 或 SUBSTRING() 等函数结合 FLOOR() 和 RAND(),以触发更多报错信息,进而提取数据。

示例:

INSERT INTO users (id, username)
VALUES (FLOOR(RAND() * 2), (SELECT database()));

此查询将尝试在插入时返回数据库名称,并利用 FLOOR() 和 RAND() 制造重复键错误。

三、FLOOR() 报错注入示例

3.1 基本示例

通过 FLOOR() 结合 RAND() 函数制造重复主键错误:

INSERT INTO products (id, name)
VALUES (FLOOR(RAND() * 10), 'malicious_product');

该查询在多次执行后将触发主键重复错误,并返回错误信息。

3.2 结合子查询的高级示例

攻击者可以利用子查询在插入过程中制造报错,并提取数据库的敏感信息。例如,通过触发重复主键错误来暴露数据库名称:

INSERT INTO users (id, username)
VALUES (FLOOR(RAND() * 2), (SELECT database()));

该查询将在数据库返回错误时泄露当前数据库的名称。

四、防御措施

为了防止 FLOOR() 函数引发的报错注入,开发者可以采取以下防御措施:

4.1 输入验证与过滤

  • 严格验证输入:对用户输入进行严格验证,确保所有输入都符合预期格式,避免将未经处理的输入直接嵌入 SQL 查询。
  • 使用预处理语句:通过使用预处理语句(Prepared Statements)和绑定参数来避免 SQL 注入。

4.2 错误信息隐藏

  • 关闭详细错误信息:在生产环境中,应关闭数据库的详细错误信息输出,以防止错误信息泄露数据库内部结构。

    示例:在 MySQL 配置文件中设置 log_error_verbosity 参数,限制错误日志的详细程度。

4.3 最小权限原则

  • 限制数据库用户权限:为应用程序使用的数据库用户分配最小权限,防止其对敏感系统表(如 information_schema)的访问,减少潜在风险。

五、思维导图

SQL 报错注入之 FLOOR 函数报错:主键重复
    1. 原理分析
        1.1 FLOOR 函数与 RAND 函数结合
        1.2 触发主键重复错误
    2. 攻击步骤
        2.1 识别注入点
        2.2 构造恶意查询
        2.3 分析错误信息
        2.4 提取数据
    3. 示例
        3.1 基本示例
        3.2 高级示例
    4. 防御措施
        4.1 输入验证与过滤
        4.2 错误信息隐藏
        4.3 最小权限原则

六、总结

通过 FLOOR() 函数制造主键重复错误是 SQL 报错注入的一种常见技术。攻击者利用数据库在处理错误时返回的详细信息,逐步获取数据库的内部结构。为了防止此类攻击,开发者应对输入进行严格验证,使用预处理语句,并在生产环境中隐藏详细错误信息。同时,遵循最小权限原则,减少数据库用户的权限,以提升整体系统的安全性。