SQL和NoSQL注入浅析(上)
字数 1845 2025-08-29 08:32:00

SQL和NoSQL注入浅析(上) - 教学文档

1. SQL注入基础原理

1.1 基本概念

SQL注入是指攻击者通过在应用程序的输入字段中插入恶意的SQL代码,从而影响原始SQL语句的结构和语义,导致数据库执行非预期的操作。

1.2 典型示例

  • 数字型注入:1 or 1=1
  • 字符串型注入:' or ''='

1.3 根本原因

程序在构造SQL语句时,没有对用户输入数据进行合法性验证,导致恶意输入能够改变SQL语句的原始结构和语义。

2. SQL语句执行流程分析

SQL语句从构造到执行涉及以下阶段:

  1. 客户端应用
  2. 客户端驱动
  3. 数据库客户端/服务器协议
  4. 数据库服务器

2.1 MySQL协议分析

MySQL协议设计简单,请求包结构:

  • 前3字节:包长度(指令加SQL语句长度)
  • 第4字节:包序列号
  • 第5字节:指令号(如03表示COM_QUERY
  • 剩余部分:SQL语句(明文传输)

2.2 服务器端处理流程

  1. 服务器接收请求并分配线程
  2. sql_parse中的do_command()处理指令
  3. dispatch_command()处理SQL语句:
    • 移除头尾空白字符和分号
    • 分配空间并填充SQL语句
    • 调用mysql_parse()进行解析
  4. 解析执行阶段:
    • mysql_parse()使用Lex/Yacc解析SQL
    • mysql_execute_command()执行命令
    • execute_sqlcom_select()执行查询

2.3 客户端驱动实现

以MySQL Connector/J为例:

  1. 加载com.mysql.jdbc.Driver
  2. DriverManager.getConnection()获取连接
  3. ConnectionImpl.createStatement()创建Statement
  4. StatementImpl.executeQuery()执行查询:
    • 处理Escape字符
    • 检查DML操作类型
    • 封装QUERY指令数据包
    • 发送命令

3. 防御机制分析

3.1 转义处理

  • PHP中的mysqli_real_escape_string()

    • mysqlnd_cset_escape_slashes():使用\转义特殊字符
    • mysqlnd_cset_escape_quotes():将'转义为''
  • JDBC中的Escape处理:

    • 实现JDBC Escape语法(非安全转义)
    • 如:{ESCAPE '='}用于LIKE子句

3.2 预处理语句

真预处理(服务器端预处理):

  1. 发送PREPARE指令
  2. 服务器解析并缓存SQL结构
  3. 发送EXECUTE指令绑定参数
  4. 服务器执行时进行类型转换和转义

伪预处理(客户端模拟):

  • JDBC默认行为
  • 客户端驱动模拟预处理效果
  • 对参数进行转义后拼接完整SQL

3.3 预处理限制

预处理无法有效保护以下场景:

  1. ORDER BY子句
  2. GROUP BY子句
    原因:
  • 这些子句需要列名或索引号
  • 字符串参数会被引号包裹导致语法错误
  • 开发人员常选择拼接实现

4. 常见Bypass技术

4.1 分类

  1. 简单规避:

    • 注释绕过:--, #, /* */
    • 大小写混合:OrDeR By
  2. 关键字限制绕过:

    • 使用等价函数/操作符
    • 编码/混淆技术
  3. 空格限制绕过:

    • 使用注释:SELECT/**/1
    • 使用括号:SELECT(1)
  4. 字符限制绕过:

    • 使用%0a等换行符
    • 使用+连接字符串
  5. 引号限制绕过:

    • 使用0x十六进制编码
    • 使用CHAR()函数

4.2 宽字节注入

  • 原理:利用GBK等多字节字符集特性
  • 示例:%df'会被转义为%df\',其中%df\可能被识别为一个中文字符
  • 防御:
    • 使用mysql_set_charset()设置正确字符集
    • 使用mysqli扩展而非mysql扩展

5. 面向对象的数据库操作

为解决SQL注入问题,现代ORM框架采用:

  • 参数化查询
  • 类型安全的数据绑定
  • 查询构建器模式
  • 如Hibernate的QBC(Query By Criteria)

6. 防御建议

  1. 使用预处理语句(注意ORDER BY等限制)
  2. 输入验证(白名单优于黑名单)
  3. 最小权限原则
  4. 错误处理(不暴露数据库细节)
  5. 使用ORM框架
  6. 定期安全审计

7. 参考资源

  1. MySQL官方文档
  2. Oracle JDBC开发指南
  3. Apache JDBC参考
  4. OWASP SQL注入防护指南
SQL和NoSQL注入浅析(上) - 教学文档 1. SQL注入基础原理 1.1 基本概念 SQL注入是指攻击者通过在应用程序的输入字段中插入恶意的SQL代码,从而影响原始SQL语句的结构和语义,导致数据库执行非预期的操作。 1.2 典型示例 数字型注入: 1 or 1=1 字符串型注入: ' or ''=' 1.3 根本原因 程序在构造SQL语句时,没有对用户输入数据进行合法性验证,导致恶意输入能够改变SQL语句的原始结构和语义。 2. SQL语句执行流程分析 SQL语句从构造到执行涉及以下阶段: 客户端应用 客户端驱动 数据库客户端/服务器协议 数据库服务器 2.1 MySQL协议分析 MySQL协议设计简单,请求包结构: 前3字节:包长度(指令加SQL语句长度) 第4字节:包序列号 第5字节:指令号(如 03 表示 COM_QUERY ) 剩余部分:SQL语句(明文传输) 2.2 服务器端处理流程 服务器接收请求并分配线程 sql_parse 中的 do_command() 处理指令 dispatch_command() 处理SQL语句: 移除头尾空白字符和分号 分配空间并填充SQL语句 调用 mysql_parse() 进行解析 解析执行阶段: mysql_parse() 使用Lex/Yacc解析SQL mysql_execute_command() 执行命令 execute_sqlcom_select() 执行查询 2.3 客户端驱动实现 以MySQL Connector/J为例: 加载 com.mysql.jdbc.Driver DriverManager.getConnection() 获取连接 ConnectionImpl.createStatement() 创建Statement StatementImpl.executeQuery() 执行查询: 处理Escape字符 检查DML操作类型 封装QUERY指令数据包 发送命令 3. 防御机制分析 3.1 转义处理 PHP中的 mysqli_real_escape_string() : mysqlnd_cset_escape_slashes() :使用 \ 转义特殊字符 mysqlnd_cset_escape_quotes() :将 ' 转义为 '' JDBC中的Escape处理: 实现JDBC Escape语法(非安全转义) 如: {ESCAPE '='} 用于LIKE子句 3.2 预处理语句 真预处理(服务器端预处理): 发送 PREPARE 指令 服务器解析并缓存SQL结构 发送 EXECUTE 指令绑定参数 服务器执行时进行类型转换和转义 伪预处理(客户端模拟): JDBC默认行为 客户端驱动模拟预处理效果 对参数进行转义后拼接完整SQL 3.3 预处理限制 预处理无法有效保护以下场景: ORDER BY 子句 GROUP BY 子句 原因: 这些子句需要列名或索引号 字符串参数会被引号包裹导致语法错误 开发人员常选择拼接实现 4. 常见Bypass技术 4.1 分类 简单规避: 注释绕过: -- , # , /* */ 大小写混合: OrDeR By 关键字限制绕过: 使用等价函数/操作符 编码/混淆技术 空格限制绕过: 使用注释: SELECT/**/1 使用括号: SELECT(1) 字符限制绕过: 使用 %0a 等换行符 使用 + 连接字符串 引号限制绕过: 使用 0x 十六进制编码 使用 CHAR() 函数 4.2 宽字节注入 原理:利用GBK等多字节字符集特性 示例: %df' 会被转义为 %df\' ,其中 %df\ 可能被识别为一个中文字符 防御: 使用 mysql_set_charset() 设置正确字符集 使用 mysqli 扩展而非 mysql 扩展 5. 面向对象的数据库操作 为解决SQL注入问题,现代ORM框架采用: 参数化查询 类型安全的数据绑定 查询构建器模式 如Hibernate的QBC(Query By Criteria) 6. 防御建议 使用预处理语句(注意ORDER BY等限制) 输入验证(白名单优于黑名单) 最小权限原则 错误处理(不暴露数据库细节) 使用ORM框架 定期安全审计 7. 参考资源 MySQL官方文档 Oracle JDBC开发指南 Apache JDBC参考 OWASP SQL注入防护指南