注入NoSql
术语NoSQL用于指各种不同于标准的关系数据库体系架构的数据存储区。NoSQL数据存储区呈现使用键/值映射的数据,并且不依赖于固定的方案,如传统的数据库表。键和值可以任意定义,而且值的格式通常与数据存储区无关。键/值存储的另一个特点在于,值可能为数据结构本身,因而可以实现层次化存储,这与数据库方案中的平面数据结构不同。
支持上述数据存储的NoSQL具有各方面的优势,这些优势主要体现在处理庞大的数据集方面,以便于根据需要对数据存储区中的层次化数据进行优化,以减少检索数据集的开销。在这些情况下,传统的数据库可能需要对表进行复杂的交叉引用,才能代表应用程序检索信息。
从Web应用程序安全的角度看,我们主要关注应用程序如何查询数据,因为这决定了攻击者可以进行何种形式的注入。就SQL注入而言,不同数据库产品采用的SQL语言答题相似。相反,NoSQL代表着一类全新的数据存储区,它们的行为各不相同。而且,它们并非全部使用单一的查询语言。
以下是NoSQL数据存储区采用的一些常用的查询方法:
- 键/值查询
- XPath
- 编程语言
NoSQL是一种快速发展的相对较新的技术。与SQL等比较成熟的技术不同,它并没有进行大规模部署。因此,对于NoSQL相关漏洞的研究仍处于早期阶段。此外,由于许多NoSQL技术访问数据的方式十分简单,讨论注入NoSQL数据存储区的示例有时候明显是虚构的。
几乎可以肯定的是,当前和将来的Web应用程序使用NoSQL数据存储区的方式将存在可被利用的漏洞。
注入MongoDB
许多NoSQL数据库利用现有的编程语言来提供灵活、可编程的查询机制。如果使用字符串连接构建查询,攻击者就可以尝试破坏数据并更改查询的语法。以下面的查询为例,它基于MongoDB数据存储区中的用户记录进行登录:
1 | $m = new Mongo(); |
$js是一个JavaScript函数,其代码是动态构建的,并且包含用户提交的用户名和密码。攻击者可以通过提供以下用户名和任意密码来避开验证逻辑:
Marcus’//
生成的JavaScript函数如下所示:
1 | function() {return this.username = 'marcus'//' & this.password = 'aaa';} |
在JavaScript中,双正斜杠(//)表示行尾注释,因此,函数中的剩余代码将被注释掉。另一种不使用注释而确保$js函数始终返回为“真”的方法,是提供以下用户名:
a’ || 1 == 1 || ‘a’ == ‘a
JavaScript以如下方式解释各种运算符:
(this.username = ‘a’ || 1 == 1) || (‘a’ == ‘a’ & this.password == ‘aaa’);
这将匹配用户集合中的所有资源,因为第一个选择性条件始终为真(1始终等于1)。