3

我从用户输入中获取一个字符串,并将其在空格上(使用 \w)拆分为一个字符串数组。然后我循环遍历数组,并像这样附加 where 子句的一部分:

            query += " AND ( "

                 + "field1 LIKE '%" + searchStrings[i] +"%' "
                 + " OR field2 LIKE '%" + searchStrings[i] +"%' "
                 + " OR field3 LIKE '%" + searchStrings[i] +"%' "
                 + ") ";

我觉得这很危险,因为我将用户输入附加到我的查询中。但是,我知道任何搜索字符串中都没有任何空格,因为我将初始输入拆分为空格。

是否可以通过 SQL 注入来攻击它?给予Robert');DROP TABLE students;--实际上不会丢弃任何东西,因为那里需要有空格。在该示例中,它不会正常运行,但不会造成任何损坏。

任何有更多对抗 SQL 注入经验的人都可以帮助我解决这个问题,或者让我放心吗?

谢谢!

编辑:

哇,这是很多很棒的输入。感谢所有回复的人。我将研究全文搜索,并至少参数化我的查询。

只是为了让我能更好地理解这个问题,如果所有空格和单引号都被转义了,是否可以注入?

4

7 回答 7

14

每当您允许用户将数据输入到这样的查询字符串中时,您都容易受到 SQL 注入的攻击,应该像瘟疫一样避免它!

您应该非常小心如何允许您的 searchStrings[] 数组被填充。您应该始终使用参数对象将变量数据附加到查询中:

+ field1 like @PropertyVal Or field2 like @PropertyVal Or field3 like @PropertyVal etc...

例如,如果您使用的是 SQL Server

Query.Parameters.Add(new SqlParameter("PropertyVal", '%' + searchStrings[i] + '%'));

要非常小心如何构建要针对生产服务器运行的查询字符串,尤其是如果其中包含任何重要数据!

在您的示例中,您提到了 Little Bobby Tables

Robert');DROP TABLE 学生;--

并指出因为它需要空格,所以你不能这样做 - 但是如果恶意用户使用这样的东西对其进行编码:

Robert');Exec(Replace('Drop_Table_students','_',Char(32)));--

我会说 - 最好是安全并以正确的方式做。没有简单的方法可以确保您捕捉到所有场景,否则......

于 2008-12-16T22:16:48.240 回答
13

是的,这个脚本不包含任何空格,只是 SQL 解码并执行的编码字符: http ://www.f-secure.com/weblog/archives/00001427.html

注入的脚本是这样的:

DECLARE%20 @ S%20NVARCHAR(4000); SET%20 @ S = CAST(0x440045004300 4C00410052004500200040005400200076006100720063006800610072 00280032003500350029002C0040004300200076006100720063006800 610072002800320035003500290020004400450043004C004100520045 0020005400610062006C0065005F0043007500720073006F0072002000 43005500520053004F005200200046004F0052002000730065006C0065 0063007400200061002E006E0061006D0065002C0062002E006E006100 6D0065002000660072006F006D0020007300790073006F0062006A0065 00630074007300200061002C0073007900730063006F006C0075006D00 6E00730020006200200077006800650072006500200061002E00690064 003D0062002E0069006400200061006E006400200061002E0078007400 7900700065003D00270075002700200061006E0064002000280062002E 00780074007900700065003D003900390020006F007200200062002E00 780074007900700065003D003300350020006 ... </ P>

将 SQL 解码为:

DECLARE @T varchar(255)'@C varchar(255) DECLARE Table_Cursor
CURSOR FOR select a.name'b.name from sysobjects a'syscolumns b where a.id=b.id and a.xtype='u' and ( b.xtype=99 或 b.xtype=35 或 b...</p>

依此类推,因此可以在不使用任何空格的情况下对数据库中的每个表执行任何操作。

于 2008-12-16T22:17:39.083 回答
5

弄错的方法太多了,如果有人告诉我“不,这将是安全的,因为……”,我不会依赖。

以某种形式(URL-Encode 或 somethign)转义空格怎么样。使用简单测试不检查的非显而易见的 Unicode 空白字符怎么样。如果您的数据库支持一些不需要空格的恶意操作怎么办?

做正确的方法:使用 PreparedStatement(或您的平台用于注入安全参数化的任何内容),将“%”附加并添加到用户输入并将其用作参数。

于 2008-12-16T22:13:54.317 回答
2

经验法则是:如果您要附加的字符串不是 SQL,则必须使用准备好的语句或 DB 客户端库中的正确“转义”函数对其进行转义。

于 2008-12-16T22:20:11.433 回答
2

我完全同意查询参数是绝对安全的方法。有了它们,您就没有任何 SQL 注入的风险(除非您对参数做了一些愚蠢的事情),并且没有转义的开销。

如果您的 DBMS 不支持查询参数,那么它必须支持字符串转义。在最坏的情况下,您可以尝试自己转义单引号,尽管仍有一个 Unicode 漏洞可以规避这一点。但是,如果您的 DBMS 不支持查询参数,它可能也不支持 Unicode。:)

补充:还有。像你写的查询是性能杀手 - 不能使用索引。我建议查看您的 DBMS 的全文索引功能。它们完全适用于此类情况。

于 2008-12-16T22:25:42.250 回答
1

是的,他们仍然可以注入项目,没有空格它可能不会做太多,但它仍然是一个漏洞。

一般来说,盲目地将用户输入添加到查询中并不是一个好主意。

于 2008-12-16T22:14:57.810 回答
1

这是一个简单的注入,如果我将 field1 设置为此我已经列出了数据库中的所有行。这可能不利于安全...

'+field1+'

您应该使用参数(这些在内联 SQL 中也有效),例如

AND Field1 = @Field1
于 2008-12-16T22:19:48.703 回答