林世鑫
摘要:SQL注入利用数据库系统的安全漏洞,以及程序中的验证漏洞,构造合适的SQL语句,并通过正常的URL访问进行代码提交,获取数据库中的相关信息,从而实现网站攻击的目的。加强用户提交数据的合法性验证,是防止SQL注入的基本方法。而改善ASP中的Request函数,使其具有对一切用户数据进行合法验证的能力,是SQL注入威胁下,Web数据安全防范方法的最佳优化。
关键词:SQL注入;数据安全;防范;优化
中图分类号:TP309.5 文献标识码:A 文章编号:1009-3044(2014)10-2184-04
Abstract: Exploiting the security vulnerabilities of database system and validation vulnerabilities of the computer programs, SQL injection builds proper SQL statements, submit code by normal URL access and get relevant information from the database in order to achieve the goal of website attacks.It is the basic approach of preventing SQL injection to strengthen the legality verification while a user submits data. And under the SQL injection threat, it is the best optimization of web data safety precautions to improve the Request function of ASP so as to make it capable to verify the legality of all user data.
Key words: SQL-injection; data security; precaution; optimization
在当前各类网站建设或者基于Web平台的软件系统建设(以下统称网站)中,由于从事开发的人员的水平与经验,参差不齐,这就直接导致许多网站,都存在着一定程度上的安全隐患,给黑客的攻击留有可趁之机,严重威胁着网站的正常运行。尤其是如果采用SQL注入进行攻击的话,由于该方法灵活多变,对网站的安全性具有更高的考验。并且,这种注入是通过WWW端口实现的,跟对网站的web页面的正常访问是一样的,因此,这种注入还能绕过许多防火墙的监控,具有很强的隐蔽性。
各种原因使然,国内目前绝大部分的网站,都采用asp技术,以Access或者SQL-Server为数据库。因此,笔者以此为技术平台,分析SQL注入的安全威胁、防范对策以及深入的优化策略。
1 SQL注入的基本原理
所谓SQL注入,是指利用网站程序对用户输入数据的合法性验证中存在的漏洞,构造合适的SQL语句,并通过正常的URL访问提交此代码,从而获取并借肋网站数据库中的相关信息,达到攻击的目的。这种注入随着攻击者的SQL语句构造能力愈强,变化也愈巧妙,对网站的开发者在数据安全防范方面的意识与能力,挑战性也就愈强。
SQL注入通常有以下四个特征:
1)利用用户输入数据的合法性验证漏洞进行突破。这与许多黑客攻击直接利用服务器的安全漏洞进行网站攻击有本质的不同。
2)应变性强。能够根据不同的数据库结构,构造出不同的SQL语句,巧妙灵活;
3)相关的攻击代码,通过Web端口,伴随着正常的页面访问进行注入,不直接与防火墙或其它安全防范软件进行“硬接触”。
4)Access数据库与Sql-server数据库一个共同的特点:如果参与运算的数据的数据类型不正确,就先尝试进行数据类型转换,如果转换失败,会返回一个错误报告。SQL注入正是利用这个特点,故意提交一些错误类型的数据,“诱惑”数据库自觉犯错并报错,从而泄露了重要信息。这一点,也是SQL注入最重要的特征。
我们举例实际分析一下SQL注入的基本原理。我们设定网站的测试服务器地址为:http://127.0.0.1,测试的URL为:http://127.0.0.1/art_detail.asp?id=8。
通过浏览器的地址栏输入以上URL,并在最后加上一个单引号,使其成为http://127.0.0.1/art_detail.asp?id=8,然后再次访问。这时,如果服务器在浏览器中返回以下信息:
Microsoft JET Database Engine 错误 '80040e14'
字符串的语法错误 在查询表达式 'ID=8'' 中。
/art_detail.asp,行9
那么,根据这个返回的错误信息就可以作出以下判断:
1)该网站存在SQL注入的安全漏洞,这是最基本的判断;
2)该网站的数据库是MS-Access,并且连接数据库的引擎是JET;
3)该页面使用的数据表中,有一个字段的名称是ID;
由此可见,如果网站程序对用户的输入信息没有严格的合法性验证的话,仅在一个URL后附加一个简单的符号,就可能试探出许多服务器及数据库中的信息,获取需要的资料。这就是SQL注入的基本原理。
2 Access数据库的SQL注入与防范对策
ACCESS数据库尽管存在着各种各样的安全漏洞,但是由于其方便、灵活的性能以及目前国内网站的实际需要,许多网站,依然是采用Access作为数据库。而针对Access数据库,利用SQL注入进行网站攻击的方法,主要有单引号探测法与1=1,1=2探测法两种。这两种方法基本都是利用了数据库对错误数据类型的数据进行运算时,有自动转换数据类型的特点,因此,在数据安全防范对策上,也主要是从阻止这种自动转换出发。
2.1 单引号探测法
无论是哪一种SQL注入方法,寻找注入点都是第一点。因此,在防范策略上也主要是从注入点着手,把存在的注入点都消除了,也就意味着堵住了SQL注入的唯一途径。
在众多的注入点探测法中,单引号探测法是比较基本、简单的一种方法。其操作方法就是在带有访问参数的网址后面,附加一个单引号提交给服务器,再从服务器返回的错误信息中,分析、获取需要的资料,然后决定如何构造进一步的注入语句。它主要利用的漏洞就是程序员在验证用户输入数据时,没有过滤掉特殊字符。因为在带有访问参数的网址中,如http://127.0.0.1/art_detail.asp?id=8,当程序收到这串URL时,它必定向数据库进行一个ID=8的查询操作,比如有可能是:
Dim v_id
V_id=request.querystring “id”
Sqlstr=”select * from #table_name where id=”&v_id
……
在大多数情况下,ID字段的数据类型是“数字型”或“数值型”。如果攻击者在后面附加一个单引号,变成ID=8,后面的“8”就不再是“数字”或“数值”,而是“字符串”了。在这种情况下,数据库就会尝试把这个“字符串型”转换成“数值型”,当然,这样的的转换一定会失败,相关的查询也就没办法完成。于是,服务器便会向客户端的浏览器返回以下信息:
Microsoft JET Database Engine 错误 '80040e14'
字符串的语法错误 在查询表达式 'ID=8'' 中。
/art_detail.asp,行9
这就是上文所述的情况了。
当然,对这种情况,我们的防范措施也是比较简单有且有效的。
第一种方法是对用户端提交来的数据,在程序上先进行数据类型转换,避免直接交给数据库进行转换。如:
V_id=request.querystring “id”
改为:
V_id=Cint(request.querystring “id”)
这样,如果提交上来的ID值,不是“数值型”的话,就在执行这个语句时,直接报错,而不再把数据提交给数据库,从而避免由于数据库处理时报错而泄露相关信息。
第二种方法是采用过滤法,对用户提交上来的数据中,可能存在的特殊字符,先过滤掉,再提交给数据库进行下一步的操作。例如定义一个过滤函数如下:
<%
Function ReplaceBadWord(g_word)
g_word=Replace(g_word,"'","")
g_word=Replace(g_word," ","")
g_word=Replace(g_word,"&","")
g_word=Replace(g_word,"(","")
g_word=Replace(g_word,"\","")
g_word=Replace(g_word,"/","")
g_word=Replace(g_word,"..","")
g_word=Replace(g_word,"^","")
g_word=Replace(g_word,"#","")
g_word=Replace(g_word,"%","")
g_word=Replace(g_word,"|","")
g_word=Replace(g_word,";","")
g_word=Trim(Replace(g_word,")",""))
ReplaceBadWord=g_word
End Function
%>
然后,对用户提交上来的数据,先执行一下过滤操作:
V_id= (ReplaceBadWord(request.querystring("id"))
这样,就可以使用户数据中存在的特殊字符,在进行数据库查询之前,全部过滤掉。强制性地将不合法的数据类型,转换为合法类型。
2.2 1=1与1=2探测法
1=1与1=2探测法是ACCESS平台中另一种比较常见的注入点试探法。尽管在SQL-SERVER数据库平台中,这种方法也依然适用,但由于在SQL—SERVER平台中,有另一种更高效的探测法,因此,这种方法,主要针对ACCESS平台使用。
该法的试探语句如下:
http://127.0.0.1/art_detail.asp?id=8;and 1=1
http://127.0.0.1/art_detail.asp?id=8;and 1=2
提交访问以后,无论是添加了1=1还是1=2,只要浏览器中返回的结果跟正常URL是一样的,或者虽然不一样,但并没有返回一个由程序员自定义的错误信息,那么,就可以判定这个网站是存在安全漏洞的,可以通过构造SQL语句,进行注入。
这是利用了运算符的运算优先级不同而构造的SQL注入语句。因为1=1的结果是true,而1=2的结果是false。再运行下一级运算时,就是id=8 and true,id=8 and false。最后,这两个URL就变成了:
http://127.0.0.1/art_detail.asp?id=true
http://127.0.0.1/art_detail.asp?id=false
至此,我们已经可以看到,这种探测法实际上还是利用了数据库在操作时,如果参与操作的数据类型错误,就自动转换类据类型,如果转换出错,就返回报错信息的原理。因此,在防范对策上,我们依然是在信息提交到数据库之前,先由程序进行数据类型的强制转换,即使转换出错,也只向客户端返回程序错误报告,而不会返回数据库错误报告。数据库的相关信息资料,也就不会随着错误报告泄露。
3 MS Sql-server数据库的SQL注入威胁与防范
对于ACCESS平台适用的注入点探测法,基本也适用于SQL-server。但是,由于SQL-server数据库管理系统具有更严谨、更复杂的系统性能,因此,也给网站攻击者留下有别于Access的注入漏洞。特别是在服务器的IIS提示没有关闭的情况下,Sql-server中的一些系统变量中的信息,更是网站数据安全的最大隐患。
3.1 user>0探测法
该探测法就是利用了Sql-server中的一个系统变量user中的信息,通过构造一个错误的SQL语句,“诱惑”数据库系统不自觉地泄露重要数据。
user在MS Sql-server数据库系统中,是一个重要的系统变量,类型是可变长度 Unicode (nvarchar),保存的是当前连接数据库的用户名。当然,通常情况下,攻击者是不知道这个用户名的。但是在user>0探测法,却是比较容易破解的。只要把正常访问URL改为:http://127.0.0.1/art_detail.asp?id=8;and user>0
这个URL分号之前的内容,是正确的。但是当服务器遇到user>0这段语句,而数据库又恰好是Sql-server时,这就相当于用一个nvarchar类型的数据与一个int类型的数据,进行比较运算。系统就会尝试把user中的数值转换成int型,由于绝大多数情况下,user中保存的数据都不会是纯数字,因此,这种转换是失败的。于是,Sql-server就会把错误报告返回到客户端:将nvarchar值 “lsx” 转换数据类型为 int时发生语法错误!
“lsx”就是系统变量user的值了,也就是当前数据库的用户名。如果返回信息中,这个值是“dbo”的话,那安全隐患就更大。因为这说明该网站的数据库是用sa这个用户登陆连接的。而sa的是一个几乎与Administrator具有同样权限的用户。
解决这个安全隐患的方法有两种。一是在构建网站的服务器时,把IIS提示关闭,这样即使是产生了数据库层面的错误,也不会向客户端返回相关的报告。方法二还是回到数据的合法性验证上,构造合适验证函数,对提交上来的相关信息,进行验证或转换,避免没有任何的检查就直接向数据库提交。
3.2 系统表探测法
如果通过3.1中的方法,成功探测到数据库是用“sa”用户登陆的话,那么,再利用系统表的探测法,依托Sql-server与操作系统之间的各种联系依赖,就几乎可以全面突破网站的数据安全防线。
在Sql-server系统中,有一张名为sysobjects的系统表,数据库中的表名、视图、约束及其它对象都存储在该表中。并且在web环境下,这张表是具有可读权限的。
那么,经过以下注入步骤,攻击者就可以将网站的数据全部获取。
1)http://127.0.0.1/art_detail.asp?id=7;exec master..xp_cmdshell “net user new_user new_pw /add”
在Sql-server系统中,分号的作用是划分语句。因此,系统会将从数据库中查询出id=7的记录。然后,通过存储过程xp_cmdshell调用系统命令net,给操作系统加一个名称为new_user,密码为new_pw的系统用户。
2)http://127.0.0.1/art_detail.asp?id=7;exec master..xp_cmdshell “net localgroup new_user administrators /add”
这段代码一旦注入成功,就意味着刚才新添加的new_user用户被攻击者添加到了数据库的管理员组,即具备了管理数据库的一切权限。
3)http://127.0.0.1/art_detail.asp?id=1 ;and db_name()>0
这里又一次利用了系统变量db_name(),这个变量中保存的是网站连接的数据库名称。因为这个名称是字符串型的,而代码中的>0是一种比较运算,于是,系统就会被“诱惑”将系统变量中的值先转成整型,这种转换必定会失败,并将错误的信息返回给客户端。而当中所保存的数据库名,就随着这些信息一起显示在浏览器中。
数据库的名称都已经暴露了,如果注入者再探出数据库的路径的话,网站数据库就是毫无安全可言了。即将没有办法探出数据库的路径,依然可以通过以下步骤,不断地构造错误的SQL代码,诱惑系统自行暴露相关的数据。
1)http://127.0.0.1/art_detail.asp?id=1 ;and (Select Top 1 name from sysobjects where xtype=U and status>0)>0
xtype=U and status>0,表示用户建立的表名。用(四)中的语句,把sysobjects系统表中保存的第一张数据表名与0进行相比较,诱惑数据库系统出错、报错,返回正确的数据表名。当然,同样的方法,其他数据表名也都不难试探出来,只要把Top 1把为2,3……即可。
2)http://127.0.0.1/art_detail.asp?id=1 ;and (Select Top 1 col_name(object_id(‘t_name),1) from sysobjects)>0
知道了数据表的名称,就可以用上面的代码探得该表中的字段名。object_id(‘t_name)返回该表名对应的内部ID。col_name(t_name ID,1)即返回t_name表中第一个字段的名称,把1改为2,就是第二个字段名,依此类推。
至此,我们可见,如果防范措施不当,系统表有时简直就是数据安全最大的威胁,只要稍作“诱惑”,就会把网站的数据全盘托出。
4 防止SQL注入的防范优化
无论是Access还是Sql-server,也无论是哪一种SQL注入点探测法,其实都是利用了用户提交的数据在验证中不严谨的漏洞。但是,简单地采用前面所提及的特殊字符替换、验证方法,也并非绝对安全,因为注入者还可以通过一些字符转换函数,将特殊字符函数化以后,混在URL中提交,例如在ASCII编码中,35是#对应的数值,那么用chr(35)函数,替代#号,就绕过了程序中的特殊字符验证。
因此,还必须有更高的安全防范优化方法。具体的优化方法可以有以下两种:
1)重要的数据,采用加密法存储。如用户表中的个人信息,尽可能采用MD5加密法加密后保存, 这样,即使被试出相关信息,返回的,也都是加密后的数据,而MD5是不可逆的。这种方法,主要是杜绝攻击者获取网站的用户信息,从而造成破坏。
2)SQL注入点探测方法之所以能够成功,最根本的原因在于ASP中Request函数的安全漏洞。因为这个函数只负责获取客户端提交上来的数据,对数据的合法性却无法判别,而注入者可能构造出来的SQL语句又是变化多样,程序员很难在编写验证程序时,考虑到每一种情况,这就导致数据库系统会被注入语句的“故意性数据类型错误”诱惑,自动转换数据类型,并报错,从而泄露了重要信息。因此,改造Request函数,提高其安全性能,保证才是杜绝SQL注入的最根本之法。
改造优化以后的Request函数如下:
Function My_Request(Cs_Name,Cs_DataType)
' Cs_Name:参数名称-字符型
' Cs_DataType:参数的数据类型-数字型(1表示Cs_Name是数字,0表示Cs_Name是字符)
Dim CS_Value
CS_Value =Request(Cs_Name)
If Cs_DataType =1 then
If not isNumeric(CS_Value) then
Response.write "所提交的数据" & Cs_Name & "必须为数字型!"
Response.end
End if
Else
CS_Value =replace(CS_Value,"'","''")
End if
My_Request = CS_Value
End function
通过调用这个函数,我们可以对用户提交的一切数据在提交阶段就进行验证,只要提交到服务器的数据与其必须对应的数据类型不一致,就在返回程序中的错误报告,而不再向数据库提交任何操作请求,从而把一切SQL注入点的试探拒之于数据库门外。
5 结束语
加强网站数据安全的保护与防范,是所有网站程序员必须面对的问题。在Access或者 Sql-server数据库中,SQL注入最有利条件的就是这两种数据库系统都会对运算操作中,自动把错误的数据类型进行转换,转换失败以后,向客户端返回错误报告。因此,要阻止这种威胁,就必须保证数据库系统接收到的操作数据,都是合法正确的数据。而程序员要保证用户所提交的数据的合法正确性,除了能够编写一些基本的且严格的数据验证程序以外,还必须对自己所使用的程序语言以及数据库系统中,可能存在的安全漏洞有所了解,并能进行改善优化。对于ASP技术平台而言,Request函数是一切用户数据的入口,只要优化好这个函数的安全性能,就可以将一切SQL注入拒于门外。
参考文献:
[1] [美] Justin ClarkeSQL注入攻击与防御[M].2版.施宏斌,叶愫,译.北京:清华大学出版社,2013.
[2] 刘宇蓉.SQL注入攻击与防范[J].北京理工学院学报,2013(3):101-103.
[2] 万民,秦川.使用ASCII字符串匹配技术检测防御SQL注入攻击[J].南京广播电视大学学报,2013(4):80-84.
[4] 庄小妹,陈日明.SQL Injection攻击原理与防范[J].广东培正学院学报,2013(1):72-76.
[5] 汪彩梅,马婷婷.基于手动SQL注入攻击及防范设计与实现[J].计算机安全,2013(11):36-41.
[6] 马海洲,张志纲.SQL注入漏洞及防范的研发究[J].电脑知识与技术,2012(5).
[7] 李晓龙.基于SQL注入攻击的三种防御技术[J].湖北文理学院学报,2013(5):18-21.
[8] 张永新,钱钦虎.浅谈SQL注入攻击的方法及其防范[J].硅谷,2013(1):5-6.
[9] 杨永国.SQL的注入攻击及防范措施探讨以——Microsoft SQL Server为例[J].软件导刊,2013(4):155-156.
[10] 武淑鹏.网站中的SQL注入攻击及防范措施[J].消费电子,2013(16):80-80.
[11] 杨省伟,杨浩杰.SQL注入数据库攻击与防御技术研究[J].长沙大学学报,2013(5):75-77.
[12] 唐宏,高勃.SQL注入漏洞的检测与防范[J].计算机科学,2008(10).