摘要:本文介绍了SQL注入攻击的原理与常见的注入方式,并给出了常见SQL注入攻击的防范方法。
关键字:SQL注入 防范技术 网络安全
引言
在任何WEB开发中,安全性都是一个重要因素。在WEB应用程序中,确保安全性是一个重要而复杂的问题。网站应用程序的安全性通常界定为在其上运行的计算机的配置,以及诸如数据库之类的连接资源。这就需要在特定文件夹、文件、组件和其他资源上限制访问,以及授权给合适的用户。我们知道可用ASP.NET提供的身份验证、授权、角色扮演,IIS自带的NTFS权限和委托技术来增强WEB应用程序和服务器安全性,但当发生SQL注入攻击时,对于保护数据库安全还是远远不够的。本文将重点讨论使用SQL注入攻击危及数据库安全的原理,以及结合所做项目实践提出防范措施.
什么是SQL注入
SQL注入攻击是当今最危险、最普遍的基于WEB 的攻击方式之一。所谓注入攻击,就是攻击者把SQL命令插入到web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令。在某些表单中,用户输入的内容直接用来构造(或影响)动态SQL命令,或作为存储过程的输入参数,这类表单特别容易受到SQL注入攻击。这种攻击的要诀在于将SQL的查询或行为命令通过‘嵌入’的方式放入合法的HTTP提交请求中从而达到攻击者的某种意图,接着通过运用一些特权登陆,能让恶意用户通过程序在你的数据库上执行命令。
下面我们以一个asp.net下的登录网页为例来了解一下SQL注入攻击。在设计登录网页时,我们会放两个TEXTBOX控件,分别让使用者填入用户名及密码,界面如下:
在使用者按下登录按钮后,我们将用户的输入提交给服务器,验证用户输入是否正确,代码如下:
private bool ValidateUser(string userName, string password)
{
SqlConnection conn = new SqlConnection(
"Data Source=JEFFRAY;Initial Catalog=Northwind;Integrated Security=True");
using (conn)
{
SqlCommand cmd = new SqlCommand("SELECT COUNT(*) FROM USERS WHERE USER_ID = '"
+ userName + "' AND PASSWORD = '" + password + "'", conn);
conn.Open();
return ((int)cmd.ExecuteScalar() > 0);
}
}
此时,如果攻击者在登录页面中输入如下数据:
Username:admin
Password:or 1=1
这时,查询语句将变为:SELECT COUNT(*) FROM USERS WHERE USER_ID =’admin’ and password=’or 1=1--‘,通过必然为真的查询语句,我们的网站就这样的暴露在网络上,这里我们加上的是“or”,如果我们加上的是“drop table”等破坏性语句,后果就不堪设想了。
3、SQL注入过程
3.1 判断能否进行SQL注入
SQL注入攻击的第一步是判断网站是否存在SQL注入安全隐患,能够进行SQL注入攻击。判断网站是否能进行SQL注入攻击,最常用的就是经典的1=1、1=2测试法。例如:这是一个正常的网址:http://localhost/show.asp?id=11,该网址递交到服务器后,服务器端将执行“select * from 表名 where 字段名=&id”的查询,并将查询结果返回到客户端。如果客户端故意通过URL提交这个网址:http://localhost/show.asp?id=11 and 1=1,如果该网址提交到服务器执行后,客户端仍是正常显示网页,那么该网站就能够进行SQL注入攻击。那么,攻击者就能够通过构建SQL语句的方式去非法的获得服务器端相关数据或进行相关非法操作。
3.2 判断数据库类型
不同数据库的函数、注入方法都是有差异的,所以在注入之前,常常需要判断一下数据库的类型。我们可以从Access和SQLServer的区别入手,Access和SQLServer都有自己的系统表,比如存放数据库中所有对象的表,Access是在系统表[msysobjects]中,但在Web环境下读该表会提示“没有权限”,SQLServer是在表[sysobjects]中,在Web环境下可正常读取。在确认可注入的情况下,在URL中向服务器提交这个网址:http://localhost/show.asp?id=11 and (select count(*) from sysobjects)>0,此时,如果数据库是SQLServer,该网址的页面与原页面http://localhost/show.asp?id=11是相同的,如果数据库使用的是ACCESS,则页面与原页面完全不同。
3.3 根据注入参数类型,重构SQL语句原貌
在知道数据库类型后,就可以根据注入参数类型,重构SQL语句原貌。接着,将查询条件替换成SQL语句,猜测表明,例如:ID=11 And (Select Count(*) from Admin)>=0,如果提交后显示页面与ID=11的相同,说明附加条件成立,即表Admin存在,反之,即不存在。如此循环,直至猜到表名为止。
表名猜出来后,将Count(*)替换成Count(字段名),用同样的原理猜解字段名。最后,在表名和列名猜解成功后,再使用SQL语句,得出字段的值。
这一个过程是一个反复猜测,测试的过程,看上去非常繁琐而且需要花费很多的时间,如果我们用此种手工方式进行SQL注入入侵的话,即使网站存在SQL注入漏洞,我们注入的成本也会很高。但是,如果攻击者使用专门的工具来进行入侵的话,情况就不同了,利用专门的入门攻击也许只需几分钟就能够完成整个注入过程,获取非法的网站操作权限。
SQL注入攻击的防范措施
从SQL注入攻击的源头、路径及攻击方式的分析,我们可以有针对性的采取如下防范措施:
(1)过滤或转义敏感字符/字符串
过滤或转义危险字符是阻止SQL注入最常用也是最简单的方法。这种技术的思想基础是,从用户输入中移除(过滤)危险字符,或者使数据库将危险字符作为文字对待(即转义)。例如:替换单引号成两个单引号:
Function reqstr(strname)
Reqstr=replace(request(strname),”’”,”’’”)
End function
(2) 限制用户输入值的长度
使用过滤法可以阻止特定字符如“’”、“or”的输入,能有效防止必然成真条件式及错误信息显示的漏洞,但如果攻击者通过SQL转码函数,攻击者可以将部分SQL语句做出编码来逃避侦测,最终突破这道防线。但由于转码后的字符串相当长,所以,只需我们搭配MaxLength的设定,限制用户输入值的长度,并可保证过滤法的有效。但过滤法本身其实很脆弱,所以需要程序员搭配其他方法才能保证过滤法的有效。
(3)使用参数化查询
使用参数化查询是目前已知的,一劳永逸的逃避SQL注入攻击的最有效的方式。要防御SQL注入,用户的输入就不能够直接嵌入到SQL语句中,使用parameters对象,可以避免用字符串直接拼接成SQL语句,从而起到防止SQL注入的目的。虽然使用parameters的方法可以有效的防止SQL注入,但与此同时也增加了书写程序的长度,通常的情况是程序员只会在特定敏感功能上才使用这种方法。
5 结束语
SQL注入总是针对于我们程序开发中的薄弱或不严密环节进行攻击,这对于大多数的防火墙来说,这种攻击是合法的。因此,有效的防止SQL注入攻击,必须依赖网站程序开发者的严密的编程设计。