【问题标题】:Does this code prevent SQL injection?此代码是否防止 SQL 注入?
【发布时间】:2010-12-20 11:27:54
【问题描述】:

背景

我已签约分析现有的数据提供者,我知道以下代码有问题;但是为了指出它有多糟糕,我需要证明它容易受到 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

【问题讨论】:

  • 如果您使用的是 VB,为什么还要努力考虑所有可能的攻击向量,而不是仅仅使用参数化查询?
  • 没有必要粗鲁。漏洞黑名单是一场艰苦的战斗,必将失败。依赖参数化查询。期间。
  • 我同意 Yann 的意见,尤其是你的粗鲁表明你没有以专业的方式行事,因为这里有些人(引用你的话并不密集)致力于是时候回答包括你在内的其他人的问题了!多一点体贴和尊重。
  • 乔希,不要粗鲁;你应该听听这里的每一个人。具有讽刺意味的是,您的个人资料说:“您可以做到这一切。”如果您对自己的能力如此自信,为什么要在这里寻求帮助?
  • 不要说得太细,但你问错了问题。您严厉地向社区发表讲话,并获得了反对票作为回报。我已经编辑了你的问题以解决问题的意图,所以它可能会被赞成,因为它可能是一个好问题。

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


【解决方案1】:

回答您的直接问题:此代码是否防止 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 语句,并立即忽略您查询的其余部分。

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

【讨论】:

  • 有多少漏洞可以说服他?我可以整晚都这样做 - 我可以从您发送的原始页面数据生成一个 POST 并修改正确的表单值以通过事件验证。然后,我可以在我的网络浏览器中使用插件,以便您的服务器将其视为同一个会话。当然替换 Chr(8) 会修复 this 漏洞,但是下一个呢?
  • 老实说,您所要求的只是一些证明该方法存在缺陷的代码,而我已经制作了该代码......因此回答了您的问题。
  • 或者只是在生成器中添加一行额外的代码,然后将其复制到剪贴板...创建一个 WinForms 应用程序以允许您即时插入控制字符几乎很有趣.
  • 如果你的经理这么固执,再多的例子也无法说服他。他只会采用您在上面使用的“好吧,只需替换 chr(8)”轨道。你正在打一场失败的战斗。
  • -1。这个“证明”只是出现来利用代码,因为控制台将 chr(8) 处理为实际的退格键。如果您将这些字符放入字符串中并按照您的建议将它们复制到剪贴板,它们将作为字符保留在字符串中并且不要吃掉任何字符。
【解决方案2】:

要回答你有问题的问题,不,这是行不通的。

.Replace("``", "''") 会阻止使用 '`' 进行合法查询

.Replace("´", "''") 会阻止使用 '´' 进行合法查询

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

.Replace("''", "'") 会错误地修改带有 '''' 的合法查询

等等。

此外,从一个 RDBMS 到另一个,完整的转义字符集可能会有所不同。参数化查询 FTW。

【讨论】:

  • 同意,没有 100% 可靠的方法来逃避查询字符串。他们只会制造一个更好的捕鼠器。
  • 作为键传入的值会导致我执行任何我想要的 SQL?我不担心无法正常工作的罕见查询,而是担心会造成严重危害的恶意查询。
  • 乔希,重点是,人们找到了利用规范化问题的新方法,而以这种方式阻止它们注定会失败。这就像试图巧妙地转义 HTML 标记或文件路径。有时,插入正确位置的空字符可以欺骗清理代码,等等。你必须依赖底层的参数化机制,并祈祷它可以工作(或者它会在适当的时候被修补)。
  • 此外,正如我所说,清理功能确实会产生误报并破坏合法查询,这也是一个问题(现在尝试乘坐飞机感受它有多痛苦)。
  • +1 不会破坏不相关的字符。只转义需要转义的字符。对于 SQL Server 和标准 ANSI SQL,这是字符串分隔符 '。对于 MySQL 和偶尔的其他人,反斜杠也可能是一个问题。您还需要确保字符串中没有任何控制字符(MySQL 不喜欢 0 字节),但希望您已经从输入中过滤掉了这些字符。
【解决方案3】:

我认为如果你只是将'替换为''是不可破解的。我听说可以更改转义引号字符,这可能会破坏这一点,但我不确定。不过我认为你很安全。

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      这个MSDN article 涵盖了您需要注意的大部分内容(关于 SQL 注入,恐怕要说全部)。

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

      至于你的例子一些陷阱[编辑:更新这些]:

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

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

      根据你要查的文章:

      ; - 查询分隔符。

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

      -- 注释分隔符。

      /* ... / - 注释分隔符。文本 / 和 */ 之间不被评估 服务器。

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

      【讨论】:

      • 如果我在写代码,你可以相信它会是这样的。
      • 更新了您的代码中可能存在的问题,将尝试考虑更多。
      • 不,WHERE Key = '1 OR 1=1' 子句不允许用户取回所有内容,因为 '1 OR 1=1' 周围有引号。
      • 那篇文章中有多么可怕的胡思乱想的建议。如果攻击者可以破解字符串文字,则删除分号对您没有帮助,因为您可以在 SQL 语句中放入许多其他不好的东西。如果他们不能因为引号被正确转义(或者,希望,因为参数化有效)而脱离字符串文字,它只会破坏完全合法的输入。
      • bobince,看文章中的第2个字符分隔符:' - 字符数据字符串分隔符。
      【解决方案6】:

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

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

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

      【讨论】:

      • 没有。我想要做的是打破这个代码。这就是我想要做的。
      【解决方案7】:

      如果您尝试使用您的代码,有人可能会传递一个键 (;select * from table; 并获取他们想要的任何表的列表。

      在您的代码中,您没有检查分号,它可以让您结束一个 t-sql 语句并开始另一个。

      我会使用参数化查询。

      【讨论】:

      • 我有一个测试环境设置来尝试打破这个。由于语法无效,该字符串除了抛出异常之外什么也不做。
      猜你喜欢
      • 2011-10-18
      • 1970-01-01
      • 1970-01-01
      • 2013-02-08
      • 2021-03-19
      • 2021-10-06
      • 1970-01-01
      • 2020-04-16
      • 2019-09-01
      相关资源
      最近更新 更多