SQL注入的防范措施

2020-08-20  本文已影响0人  文景大大

SQL注入,是利用web程序的请求,构建特殊的输入参数,将恶意的SQL语句注入到后台数据库引擎中,最终可以欺骗服务器执行恶意SQL。

车牌识别SQL注入

一般我们在根据用户的输入参数进行查询数据库时,需要对参数进行预编译;如果是不能预编译的场景,那么需要对输入参数采取类型检查、转义映射、安全过滤等措施。

一、什么是SQL预编译

很多时候,我们可能会反复地执行一条SQL语句,每次执行的时候只不过是参数值不同而已,SQL语句的结构并未发生变化。

如果没有预编译,那么每次在执行这些SQL的时候,数据库都需要进行词法分析、语义分析、制定执行计划、执行并返回结果这些操作,比较耗时和耗费资源。因此,数据库有一种机制可以将这些结构相同的SQL进行预编译,形成固定的执行计划,下次再执行的时候,直接拿这些执行计划,套入传入的参数执行即可,大大提高了效率。

SQL语句解析过程

如何启用数据库的预编译功能呢?我们使用JDBC的时候,使用PreparedStatement就可以达到目标。如此,SQL的语句会提前发送给数据库进行预编译,变量值就使用占位符来表示,等到真的要执行SQL的时候,将参数填入占位符按照事先的执行计划执行即可。

二、为什么SQL预编译可以防止SQL注入

PreparedStatement和Statement最大的区别在于,前者会提前将SQL发送给数据库进行预编译,提前确定了执行计划,对于输入的参数,无论是什么,都会按照原先的计划进行填入执行,不会再改变SQL的逻辑结构;而后者则会随着输入参数的不同改变SQL逻辑结构,因此有注入的风险。

三、MyBatis是如何做到防止SQL注入的

一般${}主要用在传入数据库对象的场景中,比如需要使用动态的表名和列名时,这种场景下无法使用#{},我们就需要手动对参数进行过滤,来确保SQL的安全;

四、不能使用预编译时该如何方式SQL注入

如下是一个对输入参数进行检查的例子:

    protected static boolean sqlValidate(String str) {    
        //统一转为小写    
        str = str.toLowerCase();
        String badStr = "'|select|update|and|or|delete|insert|truncate|char|into|iframe|href|script|activex|html|flash"  
                + "|substr|declare|exec|master|drop|execute|"  
                + "union|;|--|+|,|like|%|#|*|<|>|$|@|\"|http|cr|lf|<|>|(|)";//过滤掉的sql关键字,可以手动添加       
        String[] badStrs = badStr.split("\\|");    
        for (int i = 0; i < badStrs.length; i++) {    
            if (str.indexOf(badStrs[i]) >= 0) {    
                return false;    
            }    
        }    
        return true;    
    }

五、参考文献

如下这篇文章有更详细的介绍:
SQL注入详解

上一篇 下一篇

猜你喜欢

热点阅读