Sql-Server应用程序的高级Sql注入(8)

http://www.itjxue.com  2015-07-17 09:24  来源:未知  点击次数: 

[高级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 = '" + newpassword + "' where username = '" + rso("username") + "'"

rso("username")是登陆的查询返回的的用户名。

用户名为admin'--,上面的查询就变成了这样:

update users set password = 'password' where username = 'admin'--'

因此攻击者可以通过注册了一个名叫admin'--的用户来把admin的密码改成他们自己的。

这是个危险的问题,目前大部分的大型程序都试图过滤数据。最好的解决方法是拒绝非法输入,而不是简单的改变它。这有时候会导致一些问题,非法字符在某些地方是必要的,比如在名字带符号的情况:

O'Brien

从安全的角度,最好的解决办法是不允许出现单引号。如果这样不行,必须避免它们出现,这种情况下,最好保证所有要进入SQL语句的字符(包括从数据库里取出的字符)都被正确的处理过。

(责任编辑:IT教学网)

更多

推荐SQL Server文章