用户
搜索

该用户从未签到

i春秋-脚本小子

Rank: 2

50

主题

50

帖子

181

魔法币
收听
0
粉丝
2
注册时间
2016-11-28
发表于 2017-1-12 14:59:24 64654
作者:图南

起因


元旦放假后上班第一天,同事高高兴兴的去上班,发现每天发邮件的一个应用当天的邮件没有发送,同事觉得奇怪,去登录数据库看了一眼,顿时背后冒起了凉气儿。所有数据全部被删除,并发现了这样一句话:
1.jpg
老子把你的MongoDB里的数据库给转走了,如果你要你的数据的话,给我0.2个的比特币

(WTF!!!!)

同事已经石化了,不知如何是好,qq上求助我,我第一反应是,我X,这是我第一次与黑产接触,竟然是以这种方式,黑产好赚钱,绝不能像恶势力屈服(手动攥拳头)!

原来同事的这个应用使用的是MongoDB数据库,为了开发的快(lan)速(duo),使用了MongoDB数据库的默认配置。用过MongoDB的朋友都知道MongoDB默认不需要用户名和密码就可以以最高权限访问数据库进行任何操作,这种状态开发环境下还好,如果部署到生产环境下非常危险。

为同事制定了一套恢复方案后,我开始看MongoDB用户验证和权限的相关文章,因为MongoDB更新迅速,2.6版本和最新的3.2版本设置差距很大,我在设置用户和权限的时候遇到了很多坑,这里决定以最新的3.2版本为例理一理关于MongoDB用户和权限的一些事情,并加入我对数据库用户和权限设置和备份的一些配置实践,防止大家继续入坑。

基本概念

先说一下关于用户、验证和角色的基本概念。

用户

要在MongoDB中验证客户端,必须向MongoDB添加相应的用户。

添加用户

添加用户使用MongoDB的用户管理接口,此接口提供db.createUser()的方式添加用户(这里有坑,网络上很多关于MongoDB添加用户的内容还都在使用db.addUser(),这是2.6版本的添加用户方式)。
假如我们有test数据库,要为此数据库添加用户,我们可以在mongo shell下使用以下语句:

