我当时正在读我信任的欧莱利的书,偶然读到一段关于 Mongo 如何避免 SQL 注入式缺陷的泥潭的文章。
我的直觉告诉我,我能理解。如果未经消毒的变量被传递到查询中,它们就不能突破面向文档的查询结构,使用 UNION、 JOIN、查询转换为注释等。
UNION
JOIN
MongoDB 如何避免 SQL 注入的混乱? 是否只是这种查询语法的本质?
总结 MongoDB 文件
BSON 当客户端程序在 MongoDB 中组装查询时,它将构建一个 BSON 对象,而不是字符串。因此,传统的 SQL 注入攻击是 没问题。
BSON
当客户端程序在 MongoDB 中组装查询时,它将构建一个 BSON 对象,而不是字符串。因此,传统的 SQL 注入攻击是 没问题。
然而,MongoDB 并不能免疫注入攻击。正如在同一文档中指出的,注入攻击仍然是可能的,因为 MongoDB 操作允许在服务器上直接执行任意的 JavaScript 表达式。文档对此进行了详细介绍:
Http://docs.mongodb.org/manual/faq/developers/#javascript
MongoDB 通过不解析来避免潜在的问题。
在任何地方,任何涉及将用户数据编码为格式化文本并进行解析的 API 都有可能导致调用方和被调用方在如何解析该文本的问题上产生分歧。当数据被误解为元数据时,这些分歧可能是安全问题。无论您是在讨论 printf 格式字符串(包括用 HTML 生成的用户内容) ,还是在生成 SQL,这都是正确的。
由于 MongoDB 不解析结构化文本来确定要做什么,因此不可能将用户输入误解为指令,因此也就不存在可能的安全漏洞。
顺便提一下,http://cr.yp.to/qmail/guarantee.html中的第5项建议避免使用需要解析的 API。如果您对编写安全软件感兴趣,那么其他6个建议也值得一看。
更新(2018) : 据我所知,我给出的原始答案仍然是真实的。从发送到 MongoDB 的内容到发送回来的内容,不存在 SQL 注入攻击。我所知道的注入攻击发生在 MongoDB 之外,实际上是外部语言和库如何设置将传递给 MongoDB 的数据结构的问题。此外,漏洞的位置在于数据在成为数据结构的过程中是如何解析的。因此,最初的答案准确地描述了如何避免注射攻击,以及什么使你面临注射攻击的风险。
但是,这种准确性对于那些因自己的代码中不明显的缺陷而受到注入攻击的程序员来说是冷冰冰的安慰。我们很少有人区分外部工具和我们的代码与外部工具之间的所有层。事实仍然是,我们需要保持警惕来预测和阻止注射攻击。全副武装。在可预见的未来,情况仍将如此。
使用 PHP mongoDB 可能容易受到 No-SQL 注入的影响:
Http://www.idontplaydarts.com/2010/07/mongodb-is-vulnerable-to-sql-injection-in-php-at-least/
Http://www.php.net/manual/en/mongo.security.php
数据库可能不会解析内容,但是代码的其他部分是易受攻击的。
Https://www.owasp.org/index.php/testing_for_nosql_injection
为了防止 SQL 注入,客户端可以使用 MongoDB 的语言 API。这样,所有的输入都是简单的值-命令不能被注入。一个 Java 例子:
collection.find(Filters.eq("key", "input value"))
缺点是您不能轻易地测试您的过滤器。您不能将它复制到 Mongo 的 shell 并测试它。对于更大、更复杂的过滤器/查询,问题尤其严重。
但是! ! !还有一个不使用过滤器的 API 的 API-支持解析任何 json 过滤器。Java 例子如下:
collection.find(BasicDBObject.parse("{key: "input value"}"));
这非常好,因为您可以将过滤器直接复制到 MongoDB shell 来测试它。
但是! ! ! (最后但是,我保证)这容易导致 NoSql 注入。
collection.find(BasicDBObject.parse("{key: {$gt: ""}}"));
在最后一个示例中,将返回所有内容,即使我们的意思是仅返回特定的记录。
在直接使用过滤器时,请参阅 给你关于 SQL 注入的更全面的解释。
最后一件事。我认为有一种方法既可以使用原始过滤器,又可以防止 SQL 注入。例如,在 Java 中,我们可以使用 Jongo 的参数化查询。