网站首页 > 技术文章 正文
一句话总结
SQL 注入是一种通过插入恶意 SQL 代码来攻击数据库的技术,防范措施包括使用参数化查询、输入验证和最小权限原则。
详细解析
一、SQL 注入原理与危害
攻击原理(恶意包裹)
SQL 注入是一种安全漏洞,它允许攻击者将恶意的 SQL 代码插入到输入字段中,以操纵数据库。想象应用程序是快递分拣员,数据库是仓库管理员,注入的SQL代码如同恶意包裹。
- 输入篡改:攻击者在登录框输入' OR 1=1 --,而非正常用户名。
- 语句拼接:应用程序生成SELECT * FROM users WHERE username='' OR 1=1 --' AND password='xxx'。
- 指令操控:--注释后续密码验证,OR 1=1使条件恒真 → 绕过认证获取所有用户数据。
典型危害
- 拖库泄露:窃取用户密码、银行卡号等敏感数据。
- 越权操作:篡改商品价格、删除数据表(如'; DROP TABLE users;--)。
- 系统提权:利用数据库存储过程获取服务器控制权(如 MSSQL 的xp_cmdshell)。
二、7 类 SQL 注入攻击详解(附防御方案)
1、联合查询注入(Union Injection)
- 攻击特征:UNION SELECT 1,password,3 FROM users--
- 原理:通过 UNION 追加恶意查询,泄露其他表数据。
- 防御:禁用动态拼接 UNION 语句 + 预编译。
2、布尔盲注(Boolean Blind)
- 攻击特征:admin' AND SUBSTR(password,1,1)='a' --
- 原理:根据页面返回 真/假 状态逐字符爆破密码。
- 防御:统一错误页面(不泄露状态差异)。
3、时间盲注(Time-Based)
- 攻击特征:1'; IF(SUBSTR(database(),1,1)='a', SLEEP(5),0)--
- 原理:通过 响应延迟 判断条件真假(如 MySQL 的SLEEP())。
- 防御:限制 SQL 执行时间 + 预编译。
4、报错注入(Error-Based)
- 攻击特征:' AND (SELECT 1/0 FROM dual)--
- 原理:故意触发数据库报错,在错误信息中泄露表结构。
- 防御:关闭详细报错(生产环境返回通用错误页)。
5、堆叠查询(Stacked Queries)
- 攻击特征:'; DELETE FROM logs; --
- 原理:分号;追加多条 SQL 命令(需数据库支持)。
- 防御:禁用多语句执行(如 JDBC 设置allowMultiQueries=false)。
6、二次注入(Second-Order)
- 攻击特征:注册用户名admin'--
- 防御:存储数据时也需过滤(不仅是输入点)。
3、宽字节注入(GBK Bypass)
- 攻击特征:%bf%27→ 被转义为%bf%5c%27→ GBK 编码解析为縗'吃掉转义符。
- 防御:统一使用 UTF-8 编码 + 预编译。
三、防御方案:从开发到运维全链路
- 预编译(参数化查询)—— 最核心屏障!
// 安全写法(Java 示例)
String sql = "SELECT * FROM users WHERE username = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, inputUsername); // 输入作为参数绑定,不可篡改 SQL 结构
为何能防注入?
将 SQL 指令与数据分离 → 用户输入始终视为 字符串/数字,而非可执行代码。
- 输入过滤与验证
- 白名单校验:邮箱格式、数字范围等(如正则[a-zA-Z0-9]+)。
- 黑名单过滤:禁止'、--、UNION等危险字符(需注意绕过风险)。
- 最小权限原则
- 应用账户权限:只授予SELECT/UPDATE必要表,禁用DROP、FILE等危险权限。
- 数据库用户分离:Web 应用 ≠ DBA 账号!
- 纵深防御补充
措施 | 作用 |
Web 应用防火墙(WAF) | 拦截 UNION SELECT、SLEEP( 等特征 Payload(需定期更新规则) |
错误信息模糊化 | 生产环境返回 系统错误,请联系管理员,而非 Column 'password' not found |
定期漏洞扫描 | 使用 SQLMap 等工具主动检测(尤其新增接口) |
修复方案:
- 方案1:参数化查询(PDO)
$stmt = $pdo->prepare("SELECT * FROM products WHERE id = ?");
$stmt->execute([$id]);
- 方案2:强制类型转换(仅限数字型)
$id = (int)$_GET['id']; // 字符串注入被阻断
猜你喜欢
- 2025-07-27 Mybatis Plus框架学习指南-第六节内容(常用的类 1)
- 2025-07-27 面试题:RocketMQ如何保证消息不重复消费
- 2025-07-27 如何安全配置数据库(MySQL/PostgreSQL/MongoDB)
- 2025-07-27 SQL-执行过程详解(sql语句执行)
- 2025-07-27 SQL Server如何使用维护计划?(sql2000维护计划怎么执行)
- 2025-07-27 云服务器:SQL数据库超时的原因与解决方法
- 2025-07-27 SQL 从入门到精通:全面掌握数据库操作
- 2025-07-27 数据库 SQL 约束之 DEFAULT(sql的约束是什么)
- 2025-07-27 windows下,mysql自动备份脚本(mysql数据备份脚本)
- 2025-07-27 SQL Server中从SELECT进行UPDATE的方法
- 1518℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 596℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 521℃MySQL service启动脚本浅析(r12笔记第59天)
- 489℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 489℃启用MySQL查询缓存(mysql8.0查询缓存)
- 477℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 456℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 454℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- windowsscripthost (69)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- js判断是否是json字符串 (67)
- checkout-b (67)
- c语言min函数头文件 (68)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)