sql injection(sql 注入)

  • 前言

    • 当一个攻击者通过在查询语句中插入一系列的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
string sql1 = string.Format(
    "SELECT job_id, job_desc, min_lvl, max_lvl FROM jobs WHERE job_id='{0}'", jobId);

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

防止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;
}
  • 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;
}

总的说来,防范一般的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)   )); 

你可能感兴趣的:(JavaSE基础)