diff --git a/src/network-services-pentesting/pentesting-web/nextjs.md b/src/network-services-pentesting/pentesting-web/nextjs.md index 699fef29f83..d55b9806754 100644 --- a/src/network-services-pentesting/pentesting-web/nextjs.md +++ b/src/network-services-pentesting/pentesting-web/nextjs.md @@ -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. @@ -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}} \ No newline at end of file