通用分页存储过程真的有注入漏洞吗?

2016-02-19 18:18 16 1 收藏

图老师设计创意栏目是一个分享最好最实用的教程的社区,我们拥有最用心的各种教程,今天就给大家分享通用分页存储过程真的有注入漏洞吗?的教程,热爱PS的朋友们快点看过来吧!

【 tulaoshi.com - 编程语言 】

  今天看了两篇关于存储过程SQL注入漏洞的文章:

  1):如此高效通用的分页存储过程是带有sql注入漏洞的

  2):防SQL注入:生成参数化的通用分页查询语句

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  怎么看怎么觉的别扭,在我印象中存储过程是不会存在注入漏洞的啊?起码我目前的水平还不了解如何注入存储过程。如果大家有注入的方法请指教。换句话说存储过程本身并无注入漏洞,只不过有漏洞大多都是因为程序漏洞导致。

  我们来简化下之前两位园友讨论的分页存储过程,原代码太长,我这里呢写一个针对一个单表查询的存储过程。创建一个用户表,表结构如下:有三个字段,人员ID,姓名字段。

CREATE TABLE [dbo].[person](
  [id] [int] NULL,
  [last_name] [varchar](30) COLLATE Chinese_PRC_CI_AS NULL,
  [first_name] [varchar](30) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]

  然后写一个查询存储过程(getPerson):作用,根据不同的条件读取用户信息。

IF ( EXISTS ( SELECT  *
       FROM   sysobjects
       WHERE   id = OBJECT_ID(N'[dbo].[getPerson]')
            AND OBJECTPROPERTY(id, N'IsProcedure') = 1 ) )
  BEGIN
    DROP PROCEDURE [dbo].[getPerson]
  END
Go
CREATE PROC getPerson
  @strWhere VARCHAR(100) = '' -- 查询条件 (注意: 不要加 where)
AS
  BEGIN
    DECLARE @strSQL VARCHAR(1000) -- 主语句
    SET @strSQL = 'select top 10 * from person where 1=1 '
  --如果存在条件,则加上
    IF @strWhere != ''
      BEGIN
        SET @strSQL = @strSQL + @strWhere     
      END
    PRINT ( @strSQL )
    EXEC ( @strSQL
      )
  END

  查询方式,根据用户的姓来查询。要想最终的存储过程执行语法正确,同时不存在注入漏洞, 此时条件的正确格式是:and first_name like '%Jim''s dog%'。

  我们可以看到条件Jim's dog组装成SQL后,中间的单引号一定要变成两个。为了避免注入,我一般这样处理SQL拼接的安全问题:在C#写程序的时候应该这样写:

/// summary
    /// 屏蔽字符串中的特殊字符
    /// by minjiang 07-07-06
    /// /summary
    public string SafeRequest(string str)
    {
      //定义要返回的字符串
      string sReturn;
      //将要处理的字符串转换为小写字母
      str = str.ToLower();
      //定义特殊字符串
      string SQL_KILL = "'|and|exec|insert|select|delete|update|count|*|%
|chr|mid|master|truncate|char|declare|set|;|from|=|--|drop||";
      char[] separator ={ '|' };
      string[] sql = SQL_KILL.Split(separator);
      for(int i=0;isql .Length ;i++)
      {
        //如果有特殊字符则将它替换成为空
        if(str.IndexOf (sql [i].ToString ().ToLower ())-1)
        {
          //把单引号替换成双引号

if (sql[i].ToString() == "'")
          { str = str.Replace("'", "''"); }
          else
          {
            //把敏感字符替换成空
            str = str.Replace(sql[i].ToString().ToLower(), "");
          }
       
        }
     
      }
      sReturn = str;
      return sReturn;
   
    }
  
if(sUserName!="")
{
 strWhere +=" and first_name like'%"+this.SafeRequest(sUserName)+"%'"
}

  分页存储过程注入的机会: 上面的通用分页存储过程之所以会说存在SQL注入的机会,是因为通配符like后面的单引号,如果在后面参数中也出现单引号与like通配符后面的单引号相匹配后,后面的内容就是SQL注入的内容了。此时我们可以写一个过滤SQL特殊字符的方法,对特殊字符进行处理,可能根据自己的情况,选取相应过滤条件。最起码要把用户名中的单引号替换成双引号。下面的写法是不安全的:用户名中有单引号,例如 :Jim's dog

