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注入单引号漏洞的主要内容,如果未能解决你的问题,请参考以下文章