MyBatis中#{}与${}的区别 sql注入

1、MyBatis中#{}与${}的区别

在mybatis中#{}可以防止SQL注入而${}不可以。举个例子:

http://www.xx.com/news.jsp?id=1 

这里的sql语句中如果使用${},

SELECT title,content FROM news WHERE id = ${id};

执行时,参数id会被直接拼接入sql语句:

  SELECT title,content FROM news WHERE id = 1;

如果攻击者提交的参数为

  “id=1 and 1=2 UNION SELECT username, password FROM admin”;

拼接的sql语句就变为了:

  “SELECT title,content FROM news WHERE id = 1 and 1=2 UNION SELECT username, password FROM admin”;

这条sql的原意就会被改变,导致将管理员数据表中的用户显示在页面title位置,密码显示在页面content位置,达到成功攻击的效果。而如果用#{},

   SELECT title,content FROM news WHERE id = #{id};

在用户提交参数之前,sql语句会进行一次预编译,

   SELECT title,content FROM news WHERE id = ?;
   # 这种方式在最后运行的时候会将 “id=1 and 1=2 UNION SELECT username, password FROM admin” 当成一个整体拼在sql中,大概是如下这种效果
    SELECT title,content FROM news WHERE id = ‘id=1 and 1=2 UNION SELECT username, password FROM admin’;

攻击者提交的参数中包含的sql编译字符,不会被带入sql进行编译,只作为参数,不能造成sql注入。而且由于只进行一次预编译,sql的性能也会得到提升。在项目中,大部分SQL语句对参数的处理方式都是用了#{}这种预编译方式。但在模糊查询中,使用#{}会报错。所以使用了${ }方式代替#{},其实在项目中可以使用 concat 的方式,进行参数的拼接。

2、MyBatis框架下易产生SQL注入漏洞场景分析

MyBatis框架下易产生SQL注入漏洞的情况主要分为以下三种:

  • 2.1 模糊查询like

以按照标题进行模糊查询为例,如果考虑安全编码规范问题,其对应的SQL语句如下:

    select * from news where title like%#{title}%’;

但由于这样写程序会报错,所以将SQL查询语句修改如下:

    select * from news where title like%${title}%;

在这种情况下程序不再报错,但是此时产生了SQL语句拼接问题,如果java代码层面没有对用户输入的内容做处理势必会产生SQL注入漏洞。

  • 2.2 in之后的参数

在进行同条件多值查询的时候,如当用户输入1001,1002,1003…100N时,如果考虑安全编码规范问题,其对应的SQL语句如下:

    select * from news where id in (#{id})

但由于这样写程序会报错,研发人员将SQL查询语句修改如下:

    select * from news where id in (${id})

修改SQL语句之后,程序停止报错,但是却引入了SQL语句拼接的问题,如果没有对用户输入的内容做过滤,势必会产生SQL注入漏洞。

  • 2.3 order by之后

当根据发布时间、点击量等信息进行排序的时候,如果考虑安全编码规范问题,其对应的SQL语句如下:

    select * from news where title =‘test’ order by #{time} asc

但由于这样写程序会报错,将SQL查询语句修改如下:

    select * from news where title =‘test’ order by ${time} asc

修改之后,程序通过预编译,但是产生了SQL语句拼接问题,极有可能引发SQL注入漏洞。

3、Mybatis框架下SQL注入漏洞修复建议

  • 3.1 模糊查询like SQL注入修复建议

按照标题进行模糊查询,可将SQL查询语句设计如下:

  select * from news where tile like concat(%,#{title}, ‘%’);

采用预编译机制,避免了SQL语句拼接的问题,从根源上防止了SQL注入漏洞的产生。

  • 3.2 in之后的参数SQL注入修复建议

在对进行同条件多值查询的时候,可使用Mybatis自带循环指令解决SQL语句动态拼接的问题:

    select * from news where id in
      < foreach collection=”ids” item=”item” open=(“ separator=,close=)>
        #{item}
      < /foreach>
  • 3.3 order by SQL注入修复建议–在Java层面做映射

预编译机制只能处理查询参数,其他地方还需要研发人员根据具体情况来解决。如前面提到的排序情景:

    select * from news where title =‘test’ order by #{time} asc

这里无法使用预编译机制,只能这样拼接:

    select * from news where title =‘title’ order by ${time} asc

针对这种情况可以在java层面做映射来进行解决。如当存在发布时间time和点击量click两种排序选择时,可以限制用户只能输入1和2。当用户输入1时,在代码层面将其映射为time,当用户输入2时,将其映射为click。而当用户输入1和2之外的其他内容时,可以将其转换为默认排序选择time(或者click)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

T-OPEN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值