[AppleScript] 纯文本查看 复制代码
> db.createUser({[/color]
[color=#000000]    user: "user1",//用户名[/color]
[color=#000000]    pwd: "12345678",//密码(实际操作中设置密码要尽量复杂)[/color]
[color=#000000]    roles: [//权限数组[/color]
[color=#000000]        {[/color]
[color=#000000]            role: "readWrite",[/color]
[color=#000000]            db: "test"//test数据库的读写权限[/color]
[color=#000000]        }[/color]

[color=#000000]})

执行后的返回结果:
2.jpg

这样我们就为test数据库创建了一个拥有读写权限的用户。

验证

验证是认证客户端身份的过程。 当访问控制(即授权)被启用时,MongoDB要求所有客户端对其自身进行认证,以确定其访问。

开启验证

我们刚刚创建了一个用户,但如果我们是以默认的方式启动mongod,验证并没有生效,那么我们来停掉mongod服务并在启动时增加配置项使验证生效。

通过增加mongod参数来开启验证

在启动mongod的时候增加--auth参数就可以使验证生效。
mongod --auth

通过修改配置文件来开启验证

我们也可以通过修改MongoDB的配置文件来启用验证。
在Linux服务器上配置文件一般存放在/etc文件夹中,如果没有我们就创建一个。

vim /etc/mongodb.conf
# mongodb.conf
# Where to store the data.
dbpath=/var/lib/mongo
#where to log
logpath=/var/log/mongodb/mongod.log
logappend=true
bind_ip = 0.0.0.0
port = 27017
# Enable journaling, http://www.mongodb.org/display/DOCS/Journaling
journal=true
#fork
fork = true
# Enables periodic logging of CPU utilization and I/O wait
#cpu = true
# Turn on/off security.  Off is currently the default
#noauth = true
#我们把启用验证的设置加载这里
auth = true
#。。。。。。


我只截取了配置文件的一部分,这个配置文件的其他内容我不再赘述了,我们只需要知道怎样配置开启验证。
保存后执行下面的代码来启动mongod
mongod -f /etc/mongodb.conf


使用验证


我们刚刚开启了验证,下面两种方式可以使用刚才创建的用户来操作需要验证访问的数据库。

在连接时验证


使用-u ,-p 和--authenticationDatabase 命令行选项启动mongo shell:
mongo -uuser1 -p12345678 --authenticationDatabase test


3.jpg

在连接后验证

通过mongo shell连接MongoDB。
mongo

切换到对应的数据库。
> use test

然后使用db.auth(<username>, <pwd>)的方式验证用户。
>  db.auth('user1', '12345678')

4.jpg
两种验证方式均可以使用该用户操作对应的数据库。

用户角色

角色授予对资源执行指定操作的权限,我们在这里只讨论MongoDB的常用内置角色(对我已经足够了)。

数据库用户角色

biao1.png

数据库管理员角色
每个数据库都包含以下数据库管理员权限:

biao2.png

备份和恢复角色
在admin数据库中包括以下用于备份和恢复数据的角色:

biao3.png

超级用户角色
下面的角色为所有资源提供所有权限:

biao4.png

防护方案

我对MongoDB的配置思路是建立一个对现有生产数据库的可读写权限的用户供程序使用,建立一个超级用户和一个备份还原用户,每小时对数据库执行一次备份。这并不是一个推荐的配置方式,只是满足我当前对数据库安全的需求。

为应用程序建立可读写用户

在mongoshell下执行以下命令:
[AppleScript] 纯文本查看 复制代码
> use test   > db.createUser({
   user: "user1",//用户名
   pwd: "12345678",//密码(实际操作中设置密码要尽量复杂)
   roles: [//权限数组
       {
           role: "readWrite",
           db: "test"//test数据库的读写权限
       }
   ]})

建立后修改程序中对MongoDB的连接配置即可测试程序与数据库的连接。

建立超级用户

在mongoshell下执行以下命令:
[AppleScript] 纯文本查看 复制代码
> use admin> db.createUser({
   user: "su",
   pwd: "12345678",
   roles: [
       {
           role: "root",
           db: "admin"
       }
   ]})

建立备份还原用户

在mongoshell下执行以下命令:
[AppleScript] 纯文本查看 复制代码
> use admin> db.createUser({
   user: "dbbackup",
   pwd: "12345678",
   roles: [
       {
           role: "backup",
           db: "admin"
       }, {
           role: "restore",
           db: "admin"
       }
   ]})

配置数据库定时备份
数据库备份
数据库备份我直接从github上搜到了一个备份的脚本,修改脚本中的参数,并修改文件命名方式支持每小时备份。地址在这里。
https://github.com/controlz/Mongo-db-shell-backup

这里我们用到了刚刚创建的具有备份和恢复权限的用户,将其写入配置文件中:
### Set server settingsHOST="localhost"PORT="27017" # default mongoDb port is 27017USERNAME="dbbackup"PASSWORD="12345678"

配置后执行脚本测试:

5.jpg

执行成功后会在配置好的目录生成打包的备份文件。

加入定时任务
使用crontab将数据库备份加入定时任务中,在bash中执行以下语句:
crontab -e

进入crontab的编辑模式,加上每小时执行一次备份的脚本:
0 * * * * /path/to/shell/directory/mongodb-backup.sh

保存后启动crontab。
service crond start

将crontab加入开机启动:
chkconfig crond on

过几个小时再看备份目录中已经有了打包好的备份文件了,搞定!
6.jpg

恢复数据库
恢复数据库这块儿有一个坑,就是3.2版本的mongorestore参数和2.6版本的不一样了。网上搜到的大部分恢复数据库定位备份文件的参数都是--directoryperdb而实际使用时会报错,后来查看mongorestore帮助文档才发现变成了--dir。下面是恢复命令:
mongorestore --port 27017 -uuser1 -p12345678 --db test --dir=/path/to/backup/directory/test/

总结
后来我搜索新闻看到很多媒体推送了这次的安全事件,并取名“MONGODB赎金事件”,看来受害者不只是我的那位同事。对于像我们一样的开发人员,现在使用的很多开发框架都已经具备了防范常见安全漏洞(xss、sql注入等)的能力,反而是我们最容易忽略的弱口令和无口令问题屡屡频发,通过这篇文章和我亲身经历的这个事件我想提醒大家,不要因为懒惰忽略安全权限的设置,同事的这个应用并不涉及公司的敏感数据,万一黑客删除的数据库是公司的主要业务和很多敏感数据,那就呵呵呵呵了。



发表于 2017-1-12 15:55:56
沙发的啊
使用道具 举报 回复
板凳                  
使用道具 举报 回复
mongo数据库相对于mysql等其安全性的确需要注意
使用道具 举报 回复
发表于 2017-1-13 14:02:26
屌!
使用道具 举报 回复
发表于 2017-1-17 15:10:15
厉害了我的哥!
使用道具 举报 回复
发表于 2017-1-18 15:23:24
使用道具 举报 回复
发新帖
您需要登录后才可以回帖 登录 | 立即注册