SQL注入漏洞的检测与防范技术

提 要   本文从SQL注入的基本概念和注入原理入手,分析总结了SQL注入漏洞的检测及其防范技术措施。
关键词  SQL注入漏洞 检测 防范技术

引 言
   近几年来随着计算机网络和WEB技术的飞速发展,Internet已经成为人们沟通信息和协同工作的有效工具,气象行业也是如此。仅半年多的时间,笔者就先后编写了淮北先锋网、气象网、劳务网、星火网、农网信息站等五个网站的应用程序,并已开通运行,这主要得益于应用B/S模式和ASP技术的易操作性。但随之而来的网络安全问题也越来越引起关注。前不久,一位网友告知他通过SQL注入方式获取了我们某个网站某个功能模块的管理员帐户和密码,这使我大吃一惊,经查的确存在SQL注入漏洞,这才使我不得不放下手头的工作,研究解决这个问题。后来发现,我省气象部门的不少网站均存在这个漏洞,故在这里班门弄斧,谈谈SQL注入漏洞的检测与防范措施,供参考。

1 SQL注入的基本概念和注入原理
    ASP是当今进行WEB编程的最流行工具之一,国内的网站用ASP+Access或SQLServer的占70%以上,PHP+MySQL占20%,其它的不足10%。因为ASP编程的门槛低,新手容易上路。但在安全性方面,新手最容易忽略的问题就是SQL注入漏洞的问题。相当大一部分程序员在编写代码的时候,根本不对用户输入数据的合法性进行判断,至使应用程序存在安全隐患。
    所谓SQL注入(SQL Injection),就是利用某些WEB应用程序对用户输入数据的合法性检测不严或不检测的特点,故意从客户端提交一段特殊的数据库查询代码,根据程序返回的结果,达到收集程序、数据库及服务器的信息,获取想得到而通过正常途径无法得到的资料,使整个网站服务器失控甚至对网站进行破坏性***的目的。
    由于SQL注入是从正常的WWW端口访问,而且表面看起来跟一般的Web页面访问没什么区别,所以目前的防火墙都不会对SQL注入发出警报,如果管理员没有查看IIS日志的习惯,可能被***很长时间都不会发觉,这也是SQL注入能够成功的原因之一。

2 SQL注入漏洞的检测
    SQL注入***的漏洞并非系统造成的,而是程序员在编程中忽略了安全因素。怎样对网页的SQL注入漏洞进行测试呢?这里介绍一些简单通用的方法,具体步骤如下:
    第一步:设置浏览器的属性。即在桌面上打开“Internet Explorer”的属性或通过控制面板打开“Internet选项”或当IE浏览器已打开时选择“IE菜单=>工具=>Internet选项=>高级”下拉菜单,将“显示友好HTTP 错误信息”前面的勾去掉。否则,无论服务器返回什么错误,IE都显示为HTTP 500服务器错误,而不能获得更多的提示信息。
    第二步:打开一个带数据库操作的网页。
这种页面在IE地址栏显示的信息类似于:“http://www.xxx.com/xxx/show.asp?ID=123”。
    有的页面隐含了浏览器的地址栏等信息,仅显示页面内容,这时只要用鼠标右键点击该页面并选中“属性”,即可查出类似于:“http://www.xxx.
    Com/xxx/show.asp?ID=123”的地址信息,将它复制到IE的地址栏同样可以显示出相同的页面内容。
