HackTheBox — NODE writeup

0xRobin
8 min readApr 30, 2022
HTB — NODE

This box was created by ‘rastating’.

Let’s start the journey!

I added the ip[10.10.10.58] of the box to /etc/hosts as ‘node.htb’

Enumerations

First, let’s do the nmap scan.

nmap -A -sC -sV -Pn node.htb > nmap.scan

Open ports are : 22, 3000

Let’s go and see what’s in the HTTP Apache server running in port 3000

We can’t run gobuster or dirb or other, because the machine blocked those with some type of filtering methods.

Let’s use burpsuite to crawl the website and see if it finds something.

So, the burp found some interesting things. Let’s look at the /api/users/ directory.

burp — user_accounts

And, we got a list of possible user accounts and also an admin account. INTERESTING!!

All the passwords here are hashes. Let’s decrypt those. We can use Crackstations or hashes.com

And after decrypting the hashes we get :

User-Pass cracked

Let’s log in with the admin account.

admin login

Download the backup file. [Sometimes it gives an error when downloading the file, but I bypassed with the burp proxy on (intercept off)]

It requires a password to unzip it. We can try the brute-force method.

fcrackzip will do the trick here.

fcrackzip

So, the password is ‘magicword’.

Unzipping it gives us a folder named ‘var’ which has the full source code of the myplace web application. We can now analyze the code and let’s see if we can find something interesting.

Getting Shell — mark

In app.js file, we find mongo-db credentials for user mark.

And, user mark used the same password for his ssh.

ssh — mark

From /etc/passwd , we see that another user is ‘tom’ .

To get the user flag we need to get access to tom’s account.

Let’s run LinEnum. Using the python HTTP server I transferred the LinEnum.sh file to the machine.

LinEnum gave us some interesting things to look at.

First, we see all the users in the system and second, in the process/service section, we see that a node service is compiling a file named /var/scheduler/app.js.

After analyzing the systemd scheduler service file, we see that it’s a mongo-db process/task scheduler. and it restarts every 3 sec.

Let’s analyze the /var/scheduler/app.js file.

Okay. Basically, we can see that the service executes a command from a document in the tasks list and delete it later to stop it being executed again.

And, it is using the same credentials as before and we can access the scheduler db with user mark .

So, we can edit and put a reverse shell command that will give us shell as tom [Because TOM is the user running that service ].

# Getting Shell(privesc) — TOM

Set up a netcat listener in the attacker machine, in the victim machine, log in to the mongo and access the scheduler db as mark, put the reverse shell command there, and wait for it to execute. Simple as that.

I don’t know much about mongo-db and its commands. So, yeah..Documentations.

The documentation is pretty clear about how to interact with the db. So, I will use `db.tasks.insert()` to insert a document with a command inside. and that’s it.

We have a shell as TOM now. However, working on this shell is a real pain, it doesn’t have the usual tab completion, up-down arrow key doesn’t work, basically, it’s not a proper shell that we are used to. So, let’s change that first.

So, the shell is upgraded.
Now, we can read the user flag from user.txt file.

Now, that’s done, we have to look for some way to privesc to root.

PrivEsc — ROOT

I am gonna check for SUID files —

Here, we can see that the backup binary is owned by root and the admin group has the permit to run it. and the user tom is also a member of the admin group.

If we remember correctly, the /var/www/myplace/app.js file contains a function that uses this backup binary file.

As we can see, the binary needs 3 arguments —
./backup -q <the_backup_key> < a directory >

Using ltrace on the binary we get to know the allowed ‘backup keys’ for the binary.

/etc/myplace/keys

The /etc/myplace/keys file also has a newline at the and so, ‘ ’ also a valid key.

After running `backup -q ‘ ‘ /root` it gives us a base64 string. Decoding that will give us a zip file. I extracted the files from the zip file [password : magicword], and we get a root.txt file.

Troll face

It’s a troll face.
Okay, so there is a problem. Let’s analyze the binary again with ltrace.

There is a strstr function check and the below image explains what strstr() does.

That means ‘/root’ or ‘root’ is filtered.
If I run it on /tmp directory, it reveals more filters —

Now, one interesting thing here as you can at the last line, there is a strcpy() function. And strcpy is known to be vulnerable to Buffer Overflow.

strcpy() vulnerability.

read here — https://man7.org/linux/man-pages/man3/strcpy.3.html

Buffer OverFlow

To test the BoF, we need to copy that binary file in to our machine.

and I also created a /etc/myplace/keys file..with a blank key there.

Now, let’s run the binary in our machine. and Test the BoF in the ‘directory argument’.

Running the binary
Testing BoF

Okay..There is a BoF.

First checking the protections are enabled -

NX is enabled, so we can’t just put something on memory stack and execute it. And also, we see that the ASLR is on -

This means we need to do a ret2libc attack.

Let’s open it with gdb[I am using gdb-pwndbg; [You can use your fav one.]

gdb-pwndbg ./backup

Checking the available functions -

Okay. Here are the steps for this ret2libc attack —
1. Find the Offset
2. Find the base address of LIBC
3. Find the offset addresses for the system, exit and /bin/sh
4. Add (2+3) to get the system, exit and /bin/sh addresses respectively.
5. To bypass this ASLR, we can use brute-force method.
6. Execute the script and wait.

First, finding the offset -

We can use cyclic in gdb-pwndbg to create a long pattern.

So the OFFSET = 512

Now, the libc base address -

Because of the ASLR, the libc address changes every time but look closely — the address always starts with 0xf7 and ends with 000 . So, only the middle 3 values change.

So, we can grab one of the addresses, and later use it in the brute-force method because the address will be used again when the exploit runs multiple times.

libc_base = 0xf756c000

now, the system, exit , and /bin/sh offset addresses -

Now, let’s write the script — [In python]

exploit.py

And when we run the script `python3 exp.py` —

Unintended methods to get root

There are also some unintended methods like using Wildcards, Command injections, Symlinks etc but I wont be discussing those in here. I just wanted to discuss the Buffer OverFlow method and about `ret2libc` attack.

You can find the other methods here -

rastating(Official), Oxdf, Rana Khalil and Ippsec

I hope, now you have a fair understanding of the concept discussed above.

--

--

0xRobin

Security Researcher | CTF Player | Penetration Tester