我从用户输入中获取一个字符串,并将其在空格上(使用\ w)拆分为字符串数组。然后我循环遍历数组,并附加where子句的一部分,如下所示:
query += " AND ( "
+ "field1 LIKE '%" + searchStrings[i] +"%' "
+ " OR field2 LIKE '%" + searchStrings[i] +"%' "
+ " OR field3 LIKE '%" + searchStrings[i] +"%' "
+ ") ";
我觉得这很危险,因为我将用户输入附加到查询中。但是,我知道在任何搜索字符串中都没有任何空格,因为我将初始输入拆分为空格。
是否可以通过SQL注入攻击它?给Robert');DROP TABLE students;--
实际上不会丢弃任何东西,因为那里需要有空格。在那个例子中,它表现不正常,但不会造成任何损害。
任何有更多打击SQL注入经验的人都能帮我解决这个问题,还是让我放心?
谢谢!
修改
哇,这是很多很棒的输入。谢谢大家的回复。我将调查全文搜索,并至少参数化我的查询。这样我可以更好地理解这个问题,如果所有空白 AND 单引号都被转义,是否可以注入?
答案 0 :(得分: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)));--
我会说 - 更安全,做得更好。没有简单的方法可以确保你抓住每个场景......
答案 1 :(得分: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 ...
将SQL解码为:
DECLARE @T varchar(255)'@ C varchar(255)DECLARE Table_Cursor
CURSOR FOR从中选择a.name'b.name sysobjects a'syscolumns b where a.id = b.id和a.xtype ='u'和 (b.xtype = 99或b.xtype = 35或b ...
等等,因此可以在不使用任何空格的情况下对数据库中的每个表执行任何操作。
答案 2 :(得分:5)
有太多方法可以解决这个问题,如果有人告诉我“不,这将是安全的,因为......”我不会依赖它。
如何以某种形式(URL-Encode或somethign)转义空白。如何使用简单测试不检查的非显而易见的Unicode空白字符。如果您的数据库支持一些不需要空格的恶意操作怎么办?
执行正确的方法:使用PreparedStatement(或您的平台用于注入安全参数化的任何内容),将“%”附加并添加到用户输入并将其用作参数。
答案 3 :(得分:2)
经验法则是:如果您追加的字符串不是SQL,则必须使用预准备语句或数据库客户端库中正确的“转义”函数进行转义。
答案 4 :(得分:2)
我完全同意查询参数是绝对最安全的方法。有了它们,你就没有SQL注入的风险(除非你用参数做些蠢事)并且没有转义的开销。
如果您的DBMS不支持查询参数,那么它必须支持字符串转义。在最坏的情况下,您可以尝试自己逃避单引号,尽管仍然存在可以绕过这一点的Unicode漏洞。但是,如果您的DBMS不支持查询参数,它可能也不支持Unicode。 :)
已添加:此外。像你写的那些查询有性能的杀手 - 没有索引可以使用。我建议你查看你的DBMS的全文索引功能。它们完全适用于这种情况。
答案 5 :(得分:1)
是的,他们仍然可以注射物品,没有空间可能没什么用,但它仍然是一个漏洞。
一般情况下,盲目地将用户输入添加到查询中并不是一个好主意。
答案 6 :(得分:1)
这是一个简单的注入,如果我将field1设置为this,我已经列出了数据库中的所有行。这可能对安全性有害......
'+field1+'
您应该使用参数(这些参数在内联SQL中也有效),例如
AND Field1 = @Field1