SQL注入
SQL 注入页也是一种常见的 Web 攻击方式 , 主要是利用后端程序的漏洞 , 针对数据库(主要是关系型数据库)进行攻击 。
攻击者通常通过输入精心构造的参数 , 绕过服务器端的验证 , 来执行恶意 SQL 语句 , SQL注入会造成拖库(原始数据表被攻击者获取) , 绕过权限验证 , 或者串改、破坏、删除数据 。 数据往往是一个网站甚至一个公司的生命 , 一旦SQL漏洞被攻击者利用通常会产生非常严重的后果 , 对于SQL 注入的防范需要开发者倍加重视 。 下面通过一个例子来演示SQL注入的攻击过程 , 对于一个登陆验证的请求一般需要通过用户输入的用户名和密码进行查询验证 , 查询SQL 语句如下:
SELECT * FROM users WHERE username = "$username" AND password = "$password";
比如攻击者已知一个用户名archer2017 , 可以构造密码为 anywords" OR 1=1 , 此时 , 此时后端程序的执行的SQL语句为:
SELECT * FROM users WHERE username = "archer2017" AND password = "anywords" OR 1=1;
? 这样无论输入什么样的密码 , 都会要绕过验证 , 如果更验证一些 , 构造密码为 anywords" OR 1=1;DROP TABLE users, 那么整个表都将被删除 , 执行SQL如下:
SELECT * FROM users WHERE username = "archer2017" AND password = "anywords" OR 1=1;DROP TABLE users;
SQL 注入的防范? SQL 注入发生绝大多数情况都是直接使用户输入参数拼装 SQL 语句造成的 , 防范 SQL 注入 , 主要的方式就是避免直接使用用户输入的数据 。
? 使用预编译语句(PreparedStatement):一方面可以加速 SQL 的执行 , 一方面可以防止SQL注入 。 理解 PreparedStatement 防范 SQL 注入的原理 , 先要理解预编译语句的原理 , 如下图所示:
文章插图
SQL 语句的编译分为如下几个阶段:
- 基本解析:包括SQL语句的语法、语义解析 , 以及对应的表和列是否存在等等 。
- 编译:蒋 SQL 语句编译成机器理解可理解的中间代码格式 。
- 查询优化:编译器在所有的执行方案中选择一个最优的 。
- 缓存:缓存优化后的执行方案 。
- 执行阶段:执行最终查询方案并返回给用户数据 。
Java 代码中使用预编译语句:
String query = "SELECT * FROM users WHERE username = ? AND password = ?";PreparedStatement pstmt = connection.prepareStatement( query );pstmt.setString( 1, username); pstmt.setString( 2, password); ResultSet results = pstmt.executeQuery( );
? 如果不可避免地使用 SQL 语句进行拼装 , 可以对用户输入数据进行转移 , 尤其是多单双引号的转义 。Java 中可以使用 Apache Common类库的 StringEscapeUtils 中的方法 , 例如:
StringEscapeUtils.escapeSql(sql);
StringEscapeUtils.escapeSql 方法在最新版的Apache Common 类库中被移除掉 , 按照官方文档的说法 , 是为了避免引起程序员在处理SQL时的产生误解 , 官方推荐使用与预编译语句 , 而不是拼装字符串的方法 。或者使用 ESAPI (OWASP Enterprise Security API) , 是一套开源的企业级的安全过滤组件 。
推荐阅读
- FlinkSQL 动态加载 UDF 实现思路
- 基于Spring+Angular9+MySQL开发平台
- 与华为同行,鸿雁智能为HiLink生态注入新活力
- MySQL数据库数据归档回收工具使用场景分享-爱可生
- 实践中如何优化MySQL(建议收藏!)
- 白帽子:SQL注入之双查询注入
- 面试官问:MySQL 的自增 ID 用完了,怎么办?
- FLASK数据库模型
- 零散的MySql基础记不住,看这一篇就够啦
- MySQL性能优化——Explain使用分析