vlambda博客
学习文章列表

Web项目SQL 注入与防御

一、概念

        SQL注入,一般指web应用程序对用户输入数据的合法性没有校验或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

        总的来说就是,攻击者通过系统正常的输入数据的功能,输入恶意数据,而系统又未作任何的校验,直接信任了用户输入,使得恶意输入改变原本的SQL逻辑或者执行了额外的SQL脚本达,从而造成了SQL注入攻击。


二、SQL注入场景

        ' or '1'= '1,这是最常见的 sql 注入攻击,当我们输如用户名 xiaobaicai ,然后密码输如'or '1'= '1的时候,我们在查询用户名和密码是否正确的时候,本来要执行的是select * from user where username='' and password='',经过参数拼接后,会执行 sql 语句select * from user where username='xiaobaicai' and password=' ' or ' 1'='1 ',这个时候 1=1 是成立,自然就跳过验证了。

        但是如果再严重一点,密码输如的是';drop table user;--,那么 sql 命令为select * from user where username='xiaobaicai' and password='';drop table user;--' 这个时候我们就直接把这个表给删除了

 

三、防御

1. 在 java 中,我们可以使用预编译语句(PreparedStatement),这样的话即使我们使用 sql 语句伪造成参数,到了服务端的时候,这个伪造 sql 语句的参数也只是简单的字符,并不能起到攻击的作用。

 

2. 合理规范使用持久层框架。比如,MyBatis 框架中,${}是输出变量的值,相当于拼接SQL,而#{}则是用了jdbc中的preparedstatement预编译。所以我们在日常开发中,用#{}就可以有效避免SQL注入,而只要是用了${}都有被注入的可能。不过,在MyBatis开发过程中注意以下几点:

 

某些xml自动生成工具生成的xml,动态条件用了${};在开发过程中需注意,特别是多表查询时; 进行like查询,使用#{}会报错,某些开发人员会用${}代替,正确的用法是用concat连接;select * from xiaobaicai where tile like concat(‘%’,#{title}, ‘%’);  包含in语句的时候,使用#{}会报错,某些程序员也会用${}代替,正确的用法是用foreach标签;<foreach collection="ids" item="item" open="("separatosr="," close=")">#{ids}</foreach>  使用order by语句的时候,用#{}会导致排序失效,当用了${}的时候,需要进行严格过滤(这种场景应当在Java层面做映射,设置一个字段/表名数组,仅允许用户传入索引值。这样保证传入的字段或者表名都在白名单里面。)。

 

 

3. 数据库中密码等重要信息不应明文存储的,可以对密码进行加密(比如,MD5+盐值(随机字符长+多次散列算法)数据库存储用户名等加密后的密文存贮。


--------------------------------------