ASP.NET网站防SQL注入的方法研究

时间:2022-09-16 11:44:28

ASP.NET网站防SQL注入的方法研究

摘要:针对网站存在的SQL注入风险,分析SQL注入的原理,提出一系列防范SQL注入的措施和建议。通过综合运用这些方法,可以减少不安全因素,提高网站的安全性。

关键词:SQL注入;;SQL Server;网站安全

中图分类号:TP393文献标识码:A文章编号:1009-3044(2011)29-7078-02

The Research of Methods to Prevent SQL Injection on Website

HUANG Xiao-hua

(School of Computer Science and Engineering, Changshu Institute of Technology, Changshu 215500, China)

Abstract: According to the risk of SQL injection on website, the paper described the principles of SQL injection, put forward a series of measures and suggestions to prevent SQL injection. Through the integrated use of these methods, it can reduce the insecurity and improve the security of website.

Key words: SQL injection; ; SQL Server; website security

目前,有很多采用+SQL Server+IIS架构的网站,由于程序员的水平及经验参差不齐,不少程序员在编写代码的时候,没有对用户输入内容的合法性进行判断,导致应用程序存在SQL注入漏洞。因此,有必要通过了解SQL注入的原理,采取有效的措施来防范SQL注入,从而提高网站的安全性。

1 SQL注入概述

SQL注入就是攻击者通过正常的WEB页面,把自己SQL代码传入到应用程序中,从而通过执行非程序员预期的SQL代码,达到窃取数据或破坏的目的[1]。

当应用程序使用输入内容来构造动态SQL语句以访问数据库时,会发生SQL注入攻击。如果代码使用存储过程,而这些存储过程使用未筛选的用户输入,也会发生SQL注入。SQL注入可能导致攻击者使用应用程序登录到数据库中执行命令,如果应用程序使用特权过高的帐户连接到数据库,这种问题会变得很严重。许多网站程序在编写时,没有对用户输入的合法性进行判断或者程序中本身的变量处理不当,导致应用程序存在安全隐患。这样,用户就可以提交一段SQL代码,根据程序返回的结果,获得一些敏感的信息或者控制整个服务器,于是SQL注入就发生了。

例如,在Web 应用程序的登录验证程序中,一般有用户ID(UserId) 和密码(Password) 两个参数,程序会通过用户所提交输入的用户名和密码来执行授权操作。如果将SQL语句拼接起来可以写成:

Select * From User Where UserId = 'txtuserid.Text' And Password = 'txtpassword.Text'

其原理是通过查找User表中的用户ID和密码的结果来进行授权访问。如果分别给txtuserid.Text和txtpassword.Text赋值“' or '1' = '1' --”和“abc”,那么上述的SQL语句就会变为:

Select * From User Where UserId = '' or '1' = '1' --' And Password = 'abc'

该语句中进行了两个条件判断,只要一个条件成立就会执行成功。而“'1'='1'”在逻辑判断上是恒成立的,后面的“--” 表示注释,即后面所有的语句为注释语句,这样就能成功登录了。

如果给txtuserid.Text赋值“';Drop Table User --”,那么上述的SQL语句就会变为:

Select * From User Where UserId = '';Drop Table User --' And Password = 'abc'

如果数据表名被猜出,就会导致整个数据表的丢失。

2 SQL注入防范策略

2.1 限制错误信息输出到客户端

Web程序的错误信息往往是SQL注入攻击的重要信息来源,屏蔽这些信息可以加大SQL注入的难度,有助于提高网站的防SQL注入能力[2]。在程序中要特别注意处理错误信息,以免被攻击者轻易判断出程序的运行环境等信息。可以在web.config文件中定制出错页面,当程序发生错误时,将跳转到自定义的错误页面。

在Web.Config文件中配置如下:

这样当发生错误时就不会将信息泄露了。

2.2 在SQL语句中使用参数

SQL Server中的Parameters集合提供了类型检查和长度验证[3]。如果使用Parameters集合,则输入将被视为文字值而不是可执行代码。使用Parameters集合的另一个好处是可以强制执行类型和长度检查,范围以外的值将触发异常。

以下代码段显示了如何在调用SQL语句时使用Parameters集合:

