SQL注入
SQL注入详解
我会从原理、利用方式到防御方法全面讲解SQL注入。
一、SQL注入原理
什么是SQL注入?
SQL注入是一种代码注入技术,攻击者通过在应用程序的输入字段中插入恶意SQL代码,使其被数据库执行,从而绕过应用程序的安全机制。
核心原理
当应用程序使用字符串拼接方式构建SQL查询,且没有对用户输入进行充分验证和过滤时,攻击者可以注入额外的SQL语句。
脆弱代码示例:
1 | # Python示例 |
正常输入:
- 用户名:
admin - 密码:
123456 - 生成SQL:
SELECT * FROM users WHERE username='admin' AND password='123456'
恶意输入:
- 用户名:
admin' -- - 密码:
任意值 - 生成SQL:
SELECT * FROM users WHERE username='admin' --' AND password='任意值'
-- 是SQL注释符,后面的密码验证被注释掉,攻击者无需密码即可登录。
二、SQL注入类型
1. 基于联合查询的注入(Union-based)
通过UNION操作符合并查询结果,获取其他表的数据。
1 | ' UNION SELECT username, password FROM admin_users -- |
2. 基于错误的注入(Error-based)
通过触发数据库错误,从错误信息中获取数据库结构信息。
1 | ' AND 1=CONVERT(int, (SELECT @@version)) -- |
3. 基于布尔的盲注(Boolean-based Blind)
通过观察应用程序响应的差异(真/假)逐字猜解数据。
1 | ' AND SUBSTRING((SELECT password FROM users WHERE id=1),1,1)='a' -- |
4. 基于时间的盲注(Time-based Blind)
利用数据库延迟函数判断条件真假。
1 | ' AND IF(SUBSTRING((SELECT password FROM users WHERE id=1),1,1)='a', SLEEP(5), 0) -- |
5. 堆叠查询注入(Stacked Queries)
在一条语句中执行多个SQL操作。
1 | '; DROP TABLE users; -- |
三、利用技巧
信息收集阶段
1. 判断注入点
1 | # 尝试闭合引号 |
2. 判断数据库类型
1 | # MySQL |
3. 获取数据库信息
1 | # MySQL |
数据提取
1 | # 提取用户数据 |
常见绕过技巧
1. 注释符变体
1 | -- |
2. 空格绕过
1 | /**/ |
3. 关键字绕过
1 | # 大小写混淆 |
4. 引号绕过
1 | # 使用十六进制 |
四、防御与修复方法
1. 参数化查询(最重要)
Python (使用参数化查询):
1 | # 正确做法 |
Java (PreparedStatement):
1 | String query = "SELECT * FROM users WHERE username=? AND password=?"; |
PHP (PDO):
1 | $stmt = $pdo->prepare("SELECT * FROM users WHERE username=:username AND password=:password"); |
Node.js (使用参数化):
1 | connection.query('SELECT * FROM users WHERE username=? AND password=?', |
2. ORM框架使用
1 | # Django ORM |
3. 输入验证与过滤
1 | import re |
4. 最小权限原则
1 | -- 创建只有SELECT权限的用户 |
5. 错误处理
1 | # 不要暴露详细错误信息 |
6. Web应用防火墙(WAF)
配置WAF规则检测SQL注入特征:
- 常见注入关键字(UNION, SELECT, DROP等)
- 注释符(–, #, /**/)
- 特殊字符组合
7. 安全编码检查清单
✅ 使用参数化查询/预编译语句
✅ 永远不要拼接用户输入到SQL
✅ 使用ORM框架
✅ 输入验证(白名单优于黑名单)
✅ 最小权限数据库账户
✅ 不暴露详细错误信息
✅ 定期安全审计和代码审查
✅ 使用WAF作为额外防护层
✅ 对敏感数据加密存储
✅ 记录和监控异常查询
五、实战检测工具
- SQLMap - 自动化SQL注入工具
- Burp Suite - Web应用安全测试
- OWASP ZAP - 开源漏洞扫描器
- 手工测试 - 理解原理后的精准测试
总结
SQL注入的核心是永远不要信任用户输入。最有效的防御就是使用参数化查询,让数据库驱动自动处理转义和类型检查。记住:过滤和验证是辅助手段,参数化才是根本解决方案。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 SEEK MORE!