关于SQL注入(有例子)以及我的一些想法

背景

本文详细讨论sql注入的那些事情。聊聊自己的看法。并且会提供sql注入的例子。

sql注入的例子

例子就不用jdbc的 API 来演示了。我直接用了springboot+mybatis来模拟出来

1、代码
  • 写一个controller的接口

    @GetMapping("/user/list")
        public Object listUser(
                @RequestParam String name
        ) {
            return userService.listUser(name);
        }
    
  • service层的代码

    @Override
        public List<UserDTO> listUser(String name) {
            return userMapper.listUser(name);
     }
    
  • dao层(这是最关键的)

    @Select({"<script>",
                "select * from user where name='${name}'",
                "</script>"})
        List<UserDTO> listUser(@Param("name") String name);
    

    可以看到使用了 ${xxx} 而不是 #{xxx}

2、测试和总结

上述web跑起来后,参数传入

  • 正常访问:http://localhost:8888/user/list?name=stone

  • sql注入:http://localhost:8888/user/list?name=stone' or '1'='1

    这种方式,最终构造出来的sql是 select * from user where name='stone' or '1'='1',利用了or以及1=1恒成立。

3、进一步补充

除了上述,其实还可以利用注释符号,比如有些用 # 作为注释,有些用 --,mysql可以使用 #。如下:

select * from user_login where name='${name}' and password='${password}'

name传入 ' or 1=1; # ,password随便传什么值,最终会变成

select * from user_login where name='' or 1=1; #' and password='随便传什么值'

# 之后是注释,会被忽略。另外甚至可以传入 or 1=1;drop database test ;# 之类的,或者 or 1=1;delete from xxx ;# ,不过后面2个mybatis会报错,我没试验成功,总之你认为sql注入非常危险就是了。

解决方法

  • 如果你使用mybatis,使用 #{xxx} 替代 ${xxx} 就好了
  • 如果你用jdbc,使用PreparareStatement即可,即避免使用Statement,并且避免sql语句字符串拼接参数

PS:貌似mybatis-plus框架还搞了一些拦截器,拦截有问题的入参,有必要搞得这么复杂吗?不是使用 #{xxx} 就能解决吗? 难道就算使用 #{xxx} 也还是存在sql注入风险??

总结

其实感觉sql注入也没那么可怕。
首先,如果是内部使用的系统或者toB的话,人员没那么杂。
其次,就算是C端用户,也要猜到哪些操作对应后台的sql是可以进行注入的,就算知道了这条sql语句有问题,也很难知道sql的全貌,构造有问题的入参的时候很可能会导致sql根本就不能执行,即大概率sql执行是出错的。
最后,只要后端人员稍微规范一点用 #{xxx} 就可避免了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值