网络安全现在越来越受到重视
,经销其中后端应用最常见的商技术部实践安全漏洞就是SQL注入 ,据owasp(开放式Web应用程序安全项目组织)的注入安全漏洞统计
,注入漏洞常年排名TOP 3 。经销为了尽可能地减少SQL注入问题,商技术部实践我们进行了一些实践总结,注入并在部门内部进行了推广 。经销 SQL注入攻击是商技术部实践通过操作输入来修改SQL语句,以达到执行注入的注入SQL 、进而对web服务器进行攻击的经销方法。简单的亿华云商技术部实践说就是在web表单或页面请求的查询字符串中插入SQL命令, 最终使web服务器执行恶意命令的注入过程。可以通过一个例子简单说明SQL注入攻击
。经销假设某网站页面显示时URL为http://www.example.com?商技术部实践test=123,此时URL实际向服务器传递了值为123的注入变量test
,这表明当前页面是对数据库进行动态查询的结果
。如果服务器使用了SQL动态拼接,此时可以在URL中插入恶意SQL语句并执行 。例如预期执行语句是: 如果有人恶意构造test=123 or 1 = 1;那么最后实际执行的源码下载语句就是: SQL注入本质是利用动态SQL拼接并直接执行,并且前端输入的参数未经过严格校验直接参与SQL拼接 ,输入参数被恶意利用的话就存在不受控的命令注入风险。SQL注入会攻击数据库,所以危害是非常大的 ,SQL注入的危害包括
:1. 数据库信息泄露;2. 数据库恶意操作攻击服务器;3. 删除和修改数据库表信息;4. 服务器远程控制等。防SQL注入原则根据SQL注入的原理,免费模板我们总结了如下防SQL注入的原则
。1)尽可能参数化执行SQL,使用PreparedStatement;2)无法参数化执行就对输入参数使用强类型接收,如枚举;3)如果既不能参数化也无法用强类型
,就做好格式校验;4)如果上面都做不到,最后考虑做好注入字符的转义过滤。 关系型数据库都提供了预编译执行SQL语句的方式,和直接执行有参数拼接的SQL方式不同的是 ,在SQL预编译阶段
,所有参数都会被模板化 ,模板下载参数值不直接参与编译 ,这样参数值就无法改变SQL的结构 ,包括语句条数,参数个数 ,查询条件等等,就算参数里存在恶意注入参数值也无法破坏原来的SQL结构
。下面举例说明拼接执行和参数化执行的区别。直接执行: 使用预编译执行(也就是PreparedStatement)分两步。 第一步:模板化编译 第二步 :参数带入 预编译后的语句执行时,就算参数值里有恶意注入 ,也只是建站模板当成一个字符串的一部分 ,并不会导致SQL结构被破坏,所以这种方式能够从根本上杜绝SQL注入的风险
,也是目前公认防SQL注入最好的办法。 SQL注入依赖于SQL动态拼接,如果非String(包括枚举)参数有强类型严格校验 ,拼接的时候就没有SQL注入的风险 对于可枚举的String入参 ,在后端需要进行枚举值白名单校验
,香港云服务器防止伪造。以经常使用的排序字段为例,排序字段不少情况下是从前端传过来的,不可信
。所以需要做枚举校验
,看看传过来的排序字段是否在预期内。 存储过程因为也是预编译的
,所以也可以防止SQL注入
,不过存储过程已经是不推荐的实践了,这里只是列举一下。 这个实践方案的优先级最低
,前面的方案都无法实施或代价太大的情况下 ,才考虑使用
,因为这个办法并不是完全可靠的。这个办法是把用户输入拼到SQL之前,先对输入进行转义
,所以实现上是和数据库绑定的 ,不同的数据库转义实现都不一样 。原理是对特定的查询,数据库支持一种或多种转义的方法,如果对所有用户输入的参数拼到SQL之前进行合适的转义
,就可以防止SQL注入 ,但是不能保证所有情况都能处理完美
。OWASP组织提供了可以直接使用的java类库esapi ,可以用来完成转义,目前支持mysql,oracle ,还不支持sqlserver
,OWASP官方文档中也有说明这个类库也不能保证100%可以防SQL注入 。 Mybatis的XML Mapper中参数有两种表达方式: #{ xxx}和${ xxx},区别是#{ xxx}会被模板化为参数化形式(?)
,所以参数值不参与编译;${ xxx}会被替换为对应的参数值参与编译
。所以使用#{ xxx}语法的参数没有注入风险
,但是使用${ xxx}不当,就存在注入风险
。我们使用sonar规则来检测${ xxx}的使用情况,发现很多可以使用#{ xxx}的情况下,却使用了${ xxx} ,大概是使用者还不了解其中的区别和风险 。根据防止SQL注入的原则,针对使用Mybatis作为ORM的时候 ,我们可以得出这样的结论 : 1)常规误用风险写法: 安全写法: 2) in 参数拼接风险写法 : 安全写法: 复制 AND id IN collection="ids" item="id" open="(" separator="," close=")"> #{ id} 3) sqlserver top语法风险写法 : 安全写法: 4)between语法风险写法 : 安全写法: 5)like语法风险写法
: 安全写法1: 安全写法2 : 安全写法3:在java代码中构造好pattern,使用#{ }语法6) limit语法风险写法: 安全写法: 7) 动态order by风险写法
: 安全建议1 :可以在xml中使用if代替java中拼凑orderby(推荐);安全建议2:对排序字段和排序类型值进行白名单校验;8)动态表名安全建议:建议实现Mybatis插件 ,在框架层面对表名进行替换处理
,避免在xml使用${ }来拼凑表名 。9) Mybatis example语法风险用法
: Mybatis生成的example使用,大多数情况下是安全的,但是orderByCluase是通过字符串拼接的 ,也是不安全的,所以不建议使用
。安全建议:可以考虑使用mybatis新出的mybatis-dynamic-sql或者国内开源的mybatis-plus,比example语法更简洁
,也更安全 。例如
: WAF除了在SQL语句层面尽量保证防止SQL注入风险之外 ,基础设施WAF(Web Application Firewall)也是非常有效的防止SQL注入的措施,有条件的也可以考虑部署WAF 。 本文主要是记录了经销商技术部在安全方面防止SQL注入的一些实践探索和总结,包括SQL注入的原理
,防SQL注入总体遵循的原则 ,以及具体的实践中的安全建议,希望对其他人也有所帮助。