博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
通用分页存储过程真的有注入漏洞吗?
阅读量:5946 次
发布时间:2019-06-19

本文共 2787 字,大约阅读时间需要 9 分钟。

原文:

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

     1):

     2):

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

     我们来简化下之前两位园友讨论的分页存储过程,原代码太长,我这里呢写一个针对一个单表查询的存储过程。创建一个用户表,表结构如下:有三个字段,人员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;i<sql .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+"%'"

}

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

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

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

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

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

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

     针对分页存储过程的处理,不妨看看这篇:

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

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

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

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

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

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

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

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

注:

   欢迎大家发表意见!

 

 

转载地址:http://lefxx.baihongyu.com/

你可能感兴趣的文章
我的友情链接
查看>>
CentOS7安装mysql
查看>>
RMB數字轉換中文
查看>>
基于rhel7.2的Zabbix平台搭建和部署(二)
查看>>
Html5本地存储和本地数据库
查看>>
我的友情链接
查看>>
JQ 循环切换DIV
查看>>
Nagios监控NetAPP NAS存储容量,Volume、Qtree
查看>>
Android Fragment实践(二)
查看>>
centos 修改主机名立即生效和重启后也生效的方法
查看>>
Windows 64 位 mysql 5.7以上版本包解压安装
查看>>
知道双字节码, 如何获取汉字 - 回复 "pinezhou" 的问题
查看>>
TClientDataSet[14]: 测试 FindFirst、FindNext、FindLast、FindPrior、Found
查看>>
CentOS 6.3中配置bond多网卡负载均衡
查看>>
调整数组使奇数全部都位于偶数前面
查看>>
clamav 完整查杀 linux 病毒实战
查看>>
我的友情链接
查看>>
EIGRP的Metric计算以及负载均衡
查看>>
org-capture 配置
查看>>
linux下lvs搭建负载均衡集群
查看>>