El desafío de BloodHound en Slack
Casualmente, mientras redactaba mi publicación sobre el punto ciego de ADWS (originalmente pensada como parte 6, pero ahora Parte 5A), observé una conversación interesante en el canal #red-team de BloodHound en Slack. La conversación que siguió sentó las bases de esta investigación y terminó llevándome a dividir la Parte 6 en dos publicaciones separadas.
El intercambio original
Todo comenzó cuando Usuario 1 preguntó sobre la detección de ADWS:
"Hola a todos, ¿cuál es su forma preferida de enumerar AD de manera segura para opsec? ¿ADSI o ADWS? ¿Y cuál es su experiencia con la detección de ADWS del lado del DC? Por ejemplo, ¿al usar soapy? ADSI nos ha funcionado muy bien, incluso en entornos muy maduros. Me encantaría saber más sobre la enumeración con ADWS."
Usuario 2 respondió explicando su preferencia por ADWS y los desafíos de detección:
"Mi forma preferida es usar ADWS para la recolección de AD, aunque admito que estoy un poco sesgado jaja 😅
Pero la clave al hacer una recolección sigilosa de cualquier tipo es usar consultas acotadas y únicas. En concreto, hacer la recolección por medio de ADWS tiene muchas ventajas de opsec que, según cómo estén escritas las detecciones, pueden evadir por completo algunas detecciones orientadas a LDAP.
En cuanto a la mejor forma de detectar ADWS, probablemente sean los SACL canary."
Usuario 2 luego explicó el problema central de atribución:
"Lo que diferencia principalmente a los dos protocolos es que, con el registro de diagnóstico común de LDAP, el equipo o dispositivo desde donde parece originarse la recolección en los registros siempre es el DC en el que se ejecuta la consulta ADWS, debido a la interacción del servicio ADWS con el servicio LDAP por loopback. Además, el registro detallado para el servicio ADWS es muy limitado y por lo general no está habilitado."
Charlie Clark preguntó si era posible correlacionar esto con más registros:
"claro, pero ¿aun así es posible determinarlo para las solicitudes de ADWS, no? Solo que requiere correlacionar más registros, ¿cierto?"
La respuesta de Usuario 2:
"No, la verdad que no. No he encontrado una forma de correlacionar el equipo de origen de ninguna manera. La única forma de deducir el equipo de origen es mediante la enumeración de netsession, pero es aún más difícil con SOAPy porque se puede hacer un proxy del tráfico desde una sesión que no es de Windows."
Charlie insistió:
"¿seguro que no se podría con un evento de red? ¿el 5156?"
La respuesta completa de Usuario 2 detalló los desafíos:
"Sí, en teoría podrías identificar el equipo de origen con el 5156, pero eso es solo una conexión de red básica y por lo general se reduce su sensibilidad debido a la gran cantidad de esos eventos que se generan. Según entiendo, las grandes soluciones de identidad como MDI por lo general no alertan sobre la recolección en ese tipo de eventos, debido al volumen de tráfico normal.
Podrías detectarlo con tráfico hacia el puerto 9389 (ADWS), pero ahí hay un problema aún mayor: todo RSAT usa ADWS. Así que los administradores de sistemas haciendo operaciones normales generarían falsos positivos.
Así que podrías llegar a identificarlo durante el triaje, pero sería difícil y generar una alerta es muy complicado"
Por qué el Evento 5156 no fue una sugerencia al azar
Cuando vi que Charlie sugería el Evento 5156, supe de inmediato que había dado en el clavo. No fue una suposición al azar; Charlie, Jonathan Johnson y yo ya habíamos colaborado antes en la correlación del Evento 5156.
Trabajo previo:
- La investigación de RPC de Jonathan Johnson: el artículo de Jonny en SpecterOps de 2022, "RPC for Detection Engineers", había demostrado el poder del evento 5156 para correlacionar conexiones de red con actividad de servicios.
- Nuestra publicación colaborativa: Charlie, Jonny y yo publicamos "The Client Server Relationship - A Match Made in Heaven", donde mostramos exactamente cómo usar el evento 5156 para la correlación y atribución entre cliente y servidor.
Entonces, cuando el Usuario 2 dijo que la correlación de 5156 era “teóricamente” posible pero poco práctica, supe que la técnica funcionaba. La pregunta era si funcionaría específicamente para ADWS.
Reto aceptado.
La hipótesis
El Usuario 2 planteó inquietudes válidas:
- El evento 5156 genera un volumen alto
- Las herramientas RSAT crean falsos positivos
- La correlación es difícil
Pero yo planteé la hipótesis de que:
- El evento 5156 ya está siendo recopilado por la mayoría de los SIEM empresariales
- La detección de patrones en 1644 (como [all_with_list], SDflags:0x7, (!(FALSE))) resuelve el problema de los falsos positivos
- La correlación de marcas de tiempo con una ventana ajustada podría funcionar
Fase 1: Entender el flujo de eventos
En la Parte 5A mostramos cómo ADWS oculta la IP del atacante de los sensores de red y del evento 1644; la red solo ve un paquete cifrado en el puerto 9389, y el registro de LDAP muestra [::1] como el cliente. Aquí está la secuencia completa de eventos que, de todos modos, hace posible la atribución.
El evento 5156 es la pieza que falta. Proviene de la Windows Filtering Platform (WFP) y se registra en el log de seguridad cada vez que se permite una conexión de red. Se ha vuelto uno de mis eventos favoritos para el trabajo de correlación porque registra la aplicación propietaria de la conexión, no solo el puerto. Entonces, en lugar de ver el genérico svchost.exe, ves microsoft.activedirectory.webservices.exe. Está activado de forma predeterminada bajo la subcategoría de auditoría de conexión de Filtering Platform, así que no se necesita configuración adicional.
Cuando un equipo remoto se conecta a ADWS por el puerto 9389, el evento 5156 captura la conexión entrante con la IP de origen real. Eso ocurre antes de que ADWS traduzca la solicitud en una llamada LDAP interna, que es el paso donde se reemplaza la IP real por localhost.
Figura 1: Evento 5156 (registro de seguridad): la Windows Filtering Platform captura la conexión entrante a ADWS con la IP de origen real antes de que la solicitud se traduzca internamente.
Figura 2: Evento 1138 (registro de AD Web Services): ADWS registra la nueva conexión con la IP real del cliente y un InstanceId único que vincula la sesión con los eventos posteriores.
Figura 3: Evento 1644 (registro del Directory Service): la consulta LDAP interna muestra localhost como el cliente; la IP de origen real desaparece, pero se conservan el contexto del usuario y los detalles de la consulta.
Esta es la conexión externa que proporciona la atribución de IP de origen.
Fase 2: Correlación basada en puertos
El evento 1644 muestra el cliente como [::1]:60983 (localhost con puerto efímero). Si pudiéramos encontrar un evento 5156 interno que muestre a ADWS conectándose a LDAP en ese mismo puerto, podríamos encadenar:
5156 externo → 5156 interno (puerto coincidente) → 1644.
Ejecutando SOAPy desde la máquina Linux (10.1.1.13) y revisando los registros:
Evento 1644:
Client: [::1]:60983
User: MARVEL\loki
Filter: ( & (objectClass=user) ... )
Eventos 5156 internos encontrados:
03:54:46.406 | ::1:61532
03:53:46.393 | ::1:61522
03:52:46.380 | ::1:61514
Los puertos no coinciden. El evento 1644 muestra el puerto 60983, pero los eventos 5156 internos muestran 61532, 61522, y así sucesivamente. El puerto 60983 es una conexión LDAP persistente que ADWS estableció mucho antes de la prueba. El evento 5156 original de esa conexión ya había salido del registro de seguridad. Las consultas nuevas reutilizan esta conexión existente: no se crea un nuevo 5156 para cada consulta.
La correlación basada en puertos solo funciona en un SIEM donde el 5156 original (cuando se estableció por primera vez la conexión persistente) aún se conserva. En una consulta en vivo de un DC, es posible que ya haya salido del registro.
Fase 3: Correlación basada en marcas de tiempo
La correlación basada en puertos falló, pero los eventos aún ocurren en secuencia con una sincronización predecible. Aunque el 5156 original de la conexión persistente haya salido del registro, el 5156 externo que se generó para la consulta actual sigue ahí, con una marca de tiempo a milisegundos del evento 1644.
La hipótesis: correlacionar por ventana de tiempo.
5156 externo → [procesamiento de ADWS] → Evento 1644
~60–80ms
Mismo ataque de SOAPy, revisando marcas de tiempo:
5156 externo:
Time: 03:53:28.407
Source IP: 10.1.1.13
Dest Port: 9389
Application: microsoft.activedirectory.webservices.exe
Evento 1644:
Time: 03:53:28.469
Client: [::1]:60983
User: MARVEL\loki
Filter: ( & (objectClass=user) (objectCategory=CN=Person,CN=Schema,CN=Configuration,DC=marvel,DC=local) )
Attributes: [all_with_list]nTSecurityDescriptor
Controls: SDflags:0x7;
Delta: 62ms
Pruebas repetidas en tres ejecuciones:
|
Ejecución de prueba |
5156 externo |
Evento 1644 |
Delta |
|
Ejecución 1 |
03:52:22.256 |
03:52:22.339 |
83,2ms |
|
Ejecución 2 |
03:53:28.407 |
03:53:28.469 |
61,2ms |
|
Ejecución 3 |
03:55:25.275 |
03:55:25.341 |
65,8ms |
Una ventana constante de ~60-80ms en las tres ejecuciones. El retraso de procesamiento entre la conexión externa y la ejecución de la consulta LDAP es lo bastante estable como para correlacionar eventos.
Fase 4: Creación del script de detección
Con la correlación por marca de tiempo confirmada como confiable, el siguiente paso fue crear un script que pudiera hacer esto automáticamente: recopilar los eventos relevantes, intentar primero la correlación basada en puertos y luego recurrir a la ventana de tiempo.
Ejecutando Get-ADWSAttribution.ps1 durante una enumeración activa con SOAPy:
Figura 4: Get-ADWSAttribution.ps1 correlaciona el evento 5156 → 1644 para atribuir las consultas LDAP a su IP de origen, detectando a MARVEL\loki en plena enumeración con BloodHound.
La IP de origen 10.1.1.13 se atribuyó correctamente a las tres consultas. El modo de monitor en tiempo real lo detecta en el momento en que ocurre:
Figura 5: Tres eventos. Un atacante. El evento 5156 te dice quién se conectó. El evento 1138 te dice que ADWS lo canalizó. El evento 1644 te dice qué buscaban.
Fase 5: La prueba de realidad del 5156
La primera objeción a cualquier detección basada en el 5156 es el volumen, la preocupación de que esté reducido o deshabilitado en la mayoría de los entornos. Veamos:
auditpol /get /subcategory: "Filtering Platform Connection"
Filtering Platform Connection Success
El evento 5156 está activado de forma predeterminada. Es parte de la auditoría de Windows Filtering Platform que viene habilitada de fábrica. La preocupación por el volumen es real, pero tiene que ver con la retención, no con la disponibilidad. Cada conexión de red genera un 5156, así que en un DC con mucho tráfico, el registro de seguridad se llena rápido y los eventos antiguos se sobrescriben.
La solución es SIEM. La mayoría de los entornos empresariales ya envían los registros de seguridad a un SIEM, lo que significa que los datos se conservan durante días o semanas.
|
Entorno |
Disponibilidad de 5156 |
Método de correlación |
|
Consulta en vivo al DC |
Puede haberse eliminado |
TIMESTAMP (probabilístico) |
|
SIEM (Splunk/Sentinel) |
Se conserva durante días/semanas |
PORT (determinístico) o TIMESTAMP |
|
Respaldo forense de EVTX |
Si se capturó a tiempo |
Cualquiera de los dos métodos |
Fase 6: Cómo abordar el problema de los falsos positivos
La preocupación del Usuario 2: "Todo RSAT usa ADWS."
Cierto. Los sysadmins que usan los cmdlets de AD de PowerShell generan tráfico 5156 idéntico hacia el puerto 9389. La solución es la detección de patrones en el Evento 1644. No alertas por cada conexión ADWS, solo por las conexiones que se correlacionan con patrones LDAP sospechosos.
|
Patrón |
Significado |
¿Uso legítimo? |
|
[all_with_list] |
PowerShell -Properties * |
Poco común entre administradores |
|
SDflags:0x7 |
Solicitud completa del descriptor de seguridad |
Muy poco común |
|
(!(FALSE)) |
Firma de SOAPHound |
Nunca |
|
Alto volumen de consultas a localhost |
Enumeración masiva |
Sospechoso |
|
nTSecurityDescriptor en los atributos |
Enumeración de ACL |
Patrón de BloodHound |
El flujo de detección
Figura 6: El flujo de detección: detecta el patrón sospechoso en el evento 1644, correlaciónalo con un evento 5156 coincidente dentro de ~100 ms, y obtén una IP de origen confirmada, el usuario autenticado, los detalles de la consulta y la firma de la herramienta, todo a partir de registros que ya existían.
En qué queda el debate
El Usuario 2 tenía razón en varias cosas: los eventos LDAP muestran localhost, el 5156 genera un alto volumen, RSAT crea falsos positivos, y la detección en tiempo real a nivel del DC es más difícil cuando el 5156 original ya salió del registro de seguridad.
Pero su conclusión de que el endpoint de origen "no se puede determinar" no aplica para la detección basada en SIEM. Los datos han estado ahí todo este tiempo en la mayoría de los entornos empresariales. La correlación por marca de tiempo funciona incluso cuando la correlación por puerto no. Y la detección de patrones en el evento 1644 resuelve el problema de falsos positivos que él identificó.
La brecha nunca fue técnica. Fue que nadie había publicado el método de correlación.
Resumen: la cadena de atribución completa
Figura 7: Cadena de atribución completa: el evento 5156 captura la IP de origen real en el límite de la red; el evento 1138 vincula la sesión de ADWS con el usuario autenticado; el evento 1644 revela la consulta. Correlaciona los tres, y el atacante no tiene dónde esconderse.
Conclusión
"¿Puedes identificar quién está consultando AD a través de ADWS?"
Sí. La correlación del Evento 5156 con una ventana de tiempo de ~60–80 ms te da la IP de origen que el Evento 1644 oculta detrás de localhost. La correlación basada en puerto funciona cuando tu SIEM conserva el evento de conexión original. La correlación basada en marca de tiempo funciona incluso cuando no lo hace.
Los datos siempre estuvieron ahí. Nadie los estaba correlacionando.
Agradecimientos
- Usuario 1 - Por hacer la pregunta original en #red-team
- Usuario 2 - Por explicar el problema de loopback de ADWS/LDAP y los desafíos
- Charlie Clark - Por sugerir la correlación del Evento 5156 como posible solución
- BloodHound Slack #red-team - Donde ocurrió la conversación
Gracias a Jonathan Johnson, Anton Ovrutsky, Matt Anderson, Tyler Bohlmann, Michael Haag, Nasreddine Bencherchali, y Adam Bienvenu por su ayuda en la revisión de esta publicación.