我读了我值得信赖的O'Reilly书,发现一段关于Mongo本质上如何避免SQL注入式缺陷的麻烦的文章。
以我的直觉,我想我明白这一点。如果unsanitized瓦尔传递到查询,他们无法攻破了面向文档的查询结构的出UNION
,JOIN
,查询翻评论,等等。
MongoDB如何避免SQL注入混乱?只是这种查询语法的本质吗?
Answers:
MongoDB通过不解析避免了潜在的问题。
任何涉及将用户数据编码为已解析格式文本的API,无论在任何地方,都可能使调用方和被调用方在如何解析该文本上存在分歧。当数据被误解为元数据时,这些分歧可能是安全问题。无论您是在谈论printf格式字符串,包括用户生成的HTML内容还是生成SQL,都是如此。
由于MongoDB不会解析结构化文本来确定要做什么,因此不可能将用户输入误解为指令,因此不会存在安全漏洞。
顺便提一下,避免需要解析的API的建议是http://cr.yp.to/qmail/guarantee.html中的第5项。如果您对编写安全软件感兴趣,那么其他6条建议也值得一看。
更新(2018):就我所知,我给出的原始答案仍然正确。从发送到MongoDB的内容到发送回的内容,没有SQL注入攻击。我知道的注入攻击发生在MongoDB之外,实际上是外部语言和库如何设置将传递给MongoDB的数据结构方面的问题。此外,漏洞的位置在于如何在成为数据结构的过程中解析数据。因此,原始答案准确地描述了如何避免注入攻击,以及使您面临注入风险的原因。
但是,对于那些因自己的代码中不明显的缺陷而遭受注入攻击的程序员而言,这种准确性实在令人不寒而栗。我们很少有人区分外部工具以及代码与外部工具之间的所有层。而且事实仍然是,我们需要提高警惕,才能预测和结束注入攻击。使用所有工具。在可预见的将来,情况仍将如此。
总结MongoDB文档
BSON
客户端程序在MongoDB中组装查询时,将构建BSON对象而不是字符串。因此,传统的SQL注入攻击不是问题。
但是,MongoDB无法免受注入攻击。如同一文档中所述,由于MongoDB操作允许任意JavaScript表达式直接在服务器上执行,因此注入攻击仍然可能。该文档对此进行了详细介绍:
为了防止SQL注入,客户端可以使用MongoDB的语言API。这样,所有输入都是简单值-无法注入命令。一个Java示例:
collection.find(Filters.eq("key", "input value"))
缺点是您无法轻松测试过滤器。您无法将其复制到Mongo的外壳并对其进行测试。对于更大,更复杂的过滤器/查询尤其有问题。
但!!!还有一个API不使用过滤器的API-可以解析任何json过滤器。下面的Java示例:
collection.find(BasicDBObject.parse("{key: "input value"}"));
很好,因为您可以将过滤器直接复制到MongoDB Shell进行测试。
但!!!(最后,但我保证)这很容易发生NoSql注入。Java示例,其中输入值为{$gt: ""}
。
collection.find(BasicDBObject.parse("{key: {$gt: ""}}"));
在最后一个示例中,即使我们仅意味着要返回特定记录,也将返回所有内容。
看这里直接使用过滤器时,有关SQL注入的更详尽说明。
最后一件事。我认为有一种方法既可以使用原始过滤器,又可以防止SQL注入。例如,在Java中,我们可以使用Jongo的参数化查询。
数据库可能无法解析内容,但是代码的其他区域很容易受到攻击。
body-parser
,使用nodejsexpress
lib)。如果您将发布参数解析为JSON(这是很常见的),然后将这些参数(或这些参数的属性)直接传递到mongo查询中,则攻击者可以在您希望有字符串/数字的js对象中插入(例如他们可以通过{$gt:-1}
并查看您收藏中的所有文档)