聊聊SQL注入

SQL注入问题
  • 概述:
    • 首先SQL注入是一个非常危险的操作,很可能被一些不怀好意的人钻空导致我们系统出现异常等状况,比如数据库遭到破坏或被入侵 。
  • 原因:使用JDBC的Statement语句添加SQL语句
    • 由于我们的JDBC在对数据库进行操作时,需要客户端传入一些参数 。我们在日常中的处理是将字符串参数作为SQL语句进行拼接,但是加入客户端传入SQL语句关键字恶意篡改SQL语句就会改变服务端SQL语义发生系统异常 。严重时就会导致系统和数据库破坏,这时的攻击方式就叫SQL注入了 。
    • 实例:模拟登录请求传入用户id和密码参数,使用字符串拼接导致的SQL注入 。
      • 【聊聊SQL注入】拼接SQL语句,就会出现SQL注入的安全问题,拼接代码如下:
        String sql = "select * from user where username='" + uid + "' and password='" + passwd + "'";
      • 若此时传入参数如下:永真式 或 封号结束注释后面条件验证(只能说人的脑洞真大哈哈)
        params.put("uid", "malongfei");params.put("passwd", "111' or '1' = '1");// 或者params.put("uid", "malongfei'; -- ")// 或者params.put("uid", "malongfei'; # ")
      • 此时JDBC还没意识到安全问题,依旧将以上参数拼接到我们的SQL原语中,如下:
        select * from user where uid = 'malongfei' and passwd = '111' or '1' = '1';select * from user where uid = 'malongfei'; -- ' and passwd = '111' or '1' = '1';select * from user where uid = 'malongfei'; # ' and passwd = '111' or '1' = '1';
  • 预防SQL注入:使用PreparedStatement代替Statement可以有效防止SQL注入 。
    • PreparedStatement利用预编译的机制将sql语句的主干和参数分别传输给数据库服务器,这样即使参数中携带数据库关键字,也不能作为SQL中真正的关键字而起作用 。
    // 后端登录验证密码接口的SQL语句select * from user where uid = ? and passwd = ?;
    • 设置黑名单也可提前预防,单纯针对于用户输入中含有SQL关键字的拦截方法,比如在注册账号时,用户名和密码中不能含有SQL语句关键字;
    • 或者说在进行SQL拼接时加入逻辑处理,对传入参数含有SQL关键字的进行报输入异常 。
  • PreparedStatement与 Statment 区别:
    1. 语法不同:PreparedStatement 使用预编译的sql,而 Statment 使用静态的sql
    2. 效率不同: PreparedStatement 具有 sql缓存区,效率比 Statment 高
    3. 安全性不同:PreparedStatement 可以有效防止sql注入,而 Statment 不能
Mybatis对SQL注入的预防处理