这个页面的执行过程是这样的,浏览器将这个网址提交到服务器后,服务器将进行类似Select * from 表名 where 字段="&ID的查询(ID即客户端提交的参数,本例是123),再将查询结果返回给客户端并在浏览器中显示出来。
    第三步:检测SQL注入漏洞。
    SQL注入的形式一般有两种:一种是发生在 ASP 服务器根据 querystring 参数动态生成网页时,即从IE的地址栏构建特殊的 SQL 指令语句,由 URL 中的 querystring 参数注入。如:通过http://www.xxx.com/xxx/show.asp?ID=123; DELETE FROM tblArticles ” 之类的 URL 来访问 Web 网站,一旦***成功就有可能达到删除数据库中某个表格的目的。另一种是当 Web 网站采用form或cookies来收集访问者的用户名和密码以确认他有足够权限访问某些保密信息的时候,在这种情况下表单被发送到 Web 服务器进行处理,服务器端的ASP 脚本根据form或cookies提供的信息生成 SQL 指令语句提交到 SQL 服务器,并通过分析判断该用户名/密码组合是否有效。此时***者可能会在form或cookies的用户名或密码栏中输入包含“ or ”和“=” 等特殊字符组合。如果存在注入漏洞,提交给数据库的 SQL 指令就可能是代码:
    SELECT * FROM Users WHERE Username='a' or 1=1 and Password ='a' or 1=1这样,SQL 服务器将返回 Users 表格中的所有记录,而 ASP 脚本将会因此而误认为***者的输入符合 Users 表格中的第一条记录,从而允许***者以该用户的名义登入网站。
    无论那一种SQL注入形式,之所以能够注入成功都是因为应用程序存在漏洞,怎样才能顺利检测出这种SQL注入漏洞呢? 
针对SQL注入的第一种形式,漏洞检测的方法可分为三种情况。
2.1 传入参数是数字型时SQL注入漏洞的检测方法
    当查找到URL类似于:http://www.xxx.com/xx
    x/show.asp?ID=123的页面时,其中的ID=123表明参数是数字型的,构成的SQL语句原貌大致为: Select * from 表名 where 字段=123。检测漏洞的方法为:在IE地址栏分别输入以下三个URL参数并执行,比较其执行结果。
    ① http://www.xxx.com/xxx/show.asp?ID=123
    ②http://www.xxx.com/xxx/show.asp?ID=123 ;and 1=1
    ③http://www.xxx.com/xxx/show.asp?ID=123 ;and 1=2 
    其中,①是一个正常的URL参数,②和③分别在其后添加了用来检测漏洞的特殊字符组合,根据上面三个网址返回的结果就知道是否存在SQL注入漏洞。
    存在SQL注入漏洞的表现: 
    ① 正常显示(这是必然的,不然就是程序有错误了) 
    ② 正常显示,内容基本与①相同 
    ③ 提示BOF或EOF(程序没做任何判断时)、或提示找不到记录(判断了rs.eof时)、或显示内容为空(程序加了on error resume next) 
    没有SQL注入漏洞的表现:
    ①同样正常显示,②和③一般都会显示程序所定义的错误提示,或提示类型转换时出错。
2.2 传入参数是字符型时SQL注入漏洞的检测方法
    当查找到 URL 类似于:http://www.xxx.com/x
    xx/show.asp? type=经典小品 的页面时,其中的“type =经典小品”表明参数是字符型的,构成的SQL语句大致为: Select * from 表名 where 字段='经典小品'。检测漏洞的方法为:在IE地址栏分别输入以下三个URL参数并执行,比较其执行结果。
    ① http://www.xxx.com/xxx/show.asp? type =经典小品
    ② http://www.xxx.com/xxx/show.asp? type =经典小品' or ''='
    ③ http://www.xxx.com/xxx/show.asp? type =经典小品'or ''='1' '
    存在SQL注入漏洞的表现: 
    ① 正常显示
    ②正常显示,且显示结果为数据表中的全部内容。
    ③提示BOF或EOF(程序没做任何判断时)、或提示找不到记录(判断了rs.eof时)、或显示内容为空(程序加了on error resume next) 
    没有SQL注入漏洞的表现:
    ①同样正常显示,②和③一般都会显示程序所定义的错误提示,或提示类型转换时出错。
