Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 69 additions & 2 deletions src/network-services-pentesting/pentesting-web/nextjs.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ my-nextjs-app/
- **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.
- **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.
- **app/page.tsx:** Serves as the entry point for the root route `/`, rendering the home page.
- **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.
- **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.
- **app/api/:** Contains API routes, allowing you to create serverless functions that handle HTTP requests. These routes replace the traditional `pages/api` directory.
- **app/components/:** Houses reusable React components that can be utilized across different pages and layouts.
- **app/styles/:** Contains global CSS files and CSS Modules for component-scoped styling.
Expand Down Expand Up @@ -1268,6 +1268,73 @@ const HeavyComponent = dynamic(() => import("../components/HeavyComponent"), {
})
```

{{#include ../../banners/hacktricks-training.md}}
## Next.js Server Actions Enumeration (hash to function name via source maps)

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:

```http
POST /
Next-Action: a9f8e2b4c7d1...
```

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()`.

### Extraction approach (regex on minified JS + optional source maps)

Search downloaded JS chunks for `createServerReference` and extract the hash and the function/source symbol. Two useful patterns:

```regex
# Strict pattern for standard minification
createServerReference\)\"([a-f0-9]{40,})\",\w+\.callServer,void 0,\w+\.findSourceMapURL,\"([^\"]+)\"\)

# Flexible pattern handling various minification styles
createServerReference[^\"]*\"([a-f0-9]{40,})\"[^\"]*\"([^\"]+)\"\s*\)
```

- Group 1: server action hash (40+ hex chars)
- Group 2: symbol or path that can be resolved to the original function via the source map when present

If the script advertises a source map (trailer comment `//# sourceMappingURL=<...>.map`), fetch it and resolve the symbol/path to the original function name.

### Practical workflow

- Passive discovery while browsing: capture requests with `Next-Action` headers and JS chunk URLs.
- Fetch the referenced JS bundles and accompanying `*.map` files (when present).
- Run the regex above to build a hash↔name dictionary.
- Use the dictionary to target testing:
- Name-driven triage (e.g., `transferFunds`, `exportFinancialData`).
- Track coverage across builds by function name (hashes rotate across builds).

### Exercising hidden actions (template-based request)

Take a valid POST observed in-proxy as a template and swap the `Next-Action` value to target another discovered action:

```http
# Before
Next-Action: a9f8e2b4c7d1

# After
Next-Action: b7e3f9a2d8c5
```

Replay in Repeater and test authorization, input validation and business logic of otherwise unreachable actions.

### Burp automation

- NextjsServerActionAnalyzer (Burp extension) automates the above in Burp:
- Mines proxy history for JS chunks, extracts `createServerReference(...)` entries, and parses source maps when available.
- Maintains a searchable hash↔function-name dictionary and de-duplicates across builds by function name.
- Can locate a valid template POST and open a ready-to-send Repeater tab with the target action’s hash swapped in.
- Repo: https://github.com/Adversis/NextjsServerActionAnalyzer

### Notes and limitations

- Requires `productionBrowserSourceMaps` enabled in production to recover names from bundles/source maps.
- Function-name disclosure is not a vulnerability by itself; use it to guide discovery and test each action’s authorization.

## References

- [Pentesting Next.js Server Actions — A Burp Extension for Hash-to-Function Mapping](https://www.adversis.io/blogs/pentesting-next-js-server-actions)
- [NextjsServerActionAnalyzer (Burp extension)](https://github.com/Adversis/NextjsServerActionAnalyzer)

{{#include ../../banners/hacktricks-training.md}}