NoSQL注入是一个漏洞,攻击者能够干扰应用程序对NoSQL数据库进行的查询,本文我们将研究如何测试一般的NoSQL漏洞,然后重点研究如何利用MongoDB中的漏洞(MongoDB是最流行的NoSQL数据库)。
1. 什么是NoSQL注入
NoSQL注入是一个漏洞,攻击者能够干扰应用程序对NoSQL数据库进行的查询。NoSQL注入可能使攻击者能够:
- 绕过身份验证或保护机制。
- 提取或编辑数据。
- 导致拒绝服务。
- 在服务器上执行代码。
2. NoSQL注入的类型
- 语法注入:当您可以破坏NoSQL查询语法,使您能够注入自己的负载时,就会发生这种情况。该方法与SQL注入中使用的方法类似。然而,由于NoSQL数据库使用一系列查询语言、查询语法类型和不同的数据结构,因此攻击的性质差异很大。
- 运算符注入:当您可以使用NoSQL查询运算符来操作查询时,就会发生这种情况。
2.1. 语法注入
攻击者可以通过尝试破坏查询语法来检测NoSQL注入漏洞。要做到这一点,请通过提交模糊字符串和特殊字符来系统地测试每个输入,如果应用程序没有对它们进行充分的净化或过滤,这些字符串和字符会触发数据库错误或其他一些可检测的行为。
考虑一个显示不同类别产品的购物应用程序。当用户选择Fizzy饮料类别时,其浏览器会请求以下URL:
https://insecure-website.com/product/lookup?category=fizzy
这导致应用程序发送JSON查询,以从MongoDB数据库中的 product 集合中检索相关产品:
this.category == 'fizzy'
2.1.1. 确定要处理的字符
要确定应用程序将哪些字符解释为语法,可以注入单个字符。例如,您可以提交 ’ ,这将导致以下MongoDB查询:
this.category == '''
如果这导致原始响应发生变化,则这可能表明 ’ 字符破坏了查询语法并导致语法错误。可以通过在输入中提交有效的查询字符串来确认这一点,例如通过转义引号:
this.category == '\''
如果这不会导致语法错误,这可能意味着应用程序容易受到注入攻击。
2.1.2. 确认条件行为
检测到漏洞后,下一步是确定是否可以使用NoSQL语法影响布尔条件。
要测试这一点,请发送两个请求,一个条件为false,一个为true。例如,您可以使用条件语句 ’ && 0 && 'x 和 ’ && 1 && 'x ,如下所示
https://insecure-website.com/product/lookup?category=fizzy'+%26%26+0+%26%26+'x
https://insecure-website.com/product/lookup?category=fizzy'+%26%26+1+%26%26+'x
如果应用程序的行为不同,这表明false条件会影响查询逻辑,而true条件则不会。这表明注入这种语法风格会影响服务器端查询。
2.1.3. 覆盖现有条件
现在您已经确定可以影响布尔条件,可以尝试覆盖现有条件以利用该漏洞。例如,您可以注入一个始终计算为true的JavaScript条件,例如 ‘||1||’ :
https://insecure-website.com/product/lookup?category=fizzy%27%7c%7c%31%7c%7c%27
这将导致以下MongoDB查询:this.category == 'fizzy'||'1'=='1'
由于注入的条件始终为true,因此修改后的查询将返回所有项。这使攻击者能够查看任何类别中的所有产品,包括隐藏或未知类别。
2.2. 运算符注入
NoSQL数据库通常使用查询运算符,这些运算符提供了指定数据必须满足的条件才能包含在查询结果中的方法。MongoDB查询运算符的示例包括:
- $where:匹配满足JavaScript表达式的文档
- $ne:匹配所有不等于指定值的值
- $in:匹配数组中指定的所有值
- $regex:选择值与指定正则表达式匹配的文档
攻击者可以注入查询运算符来操作NoSQL查询。要做到这一点,请系统地将不同的运算符提交到一系列用户输入中,然后查看错误消息或其他更改的响应。
在JSON消息中,可以将查询运算符作为嵌套对象插入。例如, {"username":"wiener"}
变为 {"username":{"$ne":"invalid"}}
,对于基于URL的输入,可以通过URL参数插入查询运算符。例如, username=wiener
变为 username[$ne]=invalid
。如果这不起作用,您可以尝试以下操作:
- 将请求方法从 GET 转换为 POST
- 将
Content-Type
标头更改为application/json
- 将JSON添加到消息正文中
- 在JSON中注入查询运算符
3. 漏洞防御
- 使用接受字符的allowlist对用户输入进行消毒和验证
- 使用参数化查询插入用户输入,而不是将用户输入直接连接到查询中
- 为防止操作员插入,应用已接受密钥的允许列表
4. 参考
[1] https://portswigger.net/web-security/nosql-injection