即使引号转义,也可以通过 .NET 进行 Microsoft SQL Server SQL 注入

Jam*_*mes 5 sql-server sql-injection t-sql sql-server-2012

我一直在阅读 SQL 注入,作为对相当大的 Web 服务进行安全审计的一部分。我一直在谷歌搜索并阅读我可以在这里和 SO 上找到的所有帖子,并且对真正应该如何构建动态查询以及 MySQL 和 MSSQL 之间的一些差异有相当深入的了解。我最终看到了今年早些时候由 Microsoft 发布的名为SQL Injection 的页面。在标题为“过滤输入”的部分中,它指出:

通过删除转义字符,过滤输入也可能有助于防止 SQL 注入。但是,由于可能会出现问题的字符数量众多,因此这不是可靠的防御。以下示例搜索字符串定界符。

private string SafeSqlLiteral(string inputSQL)  
{  
  return inputSQL.Replace("'", "''");  
}  
Run Code Online (Sandbox Code Playgroud)

编写安全代码第二版也在第 401-402 页讨论了这一点,但看起来作者实际上并没有尝试 C# 示例(或者他在 2003 年使用的 SQL 版本可能没有正确处理转义字符串)。它指出字符串输入将导致无效查询(实际上,转义只是查询其中带有单引号的值),然后指出它也可能会被使用未加引号的数字字段的值攻击(尽管不能,因为示例中的字段来自类型为 的局部变量int,它不可能包含注入所需的信息)。

我不怀疑这里存在可能的攻击向量,但我无法找到有关如何实现这一点的任何解释。从我的其他研究来看,一种可能的方法可能涉及非 Unicode 字符串中的奇怪字节序列。就我而言,我正在使用 .NET,所以不可能有这样的序列,我认为 ADO.NET、SQL Server 或两者都可以正确处理 Unicode 字符串与单个内部的任何其他类型的字符-引号。(虽然有趣的是示例代码似乎是在 C# 中)。

我也很清楚微软页面上列出的其他 SQL 注入方法,对于这个问题,我并不担心这些。此外,我只关心此处正确键入的字符串文字输入。此代码始终在编写 SQL 查询之前将传入类型解析为其适当的运行时类型,因此引号转义仅适用于数据是文字字符串数据时。所以就我而言,该函数实际上更像是:

private string SafeSqlStringLiteral(string inputString)  
{  
  return "'" + inputString.Replace("'", "''") + "'";  
}  
Run Code Online (Sandbox Code Playgroud)

我最关心的就是文档中的下面这句话:

但是,由于可能会出现问题的字符数量众多,因此这不是可靠的防御。

这只是指奇怪的单字节编码,还是有适用于的 Unicode 字符(我无法以编程方式找到一个)?

我正在审查的代码非常广泛,并且在很多地方都使用了这种类型的转义(并且以一种不容易修复的方式)。我不是直接要求利用漏洞(这对 IIRC 不屑一顾),但我想得到一些比我更专业的说明,以便我可以说服自己这不是问题,或说服团队负责人这是一个问题,以便我们可以预算出解决这些问题所需的大量时间。

所以,我的问题是,假设我们没有使用 PInvoke 或不安全的代码玩任何游戏来创建单字节字符串并使用它们调用 SQL Server,有没有办法使用 .NET 通过这种类型的字符串文字转义来注入 SQL(如SafeSqlStringLiteral上述)当字符串字面量比较仅用于字符串列,不涉及LIKE条款,使得针对Microsoft SQL Server的2012+查询?

Lau*_*gil 1

如果存在未仅检查数字数据的数字字段输入(并且一如既往,如果该字段不受长度限制),则可以绕过单引号转义。这是基本方法:

输入有效数字,后跟分号以终止现有命令。然后在分号后面输入如下内容 - 这将执行命令SELECT * FROM users;

DECLARE @o varchar(max);SELECT @o= CHAR(83)+CHAR(69)+CHAR(76)+CHAR(69)+CHAR(67)+CHAR(84)+CHAR(32)+CHAR(42)+ CHAR(32)+CHAR(70)+CHAR(82)+CHAR(79)+CHAR(77)+CHAR(32)+CHAR(117)+CHAR(115)+ CHAR(101)+CHAR(114)+CHAR(115)+CHAR(59);EXEC(@o);

如今,拥有允许通过输入字段执行此操作的代码几乎是不可能的 - 一个简单的 IsNumeric() 检查就会把它从水中吹出来,而数字输入的合理字段大小限制会让您尝试执行或类似的操作DECLAR,这当然会爆炸。但这在理论上是可能的。