MongoDB如何避免SQL注入混乱?
Posted
技术标签:
【中文标题】MongoDB如何避免SQL注入混乱?【英文标题】:How does MongoDB avoid the SQL injection mess? 【发布时间】:2011-06-28 15:10:33 【问题描述】:我在阅读我值得信赖的 O'Reilly 书籍时偶然发现了一段关于 Mongo 如何从本质上避免类似 SQL 注入缺陷的泥潭。
在我的直觉中,我想我明白这一点。如果将未经处理的 var 传递到查询中,它们将无法通过 UNION
、JOIN
、查询转注释等突破面向文档的查询结构。
MongoDB 如何避免 SQL 注入混乱?仅仅是这种查询语法的本质吗?
【问题讨论】:
我认为没有人评论过使用解析中间件的潜在危险(例如body-parser
与 nodejs express
lib)。如果您将 post 参数解析为 JSON(这很常见),然后将这些参数(或这些参数的属性)直接传递到 mongo 查询中,那么攻击者可以在您期望字符串/数字的位置插入一个 js 对象(例如他们可以通过$gt:-1
并查看您收藏中的所有文档)
【参考方案1】:
总结一下MongoDBdocumentation
BSON
当客户端程序在 MongoDB 中组装查询时,它会构建一个 BSON 对象,而不是字符串。因此传统的 SQL 注入攻击是 没问题。
但是,MongoDB 也不能免受注入攻击。如同一文档中所述,注入攻击仍然可能,因为 MongoDB 操作允许直接在服务器上执行任意 javascript 表达式。文档对此进行了详细介绍:
http://docs.mongodb.org/manual/faq/developers/#javascript
【讨论】:
不是全部。在您的报价下方,相同的文档解释了如何针对 Mongo 执行任意 JavaScript。默认情况下启用此行为,文档说:"You must exercise care in these cases to prevent users from submitting malicious JavaScript."。您可以禁用 JS 支持,但 also disables JS support for server-side scripting。 OWASP 谈到了这个here 不言而喻,SQL注入攻击不是问题,MongoDB不懂SQL。但是,MongoDB 仍然可以进行 No-SQL 注入攻击。 该问题专门询问了SQL注入攻击,但我同意应该明确与no-sql相关的风险。我已经更新了答案。【参考方案2】:MongoDB 通过不解析来避免潜在的问题。
任何涉及将用户数据编码为可解析的格式化文本的 API,都可能导致调用方和被调用方在如何解析该文本方面存在分歧。当数据被误解为元数据时,这些分歧可能是安全问题。无论您是在谈论 printf 格式字符串(包括 html 中用户生成的内容)还是生成 SQL,这都是正确的。
由于 MongoDB 不解析结构化文本来确定要做什么,因此不可能将用户输入误解为指令,因此不会存在安全漏洞。
顺便提一下,避免使用需要解析的 API 的建议是 http://cr.yp.to/qmail/guarantee.html 中的第 5 项。如果您对编写安全软件感兴趣,那么其他 6 条建议也值得一看。
更新(2018 年):据我所知,我给出的原始答案仍然正确。从发给 MongoDB 的内容到发回的内容,没有 SQL 注入攻击。我知道的注入攻击发生在 MongoDB 之外,实际上是外部语言和库如何设置将传递给 MongoDB 的数据结构的问题。此外,漏洞的位置在于数据在成为数据结构的过程中如何被解析。因此,最初的答案准确地描述了如何避免注入攻击,以及使您面临风险的原因。
但这种准确性对于因自己的代码中不明显的缺陷而受到注入攻击的程序员来说是一种冷酷的安慰。我们中很少有人区分外部工具以及我们的代码与该外部工具之间的所有层。事实仍然是,我们需要保持警惕才能预测和关闭注入攻击。使用所有工具。在可预见的未来,情况仍将如此。
【讨论】:
请注意,这个答案(尽管有帮助)是不正确的——其他两个答案提供了一种可以进行“类似 SQL 注入”的攻击的情况。这是一个狂野的世界,您需要正确清理输入数据。 ;) @johndodo 请注意,我的答案出现在 php 漏洞被发现之前。另请注意,我的回答对于 PHP 以外的所有语言都是正确的,并且漏洞的原因是 PHP 自愿以一种令人惊讶的方式解析数据。 true - 我不是有意反对你,但很多人通过谷歌找到答案,所以我想我会澄清事实。此外,虽然我对其他网络语言不太熟悉,但一些 HTML 输入将值作为数组发布,所以我会说问题不仅限于 PHP。一般规则仍然适用:始终验证用户输入。 这个问题还有很多。默认情况下,MongoDB 允许执行任意 JavaScript。来自他们的文档:"You must exercise care in these cases to prevent users from submitting malicious JavaScript."。您可以禁用 JS 支持,但 also disables JS support for server-side scripting。 OWASP 谈到了这个here 很遗憾,这个答案的投票率如此之高。 MongoDB No-SQL 攻击已在多种语言中得到证明,这个答案给人一种错误的安全感。【参考方案3】:使用 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
【讨论】:
我刚刚看到了。请注意,从根本上讲,问题在于 PHP 有助于解析用户输入,这允许用户以一种本不应该发生的方式混淆数据和元数据。 @James 所以在变量之前放置一个字符串转换将解决这个问题......还有什么我应该担心的,还是唯一的解决方法?【参考方案4】:数据库可能无法解析内容,但代码的其他区域存在漏洞。
https://www.owasp.org/index.php/Testing_for_NoSQL_injection
【讨论】:
【参考方案5】:为了防止 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 注入。 Java 示例,其中输入值为$gt: ""
。
collection.find(BasicDBObject.parse("key: $gt: """));
在最后一个示例中,所有内容都被返回,尽管我们的意思是只返回特定的记录。
直接使用过滤器时,请参阅here 对 SQL 注入的更详尽说明。
最后一件事。我认为有一种方法可以同时使用原始过滤器并且仍然可以防止 SQL 注入。例如,在 Java 中,我们可以使用Jongo's parameterized queries。
【讨论】:
以上是关于MongoDB如何避免SQL注入混乱?的主要内容,如果未能解决你的问题,请参考以下文章