此代码是否会阻止SQL注入?

时间:2009-11-25 21:18:30

标签: .net sql sql-server vb.net sql-injection

背景

我已经签约分析现有的数据提供者,我知道以下代码有问题;但是为了指出它有多糟糕,我需要证明它易受SQL注入的影响。

问题

什么“Key”参数可能会破坏PrepareString函数并允许我执行DROP语句?

代码段

Public Shared Function GetRecord(ByVal Key As String) As Record
    Dim Sql As New StringBuilder()

    With Sql
        .Append("SELECT * FROM TableName")
        If String.IsNullOrEmpty(Agency) Then
            .Append(" ORDER BY DateAdded")
        Else
            .Append(" WHERE Key = '")
            .Append(PrepareString(Key))
            .Append("'")
        End If
    End With

    Return ExecuteQuery(Sql.ToString())
End Function

Public Shared Function PrepareString(ByVal Value As String) As String
    Return Value.Replace("''", "'") _
                .Replace("'", "''") _
                .Replace("`", "''") _
                .Replace("´", "''") _
                .Replace("--", "")
End Function

7 个答案:

答案 0 :(得分:21)

回答直接问题:此代码是否阻止SQL注入:否

这是证明 - 通过PrepareString方法推送此字符串:

Dim input = "'" & Chr(8) & "; Drop Table TableName; - " & Chr(8) & "-"
Dim output = PrepareString(input)

Console.WriteLine(input)
Console.WriteLine(output)

我修改了您发布的GetRecord方法,以返回完全准备好的SQL字符串,而不是从数据库中获取记录:

Console.WriteLine(GetRecord(output))

这是输出

Input  = ; Drop Table TableName; --
Output = '; Drop Table TableName; --
Query  = SELECT * FROM TableName WHERE Key = ''; Drop Table TableName; --'

添加1行额外代码:

My.Computer.Clipboard.SetText(input)

您已将需要复制的字符串复制到剪贴板上以粘贴到网站上的输入字段中以完成SQL注入:

'; Drop Table TableName; - -

[注意到StackOverflow从输出中省略了控制字符,因此您必须按照代码示例创建输出]

运行PrepareString方法之后,它将具有完全相同的输出 - Chr(8)ASCII代码是退格,它将删除你附加到我的附加“'”,这将关闭你的字符串然后我可以随意添加我想要的东西。你的PrepareString没有看到我 - 因为我实际上正在使用 - 带有退格符来删除空格。

您正在构建的结果SQL代码将不受阻碍地执行我的Drop Table语句,并立即忽略您的其余查询。

有趣的是,您可以使用不可打印的字符基本上绕过您可以发明的任何字符检查。所以使用参数化查询是最安全的(这不是你提出的问题,但是避免这种情况的最佳途径)。

答案 1 :(得分:16)

要回答你可疑的问题,不会有用。

.Replace("``", "''")会阻止使用'''

进行合法查询

.Replace("´", "''")会阻止使用'''

进行合法查询

.Replace("--", "")会阻止使用“ - ”的合法查询

.Replace("''", "'")会错误地修改其中包含“'”的合法查询

等等。

此外,完整的转义字符集可以在一个RDBMS之间变化。参数化查询FTW。

答案 2 :(得分:3)

我认为如果你只是替换'with''是不可能的。我听说可以更改转义字符,这可能会打破这个,但我不确定。我觉得你很安全。

答案 3 :(得分:2)

我认为它是安全的(至少在SQL服务器中),我也认为你真正需要做的唯一事情是s = s.Replace("'", "''")。当然你应该使用参数化查询,但你已经知道了。

答案 4 :(得分:1)

这个MSDN article涵盖了你需要注意的大部分内容(我不敢在SQL注入时说出所有内容)。

但我会回应其他人对参数参数参数的看法。

至于你的例子,有些人[编辑:更新了这些]:

  • 字符串“1 OR 1 = 1”不允许用户取回所有内容

  • 或更糟糕的“1; drop table sometablename”

根据您要检查的文章:

  

- 查询分隔符。

     

' - 字符数据字符串分隔符。

     

- - 评论分隔符。

     

/ * ... / - 评论分隔符。文本   在/ 和* /之间没有评估   服务器。

     

xp_ - 在名称的开头使用   目录扩展存储过程,   例如xp_cmdshell。

答案 5 :(得分:0)

您正在尝试黑名单字符以实现您自己的SQL Escaping版本。我建议审核this URL - SQL转义不一定是最糟糕的选择(即快速修复现有应用程序),但需要做好以避免漏洞。

该URL链接到another page以便在SQL Server中进行转义,其中作者提供的建议可帮助您避免漏洞而不会限制功能。

如果它有帮助,文章也建议转义括号(我称之为方括号 - 但是[])。

答案 6 :(得分:-4)

如果你尝试使用你的代码,有些人可以传递一个密钥(;从表中选择*;获取他们想要的表格列表。

在你的代码中你不检查分号,它允许你结束一个t-sql语句并启动另一个。

我会使用参数化查询。