背景

我已签约分析现有数据提供者,并且我知道以下代码有错误;但为了指出它有多糟糕,我需要证明它容易受到 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
有帮助吗?

解决方案

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

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

其他提示

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

.Replace("``","''")会阻止合法查询'''

.Replace("´","''")会阻止合法查询“´”

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

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

等等。

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

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

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

MSDN 文章 涵盖了您需要注意的大部分内容(恐怕在涉及 SQL 注入时会说所有内容)。

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

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

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

  • 或者更糟“1;删除表某个表名”

根据您要检查的文章:

;- 查询分隔符。

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

-- - 注释分隔符。

/* ... / - 注释分隔符。文字 /之间 */未由服务器评估。

XP_-在目录扩展的存储过程的名称的开头(例如XP_CMDShell)使用。

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

该URL链接到另一个页面用于在SQL Server中进行转义,其中作者提供的建议可帮助您在不限制功能的情况下避免漏洞。

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

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

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

我会使用参数化查询。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top