Sitemap

Reactor

OS: Linux || Difficulty: Easy

Press enter or click to view image in full size

.بسم الله والصلاة والسلام على أشرف خلق الله سيدنا محمد ﷺ وعلى آله وصحبه أجمعين

Let’s dive in

Let’s fire up our favorite Nmap scan again and see which ports are open and what services are running on them.

Press enter or click to view image in full size

There’s a Next.js web application running on port 3000.

Let’s begin the web enumeration phase.

Press enter or click to view image in full size

So far, it’s just a static page with nothing particularly useful.
Let’s move on to fuzzing and continue gathering information.

Press enter or click to view image in full size

Let’s search for virtual hosts to see if there are any additional subdomains.

At the same time, I also started directory fuzzing in the background against the current web application.

At the same time, I opened Wappalyzer to identify the technologies running on the website and check whether there were any interesting version details worth investigating.

Press enter or click to view image in full size

I actually found something interesting, the versions of Next.js and React running on the application.

So I left the fuzzing running in the background and started verifying whether this version was actually vulnerable to React-to-Shell or not.

Press enter or click to view image in full size

And indeed, it turned out to be vulnerable to React-to-Shell.

When this vulnerability was first disclosed, I saved several resources about it while studying the technique, thinking I might need them someday, and that day finally came.

Just one click … boooom.

Press enter or click to view image in full size

We successfully obtained a shell.

The next step was to identify which user we had access as and determine our next target.
After that, we started searching for useful information and sensitive files, and eventually came across reactor.db.

So we downloaded it to our local machine and began analyzing its contents.

Press enter or click to view image in full size

Inside the database, we found an admin hash as well as a hash belonging to the engineer user.
The admin hash wasn’t particularly useful for us the real target was the engineer user’s hash.

That’s exactly why identifying our target early on is such an important step.

Press enter or click to view image in full size

Now it’s time to crack the hash using Hashcat

Press enter or click to view image in full size

We successfully recovered the password, so let’s try using it to log in via SSH.

And here we go, the user flag is ours.

Press enter or click to view image in full size

As usual, say it for me.

Initial Enumeration

After gaining access as the engineer user, I started enumerating sudo permissions.

Press enter or click to view image in full size

As part of our usual initial enumeration process, we started by checking everything available to us.

We quickly noticed that running sudo -l was not allowed, so we moved on to checking the id output.
the group memberships revealed something interesting:

At first glance, the lxd group looked like the intended privilege escalation vector since members of this group can often abuse LXD containers to gain root access.

I attempted to interact with LXD:

which lxc
lxc image list

But it turned out that the LXD daemon itself was not actually installed or running on the machine, so this path was a dead end.

That meant deeper enumeration was required.
After that, we began enumerating the open ports on the system.

Press enter or click to view image in full size

Oh, a new port we don’t know anything about yet.
Let’s do some research and see what we can find.

Press enter or click to view image in full size

Port 9229 is commonly associated with the Node.js Inspector Debugger.
To confirm this, I checked the running processes:

Get Veen0o21’s stories in your inbox

Join Medium for free to get updates from this writer.

The output showed:

root1376 ... /usr/bin/node--inspect=127.0.0.1:9229 /opt/uptime-monitor/worker.js
Press enter or click to view image in full size

At this point, the privilege escalation vector became clear.

At this point, the privilege escalation vector became clear.

Now, I had to stop and fully understand what all of this actually meant.

After digging into it, I came across the following:

Understanding the Vulnerability

What is the Node.js Inspector?
The Node.js Inspector is a debugging interface used by developers for:

  • debugging applications
  • setting breakpoints
  • inspecting variables
  • executing JavaScript code at runtime

When Node is started with:

node--inspect app.js

it exposes a debugging service over WebSockets.
By default, this service listens on:

127.0.0.1:9229

Developers usually assume localhost exposure is safe.
However, this is extremely dangerous when:

  • the process runs as root
  • i already has local shell access

Because any local user can connect to the debugger and execute arbitrary JavaScript inside the running process.

Since JavaScript can spawn system commands using child_process, this effectively becomes local root RCE.

To communicate with the debugger, I queried the inspector metadata endpoint:

Press enter or click to view image in full size

The response returned the active WebSocket debugging endpoint:

{
"title":"/opt/uptime-monitor/worker.js",
"type":"node",
"webSocketDebuggerUrl":"ws://127.0.0.1:9229/8a986380-491d-4e28-973e-191799bddf75"
}

This endpoint is required to establish a WebSocket debugging session.

The Exploitation Process

The exploitation process worked like this:

  1. Open a raw TCP connection to port 9229
  2. Upgrade the connection to WebSocket
  3. Communicate using the Chrome DevTools Protocol (CDP)
  4. Use Runtime.evaluate
  5. Execute JavaScript inside the root Node.js process
  6. Spawn system commands through child_process

Building the Exploit

in the machine, I could not install external npm packages like ws.

Instead, I manually implemented the WebSocket communication using Node’s built-in net module.

The exploit:

  • opened a TCP socket
  • performed the WebSocket handshake
  • manually built WebSocket frames
  • executed JavaScript through Runtime.evaluate

The payload copied /bin/bash into /tmp/rootbash and added the SUID bit.

Exploit Script

The complete exploit script is available on GitHub:
View the exploit script →https://github.com/Veen0o21/Machines/blob/main/Reactor/exploit.js

Press enter or click to view image in full size

After running the exploit

I spawned the SUID bash shell:

/tmp/rootbash-p

The -p flag is important because modern bash versions drop privileges unless explicitly told to preserve them.

And just like that… the root flag is ours.

Press enter or click to view image in full size

See you in the next machine write-up, Insha’Allah.

Press enter or click to view image in full size

Written by Veen0o21

Bug Hunter || Top 5 Egypt HackTheBox || Top 1% TryHackMe