2017年1月,正值新年伊始,一些黑客组织发动了一场针对MongoDB数据库的攻击,全球有数以万计的MongoDB中招,它们的数据库被整个完整得清空,然后新建了一个名为“WARNING”的数据库,索要赎金。然而令人瞠目结舌的是,这些所谓的“攻击”甚至不能叫做攻击,因为这些中招的MongoDB正处于“裸奔”的状态!
所谓“裸奔”,就是说MongoDB直接对公网开放所有的读写权限,更严重的是,MongoDB默认配置甚至不需要用户名密码就能直接登录进行管理,也就是说,任何人都可以对MongoDB进行读、写、甚至直接毁灭(Drop)。而本次攻击的,正是这样的一些MongoDB。
这次攻击正突显了MongoDB的使用者安全意识的缺乏,竟然让自己的数据库对外网开发,并且还不设置密码,被攻击了也是活该。
所以,在学习MongoDB之初,就请一定不要忘记,在部署MongoDB到服务器时,一定一定要注意安全设置!!!!
1.启动服务器的两种方式
1.1 不安全的启动方式
前面提到,启动MongoDB的命令是:
mongod --dbpath ../data/db
不过,需要注意的是,这种方式是不安全的!为什么说是不安全的?原因是通过这种方式启动MongoDB,如果没有绑定可访问的IP,那么就相当于把自己的数据库直接暴露在公网中,也就是所谓的“裸奔”。因此,在部署生产环境的时,一定不能用这种方式来启动。
下图是开启了一个shell终端来访问数据库,命令是mongo <mongodb所在服务器的IP或域名>:27017
;默认端口号是 27017
,如果你修改过MongoDB服务的端口号,则将 27017
替换为你修改的端口号即可。
Paste_Image.png
1.2 安全的启动方式
要以安全的方式启动MongoDB数据库,需要在启动命令中加入 --auth
参数;一旦加上此参数,登录服务器就必须是认证的用户。
mongod --auth --dbpath ../data/db
使用 --auth
参数重新启动MongoDB后,再通过shell查看所有数据库,就会提示需要登录了:
Paste_Image.png
需要说明的是,如果你只是在MongoDB服务所在的本机中进行操作,是不会被禁止的。启动shell的命令直接用
mongo
即可,不需要在后面加上IP和端口号。
2.MongoDB的身份验证
我们在启动MongoDB后,查看所有的数据库,会发现我们什么都还没做,有已经有两个特殊的数据库: admin
和 local
。
事实上,这两个数据库正是MongoDB进行身份验证所需的。我们可以将这两个数据库中的用户看作是管理员,或者说是超级用户;经过认证后,管理员可以对任何数据库进行读写操作,并执行某些特殊命令,如listDataBases
和 shutdown
[1]。
2.1 增加一个管理员
如果MongoDB服务是在本机,则直接操作即可。但如果MongoDB在远程,则需要:
远程的MongoDB使用不安全的方式启动,然后在本地进行操作
或者在远程的MongoDB中设置允许访问的IP:
mongod --bind_ip 127.0.0.1,10.118.4.27
[2]
我们以第一种方式,即让远程MongoDB服务以不安全方式启动:
mongod --dbpath ../data/db
MongoDB启动后,我们通过shell连接到此服务器,并执行:
> use admin switched to db admin > > db.addUser("root", "123456") { "n" : 0, "connectionId" : 2, "err" : null, "ok" : 1 } { "user" : "root", "readOnly" : false, "pwd" : "34e5772aa66b703a319641d42a47d696", "_id" : ObjectId("58c20b105991fbda9129bad9") }
在创建了管理员后,我们让远程服务以安全模式重启,然后在本地用刚刚创建的管理员帐户登录:
> use admin > db.auth("root", "123456")
需要注意的是,一定要先切换到admin数据库,否则会如下图红框内所示,仍无法管理:
Paste_Image.png
在实际使用中,不要设置**
123456
**之类的弱密码!设置的密码最起码要满足以下几个条件
位数在8位以上
包含大小写字母、数字
建议包含一些特殊符号,如
$
@
#
等
2.2 设置管理员只读权限
在 db.addUser()
命令中,最后一个参数为 readOnly
,如果设置为 true
,即表示此用户只有读权限、没有写权限,操作如下:
db.addUser("reader", "123456", true)
这样创建的管理员就只能读取数据库了。
2.3 更改管理员权限
addUser()
命令既可以用来创建新用户,也可用于更改原用户的权限、设置新密码等。
比如,我们要将上面创建的 read
用户的密码改为 654321
,则:
db.addUser("reader", "654321", true)
再比如,我们要将上面创建的 read
用户的设置为读写权限 ,则:
db.addUser("reader", "654321", false)
3.管理管理员
是的,我们要知道有多少管理员、他们的权限是怎样的,我们需要管理这些管理员。
3.1 身份验证的原理
MongoDB的管理员用户是存储在system,users中的,其结构信息如下:
{ user : username, readonly : true, pwd : password hash }
其中,password hash 是基于 username
和密码生成散列值 [1]
因此,从本质上说,管理员的身份信息也是存储在一个数据库中;那么我们要管理管理员,操作方法也是一样的,只是要对 system.users
进行操作。
既然管理员身份信息是存储在
system.users
中,我们在开发过程中,也应避免将网站的数据库命名为system
3.2 删除一个管理员
很简单地,要删除一个管理员用户(如删除 read
用户),只需要执行 remove
命令即可:
db.system.users.remove({"user", "read"})
[1] 资料来自 《MongoDB权威指南》,图字01-2013-6738号,人民邮电出版社
[2] 参考资料: MongoDB限制内网访问的方法
作者:Mike的读书季
链接:https://www.jianshu.com/p/faa65fa8b086