if(sUserName!="")
{
 strWhere +=" and first_name like'%"+sUserName+"%'"
  
}

  说明:园友 小No提到,能够通过把输入注入条件编码成十六进制编码来骗过过滤程序。这种情况的确存在,所有可以针对html标签中又属于SQL敏感字符的内容进行十六进制的比较。例如:‘,;。“-”不用处理,因为它不会被HTML编码。    

  我个人不太支持这种所谓高效的通用分页存储过程,理由:

  1:可阅读性太差,整版的字符串,谁看着都不舒服。

  2:对应用程序有比较高的安全要求,稍不注意就会存在上面所说的注入漏洞。

  3:对多表的复杂查询无能无力。如果强行应用,我想远比单独写一个存储过程来的麻烦。

  4:所谓通用,即大多数人都知道你这个存储过程的大致结构,这样无疑给别有用心者更多可趁之机。

  针对分页存储过程的处理,不妨看看这篇:你是如何面对大量分页需求的?

  总结:通用分页存储过程本身是没有漏洞可言的,只不过是程序的不严谨造成的注入机会。

  解决这种拼接SQL字符串可能带来的隐患方案:

  1:尽量对输入参数进行类型设置,能设置成数字型的一定要设成数字型。


  2:设置好参数的长度,一个字符串,例如姓名,一般不会超过20个字符。

  3:输入的参数内容能删除空格的就最好利用Trim(),这样,就算有SQL敏感字符,一旦SQL连接成一串,那也是不能够正常注入。

  4:尽量过滤传入的条件,起码要把单引号替换成双引号。

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  5:严格设置数据库用户的权限,负责查询的用户,只让它具有读的权限,这样就算是注入成功,也不能造成致命的后果。

  具有插入权限的用户,严格控制删除,更新的权限。而佣有删除权限的用户,一般都佣有查看权限,删除操作是很难存在SQL注入的。

来源:http://www.tulaoshi.com/n/20160219/1617222.html

延伸阅读
标签: Web开发
建立一个 Web 应用,分页浏览功能必不可少。这个问题是数据库处理中十分常见的问题。经典的数据分页方法是:ADO 纪录集分页法,也就是利用ADO自带的分页功能(利用游标)来实现分页。但这种分页方法仅适用于较小数据量的情形,因为游标本身有缺点:游标是存放在内存中,很费内存。游标一建立,就将相关的记录锁住,直到取消游标...
标签: ASP
  /*****听以前的同事说asp页面上的分页太慢了(如果数据多了), 就想了这么个笨办法。有些地方还要考虑----比如select top 22 * from cat_list where T_id not in (select T_id from #change)是否有效率问题;数据不能重复等等 不过灵活性挺好。希望各位高手再给帮忙改正;多谢chair3的帮助---这个存储过程还可以在加入几个变量,随便...
其实在很多时候设计的度还是要把握的,不至于让自己陷入的怪圈中才是最重要的,因为我们还要留出时间还解决其他的很多问题,个人认为适度就可以了,留出一定的空间。也因为万能是不存在的,万物在一定的范畴之内都是合理的,出了范畴可能就没有合理的了。          分页存储过程大致有下列几种 1、&n...
代码如下: create database Test on primary ( name='Test_Data.mdf', filename='D:\我的资料\sql\备份\Test_Data.mdf' ) log on ( name='Test_Data.ldf', filename='D:\我的资料\sql\备份\Test_Data.ldf' ) if object_id('tb') is not null drop table tb create table tb ( Col int ) insert into tb select top 50 number ...
标签: ASP
  在  网上 讨论 如何 实现 分页  有很多程序,我在这里向大家  介绍一种实现分页的新的方法,使用 存储过程 来实现分页    由于 这段程序写的 比较早,那个时候 还没有 SQL 7,每一个 Varchar 只能 支持 255 个字符,所以 采取了一种比较笨的办法,如果大家有兴趣,请去  http:/...

经验教程

42

收藏

71
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部