当前位置:首页 >> 网络通讯 >> 网络安全 >> 内容

Web十大安全隐患之SQL注入

时间:2013/4/19 12:10:00 作者:平凡之路 来源:xuhantao.com 浏览:

注入往往是应用程序缺少对输入进行安全性检查所引起的,攻击者把一些包含指令的数据发送给解释器,解释器会把收到的数据转换成指令执行。常见的注入包括SQL注入,OS Shell,LDAP,Xpath,Hibernate等等,而其中SQL注入尤为常见。这种攻击所造成的后果往往很大,一般整个数据库的信息都能被读取或篡改,通过SQL注入,攻击者甚至能够获得更多的包括管理员的权限。

       涛涛电脑知识

    先来说说sql注入漏洞是怎么产生的,或者说对于一个程序开发人员应该怎么防范SQL注入的吧。

 

    SQL注入往往是在编写包含用户输入的动态数据库查询时产生的,但其实防范SQL注入的方法非常简单。程序员只不再写动态查询,或防止用户输入包含能够破坏查询逻辑的恶意SQL语句,就能够防范SQL注入。当然,我作为一个测试人员说起来很容易,做起来就难了。

  我本人只会java,所以后边我就用Java代码作为示例:

1.<font face="宋体" color="#000000">String query ="SELECT account_balance FROM  user_data WHERE user_name ="

2.    + request.getParameter("customerName");

3.   

4.  try {

5.  Statement statement =

6.  connection.createStatement( …);

7.  ResultSet results =

8.  Statement.executeQuery(query);

9.  }</font>

 

 

  在以上代码中,我们可以看到并未对变量customerName做验证,customerName的值可以直接附在query语句的后面传送到数据库执行,那么攻击者可以将任意的sql语句注入。

 

    上边说到怎么产生的,我们接着说怎么样才能让sql注入的漏洞避免。本来计划把这一段放在如何测试之后再介绍,但是貌似先介绍出来更方便理解。

 

防范方法一 :参数化查询

  参数化查询是所有开发人员在做数据库查询时首先需要学习的,参数化查询迫使所有开发者首先要定义好所有的SQL代码,然后再将每个参数逐个传入,这种编码风格就能够让数据库辨明代码和数据。

  参数化查询能够确保攻击者无法改变查询的内容,在下面修正过的例子中,如果攻击者输入了UsrID是“’or ‘1 ‘=’1”,参数化查询会去查找一个完全满足名字为‘or ‘1 ‘=’ 1的用户。

  对于不同编程语言,有一些不同的建议:

  Java——使用带绑定变量的PreparedStatement();

   其他的:。。。不好意思,真不会

  示例:

1.<font face="宋体" color="#000000">String custname = request.getParameter("customerName");

2.  String query ="SELECT account_balance FROM user_data WHERE user_name= ?";

3.   

4.  PreparedStatement pstmt = connection.prepareStatement(query);

5.  Pstmt.setString1,custname();

6.  ResultSet results = pstmt.executeQuery();</font>

 

防范方法二:存储过程

  存储过程和参数化查询的作用是一样的,唯一的不同在于存储过程是预先定义并存放在数据库中,从而被应用程序调用的。

  Java存储过程示例:

1.String custname = request.getParameter("customerName");

2.  try {

3.        CallableStatement cs = connection.prepareCall("call sp_getAccountBalance(?)}");

4.        cs.setString(1,custname);

5.        Result results = cs.executeQuery();

6.  }catch(SQLException se){

7.  //error handling

8.  }

 

防范方法三:对所有用户输入进行转义

  我们知道每个DBMS都有一个字符转义机制来告知DBMS输入的是数据而不是代码,如果我们将所有用户的输入都进行转义,那么DBMS就不会混淆数据和代码,也就不会出现SQL注入了。

  当然,如果要采用这种方法,那么你就需要对所使用的数据库转义机制,也可以使用现存的诸如OWASP ESAPI的escaping routines。ESAPI目前是基于MySQL和Oracle的转义机制的,使用起来也很方便。一个Oracle的ESAPI的使用示例如下:

1.ESAPI.encoder().encodeForSQL(new  OracleCodec(),queryparam);

 

  那么,假设你有一个要访问Oracle数据库的动态查询代码如下:

1.String query ="SELECT user_id FROM user_data  WHERE user_name = ‘"+req.getParameter("userID")+"’ and user_password = ‘"+req.getParameter("pwd")+"’";

2.  try {

3.        Statement statement =  connection.createStatement(…);

4.        ResultSet results =  statement.executeQuery(query) ;

5.  }

 

  那么,你就必须重写你的动态查询的第一行如下:

1.Codec ORACLE_CODEC = new OracleCodec();

2.  String query ="SELECT user_id FROM user_data WHERE user_name = ‘"+

3.  ESAPI.encoder().encodeForSQL(ORACLE_CODEC,req.getParameter("userID"))+"’ and user_password = ‘"+

4.  ESAPI.encoder().encodeForSQL(ORACLE_CODEC,req.getParameter("pwd"))+"’";

 

  最小权限法:

  为了避免注入攻击对数据库造成的损害,我们可以把每个数据库用户的权限尽可能缩小,不要把DBA或管理员的权限赋予你应用程序账户,在给用户权限时是基于用户需要什么样的权限,而不是用户不需要什么样的权限。当一个用户只需要读的权限时,我们就只给他读的权限,当用户只需要一张表的部分数据时,我们宁愿另建一个视图让他访问。

  如果你的策略是都是用存储过程的话,那么仅允许应用程序的账户执行这些查询,而不给他们直接访问数据库表的权限。诸如此类的最小权限法能够在很大程度上保证我们数据库的安全。

  • 徐汉涛(www.xuhantao.com) © 2024 版权所有 All Rights Reserved.
  • 部分内容来自网络,如有侵权请联系站长尽快处理 站长QQ:965898558(广告及站内业务受理) 网站备案号:蒙ICP备15000590号-1