SQL注入攻击与防护探析
2016-03-19李虎军林学华张辽宁
李虎军, 林学华, 张辽宁
(装甲兵学院, 蚌埠 233050)
SQL注入攻击与防护探析
李虎军, 林学华, 张辽宁
(装甲兵学院,蚌埠233050)
摘要:SQL注入攻击是针对网站中存在的漏洞,利用特殊构造的SQL语句对网站前端应用、后台管理、数据库系统、操作系统进行入侵、窃密、破坏的过程。本文着重介绍了SQL注入攻击的原理、攻击常用方式方法,并在此基础上对如何防范SQL注入攻击给出了一些防御方法,以期抵御大部分的SQL注入攻击,更好地保护Web网站安全。
关键词:SQL注入;网站;数据库;攻击
一、引言
随着Internet互联网技术的飞速发展,万维网(World Wide Web,WWW)的出现使网站数量呈指数规律增长。网站在给人们提供丰富多彩的信息的同时,网站攻击事件层出不穷。大多数网站都基于数据库的支持,开放式Web应用程序安全项目(Open Web Application Security Project Top 10 for 2013)报告称,注入漏洞攻击已成为十大网站攻击之首。信息安全和风险管理公司NTTCom Security发布的《2015全球智能威胁风险报告》称,SQL注入攻击是目前黑客攻击网络的最常见方式之一[1]。
二、SQL注入攻击原理
SQL注入就是利用现有应用程序,将(恶意)的SQL命令注入到网站后台数据库引擎执行。SQL注入(SQL Injection)攻击以网站数据库为目标,通常利用Web应用程序对特殊字符串过滤不完全的缺陷,通过精心构造的字符串达到非法访问网站数据库内容或在数据库中执行命令的目的。
SQL注入攻击主要方式有:直接将SQL代码插入到参数中,这些参数会被置入SQL命令中加以执行;还可以将恶意代码插入到字符串中,之后将这些字符串保存在数据库的数据表中或将其作为元数据,当将该字符串置入动态SQL命令中时,恶意代码被执行。SQL注入攻击的目标是数据库管理系统,通过数据库进而攻击其所在的服务器。通过一个示例简要说明SQL注入攻击。
假设有语句strSQL="SELECT*FROM user WHERE name=′"+username+"′andpwd=′"+ PassWord+"′;"。该语句含义是:将用户输入的用户名(存储在变量username中)和登录口令(存储在变量PassWord中)进行数据库检索验证,如果相应的用户名和登录口令正确,则该语句能返回正确的检索信息,否则,检索结果为空(意味着身份验证失败)。对该语句而言通过以下方式可实现注入攻击。
将username赋值如下:username="1′OR′1′=′1";将PassWord赋值如下:PassWord="1′OR′1′=′1",则程序在进行变量替换后,strSQL中实际存放的字符串为:
strSQL="SELECT*FROM user WHERE name=′1′OR′1′=′1′and pwd=′1′OR′1′=′1′;"。表达式name=′1′OR′1′=′1′值为真;表达式pw=′1′OR′1′=′1′值为真;则strSQL中实际存放的字符串相当于:strSQL="SELECT*FROM user;",就相当于不需对用户输入的用户名和密码进行验证,绕过了系统的登录验证。
三、SQL注入攻击过程
注入攻击的过程通常可以归纳为以下几步:发现SQL注入位置;判断Web后台数据库类型;确定xp_cmdshell可执行情况;发现Web虚拟目录;上传ASP木马;得到目标计算机系统管理员权限。
(一)注入漏洞探测
一般来说,只要是带有参数的动态网页,并且此网页访问了数据库,那么就有可能存在SQL注入漏洞。如果程序员安全意识不强,没有过滤输入的一些特殊字符,则存在SQL注入的可能性就很大。
1.获取SQL注入点
常用的探测SQL注入点的方法是在网页URL地址处添加诸如“and 1=1”、“and 1=2”以及“′”等一些特殊字符,通过浏览器所返回的信息来判断是否存在SQL注入点。以http://xx.xx.xx.xx/abc.asp?id=XX为样例进行分析,以整型参数为例进行SQL注入漏洞探测。通常abc.asp中的SQL语句大致如下:select* from表名where字段=XX
可以用以下步骤测试SQL注入漏洞是否存在。如果以下三种情况全部满足,则abc.asp中一定存在SQL注入漏洞。
(1)在URL链接中附加一个单引号,即http://xx. xx.xx.xx/abc.asp?id=XX′,此时abc.asp中的SQL语句变成如下形式:select*from表名where字段=XX′
测试结果为abc.asp运行异常。
(2)在URL链接中附加字符串“and 1=1”,即http: //xx.xx.xx.xx/abc.asp?id=XX and 1=1
测试结果为abc.asp运行正常,而且与http://xx. xx.xx.xx/abc.asp?id=XX运行结果相同。
(3)在URL链接中附加字符串“and 1=2”,即http: //xx.xx.xx.xx/abc.asp?id=XX and 1=2
测试结果为abc.asp运行异常。
2.某些特殊情况的注入点探测
有时网站设计者会在程序中过滤掉单引号等敏感字符,以防止SQL注入。如果网站设计者对单引号进行了严格的过滤,则字符型参数的SQL注入攻击将不能成功。对于此种情况,可以用以下几种方法尝试。
(1)大小写混合法。由于VBS并不区分大小写,而程序员在过滤时通常过滤全部大写字符串,或过滤全部小写字符串,而大小写混合往往会被忽视。SQL注入攻击者可用SELect代替select、SELECT等。
(2)UNICODE法。在IIS中以UNICODE字符集提高通用性,则SQL注入攻击者可以在IE浏览器中将输入的字符串变成UNICODE字符串进行输入,如将+换成%2B,将空格换成%20等。
(3)ASCII码替代法。SQL注入攻击者可以把输入的部分或全部字符全部用ASCII码代替,如将字符A换成chr(65),将字符a换成chr(97)等。
(二)获取数据库类型与版本
识别被攻击Web应用所用数据库的类型及版本,Web应用的开发语言提供了一个线索,例如基于ASP或者ASP.NET技术的Web应用一般情况下用Microsoft SQL SERVER作为后台数据库;基于J2EE技术的Web应用通常使用Oracle或MySQL数据库,等等。Web应用的部署环境提供了第二个线索,例如运行于Windows操作系统的IIS应用服务器,标志着Web应用可能采用Microsoft SQL Server作为后台数据库;运行于Linux操作系统的Apache应用服务器,标志着Web应用可能使用MySQL数据库。当然,不能仅仅依靠这两个线索来判断数据库类型,因为Web应用开发者会根据特定情况组合不同的开发语言及部署环境。
如果Web应用没有向用户屏蔽SQL语句错误消息,则通过一个简单的SQL语句即可识别数据库类型。例如,我们添加一个单引号作为注入参数,则数据库服务器会产生语法错误消息,根据返回错误消息的不同就可以判断是何种数据库。还可以在http:// xx.xx.xx.xx/abc.asp?id=1后面加38个0,则执行后反馈:Microsoft OLE DB Provider for SQL Server数字′100000000000000000000000000000000000000′超出数字表示范围,这里通过错误信息将数据库类型显示出来。
如果Web应用屏蔽了SOL语句错误消息,则需要利用不同数据库的独特语法来识别数据库类型。例如,Microsoft SQL Server支持select′a′+′b′;Oracle数据库支持select′a′||′b′和select concat(′a′,′b′)。多次尝试不同的连接语法,就可以推断该web应用所使用的数据库类型。
识别了数据库类型之后,由于数据库都允许通过查询语句获取版本信息来得到数据库的具体版本信息,例如Microsoft SQL SERVER,发送select @@version获得SQL Server的版本号,等等。
(三)判断目标网站可执行情况
若当前连接数据库的用户权限是SA权限,且master.dbo.xp_cmdshell扩展存储过程(调用此存储过程可以直接操作系统的shell)能够正确执行,则整个计算机可以通过以下几种方法完全控制,则以后的所有步骤都可以省略。
(1)HTTP://xx.xx.xx.xx/abc.asp?id=XX;exec master.. xp_cmdshell"netuserabc123/add"--
则URL地址中包含的SQL语句就可以在数据库中创建一个名为abc、登录口令为123的用户。
(2)HTTP://xx.xx.xx.xx/abc.asp?id=XX;exec master.. xp_cmdshell"net localgroup administrators abc/add" --,则URL地址中包含的SQL语句将用户abc添加到系统的administrators组中,成为administrator用户。
(3)HTTP://xx.xx.xx.xx/abc.asp?id=XX;backup dadabase数据库名to disk=′c:inetpubwwwrootaaa′,则URL地址中包含的SQL语句将指定数据库备份到c: inetpubwwwroot目录中,并以aaa为名保存。
(四)发现目标网站Web虚拟目录
只有找到Web虚拟目录,才能确定放在ASP木马的位置,进而得到USER权限,通常有两种方法:
(1)根据经验猜解。一般来说,WEB虚拟目录通常是c:
netpubwwroot;d:
netpubwwroot;e:
netpubwwroot等,而可执行虚拟目录是c:
netpubcripts;d:
netpubcripts;e:
netpubcripts等。
(2)遍历系统的目录结构,分析结果发现Web虚拟目录。首先创建临时表temp,接下来:
1)利用xp_availablemedia获取当前所有驱动器,并存入temp1表中;
2)利用xp_subdirs获得子目录列表,并存入temp2表中;
3)利用xp_dirtree获得所有子目录的目录树结构,并存入temp3表中。
从上述tempX表中,可以详细查询相关所需信息。
(五)破解用户名与口令并上传ASP木马
所谓ASP木马,就是一段有特殊功能的ASP代码,并放入Web虚拟目录的scripts下,远程客户通过IE浏览器就可以执行该段代码,进而得到系统的USER权限,实现对系统的初步控制。许多Web网站为了维护方便,提供了远程管理功能,对于不同用户有不同的访问权限。可以利用注入语句,将网站数据库中用户名与密码读出。要进行用户的口令猜解,首先找到系统存放用户名和密码的表,这里假设表名为pwd_table。pwd_table表中一定有一个用户名字段和一个密码字段,只有得到这两个字段的名称,才可能得到这两个字段的内容。
(1)猜测用户名字段和密码字段名称。
通过http://xx.xx.xx.xx/abc.asp?id=XX and(select top 1 col_name(object_id(′pwd_table′),1)from TestDB.dbo.sysobjects)>0进行注入。其中select top 1 col_name(object_id(′pwd_table′),1)from TestDB.dbo. sysobjects是从系统表sysobjects中得到已知pwd_table表的第一个字段名,当与整数进行比较时,abc.asp执行异常,但在异常中却可以发现字段的名称。把col_name(object_id(′pwd_table′),1)中的1依次替换为2,3,4,……就可以得到所有的字段名称。
(2)猜测用户名和密码
可以采用ASCII码逐字解码,先猜测字段的长度,然后异常猜测出每一位的值。以猜解用户名为例。http://xx.xx.xx.xx/abc.asp?id=XX and(select top 1用户名字段from TestDB.dbo.pwd_table)=YY(YY= 1,2,3,……),若YY为i值且abc.asp运行正常,则i就是第一个用户名的长度。
猜测用户名的第一个字符(猜测密码同理):http://xx.xx.xx.xx/abc.asp?id=XX and(select top 1 ASCII(substring(username,1,1)from TestDB.dbo. pwd_table)=YY,若YY为某i值且abc.asp运行正常,则i就是对应字符的ASCII码值。
获取用户名与密码后,先建立一个临时表,在表中输入一个ASP木马,然后利用SQL的BCP命令将表的内容导出文本文件并存放到指定位置,从而上传一个ASP木马文件。
(六)修改目标网站用户权限
通常ASP木马只有USER权限,在注入ASP木马后,可以采用以下多种手段提升用户权限。
(1)通过上传的木马,修改开机自动运行的.ini文件,当目标主机重启后,即可提升用户权限;
(2)下载SAM文件(Windows系统中用户帐户数据文件,包含所有用户的登录名与口令),破解并获取操作系统的所有用户名和密码;
(3)利用xp_regread扩展存储过程修改系统注册表,读取SAM值,允许建立空连接,开机自动运行程序等。
至此,目标网站计算机系统的大门已经被黑客打开。
四、SQL注入攻击防护
由于SQL注入攻击的Web应用程序运行在应用层,因而对于绝大多数防火墙来说,这种攻击是“合法”的(对Web应用防火墙例外)。问题的解决只能依赖于完善编程。因此在编写Web应用程序时,应遵循以下原则,以减少SQL注入漏洞。
(一)使用参数化语句
Web网站容易受到SQL注入攻击的根本原因是将SQL语句伪装成字符串使数据库执行了动态构造的SQL语句。作为一种更加安全的动态字符串构造方法,大多数现代编程语言和数据库访问API可以使用占位符或绑定变量来向数据库查询提供参数,而不是直接对用户输入进行操作,即使用户输入参数中包含分号、注释、select等SQL关键字,也被转义当做一般字符处理,这种处理通常被称为参数化查询。参数化查询可以避免或解决Web应用中常见的SQL注入问题,并可以替换现有的不安全的动态查询。参数化查询使用预处理语句来优化查询,相比动态查询拥有更高的效率。
(二)进行输入验证
未对用户输入参数进行验证,使其包含的恶意代码被执行是造成SQL注入攻击的主要原因。输入验证是指Web应用在接收到用户输入参数后,对其进行验证以确保其符合Web应用定义标准的过程。如果对于用户的输入进行了验证,则能有效避免SQL注入的发生。有两种不同的输入验证方法:白名单验证、黑名单验证。
白名单验证是只接收事先定义好的数据范围,比如要验证输入的是身份证号,则该输入值应该只包含数字、大写字母,总长度为15或18位,可以写一个身份证号的正则表达式来实现验证。
黑名单验证是拒绝事先定义好的非法字符(在检测前将所有字符串进行大小写格式转换,避免攻击者通过大小写混写关键字躲避检测),具体包括INSERT、DELETE、分号等SQL关键字。当用户输入的参数包含这些非法字符时,黑名单验证通常会拒绝它。两种输入验证方法相比,白名单验证功能更强大一些,但需要为每一个输入参数都定义一个匹配规则,工作量巨大。黑名单验证功能要弱一些,因为潜在的非法字符列表非常大,检索起来速度比较慢。
(三)过滤特殊符号
从前面的介绍中可以看出,在SQL注入攻击前的漏洞探测时,攻击者需要在提交的参数中包含“′”、“and”等特殊字符;在实施SQL注入时,SQL中往往需要提交“;”、“--”、“select”、“create table”、“drop”、“add”、“xp_”、“sp_”等字符构造相应的SQL注入语句。因此,防范SQL注入攻击的有效的方法是对用户的输入进行检查,根据参数的类型,可对单引号、分号、连接号等进行转换或过滤,这样就可以防止很多SQL注入攻击。仅依靠过滤用户数据中的单引号来防御SQL注入的话,那么攻击者很可能非法提交一些特殊的编码字符,在提交时绕过网页程序的字符过滤。这些编码字符经过网站服务器的二次编码后,就会重新生成单引号或空格之类的字符,构成合法的SQL注入语句,完成攻击。可以通过服务器端的存储过程对输入内容进行检查过滤。
Createprocedurefilter_string@string_input varchar(80),@string_output varchar(80)output
As
Begin
If charindex(′create′,lower(@string_input))>0 or
charindex(′grant′,lower(@string_input))>0 or
charindex(′select′,lower(@string_input))>0 or
charindex(′xp_cmdshell′,lower(@string_input))>0 or
charindex(′add′,lower(@string_input))>0 or
……
Return
End
(四)使用类安全的参数编码机制
网站在构造动态SQL语句时,一定要使用类安全(Type-safe)的参数编码机制。大多数的数据库API,包括ADO和ADO.NET都允许用户指定所提供参数的确切类型(如字符串、整数、日期等),这样可以保证这些参数都能被正确地编码,以免被黑客利用。例如,在ADO.NET中,对于动态SQL,可以按下面的格式进行编程。
Dim SSN as String=Request QueryString("SSN")
DimcmdAsnewSqlCommand("SELECT au_lname,au_fname FROM authors WHERE aujd= @au_id")
Dimparam=newSqlParameter("au_id", SqlDbType.VarChar)
Param.Value=SSN
cmd.Parameters.Add(param)
这将防止有人试图偷偷注入另外的SQL表达式,以及避免其他数据问题(例如不正确地转换数值类型等)。
(五)敏感数据加密存储
禁止将敏感性数据以明文存放在数据库中,通过哈希函数加密后存放,或通过RSA提供的加解密API在读取/写入数据时进行解密/加密处理,进行这样即使数据库被SQL注入漏洞攻击,也会减少泄密的风险。
(六)遵循最小特权原则
只给访问数据库的Web应用所需的最低权限。例如,如果Web应用不需要访问某些表,那么应确认它没有访问这些表的权限;如果Web应用只需要读权限,则应确认已禁止它对此表的插入、更新、删除等权限。数据库的启动需要配置相关底层操作系统账户,如果数据库配置的底层操作系统账户属于系统管理员组,则攻击者一旦获取数据库的控制权就可以利用操作系统的文件操作、网络连接等,从而造成更大威胁。因此,一定要确保运行在操作系统上的数据库软件所属账号配置成拥有最小权限。另外,除非有特殊用途,应关闭数据库中的额外功能,例如系统管理对象、执行操作系统命令和产生网络连接等。比如在SQL SERVER中,应当考虑关闭危险的存储过程xp_cmdshell以及xp_reg*等。而且要确保数据库软件更新到了最新并打了补丁。特别注意,web应用程序所使用的存储过程和函数的权限,也要遵循最小特权原则,并且最好只赋予存储过程和函数读的权限,限制修改和删除权限。
(七)网站服务器设置
SQL注入是根据服务器给出的错误信息入侵的,服务器端配置应将错误提示信息的反馈功能关闭,使得攻击者只能进行盲注入,大大提高攻击的难度。同时,要充分利用IIS日志服务,有利于及时发现SQL注入攻击痕迹。数据库、表、字段的命名要避免采用默认或通用的名称,避免给注入者留下可乘之机。将数据库管理系统中系统自带的数据库(例如,northwind、pubs等)删除。针对SQL注入攻击,在系统中适当设置假用户,诱骗攻击者,增加攻击难度。
将网站的执行权限设置为“纯脚本”,对于通过网站后台管理中心上传的存放文本的目录,执行权限均设置为“无”,即使网站被上传了木马也运行不了。另外,不启用网站的父目录,禁用不必要的服务器扩展,Web服务器关闭不必要的服务,Web管理员必须通过本地登录方式管理Web服务器。
五、结论
SQL注入攻击的危害日益被人们关注,但是仍然有很多的Web应用程序存在这种漏洞,而且SQL注入攻击技术与其他攻击手段组合起来,更加难以防范。SQL注入是一种综合性攻击,我们应该从网站程序设计、Web服务器、数据库管理等多方面加以规范和防御,最大限度地保障网站系统安全。
参考文献:
[1]OWASP Top10 for 2013[R].https://www.owasp.org/index. php.
[2]王希忠等.Web应用程序中SQL注入攻防策略的研究 [J].信息安全与技术,2011,(9).
[3]黄健.计算机信息安全技术及防护[J].信息安全与技术,2012,(4).
(责任编辑:魏树峰)
中图分类号:TP393
文献标识码:A
[文章编号]1671-802X(2016)02-0018-06
收稿日期:*2016-02-23
作者简介:李虎军(1969-),男,内蒙古乌海人,副教授,研究方向:计算机网络技术。E-mail:tkxylhj@163.com.
Analysis of SQL Injection Attack and Protection
LI Hu-jun,LIN Xue-hua,ZHANG Liao-ning
(Armored Force Institute,Bengbu 233050,Anhui)
Abstract:For the website loopholes,SQL Injection attack uses the SQL statement with a special structure to intrude,steal,and destroy the web application,web management,database system,and operating system.The principle and methods of the SQL Injection attack are presented.Based on the study,the defense methods are proposed to resist most SQL Injection attacks and better protect the security of the website.
Key words:SQL Injection;website;database system;attack