不安全的 Redis 的特点

  • Redis 所在机器有外网 IP
  • Redis 使用默认端口 6379 启动,并且对外网开放
  • Redis 以 root 身份启动
  • Redis 没有设置密码
  • Redis 的 bind 为 0.0.0.0""

案例:

2015年11月,全球数万个 Redis 遭受攻击,数据被清空,只有一个叫 crackit 键存在,其数据类似一个公钥,内容如下:

  1. 127.0.0.1:6379> get crackit
  2. "\n\n\nssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAsGWAoHYwBcnAkPaGZ565wPQ0Ap3K7zrf2v9p HPSqW+n8WqsbS+xNpvvcgeNT/fYYbnkUit11RUiMCzs5FUSI1LRthwt4yvpMMbNnEX6J/0W/0nlq PgzrzYflP/cnYzEegKlcXHJ2AlRkukNPhMr+EkZVyxoJNLY+MB2kxVZ838z4U0ZamlPEgzy+zA+oF 0JLTU5fj51fP0XL2JrQOGLb4nID73MvnROT4LGiyUNMcLt+/Tvrv/DtWbo3sduL6q/2Dj3VD0xGD l1kTNAzdj+jOA1Jg1SH53Va34KqIAh2n0Ic+3y71eXV+WouCwkYrDiqqxaGZ7KKmPUjeHTLUEhT5Q == root@zw_xx_192\n\n\n\n"

攻击手段:

  • 攻击者获取 Redis 访问后,通过修改 Redis 的 dirdbfilename 配置,并通过 config set 动态修改方式修改
  • 然后将自己的公钥写入到目标服务器的 /root/.ssh/authotrized_keys 实现对目标服务器的攻陷。

Redis crackit 攻击的过程与条件:

image.png

安全的 Redis

Redis 的密码机制

如何配置

  • 配置参数:requirepass
  • 命令方式:redis-server --requirepass hello_redis

如何访问

  • redis-cli -a 参数:redis-cli -a hello_redis
  • auth 命令:在 redis-cli 直接连接后,执行 auth 命令,操作如下:
    1. redis-cli
    2. 127.0.0.1:6379> ping
    3. (error) NOAUTH Authentication required. # 提示无权限
    4. 127.0.0.1:6379> auth hello_redis # 输入密码
    5. OK
    6. 127.0.0.1:6379> ping
    7. PONG

运维建议

  • 密码足够复杂(如64个字节以上),因为 Redis 的高性能,简单密码,可短时间内通过暴力破解方式破解
  • 如果是主从架构,不要忘记在从节点配置 masterauth(master 的密码)配置,否则会造成主从失败
  • auth 是通过明文传输,所以也不是 100% 可靠

伪装危险命令

引入 rename-command

常见的的“危险”命令有:

  • keys:若键值较多,存在 Redis 阻塞的可能性
  • flushall/flushdb:数据被全部清空
  • save:若键值较多,存在 Redis 阻塞的可能性
  • debug:如 debug reload 会重启 Redis
  • config:config 应交给管理员使用
  • shutdown:停止 Redis

如何使用 rename-command:

以 flushall 命令为例

  • redis.conf 配置中添加 rename-command flushall abcdefghijklmn
  • 往后执行 flushall 命令会提示未知命令,但可执行 abcdefghijklmn 去执行清空操作

引入 rename-command 带来的问题

  • 当修改命令后,常见的第三方库(如:java的jedis)内部操作,无法直接使用相关命令,增加一定的开发和维护成本。
  • rename-command 不支持动态的 config set,需在配置中设定后,启动。
  • 如果 AOF 和 RDB 文件包含了 rename-command 之前的命令, Redis 将无法正常工作。

最佳实践

  • 对于一些危险的命令(如:flushall),无论内网或外网,均使用 rename-command 配置
  • 建议第一次配置 Redis 时,就配置好 rename-command ,因为 rename-command 不支持动态的 config set,也不支持 RDB 和 AOF 文件对历史修改命令的载入。
  • 如果涉及主从关系,主从配置应该保持一致性。

防火墙

可通过防火墙限制输入、输出的 IP 或 IP 范围、以及端口或者端口范围。

bind

bind 的理解

  • 错误的理解:配置的 bind 认为 Redis 直接接收来自某个网段 IP 的客户端请求。
  • 正确的理解:bind 指的是 Redis 与哪个网卡进行绑定。

如 ifconfig 命令获取当前的网卡信息,发现包含三个 IP:

  • 内网地址: 10.10.1.192
  • 外网地址:220.181.1.123
  • 回环地址:127.0.0.1

配置参考如下:

  • Redis 如配置了 bind 10.10.1.192,那只有 10.10.1.* 的 IP 段可连接;
  • Redis 如配置了 bind 127.0.0.1,那只有本机可连接;
  • Redis 如配置了 bind 0.0.0.0,那任何 IP 段都可连接;
  • 当然 Redis 也支持绑定多个网卡,如:bind 10.10.1.192 220.181.1.123

运维提示:Redis 3.0 的 bind 默认值是 “”,也就是不限制网卡访问;但是在 Redis 3.2 中,必须配置 bind 0.0.0.0 才可达到该效果

运维建议

  • 如果机器有外网 IP,但 Redis 部署给内网使用,建议去掉外网网卡或者使用 bind 配置限制流量从外网进入
  • 如果客户端和 Redis 部署在同一台服务器,可使用回环地址:127.0.0.1
  • bind 不支持动态的 config set,所以建议第一次配置 Redis 的时候配置好

关于 protected-mode 配置的说明:

  • Redis 3.2 提供,默认开启
  • 含义:如果那个 Redis 没有配置密码,没有配置 bind,那么只允许来自本机的访问,也就是相当于配置了 bind 127.0.0.1,伪代码如下:
    1. if (protected-mode && !requirepass && !bind) {
    2. Allow only 127.0.0.1,::1 or socket connections
    3. Deny (with the long message ever!) others
    4. }

定时备份数据

  • 定时备份能晚会一些数据损失

不使用默认端口

  • Redis 默认端口:6379
  • 不适用默认端口可减低被入侵的发现可能

一般攻击者会对目标服务器端口进行扫描,比如常见的端口:MySQL的3306等

使用非 root 用户启动

root 权限过大,如 Redis 被攻陷,基本可在当前机器上“为所欲为”。