Bookmarks

You haven't yet saved any bookmarks. To bookmark a post, just click .

  • 给你的 Mongodb 和 Redis 增加密码认证

  • 前言

    最近需要使用 Redis 数据库,安装的时候发现原来 Redis 同 Mongodb一样,默认是不需要密码的,想了下是测试数据库,存的又只是用户 cookies,就并没有在意。同时使用的 Mongodb 虽然默认也是不需要密码验证的,但因为其官方的 Docker Hub 页面上有比较清晰的添加用户认证的说明,在安装的时候就顺便增加了权限认证。

    但没有想到的是这一无意举动竟然给服务器带来了风险,服务器险些变成肉鸡,这也侧面说明了一件事,每天在互联网中有无数的端口扫描工具在日夜不停的寻找漏洞目标,稍有不慎,我们的服务器就会沦为肉鸡,任人宰割。

    本文就将讲述如何给默认不包括用户认证的 Mongodb 和 Redis 数据库,增加用户认证,如果你也在使用无安全措施的 Mongodb 或者 Redis,在看到此文后,请务必根据本文内容添加安全措施,或者通过防火墙控制访问 IP。

    问题发现

    今天突然发现 Setapp 中那款叫 TablePlus 的数据库可视化管理软件增加了对 Mongodb 的支持,便想把之前用的 Robo 3T 给卸载掉(主要是界面不好看),换成 TablePlus,因为在增加了对 Mongodb 的支持后,TablePlus 基本上已经支持了所有主流数据库:

    tableplus-ui.png

    在添加数据库时,因为其同样支持 Redis,就把在使用的 Redis 数据库也添加了进去,不添加不要紧,一添加才发现情况不对:

    redis-hacked.png

    除了用于缓存存储的db1之外,还多了一个db0,虽然本人对 Redis 可以说是完全不了解,但这个db0中的内容稍微懂脚本的人就能看出来,是在下载某地址的一个脚本并执行,于是我查询了这个 IP 的归属,并打开了这个脚本文件,查看了一下内容:

    redis-hacker-ip.png

    IP 地址是一个 IDC 的,熟悉主流 VPS 厂商的应该知道,这个运营商就是 GigsGigsCloud,是一个比较常见的主机商,应该是攻击者将脚本放在自己购买的VPS服务器上。

    至于脚本内容,打开一看,我才发现又是挖矿脚本,截取一些关键内容如下:

    • 一些参数:
      hacker-shell.png

    • 清理其他探矿脚本:
      hacker-shell2.png

    下面还有很长,就不截图了,看来同行太多,抢机器也很辛苦啊。

    • 脚本下载:
      hacker-shell3.png

    • 甚至还控制自己的 CPU 占用避免被发现
      hacker-shell4.png

    • 试图添加攻击者的公钥
      hacker-shell5.png

    还有很多内容,本人也不是很懂 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,如果创建成功,会提示成功创建用户。

    整个基本流程如下图所示:

    mongo-basic.png

    之后我们可以通过 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即可。
    mongo-config.png

    • bind_ip127.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 发现服务器暴露在互联网上,则会将其 bind127.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 添加或者使用文件夹绑定:

    redis-docker-conf.png

    考虑到我们使用 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'
    

    redis-password-auth.png

    非 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-config-bind.png

    保存退出后,重启 Redis 服务器:

    service redis-server restart
    

    这样设置之后就可以从任意 IP 访问我们的 Redis 服务器了。

    增加密码访问

    继续对 redis.conf 文件进行编辑,找到内容为 # requirepass foobared 的一行,将前面的注释 # 去掉,同时将 foobared 修改为你要使用的密码。

    redis-config-passwd.png

    注意官方文档的特别提示:由于 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' }

    其他方式连接请自行搜索。

    参考文档

    本文在撰写过程中,部分参考了以下内容,向作者表示感谢:

    1. Mongo Official Docker Hub Page

    2. mongodb 远程访问配置

    3. mongodb操作之用户篇

    4. Redis Official Docker Hub Page

    5. 事件分析 | 一起攻击者利用 Redis 未授权访问漏洞进行新型入侵挖矿事件

    6. 记一个 Redis 安全漏洞和 Redis 安全规范

    7. Docker安装官方Redis镜像并启用密码认证 实践笔记

    8. redis: set a password for redis