Skip to content
Closed
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
60 changes: 60 additions & 0 deletions src/network-services-pentesting/pentesting-web/nextjs.md
Original file line number Diff line number Diff line change
Expand Up @@ -1362,10 +1362,70 @@ Next.js App Router deployments that expose Server Actions on `react-server-dom-w
}
```

### High-fidelity detection of colon-delimited RSC crashes (Next.js RSC RCE Scanner)

`react-server-dom-parcel`, `react-server-dom-turbopack`, and `react-server-dom-webpack` consume App Router Flight payloads that are streamed inside multipart bodies. Each part is indexed (`name="0"`, `name="1"`, …) and the JSON strings in those parts can reference previously seen chunks with the `$<chunkId>:<property>:...` syntax. The [Next.js RSC RCE Scanner](https://github.com/tobiasGuta/Next.js-RSC-RCE-Scanner-Burp-Suite-Extension) automates Searchlight Cyber's detection trick: make chunk `1` an empty object and make chunk `0` contain `"[$1:a:a]"`. When the vulnerable parser tries to resolve the second `:a`, it dereferences `undefined`, throws, and the server returns the characteristic RSC error stream that precedes full RCE (CVE-2025-55182 / CVE-2025-66478).

#### Detection payload

The extension clones any captured request (typically `GET /`), rewrites it to a `POST`, strips conflicting Next.js headers, and injects a controlled multipart body plus the App Router metadata needed to reach the RSC parser (`Next-Action`, `Next-Router-State-Tree`, `X-Nextjs-Request-Id`, `X-Nextjs-Html-Request-Id`).

<details>
<summary>Example detection request</summary>

```http
POST / HTTP/1.1
Host: target
Next-Action: x
Next-Router-State-Tree: %5B%22%22%2C%7B%22children%22%3A%5B%22__PAGE__%22%2C%7B%7D%2Cnull%2Cnull%5D%7D%2Cnull%2Cnull%2Ctrue%5D
X-Nextjs-Request-Id: b5dce965
X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad

------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"

{}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="0"

["$1:a:a"]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--
```

</details>

Chunk `1` is stored as handle `$1`. Chunk `0` immediately dereferences `$1` twice (`:a:a`), so the resolver attempts to read property `a` on an `undefined` value, producing the crash without injecting any JavaScript gadgets. You can manually reproduce this in Burp Repeater by copying any baseline request to a suspected RSC endpoint, switching the method to `POST`, removing the original body, and pasting the payload above.

#### Response signature

Only treat the target as vulnerable when **both** conditions below are met—the extension enforces this to avoid false positives:

- The HTTP status code is `500`.
- The response body contains an RSC error frame that starts with `E{"digest"` (React prefixes error chunks with `E`; the `digest` contains a deterministic hash of the thrown exception).

This combination means the colon-delimited resolver inside the RSC parser crashed, which implies the vulnerable code path is reachable and an RCE exploit chain is likely possible (as documented in the [Next.js advisory](https://nextjs.org/blog/CVE-2025-66478)).

#### Burp workflow

- **Active Scanner integration:** Once the extension jar is loaded, every eligible insertion point is re-issued with the multipart payload above. Burp automatically reports `Next.js RSC Remote Code Execution (CVE-2025-55182)` with High severity when the `500 + E{"digest"` signature is observed.
- **Manual testing:** From Proxy History or Repeater select any request → **Extensions → Next.js RSC RCE Scanner → Scan**. The extension replaces the body/headers and shows the result in the Dashboard so you can correlate which endpoint crashed.
- **Reporting context:** The issue detail clearly states that the target executed the vulnerable `react-server-dom-*` path and includes the failing request/response pair. This is a strong signal for deeper exploitation attempts (prototype pollution → RCE) without sending unsafe payloads.

#### Installation / build notes

- Download the latest `NextJsRceScanner-*.jar` release and add it via **Extensions → Installed → Add → Java** inside Burp.
- If you prefer to build it yourself, clone the repository, ensure JDK 21+, and run `./gradlew clean build` (or `gradlew.bat clean build` on Windows); the jar is emitted under `build/libs/`.

> [!WARNING]
> The scanner purposely crashes the target RSC handler to elicit the digest signature. Only run it against systems where you have explicit authorization, and communicate that `500` responses are an expected side effect of the detection process.

## 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)
- [CVE-2025-55182 React Server Components Remote Code Execution Exploit Tool](https://github.com/Spritualkb/CVE-2025-55182-exp)
- [Next.js RSC RCE Scanner (Burp Suite Extension)](https://github.com/tobiasGuta/Next.js-RSC-RCE-Scanner-Burp-Suite-Extension)
- [Next.js Security Advisory (CVE-2025-66478)](https://nextjs.org/blog/CVE-2025-66478)

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