更换'转义字符后,T-SQL的安全性如何?

时间:2014-12-02 08:57:24

标签: sql sql-server tsql

我完全清楚,清理SQL查询的正确做法是对它们进行参数化。

我处理了许多预先存在的代码,其中的清理措施是用动态字符串中的'替换''的所有实例。我想知道我应该如何关注。

这就是:这段代码在T-SQL(SQL Server 2008R2及更高版本)上运行独占,据我所知,'只是 < / em> T-SQL的转义字符。

那么,你将如何执行注射攻击以超越上述措施?即那个非常“天真”的消毒对T-SQL来说真的非常可靠,就像看起来一样吗?

3 个答案:

答案 0 :(得分:3)

(插入关于破坏消毒和逃离危险的评论。请参阅marc_s的评论。)

您在此提出的建议与Microsoft SQL Server托管对象(SMO)使用的方法相同。那些是可以使用反编译器检查的.NET DLL。例如:

internal static string MakeSqlString(string value)
{
    StringBuilder builder = new StringBuilder();
    builder.Append("N'");
    builder.Append(EscapeString(value, '\''));
    builder.Append("'");
    return builder.ToString();
}

public static string EscapeString(string value, char escapeCharacter)
{
    StringBuilder builder = new StringBuilder();
    foreach (char ch in value)
    {
        builder.Append(ch);
        if (escapeCharacter == ch)
        {
            builder.Append(ch);
        }
    }
    return builder.ToString();
}

所以是的,根据微软的说法,仅仅做Replace("'", "''")就足够了。我确定这不仅仅是实习代码,而是经过安全审核。由于SDL,他们总是这样做。

另请注意,此代码似乎与Unicode一起使用(请参阅N前缀)。显然,这也是Unicode安全的。

更主观的说明:如果必须,我会像这样逃避T-SQL字符串文字。我相信这种方法。

答案 1 :(得分:3)

是的,单引号是唯一的转义字符,因此您主要是,但并非完全没问题。

最好使用参数主要是手动执行'''替换。但是,它们还强制执行最大字符串长度。当然,如果我们讨论的是非字符串参数,它们将具有强制执行数据类型的好处(即'不需要为数字,日期/时间等类型进行转义,因为它对他们来说无效)。

您可能仍会遇到的问题是SQL注入的一个子集,称为SQL Truncation。这个想法是强制动态sql的某些部分离开字符串的末尾。我不确定在实践中发生这种情况的可能性有多大,但是,根据构造动态sql的方式和位置,你需要确保执行动态SQL的变量大到足以保存静态部分。假设它们以最大长度提交,您的代码加上所有变量。

以下是来自MSDN杂志的文章New SQL Truncation Attacks And How To Avoid Them,它显示了常规SQL注入和SQL截断。您将在文章中看到,为避免SQL注入,他们大多只执行REPLACE(@variable, '''', '''''')方法,但在某些情况下也会使用QUOTENAME(@variable, '[')

EDIT(2015-01-20):这是一个很好的资源,虽然不是特定于SQL Server,但详细说明了各种类型的SQL注入:https://www.owasp.org/index.php/Testing_for_SQL_Injection_(OTG-INPVAL-005)

以下文章与上述文章有关。这个特定于SQL Server,但在整体安全性方面更为通用。有一些与SQL注入相关的部分:
https://www.owasp.org/index.php/Testing_for_SQL_Server

答案 2 :(得分:2)

这是在.NET中 我现在注意到问题是标记为TSQL而不是.NET

Marc暗示你可以用unicode或hex表示来欺骗它。 我测试过,unicode和hex都没有在.NET中欺骗它。

用适当数量的撇号来欺骗它。 如果你总是用两个替换一个我不知道一个合适的数字如何欺骗它。

u0027和x0027是撇号,它被两个撇号替换 2018年和2019年是左右引号,SQL只是将它们视为文字

    string badString = "sql inject \' bad stuff here hex \x0027 other bad stuff unicode \u0027 other bad stuff left \u2018 other bad stuff right \u2019 other bad stuff";
    System.Diagnostics.Debug.WriteLine(badString);
    System.Diagnostics.Debug.WriteLine(SQLclean(badString));
}
public string SQLclean(string s)
{
    string cleanString = s.Replace("\'", "\'\'");
    return "N\'" + cleanString + "\'";
}

我认为参数是一种更好的做法