Skip to content
KitploitKITPLOIT
도구블로그
Log in
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
Next.js-Proof-of-Concept — Next.js의 CVE-2025-29927, CVE-2026-27978 및 CVE-2026-29057에 대한 일부 개념 증명(PoC)입니다. | Kitploit
도구/GitHubGitHub/nayekah/next.js-proof-of-concept
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityLearning & EducationLabs & Practice
GitHubnayekah/next.js-proof-of-concept

Next.js-Proof-of-Concept

Next.js의 CVE-2025-29927, CVE-2026-27978 및 CVE-2026-29057에 대한 일부 개념 증명(PoC)입니다.

저장소 보기
15개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Next.js CVE 개념 증명

이 저장소에는 세 가지 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외부 백엔드로의 재작성(rewrite)을 통한 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

저장소 구조

.
|- 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. 이 저장소의 루트에서 명령을 실행합니다.

모든 서비스 시작

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는 미들웨어로만 보호됩니다:

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를 여전히 제공할 수 있었고, 런타임은 해당 값을 신뢰할 수 있는 미들웨어 메타데이터로 처리했습니다. 관련 취약 로직은 다음과 같습니다:

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는 여기서 필터링되지 않았으므로 공격자가 제어하는 입력이 미들웨어 런타임에 도달할 수 있었습니다. 그런 다음 이 값은 재귀 깊이를 계산하는 데 사용되었습니다:

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를 보내면 런타임은 이미 재귀 깊이에 도달했다고 판단하고 애플리케이션 미들웨어를 실행하지 않은 채 요청을 전달할 수 있습니다.

실행

docker compose up --build cve-2025-29927-vuln cve-2025-29927-fixed
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을 노출합니다:

'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이 명시적인 불투명 출처(opaque origin) 대신 누락된 출처로 처리되었습니다:

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과 같은 불투명 출처의 요청은 호스트/출처 비교 경로를 우회하면서도 피해자 쿠키가 첨부된 채 처리될 수 있었습니다.

실행

docker compose up --build cve-2026-27978-vuln cve-2026-27978-fixed
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*를 외부 백엔드로 재작성합니다:

/** @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가 재작성에 사용하는 벤더링된(vendored) http-proxy 의존성에 있었습니다. 영향을 받는 버전에서 DELETE 및 OPTIONS 요청에 대한 프록시 로직은 content-length: 0을 추가하고 transfer-encoding을 제거할 수 있었습니다:

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']
  }
},

이로 인해 조작된 청크(chunked) 요청이 전달될 때 프록시 체인과 백엔드 간에 요청 경계 불일치가 발생했습니다. 그 결과 두 번째 요청이 동일한 연결을 통해 백엔드로 밀반입(smuggle)될 수 있었습니다.

실행

docker compose up --build cve-2026-29057-vuln cve-2026-29057-fixed
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을 모두 기록합니다.
  • 수정된 대상에서는 백엔드가 첫 번째 재작성된 요청만 기록합니다.

관찰된 예제 출력:

$ node scripts/run-cve-2026-29057.mjs http://localhost:3005
[before] {"backendRequests":[]}
[after] {"backendRequests":["DELETE /rewrites/poc","GET /secret"]}
PoC result: vulnerable behavior reproduced.
도구 다운로드