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语句从构造到执行涉及以下阶段:
- 客户端应用
- 客户端驱动
- 数据库客户端/服务器协议
- 数据库服务器
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解析SQLmysql_execute_command()执行命令execute_sqlcom_select()执行查询
2.3 客户端驱动实现
以MySQL Connector/J为例:
- 加载
com.mysql.jdbc.Driver DriverManager.getConnection()获取连接ConnectionImpl.createStatement()创建StatementStatementImpl.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注入防护指南