第四章 SQL 注入
2019-12-24 本文已影响0人
农民工进城
要点
- SQL注入
- SQL注入防护
一、SQL注入
SQL注入:黑客会通过构造一些恶意的输入参数,在应用拼接 SQL 语句的时候,去篡改正常的 SQL 语意,从而执行黑客所控制的 SQL 查询功能
- 修改 WHERE 语句
例如:SELECT * FROM Users WHERE Username ="" AND Password ="" or ""=""
恒成立
- 修改 WHERE 语句
- 执行任意语句
大部分的数据库都支持多语句执行。因此,黑客除了修改原本的 WHERE 语句之外,也可以在原语句的后面,插入额外的 SQL 语句,来实现任意的增删改查操作。例如:
INSERT INTO Users (Username, Password) VALUES("test","000000"); SELECT * FROM Users;
就可以一次性执行多个SQL语句
- 执行任意语句
二、SQL 注入防护
- 使用 PreparedStatement:
通过合理地使用 PreparedStatement,我们就能够避免 99.99% 的 SQL 注入问题;不要使用字符串拼接。
当数据库在处理一个 SQL 命令的时候,大致可以分为两个步骤:
- 使用 PreparedStatement:
- 将 SQL 语句解析成数据库可使用的指令集;
- 将变量代入指令集,开始实际执行;
之所以在批量处理 SQL 的时候能够提升性能,就是因为这样做避免了重复解析 SQL 的过程。
SQL 注入是在解析的过程中生效的,用户的输入会影响 SQL 解析的结果。因此,我们可以通过使用 PreparedStatement,将 SQL 语句的解析和实际执行过程分开,只在执行的过程中代入用户的操作。这样一来,无论黑客提交的参数怎么变化,数据库都不会去执行额外的逻辑,也就避免了 SQL 注入的发生。
String sql = "SELECT * FROM Users WHERE UserId = ?";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setInt(1, userId);
ResultSet results = statement.executeQuery();
- 使用存储过程:实际上,它的原理和使用 PreparedStatement 类似,都是通过将 SQL 语句的解析和执行过程分开,来实现防护。区别在于,存储过程防注入是将解析 SQL 的过程,由数据库驱动转移到了数据库本身
- 验证输入:
防护的核心原则是,一切用户输入皆不可信
- 验证输入:
-
SQL 注入的攻击发生在输入的时候,因此,我们只能在输入的时候去进行防护和验证;
-
大部分数据库不提供针对 SQL 的编码,因为那会改变原有的语意,所以 SQL 注入没有编码的保护方案。
因此,对所有输入进行验证或者过滤操作,能够很大程度上避免 SQL 注入的出现