SQL注入单引号漏洞

Posted

技术标签:

【中文标题】SQL注入单引号漏洞【英文标题】:SQL injection single quote Vulnerability 【发布时间】:2015-08-21 14:06:24 【问题描述】:

您好,我正在对我正在开发的网站进行安全测试。一些开发人员试图通过用双引号替换每个单引号来避免 SQL 注入。这是 C# 代码:

string sql = 
  @"SELECT *
      FROM users
     WHERE us_username = '$us'
       AND us_password = '$pw'";    

sql.Replace("$pw", txtPassword.Text.Replace("'","''"));

有什么方法可以执行 SQL 注入攻击?我已经尝试过 Unicode 技巧,但没有奏效。数据库在 SQL Server 2008R2 上运行。

【问题讨论】:

可能是的,但是不要试图弄清楚如何,您应该只用湿面条执行开发人员,然后重做他们的代码以使用已经防注入的正确方法。选择 100% 的解决方案,而不是 99.9% 的“也许”。 是的,你可能是对的,但我不会有时间修复它,除非我可以破解它并证明它的弱点。 No single quotes is allowed, Is this SQL Injection point still exploitable? 如前所述,答案可能是肯定的。如果您正在寻找可以提供证据的人,您可能需要指定您使用的数据库,因为漏洞利用会因数据库而异。 @sstan 我添加了数据库规范,SQL Server 2008 R2。而 txtPassword 文本框的值来自于一个经典的 ASP.net webforms 文本框。 【参考方案1】:

您应该改用参数化命令。使用string.Replace 是个坏主意。

var command = conn.CreateCommand();
command.CommandText = @"SELECT *
        FROM users
        WHERE us_username = @user
        AND us_password = @password";
cmd.Parameters.Add("@user", txtUser.Text);
cmd.Parameters.Add("@password", txtPassword.Text);

这可能是您设置的潜在候选者:

As an example, note the following trivial Stored Procedure:
create procedure GetData ( @param varchar(20) ) as
begin
declare @s varchar(200)
select @s = 'select * from dataTable where name = ''' + @param + ''''
exec (@s)
end

可以从执行验证代码的网页调用此 SP 在将输入传递给 SP 之前。至少,此验证码 要么验证输入不包含引号,要么清理 它将任何现有报价加倍。例如,验证码可能 正在使用string.Contains()string.Replace()、正则表达式、 等等。也有可能这个网页后面有微调 验证所有输入并验证没有的 Web 应用程序防火墙 包括引号。恶意用户或攻击者可以提交恶意 包含修饰字母撇号的代码(U+02BC,URL 编码为 %CA%BC)。这将轻松通过应用验证码和 WAF 过滤器,因为这些搜索的实际报价 (U+0027) 此时输入中不存在。显然,IDS/IPS 系统会 也没有发现任何问题。验证机制甚至可能 搜索报价的各种编码,例如 URL 编码、UTF-8 编码、十六进制编码、双重编码等等——然而,U+02BC 是 这些都不是,实际上是完全不同的字符值。


这就是有趣(或可怕)部分的开始——Unicode 同形文字翻译不仅限于基本字母字符... 具体来说,Unicode 字符 U+02BC(修饰符字母 撇号)可以被数据库服务器翻译成一个简单的引号 - ' (U+0027)。当然,还有很多其他类似的例子。

来源:http://web.archive.org/web/20130401091931/http://www.comsecglobal.com/FrameWork/Upload/SQL_Smuggling.pdf

【讨论】:

这不是 OP 所要求的。很好的建议,但不是问题所在。 确实我需要漏洞利用,而不是修复。无论如何,谢谢。 感谢更新,我尝试在文本框中输入以下内容,但没有成功:\u0027 或 \u00271\u0027=\u00271 C# 中的字符串如下所示:password = ' \"\\u0027 或 \\u00271\\u0027=\\u00271\"'【参考方案2】:

该部分查询的代码不会受到 SQL 注入的影响,但在用于特定数据库时。每个系统都有自己的一组需要转义的字符,所以如果你将它与例如 mysql 一起使用,那么它是 not 安全的。其他查询可能是安全的。

代码已损坏,应予以更换。由于您需要修复代码,因此您还应该将其更改为使用参数化查询,这是一种更健壮且可移植的解决方案。

那么,让我们看看有什么问题。由于代码一次替换一个参数,它们可能会相互干扰。例如,如果我输入用户名has$$$pwnd 和密码1234(是的,弱密码),您最终会得到如下查询:

SELECT *
  FROM users
WHERE us_username = 'has$$1234nd'
  AND us_password = '1234'

如果某些值包含用于在其后替换的参数的代码,则这些值会损坏。

如果存在不同类型的参数并且值未正确验证,这甚至可以用于在代码中的其他查询中进行 SQL 注入。由于来自一个参数的值可能会出现在另一个参数中,因此字符串值可能会出现在没有撇号的数字参数中,因此无需偷偷插入撇号来突破字符串文字来放置查询中的有害代码。

【讨论】:

感谢您指出替换错误和数字参数。辛苦了!【参考方案3】:

应对 SQL 注入的最佳方法是添加参数。

   SqlCommand sql = new SqlCommand (@"SELECT *
            FROM users
            WHERE us_username = @user
            AND us_password = @password")

sql.Parameters.Add("@users", SqlDbType.Varchar2, 5).Value = "users"; 
sql.Parameters.Add("@user", SqlDbType.Varchar2, 6).Value = "your_value";
sql.Parameters.Add("@password", SqlDbType.Varchar2, 8).Value = "your_value";

如您所见,您可以做很多事情来确保正在执行的是您只想执行的值。

开发人员编写的代码只会在事后更改 sql 语句,如果他们正在记录此 sql 语句,这很好。但是,您现在拥有的东西并不能防止 Sql Injection。

【讨论】:

以上是关于SQL注入单引号漏洞的主要内容,如果未能解决你的问题,请参考以下文章

查明sql注入漏洞

如何寻找sql注入漏洞?

DVWA亲测SQL注入漏洞

SQL注入漏洞靶场-sqli-labs学习[1-10]

SQL注入漏洞靶场-sqli-labs学习[1-10]

SQL注入点判断