SqlDataAdapter myAdapter = new SqlDataAdapter("Select UserName From User Where

UserId = @UserId", conn);

SqlParameter useridparameter = myAdapter.SelectCommand.Parameters.Add("@UserId",

SqlDbType.VarChar, 10);

useridparameter.Value = txtuserid.Text;

其中,@UserId参数被视为文字值而不是可执行代码,将对此值进行类型和长度检查。如果@UserId值不符合指定的类型和长度约束,则将引发异常。

SQL参数的传递方式将防止攻击者利用单引号和连字符实施攻击。通过这种方法,在不能使用存储过程的情况下,也能够很好地防范SQL注入式攻击。

2.3 在存储过程中使用参数

存储过程是存储在数据库服务器上的一系列SQL代码,它与函数相似,有良好的逻辑封装结构,可以接收和返回数据。使用存储过程可以使代码更易于维护,因为对存储过程的更改不会导致应用程序的重新编译,使用存储过程还可以节省带宽,提高应用程序性能。因为存储过程是存储在数据库服务端的独立的封装体,所以调用存储过程可以保证应用程序只执行存储过程中的固定代码。

通过结合使用类型安全的SQL参数,可以实现SQL代码可以实现的任何功能,并进一步提高应用程序的安全等级。

以下代码段显示了如何在调用存储过程时使用Parameters集合:

SqlDataAdapter myAdapter = new SqlDataAdapter("UserLogin", conn);

mandType = CommandType.StoredProcedure;

SqlParameter useridparameter = myAdapter.SelectCommand.Parameters.Add("@UserId",

SqlDbType.VarChar, 10);

useridparameter.Value = txtuserid.Text;

2.4 限制访问数据库帐号的权限

对于数据库的任何操作都是以某种特定身份和相应权限来完成的,SQL语句执行前,在数据库服务器端都有一个用户权限验证的过程,只有具备相应权限的帐号才可能执行相应权限内的SQL语句。在权限设计中,对于终端用户,即应用软件的使用者,没有必要给他们数据库对象的建立、删除等权限[4]。那么即使在他们使用SQL语句中带有嵌入式的恶意代码,由于其用户权限的限制,这些代码也将无法被执行。建议不要开启扩展存储过程,这样可以很好地防止通过执行xp_cmdshell来攻击服务器。

因此,限制数据库帐号权限,实际上就阻断了某些SQL语句执行的可能。不过,这种方法并不能根本解决SQL注入问题,因为连接数据库的帐号几乎总是比其他单个用户帐号拥有更多的权限。通过限制帐号权限,可以防止删除表的攻击,但不能阻止攻击者偷看别人的信息。

2.5 验证用户输入的内容

为了预防恶意输入,应该假定所有的用户输入都是非法的,通过测试类型、长度、格式和范围来验证用户输入。应在所有需要用户输入的地方进行验证,比如文本框和其它表单输入字段、查询字符串参数等。过滤策略应该是只允许正确的输入然后拒绝非法输入,这是因为定义正确的输入策略比过滤所有的非法输入要容易,那通常很难包括所有的非法输入。

1) 验证输入

验证用户输入的内容是否是正确的类型、长度、格式和范围,可以应用验证控件来实现。目前,提供了六种数据输入验证控件,同一个输入控件可以同时使用多种验证控件,结合正则表达式,程序员可以对用户的输入实施一系列复杂的验证规则,从而确保用户的输入符合程序的要求。例如,如果用户的登录名最多只有10个字符,那么不要认可表单中输入10个以上的字符,这将大大增加攻击者在SQL命令中插入有害代码的难度。

在验证用户输入的内容时,尽量使用服务器端的输入验证,不要依赖于客户端的验证,因为它很容易就被绕过。使用客户端验证是为了减少页面往返次数,提升性能,改进用户体验。

数据类型要用强数据类型。例如,为数字输入指定Integer或者Double类型,为字符输入指定String类型,为日期时间输入指定DateTime类型。

2) 过滤检查

对用户输入的内容进行过滤检查,可以有效地减少SQL注入的发生。可编写专用函数用来检测用户输入数据中可能有潜在威胁的字符[5],如构建SQL语句常用的单引号、连接符、关系运算符、SQL关键字等。对所有用户输入数据使用此函数检测后,再允许Web程序执行相应的数据库操作。

对于用户输入的字符型数据,替换单引号、删除连字符,是一个较好的处理方式。

替换单引号,即把所有单独出现的单引号改成两个单引号,防止攻击者修改SQL命令。例如,前面提到的“Select * From User Where UserId = '' or '1' = '1' --' And Password = 'abc'”,显然与“Select * From User Where UserId = ''' or ''1'' = ''1'' --' And Password = 'abc'”得到不同的结果。

删除连字符,防止攻击者构造出如“Select * From User Where UserId = '' or '1' = '1' --' And Password = 'abc'”之类的查询。因为这类查询的后半部分已经被注释掉,攻击者不通过验证可以顺利获得访问权限。

3 结束语

随着网络应用的日益普及,各种安全问题层出不穷,网站的安全问题也日益引起大家的关注。本文针对网站存在的SQL注入风险,提出了一系列防范SQL注入的措施和建议。通过综合运用这些策略,有针对性的防范,可以有效提高网站的安全性。

参考文献:

[1] 孙炯宁,徐永华.在中SQL注入式攻击探析[J],电脑学习,2009,(6):63-65.

[2] 周益宏,陈建勋.浅析基于的网站SQL注入攻击及防范措施[J].计算机安全,2010,(6):93-95.

[3] 吴晨,王春霞 2.0数据库项目案例导航[M].北京:清华大学出版社,2007.

[4] 王云,郭外萍,陈承欢. Web项目中的SQL注入问题研究与防范方法[J].计算机工程与设计,2010,31(5):976-978.

[5] 游向峰.SQL注入式攻击的分析与防范[J].电脑编程技巧与维护,2009,(1):84-85.

上一篇:关于计算机网络安全风险的分析与防范对策的研... 下一篇:基于sufferage的动态出租车拼车调度算法