使用mybatis时防止sql注入

一.where条件 like 注入
  错误代码示例:select id,name from user where name like '${name}%'
  注入方式1:在文本框直接把name对应的值写为%,那后端sql直接变为select id,name from user where name ‘%%’将把所有数据给查出来。
  注入方式2:将错误示例代码改为select id,name from user where name like '${name}%’and id=1在文本框直接把name对应的值写为%' or '1'='1,那后端sql直接变为select id,name from user where name ‘%%’将把所有数据给查出来。
  解决办法:将sql改为
select id,name from user where name like CONCAT(#{name},'%’)或select id,name from user where name like #{name}||’%’
,但这样仅能避免注入方式2的漏洞,还需要判断name是否为空或是否包含%,如果不包含再走like 语句。

二、in 条件注入
  错误代码示例:select id,name from user where id in (${ids})
  注入方式:直接把ids设置为1) or (1=1即可完成注入,sql将变为select id,name from user where id in (1) or (1=1),将查出全部数据
  解决办法:将sql改为通过foreach结构,如:

select id,name from user
  <where>  
    id in  
    <foreach item="item" collection="list" separator="," open="(" close=")" index="">  
      #{item.id, jdbcType=NUMERIC}  
    </foreach>  
  </where>  


三、列名、表名、order by 注入
  这几种只能使用${param}这种格式的,经过测试及资料查阅暂时没有好的解决办法,建议在写的时候尽量避免
  用$形式的动态变量,如表不多的话,可以复制几个一样的sql把表名换下,对于分表的,需要对动态变量进行校验及匹配,
  列名、order by 后面的列名同样。另外避免在前端页面可传入这些数据。
  这几类sql注入方式如下:
  1.列名注入方式:select ${column} name from user,将column赋值为 (select sleep(5)) ,sql则变为select  (select sleep(5)) from user;或已知其他列名,将column改为pwd,sql则变为 select pwd name from user;
  2.表名注入:select name,age from ${table} ,将column赋值为(select pwd name,prex age from dept) b,则sql变为select name,age from (select pwd name,prex age from dept) b,用另外已知的表伪装成正常表返回数据。
四、${}存在sql注入风险
  能用#{}的尽量用这个,正常where 条件中禁止使用${}。

猜你喜欢

转载自liushuiwuyan.iteye.com/blog/2383427