- 发布于
给你的 Mongodb 和 Redis 增加密码认证
- 作者
- 姓名
前言
最近需要使用 Redis 数据库,安装的时候发现原来 Redis 同 Mongodb一样,默认是不需要密码的,想了下是测试数据库,存的又只是用户 cookies,就并没有在意。同时使用的 Mongodb 虽然默认也是不需要密码验证的,但因为其官方的 Docker Hub 页面上有比较清晰的添加用户认证的说明,在安装的时候就顺便增加了权限认证。
但没有想到的是这一无意举动竟然给服务器带来了风险,服务器险些变成肉鸡,这也侧面说明了一件事,每天在互联网中有无数的端口扫描工具在日夜不停的寻找漏洞目标,稍有不慎,我们的服务器就会沦为肉鸡,任人宰割。
本文就将讲述如何给默认不包括用户认证的 Mongodb 和 Redis 数据库,增加用户认证,如果你也在使用无安全措施的 Mongodb 或者 Redis,在看到此文后,请务必根据本文内容添加安全措施,或者通过防火墙控制访问 IP。
问题发现
今天突然发现 Setapp 中那款叫 TablePlus 的数据库可视化管理软件增加了对 Mongodb 的支持,便想把之前用的 Robo 3T 给卸载掉(主要是界面不好看),换成 TablePlus,因为在增加了对 Mongodb 的支持后,TablePlus 基本上已经支持了所有主流数据库:
在添加数据库时,因为其同样支持 Redis,就把在使用的 Redis 数据库也添加了进去,不添加不要紧,一添加才发现情况不对:
除了用于缓存存储的db1
之外,还多了一个db0
,虽然本人对 Redis 可以说是完全不了解,但这个db0
中的内容稍微懂脚本的人就能看出来,是在下载某地址的一个脚本并执行,于是我查询了这个 IP 的归属,并打开了这个脚本文件,查看了一下内容:
IP 地址是一个 IDC 的,熟悉主流 VPS 厂商的应该知道,这个运营商就是 GigsGigsCloud,是一个比较常见的主机商,应该是攻击者将脚本放在自己购买的VPS服务器上。
至于脚本内容,打开一看,我才发现又是挖矿脚本,截取一些关键内容如下:
一些参数:
清理其他探矿脚本:
下面还有很长,就不截图了,看来同行太多,抢机器也很辛苦啊。
脚本下载:
甚至还控制自己的 CPU 占用避免被发现
试图添加攻击者的公钥
还有很多内容,本人也不是很懂 shell 语言,也只能大约知道是在干啥,就不贴图了,总之我们知道这是一个挖矿脚本,并且试图完全控制我们的服务器。
不过本人检查了服务器运行情况,一切正常,相关脚本并没有运行,攻击者的公钥也没有添加到authorized_keys
文件中,原因应该是由于本人的 Redis 是运行在 Docker 容器中,这倒也省了本人解决问题的时间,下面直接进入本文的主题,那就是给没有保护措施的 Mongodb 和 Redis 加一道锁。
给 Mongodb 增加安全认证
Docker 安装
安装方式
官方镜像默认是不包括安全策略的,但可以通过增加环境参数的方式在创建容器的时候创建超级用户,如果添加了用户名和密码的参数,那么 Mongodb 将默认以 --auth 即认证方式运行:
具体可参考官方 Docker Hub 页面
我们参考官方页面可以直接运行如下命令:
docker run -d -p 27017:27017 --name mongo \
-e MONGO_INITDB_ROOT_USERNAME=mongoadmin \
-e MONGO_INITDB_ROOT_PASSWORD=your_password \
-v mongo_db:/data/db \
-v mongo_configdb:/data/configdb \
mongo
官方提供的示例中包括了
--network
的选项这里省略了,如果你需要添加进特定子网,可以在创建容器后使用docker network connect
连接。
通过上面的命令我们就能创建一个初始超级用户为 mongoadmin 的需要认证才能访问的 Mongodb。
Mongodb 的基本使用
通过 Docker 安装的 Mongodb,要使用 mongo cli
,需要使用docker exec
命令,具体如下:
docker exec -it mongo bash
当然这里的mongo
,要换成你自己起的容器名,运行上面命令之后,我们就进入了容器内部,这时直接输入mongo
就能进入到 Mongodb 的命令行模式,这里提供几个常用操作,一般应用基本足够应付:
用户认证
我们需要切换到 admin 数据库下使用超级用户认证:
use admin
db.auth('mongoadmin','your_password')
回车后显示1,就说明认证成功。
创建数据库
比如我们要创建一个名叫 test 的数据库,直接使用 use test
即可完成创建并切换至 test 数据库
创建用户
创建数据库后,如果不添加用户,我们无法使用该数据库,所以我们必须添加一个针对该数据库的用户,需要使用如下命令:
db.createUser(
{
user: "test",
pwd: "test12345",
roles: [ { role: "readWrite", db: "test" } ]
}
)
运行以上命令将创建一个能够对 test 数据库进行读写的 test用户,密码为 test12345,如果创建成功,会提示成功创建用户。
整个基本流程如下图所示:
之后我们可以通过 mongodb://test:test12345@服务器IP:27017/test
来连接数据库。
非 Docker 安装
如果你并未使用 Docker 安装 Mongodb,并且已经安装好了无安全认证的 Mongodb 又不想重新安装,可以通过以下步骤添加安全认证。
本部分使用 Ubuntu 18.04 进行测试,初始状态是直接使用
apt install mongodb
命令安装了 Mongodb,并且打开了远程访问,这会是很多人将 Mongodb 用于测试的基本流程
打开远程访问以及认证模式
我们需要修改 /etc/mongodb.conf
文件,如果你已经在使用 Mongodb 应该已经修改过 bind_ip
了,这里就只需增加 auth=true
即可。
- 将
bind_ip
由127.0.0.1
改为0.0.0.0
- 将
auth=true
前的 # 去掉使之生效。
之后使用 service mongodb restart 重启 Mongodb
,这时我们将无法再不使用用户名密码直接访问 Mongodb 数据库了。
增加超级用户
首先使用 mongo
进入 Mongodb 的命令行模式,这时用户列表为空,我们需要创建一个超级用户,虽然我们已经开启了认证模式,但由于此时用户列表为空,我们不需认证就能创建一个超级用户:
use admin
db.createUser({
user: "mongoadmin",
pwd: "your-password",
roles: [ { role: "userAdminAnyDatabase", db: "admin" }]
})
之后的步骤请参考上文,完全一致。
Redis增加安全认证
与 Mongo 类似,如果 Redis 发现服务器暴露在互联网上,则会将其 bind
到 127.0.0.1
,禁止非本机之外的访问,同样可以通过简单的将127.0.0.1
修改为0.0.0.0
开放外网访问。使用 Docker 安装的 Redis 如果未添加特别参数,将默认开放外网访问。
如果你的 Redis 是非 Docker 安装,又暴露在了互联网上,将是非常危险的,经了解要防范可能的攻击,可以进行的安全措施主要包括以下几点:
- 避免公网访问
- 更换默认的 6379 端口
- 使用非 root 用户运行 Redis
- 开启密码验证并设置复杂密码
- 禁用或重命名危险命令
本文将只添加密码验证,如果有更高的安全需求,可以参考下方参考文档以及官方文档进行设置。
通过 Google 搜索
Redis 入侵
关键字,发现一篇遇到的问题与本文开头类似,甚至内容风格也与本文类似,但更加详细的文章,有兴趣的朋友请点击这里访问。
Docker 安装
Redis 官方 Docker Hub 页面提供的内容价值有限,并未提供任何有关访问控制的信息,我们可以直接运行如下命令启动一个 Redis 容器:
docker run --name some-redis -d -p 6379:6379 redis redis-server --appendonly yes
之后我们可以直接通过连接服务器 IP 的 6379 端口访问 Redis 服务器。通过这种方式使用Redis,将无法自定义设置,因为在容器中是没有 redis.conf
这个文件的。官方 Docker Hub 表示如果需要使用自定义的 redis.conf
文件,需要使用 Dockerfile 添加或者使用文件夹绑定:
考虑到我们使用 Docker 的目的就是方便,本人不建议使用这些复杂的方式,如果仅需使用密码验证,在创建 Docker 容器的时候,添加额外参数即可实现。
开启密码验证
在创建 Docker 容器时,添加requirepass
参数可以设置为需要密码访问。
我们使用的命令如下:
docker run -d -p 6379:6379 \
--name some-redis \
-v redis_data:/data \
redis \
redis-server --appendonly yes \
--requirepass "your_password"
其中的
some-redis
更换成你想要起的容器名,redis-server --appendonly yes
大意是开启持久化配置,未详细了解,这里我们还顺便对数据进行了持久化储存,使用volume
保存容器/data
目录的内容。
之后我们使用 Redis 数据库时,必须输入密码,否则没有任何操作权限。
- 使用 Redis-cli的方式
通过 -a 直接添加密码
docker exec -it some-redis redis-cli -a 'your_password'
或者进入 redis-cli 后再进行认证,看命令行提示,官方应该是更推荐这种方式:
docker exec -it some-redis redis-cli
auth 'your_password'
非 Docker 安装
如果你已经直接通过 apt
或者 yum
等命令将 Redis 安装到了系统中,并且没有设置密码验证,需要通过修改 redis.conf
文件来增加密码验证。
Redis 官方提供的 redis.conf 文件注释真的是非常非常的详细,即使我们对 Redis 完全不了解,也能够通过参考官方说明进行修改。
该文件的路径经测试在
/etc/redis/redis.conf
,看网上的指引一般都说在/etc/redis.conf
,请自行测试。
开放外部访问
vim /etc/redis/redis.conf
之后找到 bind 127.0.0.1 ::1
这一行,在下面添加一行,内容为bind 0.0.0.0
,如下图所示:
保存退出后,重启 Redis 服务器:
service redis-server restart
这样设置之后就可以从任意 IP 访问我们的 Redis 服务器了。
增加密码访问
继续对 redis.conf
文件进行编辑,找到内容为 # requirepass foobared
的一行,将前面的注释 # 去掉,同时将 foobared
修改为你要使用的密码。
注意官方文档的特别提示:由于 Redis 速度很快,所以外部用户可以以高达每秒15万次的速度尝试,所以推荐我们使用一个强密码避免被轻松破解。
设置完成后,保存退出,重启 Redis 服务器:
service redis-server restart
这样设置之后再访问我们的 Redis 服务器就必须使用密码验证了。
外部连接方式
在设置了密码后,外部连接 Redis 需要使用以下方式:
使用 redis-cli 连接
远程连接使用如下命令:
redis-cli -h 服务器IP -p 6379
参考上文内容可知,可通过在命令最后增加 -a 'your_password',或者连接后使用 auth 'your_password'的方式,这里不再详述。
Node.js 中连接
在引入 redis 的 npm 包之后,连接 Redis 服务器的命令格式如下:
redis.createClient(port,host,config)
port
表示端口,一般为 6379 host
表示服务器,填写服务器 IP config
为配置文件,我们需要将密码添加到这里,形式为{ auth_pass: 'your_password' }
其他方式连接请自行搜索。
参考文档
本文在撰写过程中,部分参考了以下内容,向作者表示感谢: