服务端请求伪造 (Server-Side Request Forgery)
服务端请求伪造(SSRF)是一种安全漏洞,攻击者可以利用该漏洞迫使服务器代表自己发起请求。
摘要 (Summary)
- 工具 (#tools)
- 方法论 (#methodology)
- 绕过过滤器 (#bypassing-filters)
- 默认攻击目标 (#default-targets)
- 利用 IPv6 记法绕过 Localhost (#bypass-localhost-with-ipv6-notation)
- 利用域名重定向绕过 Localhost (#bypass-localhost-with-a-domain-redirect)
- 利用 CIDR 绕过 Localhost (#bypass-localhost-with-cidr)
- 利用稀有地址记法绕过 (#bypass-using-rare-address)
- 利用编码后的 IP 地址绕过 (#bypass-using-an-encoded-ip-address)
- 利用不同的编码方式绕过 (#bypass-using-different-encoding)
- 利用 HTTP 重定向绕过 (#bypassing-using-a-redirect)
- 利用 DNS 重绑定绕过 (#bypass-using-dns-rebinding)
- 利用 URL 解析差异绕过 (#bypass-abusing-url-parsing-discrepancy)
- 绕过 PHP filter_var() 函数 (#bypass-php-filter_var-function)
- 利用 JAR 伪协议绕过 (#bypass-using-jar-scheme)
- 通过 URL 伪协议进行利用 (#exploitation-via-url-scheme)
- 盲 SSRF 利用 (#blind-exploitation)
- 升级为 XSS (#upgrade-to-xss)
- 实验环境 (Labs)
- 参考资料 (#references)
工具 (Tools)
- swisskyrepo/SSRFmap - 自动 SSRF 模糊测试与利用工具
- tarunkant/Gopherus - 生成 gopher 链接,用于在多种服务器中利用 SSRF 并获取 RCE
- In3tinct/See-SURF - 基于 Python 的扫描器,用于寻找潜在的 SSRF 参数
- teknogeek/SSRF-Sheriff - 使用 Go 编写的简易 SSRF 测试工具
- assetnote/surf - 返回可行的 SSRF 候选目标列表
- dwisiswant0/ipfuscator - 一个超快、线程安全、直接且零内存分配的工具,用于在 Go 中迅速生成 IP(v4) 地址的多种替代表示形式
- Horlad/r3dir - 一个重定向服务,旨在帮助绕过那些不校验重定向位置的 SSRF 过滤器。已通过 Hackvertor 标签集成到 Burp 中
方法论 (Methodology)
SSRF 是一种安全漏洞,当攻击者操纵服务器向非预期的位置发起 HTTP 请求时就会发生。这种情况发生在服务器在没有经过适当验证的情况下处理用户提供的 URL 或 IP 地址时。
常见的利用路径:
- 访问云环境元数据 (Cloud Metadata)
- 读取服务器上的本地文件
- 网络发现,利用 SSRF 进行端口扫描
- 向网络中的特定服务发送数据包,通常旨在实现对另一台服务器的远程命令执行 (RCE)
示例:服务器接受用户输入来获取某个 URL。
攻击者提供恶意输入:
这将从 AWS EC2 元数据服务中获取敏感信息。
绕过过滤器 (Bypassing Filters)
默认攻击目标 (Default Targets)
默认情况下,SSRF 常被用于访问部署在 localhost 或者是网络深处隐藏的服务。
- 使用
localhost
- 使用
127.0.0.1
- 使用
0.0.0.0
利用 IPv6 记法绕过 Localhost
-
使用 IPv6 中的未指定地址
[::] -
使用 IPv6 环回地址
[0000::1]
利用域名重定向绕过 Localhost
| 域名 | 重定向至 |
|---|---|
| localtest.me | ::1 |
| localh.st | 127.0.0.1 |
| spoofed.[BURP_COLLABORATOR] | 127.0.0.1 |
| spoofed.redacted.oastify.com | 127.0.0.1 |
| company.127.0.0.1.nip.io | 127.0.0.1 |
nip.io 服务在此类场景下非常强大,它能将任何 IP 地址转换为 DNS 域名。
利用 CIDR 绕过 Localhost
在 IPv4 中,IP 范围 127.0.0.0/8 被保留用于环回地址。
如果你尝试在网络中使用该范围内的任何地址(如 127.0.0.2, 127.1.1.1 等),它们仍会解析到本地机器。
利用稀有地址记法绕过
你可以通过省略零来简写 IP 地址:
利用编码后的 IP 地址绕过
-
十进制 IP 地址
-
八进制 IP:不同的实现方式处理 IPv4 的八进制格式可能有所不同。
-
十六进制 IP
利用不同的编码方式绕过
-
URL 编码:对特定 URL 进行单次或多次编码以绕过黑名单
-
带圈/特殊字形字符 (Enclosed Alphanumeric):
①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇⒈⒉⒊⒋⒌⒍⒎⒏⒐⒑⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⓪⓫⓬⓭⓮⓯⓰⓱⓲⓳⓴⓵⓶⓷⓸⓹⓺⓻⓼⓽⓾⓿ -
Unicode 编码:在某些语言(.NET, Python 3)中,正则默认支持 Unicode。
\d不仅包含0123456789,还包含如๐๑๒๓๔๕๖๗๘๙等字符。
通过 IPv6 主机名绕过
-
在 Linux 下,
/etc/hosts包含该行:::1 localhost ip6-localhost ip6-loopback。但这仅在 HTTP 服务器运行在 IPv6 时有效。
利用 HTTP 重定向绕过
- 在一个受信任(白名单内)的主机上创建一个页面,该页面将请求重定向到攻击者目标的 SSRF URL(例如 192.168.0.1)。
- 发起 SSRF,指向
vulnerable.com/index.php?url=http://你的重定向服务器。 - 你可以使用状态码 HTTP 307 或 HTTP 308,以便在重定向后保留原有的 HTTP 方法和请求体 (Body)。
要在无需自行托管重定向服务器的情况下进行重定向或执行无缝的重定向目标模糊测试,请使用 Horlad/r3dir。
-
以
307 Temporary Redirect状态码重定向至http://localhost -
以
302 Found状态码重定向至http://169.254.169.254/latest/meta-data/
利用 DNS 重绑定 (DNS Rebinding) 绕过
创建一个在两个 IP 之间切换解析的域名。
- 1u.ms - DNS 重绑定实用工具
例如,要在 1.2.3.4 和 169.254.169.254 之间轮换,请使用以下域名:
使用 nslookup 验证地址:
$ nslookup make-1.2.3.4-rebind-169.254-169.254-rr.1u.ms
名称: make-1.2.3.4-rebind-169.254-169.254-rr.1u.ms
地址: 1.2.3.4
$ nslookup make-1.2.3.4-rebind-169.254-169.254-rr.1u.ms
名称: make-1.2.3.4-rebind-169.254-169.254-rr.1u.ms
地址: 169.254.169.254
利用 URL 解析差异绕过
Orange Tsai 的研究:主流编程语言中利用 URL 解析器的新 SSRF 时代
http://127.1.1.1:80\@127.2.2.2:80/
http://127.1.1.1:80\@@127.2.2.2:80/
http://127.1.1.1:80:\@@127.2.2.2:80/
http://127.1.1.1:80#\@127.2.2.2:80/
http:127.0.0.1/
针对 http://1.1.1.1 &@2.2.2.2# @3.3.3.3/,不同库解析后的行为:
urllib2将1.1.1.1视为目的地。requests和浏览器会重定向到2.2.2.2。urllib会解析到3.3.3.3。- 某些解析器会将
http:127.0.0.1/替换为http://127.0.0.1/。
绕过 PHP filter_var() 函数
在 PHP 7.0.25 中,带有 FILTER_VALIDATE_URL 参数的 filter_var() 函数允许如下 URL:
http://test???test.com0://evil.com:80;http://google.com:80/
<?php
echo var_dump(filter_var("http://test???test.com", FILTER_VALIDATE_URL));
echo var_dump(filter_var("0://evil.com;google.com", FILTER_VALIDATE_URL));
?>
利用 JAR 伪协议绕过
该攻击技术属于全盲注入 (Blind),你将无法看到返回结果。
通过 URL 伪协议进行利用 (Exploitation via URL Scheme)
File
允许攻击者获取服务器上的文件内容。可将 SSRF 转化为文件读取漏洞。
HTTP
允许攻击者获取互联网上的任何内容,也可用于端口扫描。
Dict
DICT URL 伪协议用于引用可通过 DICT 协议获得的定义或词表:
SFTP
一种通过安全外壳 (SSH) 实现安全文件传输的网络协议。
TFTP
简单文件传输协议,运行在 UDP 之上。
LDAP
轻量级目录访问协议。它是一种运行在 IP 网络之上的应用协议,用于管理和访问分布式目录信息服务。
Netdoc
当你的载荷在处理 "\n" 和 "\r" 字符遇到困难时,该协议可作为 Java 的封装器 (Wrapper)。
Gopher
gopher:// 协议是一种早于现代万维网的轻量级、基于文本的协议。它被设计用于在互联网上分发、搜索和检索文档。
该伪协议非常有用,因为它可被用于向 TCP 协议发送自定义数据。
查阅 SSRF 进阶利用部分以深入了解 gopher:// 协议。
盲 SSRF 利用 (Blind Exploitation)
在利用服务端请求伪造时,我们经常会遇到无法读取响应的情况。
利用 SSRF 链来实现带外 (Out-of-Band) 输出:assetnote/blind-ssrf-chains
可通过 HTTP(s) 实现的连锁攻击:
- Elasticsearch
- Weblogic
- Hashicorp Consul
- Shellshock
- Apache Druid
- Apache Solr
- PeopleSoft
- Apache Struts
- JBoss
- Confluence
- Jira
- 其他 Atlassian 产品
- OpenTSDB
- Jenkins
- Hystrix Dashboard
- W3 Total Cache
- Docker
- Gitlab Prometheus Redis 导出器
可通过 Gopher 实现的连锁攻击:
- Redis
- Memcache
- Apache Tomcat
升级为 XSS
当 SSRF 没有关键影响,网络被隔离且无法触达其他机器,且 SSRF 无法外带服务器文件时。
你可以尝试通过包含一个内嵌 Javascript 代码的 SVG 文件,将 SSRF 升级为 XSS。
实验环境 (Labs)
- PortSwigger - 针对本地服务器的基础 SSRF
- PortSwigger - 针对其他后端系统的基础 SSRF
- PortSwigger - 带有基于黑名单输入过滤的 SSRF
- PortSwigger - 带有基于白名单输入过滤的 SSRF
- PortSwigger - 通过开放重定向漏洞绕过过滤的 SSRF
- Root Me - 服务端请求伪造
- Root Me - Nginx - SSRF 配置错误
参考资料 (References)
- SSRF 的新时代 - 利用 URL 解析器 - Orange Tsai - 2017年9月27日
- errors.hackerone.net 上的盲 SSRF - chaosbolt - 2018年6月30日
- ESEA SSRF 及 AWS 元数据查询 - Brett Buerhaus - 2016年4月18日
- Hacker101 SSRF - Cody Brocious - 2018年10月29日
- Hackerone 教程:如何进行服务端请求伪造 (SSRF) - Jobert Abma - 2017年6月14日
- 黑掉黑客:利用 HackerTarget 中的 SSRF - @sxcurity - 2017年12月17日
- 我如何在 GitHub Enterprise 上串联 4 个漏洞,从 SSRF 执行链到 RCE!- Orange Tsai - 2017年7月28日
- SSRF:如何绕过防火墙 - Geluchat - 2017年9月16日
- PHP SSRF 技巧 - @secjuice - theMiddle - 2018年3月1日
- 揭秘:从 SSRF 到 NIPRNet 访问 - Alyssa Herrera - 2018年4月9日
- 服务端浏览被视为有害行为 - Nicolas Grégoire (Agarri) - 2015年5月21日
- SSRF - 类型与攻击方式 第一部分 - SaN ThosH (madrobot) - 2019年1月10日
- Video to GIF 转换器中的 SSRF 与本地文件读取 - sl1m - 2016年2月11日
- imgur.com/vidgif/url 中的 SSRF - Eugene Farfel (aesteral) - 2016年2月10日
- proxy.duckduckgo.com 中的 SSRF - Patrik Fábián (fpatrik) - 2018年5月27日
- shopifycloud.com 上的 SSRF - Rojan Rijal (rijalrojan) - 2018年7月17日
- 纯文本凭据处理器中的 SSRF 协议走私:LDAP - Willis Vandevanter (@0xrst) - 2019年2月5日
- SSRF 贴士 - xl7dev - 2016年7月3日
- SSRF 来了!真实的 SSRF 案例 - Alberto Wilson 和 Guillermo Gabarrin - 2019年1月25日
- 利用 SSRF 漏洞攻击 GCE/GKE 实例的示例 - mrtc0 - 2018年9月5日
- SVG SSRF 速查表 - Allan Wirth (@allanlw) - 2019年6月12日
- Java 中的 URL 特性 - sammy (@PwnL0rd) - 2020年11月2日
- Web 安全学院:服务端请求伪造 (SSRF) - PortSwigger - 2019年7月10日
- X-CTF 决赛 2016 - John Slick (Web 25) - YEO QUAN YANG (@quanyang) - 2016年6月22日