本教程的早期版本由
Melissa Anderson
编写
。
MongoDB
,也称为
Mongo
,是许多现代 Web 应用程序中使用的开源文档数据库。
它被归类为
NoSQL 数据库,
因为它不依赖于传统的基于表的关系数据库结构。
相反,它使用具有动态模式的类 JSON 文档。
MongoDB 默认不启用身份验证,这意味着任何有权访问安装数据库的服务器的用户都可以不受限制地添加和删除数据。
为了保护此漏洞,本教程将引导您创建管理用户并启用身份验证。
然后,您将进行测试以确认只有该管理用户有权访问数据库。
要完成本教程,您将需要以下内容:
运行 Ubuntu 20.04 的服务器。
此服务器应具有非 root 管理用户和使用 UFW 配置的防火墙。
按照我们
针对 Ubuntu 20.04 的初始服务器设置指南进行设置
。
MongoDB 安装在您的服务器上。
本教程使用 MongoDB 版本
4.4
进行了验证
,但它通常也适用于旧版本的 MongoDB。
要在您的服务器上安装 Mongo,请按照我们关于
如何在 Ubuntu 20.04 上安装 MongoDB 的
教程进行操作
。
第 1 步 – 添加管理用户
自
3.0
版本发布以来
,MongoDB 守护进程被配置为仅接受来自本地 Unix 套接字的连接,并且不会自动向更广泛的 Internet 开放。
但是,默认情况下仍禁用身份验证。
这意味着可以访问安装了 MongoDB 的服务器的任何用户也可以完全访问数据库。
作为保护此漏洞的第一步,您将创建一个管理用户。
稍后,您将启用身份验证并以此管理用户身份连接以访问数据库。
要添加管理用户,您必须首先连接到 Mongo shell。
因为身份验证被禁用,您可以使用该
mongo
命令执行此操作,无需任何其他选项:
- mongo
Mongo shell 提示上方会有一些输出。因为您还没有启用身份验证,这将包括一个警告,指出未为数据库启用访问控制,并且对数据和数据库的配置的读写访问不受限制:
Output
MongoDB shell version v4.4.0
. . .
2020-06-09T13:26:51.391+0000 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2020-06-09T13:26:51.391+0000 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
. . .
在您启用身份验证后,这些警告将消失,但就目前而言,它们意味着任何可以访问您的 Ubuntu 服务器的人也可以控制您的数据库。
为了说明,运行 Mongo 的show dbs
命令:
- show dbs
此命令返回服务器上每个数据库的列表。但是,启用身份验证后,列表会根据 Mongo 用户的角色或它对某些数据库的访问级别而更改。但是,由于身份验证被禁用,它将无限制地返回系统上当前的每个数据库:
Output
admin 0.000GB
config 0.000GB
local 0.000GB
在此示例输出中,仅显示默认数据库。但是,如果您的系统上有任何保存敏感数据的数据库,任何用户都可以使用此命令找到它们。
作为缓解此漏洞的一部分,此步骤的重点是添加管理用户。为此,您必须首先连接到admin
数据库。这是有关用户的信息(如用户名、密码和角色)的存储位置:
- use admin
Output
switched to db admin
MongoDB 随附了许多可用于管理数据库的基于 JavaScript 的 shell 方法。其中之一是db.createUser
方法,用于在运行该方法的数据库上创建新用户。
启动db.createUser
方法:
- db.createUser(
此方法要求您为用户指定用户名和密码,以及您希望用户拥有的任何角色。回想一下,MongoDB 将其数据存储在类似 JSON 的文档中。因此,当您创建新用户时,您所做的只是创建一个文档,将适当的用户数据保存为单独的字段。
与 JSON 中的对象一样,MongoDB 中的文档以花括号 ( {
and }
)开头和结尾。要开始添加用户,请输入左花括号:
注意:db.createUser
在您输入右括号之前,Mongo 不会将该方法注册为完整的。在您这样做之前,提示将从大于号 ( >
) 变为省略号 ( ...
)。
接下来,输入一个user:
字段,将您想要的用户名作为双引号中的值,后跟一个逗号。以下示例指定用户名AdminSammy,但您可以输入任何您喜欢的用户名:
- user: "AdminSammy",
接下来,输入一个pwd
以passwordPrompt()
方法作为其值的字段。当您执行该db.createUser
方法时,该passwordPrompt()
方法将提示您输入密码。这比替代方法更安全,替代方法是像输入用户名一样以明文形式输入密码。
注意:该passwordPrompt()
方法仅与 MongoDB 4.2及更新版本兼容。如果您使用的是旧版本的 Mongo,那么您必须以明文形式写出密码,类似于您写出用户名的方式:
- pwd: "password",
请务必在此字段后面加上逗号:
- pwd: passwordPrompt(),
然后输入您希望管理用户具有的角色。因为您正在创建一个管理用户,所以您至少应该授予他们userAdminAnyDatabase
对admin
数据库的角色。这将允许管理用户创建和修改新用户和角色。因为管理用户在admin
数据库中有这个角色,这也将授予它对整个集群的超级用户访问权限。
此外,以下示例还授予管理用户readWriteAnyDatabase
角色。这使管理用户能够读取和修改集群中任何数据库上的数据,除了主要供内部使用的config
和local
数据库:
- roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
然后,输入一个右大括号来表示文档的结尾:
然后输入一个右括号来关闭并执行该db.createUser
方法:
总之,您的db.createUser
方法应该如下所示:
> db.createUser(
... {
... user: "AdminSammy",
... pwd: passwordPrompt(),
... roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
... }
... )
如果每一行的语法正确,该方法将正确执行,并提示您输入密码:
Output
Enter password:
输入您选择的强密码。然后,您将收到添加用户的确认信息:
Output
Successfully added user: {
"user" : "AdminSammy",
"roles" : [
"role" : "userAdminAnyDatabase",
"db" : "admin"
"readWriteAnyDatabase"
之后,您可以退出 MongoDB 客户端:
此时,您的用户将被允许输入凭据。但是,在您启用身份验证并重新启动 MongoDB 守护程序之前,他们不需要这样做。
第 2 步 – 启用身份验证
要启用身份验证,您必须编辑mongod.conf
MongoDB 的配置文件。启用它并重新启动 Mongo 服务后,用户仍然可以在不进行身份验证的情况下连接到数据库。但是,在他们提供正确的用户名和密码之前,他们将无法读取或修改任何数据。
使用您喜欢的文本编辑器打开配置文件。在这里,我们将使用nano
: