就在前几天,实验室挂在阿里云上的MongoDB被攻击了,数据全部被删除,只留下了一个叫 WARNING 的数据库,其中表里面的内容如下:

酷壳上也有一篇对这一系列事情介绍的文章: 从 MONGODB “赎金事件” 看安全问题

这件事情给我们留下了深刻的教训,以前一直抱有侥幸心理,觉得这种事情不会发生在自己身上,然后能省事就省事,得到真正发生了,便各种手忙脚乱。

MongoDB默认是不开启授权认证的,只要客户端程序能够访问MongoDB服务器,就可以与它进行连接。但是在生产环境,一般都需要开启授权认证,只有经过授权的用户才能够连接到MongoDB,才允许访问相关的资源,即:用户-角色-资源,这种模式与其它关系型数据库的权限模式基本一致。


在开启授权认证模式之前,需要先在MongoDB中创建一个管理员用户,MongoDB默认是不提供用户的

首先切换到admin数据库,这个库的作用是用来存放MongoDB中所有的授权用户,默认这个库是不存在的,我们先切换过来,在用的时候它会自动创建

1
use admin; //切换成功会显示 switched to db admin

创建用户,把下面代码复制进去执行:

1
2
3
4
5
6
db.createUser({
"user":"jwcqc","pwd":"jwcqc",
"roles":[
{role:"userAdminAnyDatabase", db: "admin"},
{role:"readWriteAnyDatabase", db: "admin"}
]});

MongoDB中内置了很多角色,我们可以直接使用。角色可以设置多个

role:表示角色,db:表示当前角色针对哪个数据库有效。比如设置了admin 那么这个用户的权限范围只在admin数据库有效。
比如我设置 role:”readWrite”, db:”mydb” 那么这个用户只能在mydb这个数据库有读写的权限。

但是MongoDB中提供了几个全局数据库的角色,例如上面的userAdminAnyDatabase, readWriteAnyDatabase
注意后面的AndDataBase, 如果设置了这个角色,那么意味着这个角色是针对所有数据库有效的,尽管它设置了db:”admin”。


要开启认证模式,可以有两种方式:

1、修改MongoDB的配置文件: /etc/mongod.conf (路径可能会有所不同)

1
2
3
4
5
6
port=52914
dbpath=/alidata/mongodb/mongodb_data/
logpath=/alidata/mongodb/mongodb_log/mongodb.log
fork=true
logappend=true
auth=true #这个就是开启认证的配置

开启完成后重启MongoDB即可生效:

1
sudo service mongod restart

有了配置文件后MongoDB的启动:

1
./mongod --config /alidata/mongodb/mongod.cnf

2、以–auth 重新启动mongodb

1
./mongod --auth --port 52914 --dbpath=/alidata/mongodb/mongodb_data/ --logpath=/alidata/mongodb/mongodb_log/mongodb.log --logappend --fork

开启授权认证模式后在此进入MongoDB的客户端
第一步切换到admin数据库,第二步进行身份认证。

1
2
use admin; //switched to db admin
db.auth("jwcqc","jwcqc"); //认证成功返回1,如果认证失败会提升相关的错误信息

如果不先执行db.auth,而去执行查询命令,则会遇到如下报错

1
2
3
4
5
6
7
show collections
2016-09-05T16:46:13.013+0800 E QUERY [thread1] Error: listCollections failed: {
"ok" : 0,
"errmsg" : "not authorized on picadb to execute command { listCollections: 1.0, filter: {} }",
"code" : 13
} :

可以使用如下命令查看一下系统用户

1
2
3
db.system.users.find()
{ "_id" : "admin.dbadmin", "user" : "jwcqc", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "NuYMHdgcMc4KXcghSaahbw==", "storedKey" : "WIddwwnCu5a88R5Osix4BHdml0w=", "serverKey" : "0jPPRIQEXMNdH3IJ8RWyGyJ5rGQ=" } }, "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" }, { "role" : "readWriteAnyDatabase", "db" : "admin" } ] }

然后就可以给具体的数据库设置授权用户了,别忘了先 use dbname 切换到那一个数据库

1
2
use PMC;
db.createUser({"user":"jwcqc","pwd":"jwcqc","roles":[{role: "readWrite",db: "PMC" }]});

打开后关闭mongo数据库的两种办法:
1、通过./mongo 127.0.0.1:52914进入mongo shell后,先use admin,再db.shutdownServer()
2、pkill mongod

mongo命令行下导入数据文件示例如下:
./mongoimport -h 127.0.0.1:52914 -d PMC -c ServiceMonitor /alidata/server/pmc-backup/ServiceMonitor.json