NoSQL注入总结(MongoDB)

遇到好几次Nosql注入的问题了,这次在BSidesTLV2018赛题环境中也遇到了一道Nosql注入的题,就趁着这一次总结一下。

NoSQL数据库提供比传统SQL数据库更宽松的一致性限制。 通过减少关系约束和一致性检查,NoSQL数据库提供了更好的性能和扩展性。 然而,即使这些数据库没有使用传统的SQL语法,它们仍然可能很容易的受到注入攻击。 由于这些NoSQL注入攻击可以在程序语言中执行,而不是在声明式SQL语言中执行,所以潜在影响要大于传统SQL注入。

这上面是owasp对于NoSQL注入的描述,NoSQL注入由于NoSQL本身的特性和普通的SQL注入有所区别,本篇文章以MongoDB为例,总结一下NoSQL的注入方法。

MongoDB查询语法

着这里简单总结一下MongoDB查询语法,

命令行

php 操作Mongodb

php 操作Mongodb与命令行操作差不多,以下只是简单介绍

搭建靶场

在查找资料中,发现了不少人都用了这个NoSQLInjectionAttackDemo github项目,可以很清楚的看到输入和注入语句的拼接,所以我也用这个测试。
搭建好php5.6、apache2.4环境后,安装mongodb以及mongo之于php的扩展。值得注意的是, 本次试验使用的是mongo.so扩展,还有一种mongodb.so扩展php适用语法不同,但注入原理是同样的

MongoDB注入分类

我在网上搜集到了两种分类方法。
第一种是按照语言的分类:php数组注入、js注入、mongo shell拼接注入。
第二种是按照攻击机制分类:永真式、联合查询、Js注入、盲注等。
注:很多NoSQL数据库允许执行数据内容中JavaScript,JavaScript使在数据引擎进行复杂事务和查询成为可能。传递不干净的用户输入到这些查询中可以注入任意JavaScript代码,这会导致非法的数据获取或篡改。

注入尝试

php永真式注入

这是通常php查询的方法,以数组的方式插入,没有字符串的拼接似乎我们没有办法注入。
但是由于php松散结构的特性,如果我们_GET传入的是数组那么,会自动被解析成字典。比如我们输入?username[$ne]=1&password[$ne]=1, 就会被解析成:

相当于查询username不等于1且password不等于1的用户,可以的话会返回所有用户信息。

Js注入($where 注入)

NoSQL经常需要JavaScript来处理一些事务等问题,也允许在查询的时候执行Js,如果此时有字符串拼接可以注入Js,那相当于可以直接在Mongo shell里执行代码了。
关键代码:

$where操作符表示执行其中的Js内容,返回True的话返回所有内容。
我们可以看到我们可以注入使得Js代码提前返回True
payload:?username=qwer&password= 1';return true;var qwer='1

盲注

大多数注入的情况下是无法回显的,在这里我们也介绍一下Mongodb的盲注

this.news代表的查找Mongo数据库中test集合中的news,所以这里的js意味着查找是否有用户输入的news。
这意味着我们必须输入数据库集合中其中一个news的值才能返回’该新闻存在’。
我们可以使用如下payload:
?news=123' || '1'== '1使得query语句变成function() {if(this.news == '123' || '1'== '1') return true}

但是如果我们需要知道news的内容的话,我们还可以这样:
?news=123' || this.news[0] == 'A 来一个个的猜解,进行盲注。更多玩法就参照Js的语法啦。

Shell注入

php可以用函数直接执行mongo shell命令,如果存在这种操作,并且可以注入的话,会产生更大的危害。注入方法还是由于字符串不正当的拼接导致的,原理很相似这里就不介绍啦。

发表评论

电子邮件地址不会被公开。 必填项已用*标注