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

Posted 石头StoneWang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于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} 就可避免了。

以上是关于关于SQL注入(有例子)以及我的一些想法的主要内容,如果未能解决你的问题,请参考以下文章

Android 仪器测试中的 Dagger 2 注入

SQL注入多试试总会有的

如何判断是不是存在SQL注入以及注入类型?

SQL注入关于GORM的SQL注入问题

SQL注入关于GORM的SQL注入问题

以下代码片段是不是容易受到 Rails 5 中 SQL 注入的影响?