2.3 传入参数是搜索型时SQL注入漏洞的检测方法
    当查找到 URL 类似于:http://www.xxx.com/x
    xx/show.asp? Keyword=关键字的页面时,构成的SQL语句大致为: Select * from 表名 where 字段 like '%关键字%',其中的“字段 like '%关键字%'”表明参数是搜索型的。检测漏洞的方法为在IE地址栏输入:
http://www.xxx.com/xxx/show.asp? Keyword=关键字' and [查询条件] and '%25'='
    当提示BOF或EOF(程序没做任何判断时)、或提示找不到记录(判断了rs.eof时)、或显示内容为空(程序加了on error resume next)时表明有SQL注入漏洞;否则如果显示程序所定义的错误提示,或提示类型转换时出错,则表明没有SQL注入漏洞。
2.4 通过form或cookies传入参数时SQL注入漏洞的检测方法
    针对上述SQL注入的第二种形式,即当 Web 网站采用表单来收集访问者的用户名和密码以确认他是否有足够权限访问某些保密信息时,检测漏洞的方法是:在表单的用户名和密码栏中分别输入“a 'or'1=1 ”等特殊字符。于是,提交给数据库的 SQL 指令就可能是代码:SELECT * FROM 表名 WHERE Username='a' or 1=1 and Password ='a' or 1=1,这时如果存在明显的SQL注入漏洞则SQL 服务器将返回表格中的所有记录,而 ASP 脚本将会因此而误认为***者的输入符合表格中的第一条记录,从而允许***者以该用户的名义登入网站;如果显示程序所定义的错误提示,或提示类型转换时出错,则表明没有这方面的SQL注入漏洞。

3 防范SQL注入的措施
    检测发现SQL注入漏洞,就应立即采取必要的防范措施来堵住这个漏洞,确保网站运行安全。通过分析我们注意到,存在SQL注入漏洞的根源就是在程序中缺少对用户输入数据的合法性进行严格的判断,加上WEB服务器的访问权限和出错提示设置不当造成的。防范SQL注入的措施可以归结为以下几个方面:
3.1 程序员要采取的措施
    程序员可以从两个方面采取措施以堵住SQL注入的漏洞:一个是对用户提交的数据进行严格的审查,即采用各种安全手段监控来自 ASP Request 对象 (Request 、 Request.QueryString 、 Request.Form 、 Request.Cookies 和 Request.ServerVariables) 的用户输入,以确保 SQL 指令的可靠性;另一个是给用户密码进行加密处理。
