MongoDB数据库评估
1. 介绍和Labs安装.
1.1 什么是MongoDB ?
MongoDB是一种开源的、文档导向的数据库管理系统,由C++撰写而成。
在MongoDB中,数据以JSON样式文档的形式存储。
MongoDB的一些主要特性:
• 基于文档
• 高性能
• 高可用性
• 简单的可扩展性
• 没有复杂的联接
1.2 安全性如何 ?
随着NoSQL数据库的使用越来越多,安全性应该被认真考虑。 就像其他系统一样,MongoDB的安全性也不是一个单一的工作。 生态系统中的每个人都对此负责。 尽管MongoDB具有一些内置的安全功能,但由于各种原因(如配置错误,不更新,编程不佳等),在生产中可能存在漏洞 。
1.3 在ubuntu中安装MongoDB
我这里使用的是Ubuntu14.04,不同的版本安装MongoDB的命令可能有点差异,为了方便,Ubuntu开启了SSH服务,安装了特定版本的MongoDB 3.0.4。
step 1 : 导入MongoDB GPG密钥。sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
step 2 : 为mongodb创建一个list fileecho "deb http://repo.mongodb.org/apt/ubuntu precise/mongodb-org/3.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.0.list
step 3 : 只更新mongodb-org-3.0.listsudo apt-get update
step 4 : 安装特定版本的mongodbsudo apt-get install -y mongodb-org=3.0.4 mongodb-org-server=3.0.4 mongodb-org-shell=3.0.4 mongodb-org-mongos=3.0.4 mongodb-org-tools=3.0.4
step 5 : 配置防止意外升级echo "mongodb-org hold" | sudo dpkg --set-selections
echo "mongodb-org-server hold" | sudo dpkg --set-selections
echo "mongodb-org-shell hold" | sudo dpkg --set-selections
echo "mongodb-org-mongos hold" | sudo dpkg --set-selections
echo "mongodb-org-tools hold" | sudo dpkg --set-selections
step 6 : 启动MongoDB服务sudo service mongod start
step 7 : 验证进程是否成功启动tail -20 /var/log/mongodb/mongod.log
如果看到如下输出信息,意味着进程已成功启动[initandlisten] waiting for connections on port <port>
step 8 : 为了实现渗透测试,需要使用以下步骤启动MongoDBsudo mongod --httpinterface --rest --smallfiles
1.4 学习Mongo Shell
在前几节中,我们已经看到了对MongoDB及其设置的简要介绍。现在是时候使用Mongo shell并在MongoDB上执行一些命令来更好了解MongoDB及其工作。
MongoDB使用JavaScript风格的查询,因此我们觉得大部分时间都在运行JavaScript代码。
本节将简要介绍MongoDB的工作原理,并且介绍简单的Mongo shell命令。
在我们开始之前,有几个术语要理解。
• MongoDB 可以有多个数据库.
• 每个数据库都含有一个或多个集合 “collections”.
• 每个集合都含有一个或多个文档 “documents”.
现在,我们继续运行MongoDB命令。
1.4.1 创建数据库
如果要创建的数据库名不存在,以下命令将创建一个新的数据库,数据库名已存在会直接使用它。
让我们来创建一个名为”testdb”的数据库。
1.4.2 检查当前数据库
我们可以使用命令”db”来检查当前的数据库。 我们运行命令”db”来检查当前的数据库。
1.4.3 检查数据库列表
“show dbs”是列出可用数据库的命令,但是这里并没有输出我们刚才创建的testdb数据库,因为它至少需要一个文档,当我们插入一个文档,我们就可以看到列出的数据库。
1.4.4 将数据插入集合
这个是把一个数据插入到data集合中。
“db.data.insert({“user”:”test1”})
1.4.5 查询数据
从MongoDB集合中查询数据,可以使用find()方法。
让我们查询data集合中的全部文档数据。
“db.data.find()”
1.4.6 在查询数据时写入条件
我们还可以使用MongoDB特定的语法在类似于RDBMS条件的查询中编写条件,让我们来匹配用户名user为test1的数据。
1.4.7 删除数据
我们可以使用remove()方法根据特定条件从集合中删除文档。让我们来删除用户名user为test3的数据。
1.4.8 删除集合
我们可以使用drop()方法来删除集合,让我们来删除data集合。
1.4.9 删除数据库
我们可以使用db.dropDatabase()删除目前使用的数据库。
1.5 Lab实验环境安装
熟悉了MongoDB的基本操作之后,接下来我们本地搭建一个Lab实验环境来开始我们的MongoDB数据库渗透测试。
这里我是通过Parrot和Ubuntu虚拟机来搭建Lab实验环境的,只要确保两主机网络互通即可,桥接和NAT都可以实现。
用Ubuntu来模拟现实中的生产机器,安装MongoDB和php web应用程序。
接下来正式开始我们的Lab实验环境搭建,我这里先安装好了LAMP。
注意: 请使用与我用来创建数据库和集合相同的名称。这是PHP Web应用程序的工作所必需的。如果您更改这些名称,则可能需要相应地更改PHPWeb应用程序。
step 1 : 创建一个新的数据库
step 2 : 插入数据
把测试数据插入集合”users”和集合”products”。1
2
3
4
5
6db.users.insert({"username":"tom","password":"tom","email":"tom@gmail.com","cardnumber":12345})
db.users.insert({"username":"jim","password":"jim","email":"jim@gmail.com","cardnumber":54321})
db.users.insert({"username":"bob","password":"bob","email":"bob@gmail.com","cardnumber":22222})
db.products.insert({"email":"tom@gmail.com","prodname":"laptop","price":"1500USD"})
db.products.insert({"email":"jim@gmail.com","prodname":"book","price":"50USD"})
db.products.insert({"email":"bob@gmail.com","prodname":"diamond-ring","price":"4500USD"})
step 3 : 安装mongo的PHP驱动程序
为了使PHP Web应用程序能够使用MongoDB,我们需要安装PHP驱动程序。
1
2 sudo apt-get install php-pear
sudo pecl install mongo
如果出现如下报错,使用sudo apt-get install php5-dev
,安装完成后。
再使用sudo pecl install mongo
即可。
安装完成后,会提示把”extension=mongo.so”添加到php.ini中,添加即可。
step 4 : 安装PHP Web应用程序
这里安装比较简单了,直接把mongo.zip拷贝到Ubuntu,解压到/var/www/html目录下,启动apache服务即可。
这一步完成了PHP漏洞应用程序的安装。一旦一切正常,我们可以在浏览器中启动Web应用程序。如图所示:
之前我们已经在Mongo数据库中插入了测试数据,现在我们直接用tom用户密码登录。
如果你看到如上所示的主页,那就证明MongoDB渗透环境已经搭建好了。
2. 漏洞评估
2.1 介绍
面对错误配置问题,MongoDB可能会像其他数据库/服务器一样。在本节中,我们将看到一些常见的错误配置以及如何识别它们。我们也将看到与使用MongoDB作为后端的Web应用程序相关的漏洞。
2.2 扫描开放端口
在进行黑盒评估时,我们可以使用nmap来确定MongoDB是否在远程主机上运行。 MongoDB服务的默认端口是27017。扫描到27017是open表示允许在远程主机上运行,默认绑定地址是127.0.0.1,是扫不出来的,我这里修改了绑定地址为0.0.0.0
MongoDB默认设置不需要使用客户端控制台进行连接的任何验证。如果MongoDB服务在没有适当的安全控制的情况下通过网络公开,任何人都可以远程连接到数据库,并执行命令来创建/读取/更新/删除数据库。我们将在后面的章节中试图做到这一点。
2.3 服务枚举
虽然我们知道了开放端口2017,但其他一些服务可能会使用此端口。也可以运行MongoDB在不同的端口上。 为了确保我们找到的端口是MongoDB,我们可以使用nmap的“-sV”标志来执行服务枚举。
这也有助于弄清楚MongoDB的版本,以便我们可以找到任何已知的版本可用漏洞。
在我们的渗透测试中,我们可能会遇到MongoDB的老版本。一个快速的Shodan搜索显示,大部分被发现的MongoDB版本都在运行旧版本的MongoDB。
这对攻击者来说绝对是个好消息,因为旧版本的MongoDB实例中存在许多默认的错误配置。
2.4 扫描HTTP接口
MongoDB提供了一个简单的HTTP界面,列出管理员感兴趣的信息。如果使用带–rest选项的接口启用mongod,则可以通过比配置的mongod端口多1000个端口来访问它。 HTTP接口的默认端口是28017。我们在搭建实验环境时已经使用了带–rest选项的命令来启动mongod。
我们可以使用nmap查看远程主机是否使用http接口运行,通过-sV确认它是MongoDB的http界面。
注 意 : 默认情况下运行的MongoDB版本大于2.6,禁用http接口。
2.5 访问HTTP接口
可直接通过HTTP链接访问:http://192.168.2.105:28017/,可实现多种功能,大家自行研究。
2.6 用nmap NSE scripts进行扫描
如果http接口需要认证,我们需要尝试暴力破解。有相当多的nmap nse 脚本可用于MongoDB漏洞评估。我们可以使用它们来识别目标机器中的漏洞。
2.7 mongodb-brute
使用这个NSE脚本对MongoDB数据库执行暴力破解密码审计,我们可以看到mongodb-brute已经进行了测试并确认不需要认证。
2.8 mongodb-databases
使用这个NSE脚本尝试从MongoDB数据库获取表的列表。这只有在MongoDB接口不需要验证的情况下才有效。
2.9 Metasploit辅助模块
使用auxiliary/scanner/mongodb/mongodb_login辅助模块
show options 查询需要配置的选项。
设置好参数,直接run,这里看到是没认证的,如果有认证需要配合字典爆破。
从MongoDB版本3.0开始,MongoDB已经将其默认的认证方法改变为质询和响应机制(SCRAM-SHA-1)。根据文档,“SCRAM-SHA-1根据用户的名称,密码和数据库验证提供的用户凭证。
当用户使用MongoDB进行身份验证时,他必须提供用户名,密码和创建数据库。mongo 192.168.2.105 -u user -p password –authenticationDatabase userdb
在MongoDB上暴力破解是有点困难,因为我们需要能够正确地通过所有这三个。 知道创建用户的数据库的名称很重要。 通常情况下,自动化工具默认选择“admin”作为数据库。
2.10 攻击利用
在最初的信息收集阶段,我们了解到远程主机正在运行MongoDB,并且不需要进行身份验证即可连接到服务器。
当在生产环境中使用MongoDB时,必须从其他数据库和/或应用程序服务器访问。当mongod通过网络暴露给其他主机时,必须小心防止不必要的暴露出公网。
当我们可以免认证直接连接到MongoDB数据库或者WEB访问28017端口,就可以随意进行自己想要的操作。
3. 攻击应用程序
3.1 介绍
到目前为止,在给出MongoDB主机的IP地址时,我们学会了评估Mongo主机安全性的技术。 本节将介绍在MongoDB与Web应用程序一起使用时执行NoSQL注入攻击的技术。
SQL数据库(如MySQL)上的注入是非常常见的。 有一个误解,即MongoDB不使用SQL,因此在使用MongoDB的应用程序中不能使用注入。但当用户输入没有正确过滤时,仍然可以对基于MongoDB的应用程序进行注入攻击。
我们将用使用MongoDB作为后端的PHP应用程序来演示这种攻击。
以PHP和MongoDB为后端的NoSQL注入
让我们开始使用之前搭建好的实验环境-PHP-MongoDB应用程序,先了解应用程序功能,我们打开首页,需要输入正确的用户名和密码登录。 如果用户名/密码不正
确,应用程序将会报错。
接下来让我们通过使用注入绕过这个认证。
认证绕过
确保浏览器配置为通过Burp代理发送所有流量,因为应用程序使用POST方法发送凭证,我们直接把请求包截取下来。
从上图可以看出,我们通过”tom”作为用户名和密码。我们可以对数据进行修改再转发到服务器。 在修改这些参数之前,我们先理解MongoDB注入是如何工作的。
了解MongoDB中的注入:
在后台运行的查询将创建以下语句
这看起来没问题,因为它正在提取我们请求的文件,这个文件的用
户名和密码是”tom”
但是,如果上面的命令被修改会怎样? 如下所示 :
如果你注意到,上面的MongoDB命令是获取用户名是“tom”而密码不等于“test0x00”的所有文档。
我们直接修改命令,同时对用户名和密码注入。
这一次,我们可以看到所有不符合条件用户名和密码的文件。
那么就这些条件的功能而言,这个输出就像预期的一样。
试想一下,如果可以从Web应用程序入口点创建这种情况,即使密码不匹配,我们也能够看到特定用户名的文档。 显然,这会对应用程序造成严重的危险。
测试注入:
在我们继续向数据库中注入一些恶意查询之前,我们来测试一下MongoDB及其异常的存在。 这个想法和其他注入一样。
正如我们在前面的章节中看到的,在MongoDB查询中可以传递[$ne]这样的条件。 如果我们传递一些MongoDB未知的东西,会发生什么?
我们可以往MongoDB查询中传递一个[$nt].
正如我们在上面的输出中可以看到的,我们打破了查询,并得到一个错误,说“未知的操作符:[$nt]”
让我们从实验环境PHP应用程序中尝试这个。 如果异常处理不当并抛出给用户,与MySQL数据库中的SQL注入类似,我们可以看到MongoDB的存在并收集其他关键信息。
让我们注入一些未知的运算符,重发刚才拦截到的数据包,看看MongoDB是否执行它。
在浏览器看不出问题所在,没有任何错误回显。但burp就可以看到出现500内部错误。
当我们把不存在的数组修改器[$nt]
改成[$ne]
,重发数据包后就发现登录成功了。
我这里直接用hackbar进行post数据,可以看到我们已经成功登录进后台了。
下面贴上index.php的漏洞代码片段:
我们来分析一下MongoDB层面发生了什么
我们传递的数据已经发送到数据库,下面的查询已经被执行,允许我们登录。
我们还可以检查MongoDB控制台日志,以了解攻击者执行的操作。
这不仅仅是绕过认证,而且我们也可以使用相同的技术在某些情况下从数据库中提取数据,如下所示。
实验环境WEB应用程序有一个功能,我们可以在其中搜索用户所做的购买细节 。首先,用户必须登录到应用程序,然后他可以输入他的电子邮件ID来查看他的购买细节。
注 意 : 虽然在这个应用程序中没有实现 输入控制 ,但假设这个应用程序在输入电子邮件ID时不会显示其他用户的详细信息。
枚举数据:
当用户输入他的邮箱地址进行搜索详细信息,URL会变成如下:http://192.168.2.105/home.php?search=tom@gmail.com&Search=Search
上面的查询显示了与输入的电子邮件ID相关的输出,如下所示。
让我们再次测试MongoDB注入 ,如下所示
MongoDB可能会执行我们传递的查询,因为它正在执行我们在URL中传递的操作符并中断查询。我们把
[$nk]
替换成[$ne]
再次进行注入。
如上所示,我们看到正确查询到了3条数据,但是默认只显示一条。我们可以通过
[$ne]
来遍历数据。
这个例子显示了对基于MongoDB的应用程序的严重注入攻击的可能性。
下面贴上home.php的漏洞代码片段
如何解决这个问题?
这个问题背后的根本原因是缺乏对来自用户的数据类型进行适当的输入验证。 确保用户输入在处理之前被严格验证。
我们只需要做下严格验证即可,例如:(string)$_POST['uname']
(string)$_POST['upass']
确保变量在被传递到MongoDB驱动程序之前被正确输入。
以 NodeJS和MongoDB 为后端的 NoSQL注入,跟PHP应用程序注入方式一样,感兴趣的可以自行研究。
4. 自动化评估
在之前的所有章节中,我们都使用了一些使用nmap等半自动化工具的手动技术来识别目标中的漏洞。在本节中,我们使用自动化方法来查找前面部分提到的所有漏洞。
我们将使用一个非常好的工具,称为NoSQLMap。
介绍
NoSQLMap是一个开源的Python工具,用于审计和自动化注入攻击,并利用NoSQL数据库中的缺省配置弱点,以及使用NoSQL的Web应用程序来泄露数据库中的数据。目前,这个工具的漏洞主要集中在MongoDB上,但是在未来的版本中计划对其他基于NoSQL的平台(如CouchDB,Redis和Cassandra)提供额外的支持。
特性
• 自动化的MongoDB和CouchDB数据库枚举和克隆攻击。
• 通过MongoDB Web应用程序提取数据库名称,用户和密码哈希。
• 使用默认访问和枚举版本扫描MongoDB和CouchDB数据库的子网或IP列表。
• 使用 强力字典 爆破 MongoDB和CouchDB 的 哈希。
• 针对MongoClient的PHP应用程序参数注入攻击返回所有数据库记录。
• Javascript函数变量转义和任意代码注入来返回所有的数据库记录。
• 基于计时的攻击类似于SQL盲注来验证没有回显信息的Javascript注入漏洞。
下载并安装好NoSQLMap,运行:
4.1 准备好NoSQLMap
根据我们的目标,我们可以选择一个合适的选项。 在进行漏洞评估之前,我们需要使用选项1来设置参数。
• 第一个选项是指定目标IP地址。
• 第二个选项是指定被渗透机WEB应用的地址。
• 第三个选项是指定可能存在注入的路径。
• 第四个选项是切换HTTPS。
• 第五个选项是指定MongoDB的工作端口。
• 第六个选项是设置HTTP请求模式。
• 第七个选项是设置本地的IP地址。
• 第八个选项是设置本地监听端口(MongoDB shell的反弹端口)。
• ……
下面让我们开始实验。我们先需要设置好相关参数。
4.2 NoSQL DB访问攻击
退出主界面选择第二个NoSQL DB Access Attacks。此选项将检查目标服务器上的MongoDB是否可通过网络访问。 如果可以访问,它将检查我们在前面章节中讨论的错误配置(没有认证,暴露的WEB控制台,暴露的REST端口)
从上面的输出我们可以看到,NoSQLMap发现通过网络访问MongoDB没有认证,然后给我们提供了获取服务器系统和版本,数据库枚举,检查规范,克隆数据库等功能。
我们先获取服务器系统和版本,如图:
数据库枚举,从远程服务器 dump 所有数据库和集合:
4.3 匿名MongoDB访问扫描
NoSQLMap有一个扫描器,可以扫描整个子网上的MongoDB访问。
我们可以直接输入整一个子网网段进行扫描,例如192.168.152.0/24
。
我们回到主界面,选择选项4,
它将显示以下选项。
• 可以通过命令输入ip地址
• 可以从一个文件加载IP地址
• 启用/禁用ping之前,尝试与目标服务器的MongoDB连接。
首先,我们提供一个IP地址并观察结果。
正如我们在上面的结果中看到的,NoSQLMap已经扫描了提供的IP,并确认远程机器上有默认访问。
此外,它还提供了一个选项来将结果保存到CSV文件,我这里把CSV文件命名为test。
我们可以直接使用cat
命令查看文件的内容。
我们还可以提供一个网段来进行扫描。
NoSQLMap正在检查我们提供网段的每台机器MongoDB匿名访问是否能成功。
成功获取到这台机器存在匿名访问,其他步骤跟以上相同,在此直接跳过。
4.4 使用NoSQLmap进行NoSQL注入
到目前为止,我们已经看到了使用NoSQLMap工具评估MongoDB服务器安全性的各种方法。
现在,让我们检查一下之前搭建好的实验环境(利用MongoDB作为后端Web应用程序中的漏洞)。
我们选择选项3 WEB应用程序攻击,这里会提示我们没有设置options。我们直接选择1,根据自己的实验情况设置即可。
退出主界面,选择3开始WEB应用程序攻击
选择随机数的长度及填充格式,我这里选择1,字母数字。一旦完成,NoSQLMap会提示我们选择要测试的参数。 在我们的例子中,第一个参数是处理MongoDB的动态参数。
我们看到这里可能存在注入,因此我们选择不开始时间盲注。
我们看到NoSQLMap已经完成了对应用程序中的注入漏洞的测试,并显示了所有注入点和使用的有效载荷的输出。在使用手动技术学习评估时,我们已经看到了这一点。1
2http://192.168.152.151:80/home.php?search[$ne]=OybrUiUGatApIIdOioUS&Search=Search
http://192.168.152.151:80/home.php?search[$gt]=&Search=Search
结论:
任何系统的安全性与其最薄弱的环节一样强大。 小小的错误配置会导致严重的损坏。 我们在这里展示的所有例子都是人们常犯的错误。请保持你的MongoDB是最新的,并且在把它传递给MongoDB之前总是验证用户的输入。
这里嵌套几个利用NoSQLMAP对MongoDB进行渗透的视频:
这个视频是NoSQLMAP management attack,主要测试匿名访问。
这个视频是NoSQLMAP WEBAPP attack,主要测试WEB应用程序注入。
MongoDB Labs实验环境
链接:https://pan.baidu.com/s/1nuEy6b3 密码:4c84
转载请注明原作者\xeb\xfe,谢谢~~