Skyphobia

记一次mongodb被黑的经历

0x00 比特币勒索

有一阵子经常有 GSR 的用户反馈说登录不上,检查到最后发现都是因为 mongodb 的数据被清了。所幸定时脚本有备份,因此每次也都是草草地恢复备份没有深究。

直到这次有用户让我帮忙重置密码,我登服务器看 mongodb 数据的时候,发现了一个本不该有的名为 Warning 的 collection。

被黑客写入的 Warning collection

Your Database is downloaded and backed up on our secured servers. To recover your lost data: Send 0.2 BTC to our BitCoin Address and Contact us by eMail with your server IP Address and a Proof of Payment. Any eMail without your server IP Address and a Proof of Payment together will be ignored. You are welcome!

我的草,人在江湖飘,哪能不挨刀,这是被黑了呀!虽然没有造成什么实际损失,但总觉得非常不甘心,打算亡羊补牢,避免以后再被人捅刀子。

网上查了下发现同样劫持 mongodb 数据勒索比特币的事件比比皆是,最早可溯源到 2016 年底。攻击者会针对那些端口暴露在公网下,并且默认未设置帐号密码鉴权的 mongodb 实例进行数据劫持,并勒索比特币。这样的 mongodb 堪比在人民广场裸奔,任人宰割。当年勒索 0.2 比特币,现在还勒索 0.2 比特币,这也太不要脸了吧。

说归说,今时今日给黑客送上肉鸡和当初嫌麻烦裸奔数据库的都是我,只得乖乖填上这个坑了。下面记录一下添加用户鉴权的操作步骤。

0x01 创建用户鉴权

先解决一下用户鉴权问题,这个其实非常容易,主要死于懒癌……

首先我们先要有一个管理员账号,并用其登录

1
2
3
4
5
6
> use admin // 切换到 admin database
switched to db admin
> db.createUser({ user: "admin", pwd: "password", roles: ["userAdminAnyDatabase"] }) // 创建管理员
Successfully added user: { "user" : "admin", "roles" : [ "userAdminAnyDatabase" ] }
> db.auth("admin", "password") // 切换到管理员
1

然后切换数据库,并为其创建一个新的用户帐号

1
2
3
4
5
> use someDB // 切换到需要添加鉴权的 database
switched to db someDB
> db.createUser({ user: "user", pwd: "password", roles: ["readWrite"] }) // 创建普通用户
Successfully added user: { "user" : "user", "roles" : [ "readWrite" ] }
1

0x02 禁用外网访问

上面鉴权做好以后已经足以抵挡攻击者的入侵了,不过为了以防万一,干脆禁用掉 mongodb 端口的外网访问。

先要找到 mongodb 配置文件的路径,macOS 是 /usr/local/etc/mongod.conf,Linux 则是 /etc/mongod.conf。mongodb 从 2.6 开始配置文件改为 YAML 格式,我用的是 3.X,这里只记录一下新的配置方式。

1
2
3
net:
bindIp: 127.0.0.1 # 改为 127.0.0.1
port: 27017 # 可以视情况改成其他端口

配置完毕,mongod --config [CONFIG_PATH] 重启一下生效。

0x03 结语

虽然这样的配置漏洞是由于用户的疏忽引起的,但我总觉的这个事情 mongodb 多多少少也得背口锅。毕竟人总是懒的,默认配置直接干的人总是占绝大多数,如果一开始 mongodb 的配置是默认禁用外网的话,相信同类事件的发生机率能够大大地减少。不过从这个漏洞被发现至今,mongodb 也只是发过公告提醒用户重视这个漏洞并没有采取其他措施,更有趣的是,同类问题在 Redis、CouchDB 等等数据库均由发生,看来也真的只能靠用户自己多注意些了吧。