3.1.1 查堵URL端的漏洞
    审查用户端通过URL提交的参数中是否含有“and、or、'、"、:、;、exec、insert、select、delete、from、update、count、user、xp_cmdshell、add、net、asc(、char(、chr( 、drop、table、truncate 、%、mid”,等用于SQL注入的常用字符或字符串(其中最关键的是单引号(')、分号(;)、空格符( )及转义字符(asc()、(chr()、(char()、(%)),一经发现立即停止执行ASP并给出警告信息或转向出错页面,比较简单有效的方法是将下列代码保存为KSQLI.ASP存放在网站根目录下,然后在每个含有接收用户端URL提交参数的程序(最高效的是在每个数据库链接文件conn.asp)中用<!--#include file="../ksqli.asp"-->引入即可。KSQLI.ASP的代码如下:
<%
Dim K_Url,K_a,K_x,K_Cs(),strurl
On Error Resume Next
K_Url=Request.ServerVariables("QUERY_STRING")
K_a=split(K_Url,"&")
redim K_Cs(ubound(K_a))
On Error Resume Next
for K_x=0 to ubound(K_a)
K_Cs(K_x)=Left(K_a(K_x),instr(K_a(K_x),
"=")-1)
Next
For K_x=0 to ubound(K_Cs)
If K_Cs(K_x)<>"" Then
strurl=LCase(Request(K_Cs(K_x)))
If Instr(strurl,"'")<>0 or Instr(strurl,";")<>0 or Instr(strurl," ")<>0 or Instr(strurl," %20")<>0 or Instr(strurl," %25")<>0 or Instr(strurl,"chr(")<>0 or
Instr(strurl,"asc(")<>0 orInstr(strurl,"char(")<>0 Then
Response.Write "<Script Language=JavaScript
>Alert('URL中含有非法字符串!');window.close();
</Script>"
Response.End
End If
End If
Next
%> 
    注:以上代码足以阻挡大多数***者,而且不大影响程序的执行速度;您可以在if语句中加入前面列举的其它用于SQL注入的常用字符或字符串,使防范更严密,但对程序的执行速度有一定影响。
3.1.2 查堵form或cookies的漏洞
    既然***者是通过form或cookies提交包含“ or ”和“=” 等特殊字符,那么我们的防范措施就是在这部分程序中加入检查或过滤这些特殊字符的代码,以实现安全目的。方法是在使用: paraname=
Request.form()或paraname=Request. Cookies()获取用户名和密码后加入代码:
If instr(paraname," ")>0 or instr(paraname," or ")>0 or instr(paraname,"=")>0 or instr(paraname,"'")
>0 or instr(paraname,";")>0 then
Response.Write "<Script Language=JavaScript>alert('用户参数中含有非法字符串!'); history.back();</Script>"
Response.End
End If
    含义:假如在用户参数paraname中找到了(空格)、( or )、(=)、(')与(;)等非法字符,就立即执行then 后的语句,终止ASP的运行,***者也就无法进行SQL注入了。 
3.1.3 给用户密码进行加密处理
    程序员要做的另一件事是给用户密码加密,一般用MD5加密较好。MD5没有反向算法,不能解密,人家即使知道经加密后存在数据库里的像乱码一样的密码,他也没办法知道原始密码。除非使用UPDATE方法用他的密码代替你的密码,但这个操作在3.1.1和3.1.2中已经堵死了。要注意的是,正因为MD5加密以后的信息不可以解密,如果用户丢失密码,任何人都很难找到用户原来的密码,这时候,网站也就相应的失去了为用户提供其他信息来取得忘记的密码的功能。另外,采用这样的加密方式,必须完全修改以前的用户资料,要求用户完全重新注册,或将数据库中相关字段经MD5加密计算后再重新保存,这是MD5加密方法比较困难的一个地方,请权衡使用。鉴于篇幅,MD5加密的具体做法请参考有关资料,这里不作阐述。
3.2 服务器管理员要采取的措施
    精心配置IIS打造一个安全Web服务器是一项科学严谨的工作,事关网络安全之首要,也是服务器管理员的神圣职责,具体做法请参见有关资料。针对防范SQL注入要做的主要是把IIS设置成不管出什么样的ASP错误,只给出一种错误提示信息,即http 500错误,再小心设置数据库用户权限。这样人家就无法***了。IIS设置参见图1。首先把500:100这个错误的默认提示页面C:\WINDOWS\He
lp\iisHelp\common\500-100.asp改成C:\WINDOW
SHelp\iisHelp\Common\500.htm。
    其次还应在IIS中为每个网站设置好执行权限,一般情况下有"纯脚本"权限就够了,对于那些存放网站后台管理中心上传文件的目录执行权限设为"无"更好,这样可以防止人家上传运行ASP***。

 

 


    第三,当使用MS_SQL数据库时,一般把权限设为PUBLIC就够了,注意不能让用户随便得到SA级别的权限。ACCESS则没有用户权限配置这一步骤。

4 结束语
    SQL注入是网络安全领域的新事物,但发展快危害大,而且经常被一些网站开发或网页设计人员所忽视。只要我们提高认识,在设计开发和网站运行的过程中随时注意查堵SQL注入漏洞,不给***者以可乘之机,就可以在很大程度上提高网络的运行安全。本文所作的一些研究和总结,希望能给读者以启发和借鉴。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章