Mybatis防止SQL注入

防止SQL注入的中心思想就是参数化查询,将输入当作参数传递,而不是直接拼接到 SQL 语句中。

常见的防止SQL注入的方式

使用#{}占位符

  • 先来看一个错误的示范${}
// 错误示范
@PostMapping("mybatiswrong")
public List mybatiswrong(@RequestParam("name") String name) {
  //curl -X POST http://localhost:18081/sqlinject/mybatiswrong?name=test
  //python sqlmap.py -u  http://localhost:18081/sqlinject/mybatiswrong --data name=test --current-db --flush-session
  return userDataMapper.findByNameWrong(name);
}

@Select("SELECT id,name FROM `userdata` WHERE name LIKE '%${name}%'")
List<UserData> findByNameWrong(@Param("name") String name);
  • 使用sqlmap测试是否注入
C:\Python310\sqlmap>python sqlmap.py -u  http://localhost:18081/sqlinject/mybatiswrong --data name=test --current-db --flush-session
...........................

[13:32:44] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.6
[13:32:44] [INFO] fetching current database
current database: 'sqlinject'
....................................

C:\Python310\sqlmap>

从结果可以看出来,注入成功了,获取到了数据库名称。

${} 占位符会将参数值直接替换到 SQL 语句中。这可能导致 SQL 注入的风险,因此应谨慎使用。只有当你完全信任传入的值并且确定它是安全的时,才可以使用${} 占位符。

  • #{}占位符
@PostMapping("mybatisright")
public List mybatisright(@RequestParam("name") String name) {
  //curl -X POST http://localhost:18081/sqlinject/mybatisright?name=test
  // python sqlmap.py -u  http://localhost:18081/sqlinject/mybatisright --data name=test --current-db --flush-session
  return userDataMapper.findByNameRight(name);
}


//正确示范,采用#{} 占位符的方式
@Select("SELECT id,name FROM `userdata` WHERE name LIKE CONCAT('%',#{name},'%')")
List<UserData> findByNameRight(@Param("name") String name);
  • 使用sqlmap测试是否注入
C:\Python310\sqlmap>python sqlmap.py -u  http://localhost:18081/sqlinject/mybatisright --data name=test --current-db --flush-session
................................

[13:37:28] [WARNING] POST parameter 'name' does not seem to be injectable
[13:37:28] [CRITICAL] all tested parameters do not appear to be injectable. Try to increase values for '--level'/'--risk' options if you wish to perform more tests. If you suspect that there is some kind of protection mechanism involved (e.g. WAF) maybe you could try to use option '--tamper' (e.g. '--tamper=space2comment') and/or switch '--random-agent'

C:\Python310\sqlmap>

从结果可以看出来注入失败,Mybatis将#{}参数值视为一个 JDBC 参数,而不是 SQL 语句的一部分。MyBatis 会自动将参数值进行转义,确保其安全性。

  • ${}VS #{}对比

这两位同志有各自的用处,

${}#{}
拼接符占位符
字符串替换,SQL拼接SQL预编译
执行前:select * from t_user where uid= ‘${uid}’ 执行后:select * from t_user where uid= ‘1’执行前: select * from t_user where uid=#{uid} 执行后:select * from t_user where uid= ?
不能防止sql 注入能防止sql 注入

使用动态SQL

MyBatis提供了动态SQL的功能,可以根据条件动态拼接SQL语句。在使用动态SQL时,MyBatis会自动对参数值进行转义,从而防止注入攻击。

<select id="findByNameDynamic" resultType="icu.kevin.dataandcode.sqlinject.UserData">
        SELECT id, name
        FROM `userdata`
        <where>
            <if test="name != null">
                AND name LIKE CONCAT('%',#{name},'%')
            </if>
        </where>
    </select>
  • 使用sqlmap探测,发现确实达到了防止注入的能力。

配置 SQL 注入过滤器

// 配置 SQL 注入过滤器
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.addInterceptor(new SqlExplainInterceptor());

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

半山猿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值