证明SQL注入

时间:2009-12-02 17:12:41

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

我试图在这里简单地证明这个简单的函数不足以阻止世界上的每个sql注入:

Function CleanForSQL(ByVal input As String) As String
    Return input.Replace("'", "''")
End Function

以下是我们其中一个应用的典型插入声明:

Database.DBUpdate("UPDATE tblFilledForms SET Text1 = '" + CleanForSQL(txtNote.Text) + "' WHERE FilledFormID = " + DGVNotes.SelectedRows(0).Cells("FilledFormID").Value.ToString)

我知道它不安全,因为谷歌搜索和查找StackOverflow.com上的其他问题。 Here是我发现的一个问题,其中所有函数(例如我上面提到的函数)都是无关紧要和毫无意义的。

所以基于我链接的帖子,只需输入

即可
  

“CHR(8); update tblMaint SET Value1 = 2 WHERE ValueID = 2 -

进入txtNote应该足以清除整个tblFilledForms表中text1中的每个值,然后将tblmaint表的第二行更新为2正确吗?

这里应该发生的是VB将其解释为

  

UPDATE tblFilledForms SET Text1 ='''Chr(8); update tblMaint SET Value1 = 2 WHERE ValueID = 2--'WHERE FilledFormID = 5120327

并将其发送到SQL,它将实习执行Chr(8)以擦除第三个'将产生

  

UPDATE tblFilledForms SET Text1 =''; update tblMaint SET Value1 = 2 WHERE ValueID = 2--'WHERE FilledFormID = 5120327

要在数据库上实际执行正确吗?

然后我从剪贴板中清除了一个Chr(8)并用剪贴板内容替换了文本框中的Chr(8)并且仍然是禁止的。它将整个字符串直接放入没有问题的字段中。

那我在这里做错了什么?或者我还能做些什么来打破它?

技术和背景: 我正在使用MS SQL Server 2005和VB .NET 2005。 数据库中的Text1字段是一个Varchar(600)字段(不要问我为什么它不是MAX,它没有意义,我知道) 表上有一些触发器会阻止像这样的大量更新,如果注入实际工作正确,则会抛出一些错误。

PS。我知道参数化查询是去这里的方式,我不是在寻找像“我不知道为什么它不起作用,但参数化查询是要走的路”的答案。我正在寻找能够证明我们的软件已被破坏并且我们需要使用更好的原则重写它的能力。

对于阅读此问题的任何人来说明如何更好地过滤文本字段,答案是不要!使用参数!它们更好,更安全,更容易!

5 个答案:

答案 0 :(得分:6)

Chr(8)是引用的文字字符串的一部分,更新语句也是如此,因此SQL Server不会将其解释为函数调用。在此示例中,Text1将设置为文字值:

'Chr(8); update tblMaint SET Value1 = 2 WHERE ValueID = 2--

(是的,包括那个单引号)

因此,在此示例中,您的代码 是安全的。对SQL注入的大多数困扰是意外地失败来验证和引用值,在正确引用的SQL语句中没有任何本质上不安全的东西。

答案 1 :(得分:4)

您的CleanForSQL方法只处理字符串情况。当你不使用字符串而是使用INT时会发生什么?在这种情况下,将无法收尾,因此注入仍将发生。考虑这个例子......

Database.DBUpdate("UPDATE tblFilledForms SET Int1 = " + CleanForSQL(txtNote.Text) + " WHERE FilledFormID = " + DGVNotes.SelectedRows(0).Cells("FilledFormID").Value.ToString)

在这种情况下,只需输入以下内容即可...

0; update tblMaint SET Value1 = 2 WHERE ValueID = 2--

答案 2 :(得分:3)

Scott Ivey拥有可以打破它的经典案例,缺少保护数字输入的引号。 (+ 1'),

根据语言以及字符串被“清理”的位置以及正在使用的数据库,您的直接风险是他们的语言允许转义字符串。那时你试图避免通过的单引号出错了

\'; DROP yourTable; - => \ ''; DROP yourTable; -

这就是你的sql字符串

UPDATE tblFilledForms SET Text1 = '" + \''; DROP yourTable;-- + ' etc.

然后是:

UPDATE tblFilledForms SET Text1 = '\''; DROP yourTable;-- ' etc.
如果您的数据库支持转义字符,那么

'\''将被视为单引号的文字字符串 - bingo您的被攻陷者。

同样必须记住保护是有效的,即使提供的示例更新语句未能保护where子句中的参数,是因为DGVNotes.SelectedRows(0).Cells(“FilledFormID”)。Value.ToString )用户永远不能输入?应用程序的整个生命周期都适用吗?

答案 3 :(得分:1)

你没有做错任何事。这就是SQL Server分析字符串的方式。第一个引号打开字符串,然后您立即使用转义引号,然后是Chr(8)。

作为练习,如果在SQL Server中运行此操作会发生什么:SELECT '''Hello'?在这种情况下,正在应用完全相同的解析规则。

答案 4 :(得分:0)

我认为您的问题是Chr(8)未执行,您需要找到另一种方法来获取引号。