SQL注入之二次注入
字数 1194 2025-08-15 21:32:05

SQL二次注入攻击详解

一、二次注入原理

二次注入是一种特殊的SQL注入攻击形式,其核心原理如下:

  1. 数据存储阶段:攻击者向数据库存入恶意构造的数据(如包含SQL特殊字符的输入)
  2. 数据转义处理:在数据插入数据库时,应用程序会对输入进行转义处理(如使用mysql_real_escape_string()函数)
  3. 数据信任假设:应用程序默认数据库中存储的数据都是安全的,在后续查询使用时不再进行转义处理
  4. 恶意数据触发:当这些被存储的恶意数据被应用程序从数据库取出并用于构建新的SQL查询时,就会触发注入漏洞

与普通SQL注入相比,二次注入更难被发现,因为:

  • 攻击发生在两个阶段(存储阶段和使用阶段)
  • 常规安全扫描工具难以检测
  • 攻击行为与正常操作流程相似

二、典型攻击场景分析

以SQL-Labs第24关为例,演示完整的二次注入攻击流程:

1. 注册恶意账号

攻击者注册一个特殊构造的用户名:

admin'#
  • 单引号(')用于破坏SQL语句结构
  • 井号(#)是MySQL注释符,用于注释掉后续语句

2. 修改密码操作

当攻击者登录后尝试修改密码时,后端执行的SQL语句:

$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass'";

由于$username从数据库直接取出未转义,实际执行的语句变为:

UPDATE users SET PASSWORD='newpass' where username='admin'#' and password='$curr_pass'

被注释掉的部分:

#' and password='$curr_pass'

最终有效执行的语句:

UPDATE users SET PASSWORD='newpass' where username='admin'

结果:admin用户的密码被修改,而非攻击者自己的账号

三、深入技术分析

1. 关键函数说明

mysql_real_escape_string()函数:

  • 转义SQL语句中的特殊字符
  • 影响的特殊字符:\x00, \n, \r, \, ', ", \x1a
  • 仅在数据插入时有效,无法防止从数据库取出数据后的注入

2. 二次注入的利用方式

通过UNION查询获取敏感信息:

  1. 注册特殊构造的用户名:
1' union select 1,user(),database()#
  1. 当应用程序从数据库取出该用户名并用于查询时:
$sql_detail = "SELECT * FROM users where username='$username'";

实际执行:

SELECT * FROM users where username='1' union select 1,user(),database()#'
  1. 有效执行的查询:
SELECT * FROM users where username='1' union select 1,user(),database()

结果:泄露数据库用户和当前数据库名称

四、防御措施

  1. 输入验证

    • 对所有用户输入进行严格验证
    • 使用白名单机制限制输入格式
  2. 参数化查询

    • 使用预处理语句(Prepared Statements)
    • 确保查询结构与数据分离
  3. 输出转义

    • 即使数据来自数据库,在使用前也应进行转义
    • 根据使用场景选择合适的转义函数(如HTML、SQL等)
  4. 最小权限原则

    • 数据库账户应仅具有必要的最小权限
    • 避免使用高权限账户执行常规操作
  5. 代码审计

    • 检查所有从数据库取出数据后直接用于SQL查询的代码
    • 特别注意用户可控数据的流动路径

五、总结

二次注入攻击利用了应用程序对数据库数据的过度信任,通过以下特点区别于传统注入:

  • 攻击分两个阶段完成
  • 恶意数据先被"合法"存储
  • 漏洞触发时数据来源看似可信
  • 防御需要关注整个数据处理生命周期

彻底防御二次注入需要开发者建立"永远不信任任何数据"的安全意识,无论数据来自用户输入还是数据库。

SQL二次注入攻击详解 一、二次注入原理 二次注入是一种特殊的SQL注入攻击形式,其核心原理如下: 数据存储阶段 :攻击者向数据库存入恶意构造的数据(如包含SQL特殊字符的输入) 数据转义处理 :在数据插入数据库时,应用程序会对输入进行转义处理(如使用 mysql_real_escape_string() 函数) 数据信任假设 :应用程序默认数据库中存储的数据都是安全的,在后续查询使用时不再进行转义处理 恶意数据触发 :当这些被存储的恶意数据被应用程序从数据库取出并用于构建新的SQL查询时,就会触发注入漏洞 与普通SQL注入相比,二次注入更难被发现,因为: 攻击发生在两个阶段(存储阶段和使用阶段) 常规安全扫描工具难以检测 攻击行为与正常操作流程相似 二、典型攻击场景分析 以SQL-Labs第24关为例,演示完整的二次注入攻击流程: 1. 注册恶意账号 攻击者注册一个特殊构造的用户名: 单引号( ' )用于破坏SQL语句结构 井号( # )是MySQL注释符,用于注释掉后续语句 2. 修改密码操作 当攻击者登录后尝试修改密码时,后端执行的SQL语句: 由于 $username 从数据库直接取出未转义,实际执行的语句变为: 被注释掉的部分: 最终有效执行的语句: 结果 :admin用户的密码被修改,而非攻击者自己的账号 三、深入技术分析 1. 关键函数说明 mysql_real_escape_string() 函数: 转义SQL语句中的特殊字符 影响的特殊字符: \x00 , \n , \r , \ , ' , " , \x1a 仅在数据插入时有效,无法防止从数据库取出数据后的注入 2. 二次注入的利用方式 通过UNION查询获取敏感信息: 注册特殊构造的用户名: 当应用程序从数据库取出该用户名并用于查询时: 实际执行: 有效执行的查询: 结果 :泄露数据库用户和当前数据库名称 四、防御措施 输入验证 : 对所有用户输入进行严格验证 使用白名单机制限制输入格式 参数化查询 : 使用预处理语句(Prepared Statements) 确保查询结构与数据分离 输出转义 : 即使数据来自数据库,在使用前也应进行转义 根据使用场景选择合适的转义函数(如HTML、SQL等) 最小权限原则 : 数据库账户应仅具有必要的最小权限 避免使用高权限账户执行常规操作 代码审计 : 检查所有从数据库取出数据后直接用于SQL查询的代码 特别注意用户可控数据的流动路径 五、总结 二次注入攻击利用了应用程序对数据库数据的过度信任,通过以下特点区别于传统注入: 攻击分两个阶段完成 恶意数据先被"合法"存储 漏洞触发时数据来源看似可信 防御需要关注整个数据处理生命周期 彻底防御二次注入需要开发者建立"永远不信任任何数据"的安全意识,无论数据来自用户输入还是数据库。