当前位置: 主页 > 网络知识 > 网络安全 > 新型SQL截断攻击和防御方法

新型SQL截断攻击和防御方法

时间:2010-6-11来源:互联网 点击:

  通过截断进行 SQL 注入

  图 7 显示了相同代码的另一变体,但可使用单独的变量进行修复。可以看出,此代码将转义后的字符串存放在单独的变量中,而且 @command 有足够的缓冲区来存放整个字符串。@escaped_username、@escaped_oldpw 和 @escaped_newpw 被声明为 varchar(25),但如果 @username、@old 和 @new 中的所有字符是 25 个单引号,则它们需要存放 50 个字符。这就为截断已转义的字符串创造了机会。

SQL 安全性: 新型 SQL 截断攻击和防御方法Figure7Using Seperate Variables to Avoid Injection

CREATE PROCEDURE sp_setPassword
  @username varchar(25),
  @old varchar(25),
  @new varchar(25)
AS
-- Declare variables.
DECLARE @escaped_username varchar(25)
DECLARE @escaped_oldpw varchar(25)
DECLARE @escaped_newpw varchar(25)
DECLARE @command varchar(250)
SET @escaped_username = REPLACE(@username, ‘‘‘‘, ‘‘‘‘‘‘)
SET @escaped_oldpw = REPLACE(@old, ‘‘‘‘, ‘‘‘‘‘‘)
SET @escaped_newpw = REPLACE(@new, ‘‘‘‘, ‘‘‘‘‘‘)
SET @command =
  ‘update Users set password=‘‘‘ + @escaped_newpw + ‘‘‘‘ +
  ‘ where username=‘‘‘ + @escaped_username + ‘‘‘‘ +
  ‘ AND password = ‘‘‘ + @escaped_oldpw + ‘‘‘‘
EXEC (@command)
GO

  攻击者可以传递 123...n‘ 作为新密码,其中 n 是第 24 个字符,使 @escaped_newpw 也成为 123...n‘(REPLACE 函数返回的第二个单引号字符会被截断),使最后的查询如下所示,攻击者可以通过用户名字段注入代码,从而利用此查询:

update users set password=‘123...n‘‘
where username=‘<SQL Injection here using Username>
这种代码模式更危险,因为这为注入 SQL 代码(而不仅仅是截断现有 SQL)提供了机会。

  图 8 提供了使用 QUOTENAME 函数而非 REPLACE 的同一变体的另一个例子。由于 QUOTENAME 函数要添加分隔符,因此负载会有所不同,但仍旧容易受到 SQL 注入攻击。

SQL 安全性: 新型 SQL 截断攻击和防御方法Figure8Using QUOTENAME with Seperate Variables

ALTER PROCEDURE sp_setPassword
  @username varchar(25),
  @old varchar(25),
  @new varchar(25)
AS
-- Declare variables.
DECLARE @quoted_username varchar(25)
DECLARE @quoted_oldpw varchar(25)
DECLARE @quoted_newpw varchar(25)
DECLARE @command varchar(250)
-- In the following statements, all the variables can only hold
-- 25 characters, but quotename() will return 52 characters when all
-- the characters are single quotes.
SET @quoted_username = QUOTENAME(@username, ‘‘‘‘)
SET @quoted_oldpw = QUOTENAME(@old, ‘‘‘‘)
SET @quoted_newpw = QUOTENAME(@new, ‘‘‘‘)
-- By passing the new password as 123...n where n is 24th character,
-- @quoted_newpw becomes ‘123..n
-- Observe carefully that there is no trailing single quote as it gets
-- truncated.
-- So the final query becomes something like this
-- update users set password=‘123...n where username=‘ <SQL Injection
-- here using Username>
SET @command= ‘update Users set password=‘ + @quoted_newpw +
       ‘ where username=‘ + @quoted_username +
       ‘ AND password = ‘ + @quoted_oldpw
EXEC (@command)
GO

  在此例中,代码将分隔后的字符串存放在单独的变量中,而且 @command 有足够的缓冲区来存放整个命令字符串。正如上例所示,问题在于被引用的变量 @quoted_username、@quoted_oldpw 和 @quoted_newpw。它们都被声明为 varchar(25),但如果 @username、@old 和 @new 中的所有字符是 25 个单引号,则它们需要存放 52 个字符。(QUOTENAME 还将添加开始和结束的分隔符。)这就为攻击者截断已分隔的字符串创造了机会。

  攻击者可以传递 123...n(其中 n 是第 24 个字符)作为新密码,使 @escaped_newpw 也成为 ‘123...n(开始的单引号由 QUOTENAME 添加),使最后的查询如下所示,攻击者可以通过用户名字段注入代码,从而利用此查询:

update users set
password=‘123...n where
username=‘ <SQL Injection here using Username>
图 9 是 C/C++ 中此代码的缩写版本,可实现相同功能。它同样容易受到相同攻击。

SQL 安全性: 新型 SQL 截断攻击和防御方法Figure9Variable Truncation Issues in C++

DWORD ChangePassword(char* psUserName, char* psOld, char* psNew)
{
  char szEscapedUserName[26];
  char szEscapedOldPW[26];
  char szEscapedNewPW[26];
  char szSQLCommand[250];
  
  // Input Validation
  // Escape User supplied data
  Replace(psUserName, "’", "’’", szEscapedUserName,
      sizeof(szEscapedUserName));
  Replace(psPassword, "’", "’’", szEscapedOldPW,
      sizeof(szEscapedOldPW));
  Replace(psPassword, "’", "’’", szEscapedNewPW,
      sizeof(szEscapedNewPW));
  
  // Construct the query
  StringCchPrintf(szSQLCommand, sizeof(szSQLCommand)/sizeof(char),
    "Update Users set password=‘%s’ where username=‘%s’"
    "AND password=‘%s’,
    szEscapedNewPW, szEscapedUserName,szEscapedOldPW);
  // Execute and return
}

.
分页: [1] [2] [3] [4]
TAG: SQL攻击 防御
推荐内容最近更新人气排行