防sql注入常用方法

sql注入的原理与应对

sql注入是黑客通过代码注入(前端表单、URL等),攻击数据库的一种手段。简单的说,可以将数据库语句区分成编译前和编译后两种状态,sql注入攻击数据库,只对编译前的sql有作用。

举个栗子:一个校验用户登入的sql语句。

SELECT id,name FROM user where username = 'A'  and password = 'B';

其中A和B是传入的参数,正常情况通过该语句进行密码校验没啥问题。

假设A的参数被人拦截,模拟数据请求  A 的值设为 ' or 1=1 --  那么该语句将变成 ;

SELECT id,name FROM user where name = '1' or 1=1   -- and password = 'B';

从图中可以很明细的看出 -- 后的语句被注释掉,同时通过or 1=1 可以查询出所有的账号和密码 ,轻而易举的登入系统,当然这只是一个简单的例子,如果将A替换成 '; drop XXX,可以将整个数据库删除。

SELECT id,name FROM user where name = '1'; drop XXX   -- and password = 'B';

以下简单介绍几种防sql注入的方法,知道了sql注入的原理我们可以通过避免这类语句的插入来达到防注入的目的:

1、简单通过,正则表达式和字符串过滤等,过滤掉存在  ‘ 、-- 、;、等这里字符串。

 private String CHECKSQL = “^(.+)\\sand\\s(.+)|(.+)\\sor(.+)\\s$”;
 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;

  }

2、也可以通过js前端校验表单提交的数据内容。

3、通过jdbc预编译好的sql语句进行防注入,通过 占位符 ?,通过参数传递的方式,编译后的语句无法进行sql注入。

  String sql= "select * from user where username=? and password=?;
        PreparedStatement preState = conn.prepareStatement(sql);
        preState.setString(1, userName);
        preState.setString(2, password);
        ResultSet rs = preState.executeQuery();

采用预编译语句集,它内置了处理SQL注入的能力,只要使用它的setXXX方法传值即可。

使用好处:

  •      代码的可读性和可维护性.
  •      PreparedStatement尽最大可能提高性能.
  •      最重要的一点是极大地提高了安全性.

原理:

  • sql注入只对sql语句的准备(编译)过程有破坏作用
  • 而PreparedStatement已经准备好了,执行阶段只是把输入串作为数据处理,
  • 而不再对sql语句进行解析,准备,因此也就避免了sql注入问题.

4、通过调用现有的框架,hibernate、mybatis他们已经内置过滤了部分的sql注入。

通过mybatis调用数据库,用#进行参数传递,他可以事先将sql语句编译好,通过占位符 ?进行参数传递,编译后的sql是无法进行sql注入的。我们开发时应尽量使用 # ,在开发中对于表名、字段名不可避免的用到$ 进行参数传递,由于他是后编译的,我们应在参数传递时做好字符过滤。

猜你喜欢

转载自blog.csdn.net/lq18050010830/article/details/82689970