转自:https://blog.csdn.net/m0_37204491/article/details/72717091

  • 前言

  • 当一个攻击者通过在查询语句中插入一系列的SQL语句来将数据写入到应用程序中,这种方法就可以定义成SQL注入。

  • SQL Injection:就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。

  • SQL注入是从正常的WWW端口访问,而且表面看起来跟一般的Web页面访问没什么区别,所以目前市面的防火墙都不会对SQL注入发出警报,如果管理员没查看IIS日志的习惯,可能被入侵很长时间都不会发觉。但是,SQL注入的手法相当灵活,在注入的时候会碰到很多意外的情况。能不能根据具体情况进行分析,构造巧妙的SQL语句,从而成功获取想要的数据。

  • 作为一名Web应用开发人员,一定不要盲目相信用户的输入,而要对用户输入的数据进行严格的校验处理,否则的话,SQL Injection将会不期而至。

  • 普通SQL注入技术概述

    • (1) 脚本注入式的攻击
    • (2) 恶意用户输入用来影响被执行的SQL脚本
  • SQL注入攻击的防御手段

    • (1) 在服务端正式处理之前对提交数据的合法性进行检查;
    • (2) 封装客户端提交信息;
    • (3) 替换或删除敏感字符/字符串;
    • (4) 屏蔽出错信息。
  • 接下让我们学习如何防止SQL Injection。总的来说有以下几点:

    • 1.永远不要信任用户的输入,要对用户的输入进行校验,可以通过正则表达式,或限制长度,对单引号和双”-“进行转换等。

    • 2.永远不要使用动态拼装SQL,可以使用参数化的SQL或者直接使用存储过程进行数据查询存取。

    • 3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。

    • 4.不要把机密信息明文存放,请加密或者hash掉密码和敏感的信息。

    • 5.应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装,把异常信息存放在独立的表中。

  • 代码示意

  • SELECT job_id, job_desc, min_lvl, max_lvl FROM jobs WHERE (job_id = 1) OR 1 = 1
     
    • 1
    • 2
    • 3
    string sql1 = string.Format(
        "SELECT job_id, job_desc, min_lvl, max_lvl FROM jobs WHERE job_id='{0}'", jobId);
     
    • 1
    • 2

    SELECT job_id, job_desc, min_lvl, max_lvl FROM jobs WHERE job_id = '1' OR '1' = 1'
     
    • 1
    • 2
    • 3
    SELECT job_id, job_desc, min_lvl, max_lvl FROM jobs WHERE job_id='1'or 1=(select count(*) from jobs)
     
    • 1
    • 2
    • 3

    防止sql注入的方法总结

    • 1.(简单又有效的方法)PreparedStatement

    • 使用好处:

    • (1).代码的可读性和可维护性.

    • (2).PreparedStatement尽最大可能提高性能.

    • (3).最重要的一点是极大地提高了安全性.

  • 原理:

    • sql注入只对sql语句的准备(编译)过程有破坏作用

    • 而PreparedStatement已经准备好了,执行阶段只是把输入串作为数据处理,

    • 而不再对sql语句进行解析,准备,因此也就避免了sql注入问题.

  • 2.使用正则表达式过滤传入的参数
    • 正则表达式:private String CHECKSQL = “^(.+)\\sand\\s(.+)|(.+)\\sor(.+)\\s$”;
    • 判断是否匹配:Pattern.matches(CHECKSQL,targerStr);
  • 下面是具体的正则表达式:
    检测SQL meta-characters的正则表达式 :
    /(\%27)|(\’)|(–)|(\%23)|(#)/ix
    修正检测SQL meta-characters的正则表达式 :
    /((\%3D)|(=))[^\n]*((\%27)|(\’)|(–)|(\%3B)|(:))/i
    典型的SQL 注入攻击的正则表达式 :
    /\w*((\%27)|(\’))((\%6F)|o|(\%4F))((\%72)|r|(\%52))/ix
    检测SQL注入,UNION查询关键字的正则表达式 :
    /((\%27)|(\’))union/ix(\%27)|(\’)
    检测MS SQL Server SQL注入攻击的正则表达式:
    /exec(\s|+)+(s|x)p\w+/ix

    • 3.字符串过滤
      • 比较通用的一个方法:(||之间的参数可以根据自己程序的需要添加)
    public static boolean sql_inj(String str)
    
    {
    
    String inj_str = "'|and|exec|insert|select|delete|update| count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";
    
    String inj_stra[] = split(inj_str,"|");
    
    for (int i=0 ; i < inj_stra.length ; i++ ){
        if (str.indexOf(inj_stra[i])>=0){
            return true;
        }
    }
    return false;
    }
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 4.jsp中调用该函数检查是否包函非法字符
    • 5.JSP页面判断代码:
      • 使用JavaScript在客户端进行不安全字符屏蔽
      • 功能介绍:检查是否含有”‘”,”\”,”/”
      • 参数说明:要检查的字符串
      • 返回值:0:是1:不是
    function check(a){
        return 1;
        fibdn = new Array (”‘” ,”\\”,”/”);
        i=fibdn.length;
        j=a.length;
        for (ii=0; ii<i; ii++){ for (jj=0; jj<j; jj++){ temp1=a.charAt(jj); temp2=fibdn[ii]; if (tem’; p1==temp2){ return 0; }
            }
        }
        return 1;
    }
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    总的说来,防范一般的SQL注入只要在代码规范上下点功夫就可以了。

    凡涉及到执行的SQL中有变量时,用JDBC(或者其他数据持久层)提供的如:PreparedStatement就可以,切记不要用拼接字符串的方法就可以了

    • 非关系型数据库防止sql注入(mongoDB、dynamoDB)
    login.php?username=admin&passwd[$ne]=1//password != 1
    
    
    $collection->find(array(   "username" => "admin",   "passwd" => array("$ne" => 1)   )); 
    
     
    • 1
    • 2
    • 3
    • 4
    • 5