加入收藏 | 设为首页 | 会员中心 | 我要投稿 衡阳站长网 (https://www.0734zz.cn/)- 数据集成、设备管理、备份、数据加密、智能搜索!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

彻底干掉恶心的SQL注入漏洞, 一网打尽!

发布时间:2019-07-24 17:39:10 所属栏目:MySql教程 来源:佚名
导读:简介 文章主要内容包括: Java 持久层技术/框架简单介绍 不同场景/框架下易导致 SQL 注入的写法 如何避免和修复 SQL 注入 JDBC 介绍 JDBC: 全称 Java Database Connectivity 是 Java 访问数据库的 API,不依赖于特定数据库 ( database-independent ) 所有
副标题[/!--empirenews.page--]

 彻底干掉恶心的SQL注入漏洞, 一网打尽!

简介

文章主要内容包括:

  •     Java 持久层技术/框架简单介绍
  •     不同场景/框架下易导致 SQL 注入的写法
  •     如何避免和修复 SQL 注入

JDBC

介绍

JDBC:

  •     全称 Java Database Connectivity
  •     是 Java 访问数据库的 API,不依赖于特定数据库 ( database-independent )
  •     所有 Java 持久层技术都基于 JDBC

说明

直接使用 JDBC 的场景,如果代码中存在拼接 SQL 语句,那么很有可能会产生注入,如

  1. // concat sql  
  2.   String sql = "SELECT * FROM users WHERE name ='"+ name + "'";  
  3.   Statement stmt = connection.createStatement();  
  4.   ResultSet rs = stmt.executeQuery(sql); 

安全的写法是使用 参数化查询 ( parameterized queries ),即 SQL 语句中使用参数绑定( ? 占位符 ) 和 PreparedStatement,如 

  1. // use ? to bind variables  
  2.    String sql = "SELECT * FROM users WHERE name= ? ";  
  3.    PreparedStatement ps = connection.prepareStatement(sql);  
  4.    // 参数 index 从 1 开始  
  5.    ps.setString(1, name); 

还有一些情况,比如 order by、column name,不能使用参数绑定,此时需要手工过滤,如通常 order by 的字段名是有限的,因此可以使用白名单的方式来限制参数值

这里需要注意的是,使用了 PreparedStatement 并不意味着不会产生注入,如果在使用 PreparedStatement之前,存在拼接 sql 语句,那么仍然会导致注入,如 

  1. // 拼接 sql  
  2.     String sql = "SELECT * FROM users WHERE name ='"+ name + "'";  
  3.     PreparedStatement ps = connection.prepareStatement(sql); 

看到这里,大家肯定会好奇 PreparedStatement 是如何防止 SQL 注入的,来了解一下

正常情况下,用户的输入是作为参数值的,而在 SQL 注入中,用户的输入是作为 SQL 指令的一部分,会被数据库进行编译/解释执行。

当使用了 PreparedStatement,带占位符 ( ? ) 的 sql 语句只会被编译一次,之后执行只是将占位符替换为用户输入,并不会再次编译/解释,因此从根本上防止了 SQL 注入问题。

Mybatis

介绍

  •  首个 class persistence framework
  •  介于 JDBC (raw SQL) 和 Hibernate (ORM)
  •  简化绝大部分 JDBC 代码、手工设置参数和获取结果
  •  灵活,使用者能够完全控制 SQL,支持高级映射

更多请参考: http://www.mybatis.org

说明

在 MyBatis 中,使用 XML 文件 或 Annotation 来进行配置和映射,将 interfaces 和 Java POJOs (Plain Old Java Objects) 映射到 database records。

XML 例子

Mapper Interface 

  1. @Mapper  
  2.    public interface UserMapper {  
  3.        User getById(int id);  
  4.    } 

XML 配置文件 

  1. <select id="getById" resultType="org.example.User">  
  2.        SELECT * FROM user WHERE id = #{id}  
  3.    </select> 

Annotation 例子 

  1. @Mapper  
  2.     public interface UserMapper {  
  3.         @Select("SELECT * FROM user WHERE id= #{id}")  
  4.         User getById(@Param("id") int id);  
  5.     } 

可以看到,使用者需要自己编写 SQL 语句,因此当使用不当时,会导致注入问题与使用 JDBC 不同的是,MyBatis 使用 #{} 和 ${} 来进行参数值替换。推荐:Mybatis传递多个参数的4种方式。

使用 #{} 语法时,MyBatis 会自动生成 PreparedStatement ,使用参数绑定 ( ?) 的方式来设置值,上述两个例子等价的 JDBC 查询代码如下:

  1. String sql = "SELECT * FROM users WHERE id = ?";  
  2.   PreparedStatement ps = connection.prepareStatement(sql);  
  3.   ps.setInt(1, id); 

因此 #{} 可以有效防止 SQL 注入,详细可参考 http://www.mybatis.org/mybatis-3/sqlmap-xml.html String Substitution 部分。

(编辑:衡阳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读