Terrance DeJesus

Registros de actividad de Azure AD Graph: Detección de ingestión y amenazas para cerrar la brecha de visibilidad

Los registros de actividad de grafos de Azure AD aterrizan en Elastic con análisis ECS completo. Detectar la enumeración de ROADrecon y AADInternals con reglas de detección listas para usar.

11 min de lecturaIngeniería de detección

Los registros de actividad de grafos AAD ahora son indigestos en Elastic y utilizables para la detección de amenazas dentro de la solución SIEM/XDR. Esa frase no debería ser emocionante, pero lo es. Durante la mayor parte de la última década, esta porción de telemetría simplemente no existía como un flujo de registro accesible para el cliente. Microsoft Graph Activity Logs (la superficie graph.microsoft.com moderna) pasó a ser GA en abril de 2024. El legado graph.windows.net superficie, el único adversario que realmente alcanza el tooling, se mantuvo oscuro hasta principios de 2026.

Esta publicación recorre el bucle de principio a fin. Por qué importa la visibilidad, cómo ingerir los registros en Elastic, cómo generar un reconocimiento realista manualmente y con ROADrecon, y cómo buscar el resultado en ES|QL. Todo lo que aparece a continuación se validó frente a un inquilino en tiempo real.

Conclusiones clave

  • Los registros de actividad de grafos de AAD se incorporan a Elastic a través de la integración con Azure y aterrizan en logs-azure.aadgraphactivitylogs-* con la extracción completa de ECS.

  • ROADtools, AADInternals y colegas llevan años operando en una brecha de visibilidad. Los defensores no captaban las jugadas.

  • AAD Graph está "obsoleto" pero sigue siendo consultable en la mayoría de los tenants. La versión interna de la API 1.61 sigue devolviendo datos que Microsoft Graph no devuelve datos.

  • Los campos ECS se generan tipados (event.action, event.outcome, http.request.method, source.ip, user.id, user_agent.original). Los extras del conjunto de datos siguen siendo consultables bajo azure.aadgraphactivitylogs.properties.*.

  • Cinco búsquedas capturan de forma fiable la actividad: agentes de usuario de herramientas, amplitud de endpoints, *-internal mal uso de la API, desajustes de FOCI en el cliente-ID y picos 4xx.

Una breve historia de la visibilidad de los defensores

Los defensores pasaron años en firmas, acceso condicional, asignaciones de roles y concesiones de consentimiento OAuth. Muy poco contenido cubre las APIs de directorio subyacentes que las herramientas adversarias realmente afectan. La razón es estructural: no existían registros accesibles para el cliente para esas APIs. Los registros de actividad de Microsoft Graph llegaron primero (vista previa octubre 2023, GA abril 2024). AzureADGraphActivityLogs finalmente apareció a principios de 2026.

Durante la mayor parte de la última década, la enumeración de gráficos AAD fue invisible para los SOCs, no porque la telemetría estuviera oculta, sino porque no existía. ROADtools, AADInternals, MSOLSpray, Microburst. Ninguno de ellos producía datos que cualquiera pudiera capturar, incluso con una configuración perfecta de registro.

Eso cambia el día en que AzureADGraphActivityLogs empiezan a aparecer en tu índice de platform-logs.

AAD Graph está "obsoleto" pero sigue muy vivo

Un repaso rápido. Azure AD Graph es la API REST heredada para los objetos de directorio Entra ID, alojada en https://graph.windows.net/{tenantId}/{objecttype} con versiones de API como 1.5, 1.6 y 1.61-interna. Microsoft lleva diciendo a todo el mundo que migre a Microsoft Graph desde 2019, y la fecha de retirada se retrasó varias veces.

La depreciación no desapareció. En 2026, AAD Graph aún puede responder solicitudes en entornos donde las rutas de acceso heredadas siguen disponibles o donde las aplicaciones no fueron bloqueadas explícitamente para su uso. Algunas razones por las que sigue siendo objetivo de los atacantes:

  • Las herramientas adversariales no se portaron. ROADrecon todavía lo usa para gather. AADInternals tiene docenas de cmdlets envolviéndolo.

  • Las versiones *-internal API devuelven más datos. 1.61-internal expone strongAuthenticationDetail en línea en el objeto de usuario durante una caminata normal por el directorio. El equivalente a Microsoft Graph está detrás de un endpoint /authentication/methods separado con filtro de UserAuthenticationMethod.Read.All. Esa asimetría es exactamente lo que explota la herramienta de enumeración masiva.

  • El bloqueo no es un solo interruptor de activación. El control de blockAzureADGraphAccess está por aplicación en application.authenticationBehaviors, así que bloquear a nivel de inquilino significa iterar cada registro de la app. La mayoría de los entornos no lo hicieron porque algunas automatizaciones heredadas aún dependen de la API. La aplicación gradual de la jubilación de Microsoft realiza el trabajo según el calendario de Microsoft, no el del defensor.

  • No existía la visibilidad, por lo que los red-teamers y adversarios podían presionar los endpoints de la API para obtener información relevante.

El tráfico legítimo de AAD Graph está dominado por un puñado de usuarios de Microsoft de primera mano. En nuestro tenant de prueba, el pedido, por volumen, era Microsoft.OData.Client, Microsoft Azure Graph Client Library, una cola de UA vacía de AppIds de primera parte, Microsoft ADO.NET Data Services, y el portal Azure (Chrome UAs contra el ID de la app del portal). Cualquier cosa fuera de ese conjunto reconocible es o bien herramientas internas o actividad no autorizada. Eso lo convierte en un conjunto de datos estable para cazar y detectar amenazas. Si lo estás capturando.

Configuración de la tubería de ingestión

Si ya estás ejecutando la integración de Elastic Azure con ajustes de diagnóstico reenviando a un hub de eventos, echa un vistazo a esta sección. Probablemente solo necesites activar una categoría extra de registro. Desde cero, es un recorrido de unos 20 minutos.

Paso 1: Una pila para recibir los registros

Cualquier despliegue de Elastic funciona. Un ensayo de Nube Elástica es la opción de menor fricción para prototipar. Otra opción es el Proyecto Contenedor Elástico para empezar. La integración con Azure ya gestiona AzureADGraphActivityLogs una vez habilitada.

Paso 2: Agregar la integración con Azure

En Kibana, las integraciones > Azure Logs > agregar Azure Logs. Introduce tu cadena de conexión del Event Hub, el nombre del Event Hub y una cuenta de Storage para el desplazamiento de puntos de control, todo en un event hub con la misma subscripción que tu tenant.

Activa específicamente el flujo de datos de Azure logs v2. Ese es el punto de entrada para los registros de actividad de grafos AAD. El router de eventos empareja category == "AzureADGraphActivityLogs" y redirige documentos a logs-azure.aadgraphactivitylogs-*, donde la canalización de datos aplica la extracción completa de ECS.

También dividimos los Logs de Actividad de Grafos de Azure AD en un elemento de integración propio, para que puedas buscar "Logs de Actividad de Grafos de Azure AD" e instalarlos directamente mediante la plantilla de política.

Paso 3: Activar la configuración de diagnóstico en Entra ID

Este es el paso que la mayoría de los defensores pasan por alto. AzureADGraphActivityLogs como categoría diagnostic-settings es más reciente. Aunque la configuración de diagnóstico de tu ID de Entra lleva un tiempo configurada, la nueva categoría necesita un nuevo tick. De lo contrario, los datos viven y mueren dentro del límite de los tenants de Microsoft.

En el portal de Azure:

  1. Entra ID > Monitorización > Configuración de diagnóstico > + Agregar configuración de diagnóstico.
  2. Dilo.
  3. En Logs, comprueba AzureADGraphActivityLogs. Ya que estás, MicrosoftGraphActivityLogs, LogInLogs y AuditLogs merecen la pena activarlos si no lo están ya. La integración se encarga de todos.
  4. En detalles de destino, haz streaming a un hub de eventos (el mismo que aparece en el paso 2).
  5. Almacenar.

Paso 4: Verificar que los datos fluyen

En unos minutos, deberías empezar a ver eventos. La comprobación de cordura más rápida:

FROM logs-azure.aadgraphactivitylogs-*
| LIMIT 20

Si los documentos aparecen con campos de event.action http.request.methody zure.aadgraphactivitylogs.properties.* poblados, estás bien. Si no aparece nada, los sospechosos habituales son una licencia olvidada del hub de eventos, un error tipográfico en la cadena de conexión o que la categoría AAD Graph simplemente no esté marcada.

Para forzar algunos eventos, inicia sesión en el portal de Azure y haz clic en Usuarios o Aplicaciones. El portal sigue llamando internamente a AAD Graph para algunos detalles de objetos. Si eso no genera nada, este bucle de rotación hará:

TOKEN=$(az account get-access-token --resource https://graph.windows.net --query accessToken -o tsv)
TID=$(az account show --query tenantId -o tsv)
for obj in users groups servicePrincipals applications tenantDetails; do
  curl -sS -o /dev/null -H "Authorization: Bearer $TOKEN" \
    "https://graph.windows.net/$TID/$obj?api-version=1.6&\$top=5"
done

Forma del campo

Una vez que los datos fluyen, las propiedades aparecen como campos de nivel superior tipados. Los que importan para la caza:

  • ECS, poblado directamente: event.action (un verbo semántico derivado de método + colección, por ejemplo, users-read, batch-execute), event.outcome, event.duration, http.request.method, http.response.status_code, source.ip, y source.geo.*, user.id, user_agent.original (más subcampos analizados), url.path, azure.tenant_id, cloud.service.name = "Azure AD Graph".
  • Específico de conjunto de datos bajo zure.aadgraphactivitylogs.properties.*: app_id,, app_id, api_version, actor_type, roles, scopes, wids, identity_provider, client_auth_method, sign_in_activity_id, token_issued_at.
  • related.user obtiene tanto user.id como properties.app_id, así que los pivotes en la dimensión OAuth del cliente trabajan junto con el pivote del usuario.

El JSON en bruto se mantiene en el evento original para la repetición forense. No deberías necesitar buscar para cazar normalmente. Si lo haces, ES|El JSON_EXTRACT() de QL es la palanca.

Enumeración de gráficos AAD con ROADrecon

Para saber qué cazar, necesitas saber cómo es la actividad. Los dos kits de herramientas que se muestran a continuación son las fuentes más comunes de tráfico de AAD Graph en los flujos de trabajo de red team y de investigación en seguridad. Presenté ambos contra nuestro inquilino de pruebas.

Nota: No asumo ninguna responsabilidad por el mal uso de este código. Ejecuta estas herramientas solo contra inquilinos que poseas o que tengas autorización explícita por escrito para probar.

ROADrecon: Prueba de enumeración masiva

ROADrecon es el módulo de recopilación de datos de ROADtools, el marco de investigación Entra ID de Dirk-jan Mollema. Muy recomendable si no lo usaste. recoge cada tipo de objeto interesante en el directorio (usuarios, grupos, principales de servicio, aplicaciones, dispositivos, roles de directorio, asignaciones de roles, asignaciones de roles elegibles, licencias OAuth2, unidades administrativas) y escribe el resultado en SQLite.

La configuración es el flujo de trabajo estándar:

pip install roadrecon
roadrecon auth --device-code -c 04b07795-8ddb-461a-bbee-02f9e1bf7b46 -r https://graph.windows.net

El flujo de código del dispositivo te da una URL y un código. Usamos la CLI de Microsoft Azure como predeterminada (1b730954-1685-4b74-9bfd-dac224a7b894 - AAD PowerShell), que devolvía los 403 en nuestro tenant. Luego de iniciar sesión:

roadrecon gather

Haciendo roadrecon se recoge con el token resultante completado limpiamente. Desde la perspectiva del inquilino, la emisión produjo poco más de ~2.000 llamadas y registros AAD Graph en aproximadamente 1 minuto. Enumeración masiva en todos los tipos de objetos que conoce ROADrecon.

A partir de esto, podemos formar algunas detecciones iniciales para empezar a señalar estas anomalías.

Campos clave para la detección de amenazas en grafos AAD

Antes de las cacerías, aquí tienes algunos campos de inicio estables para detectar anomalías.

CampoDescripciónLo que puedes encontrar
event.actionVerbo semántico (método HTTP + colección, por ejemplo, 'users-read, batch-execute')Un filtro barato para aislar la actividad del grafo AAD por intención
http.request.methodOBTENER, PUBLICAR, PARCHEAR, BORRARLecturas (reconocimiento) vs escrituras (modificación, inyección de credenciales, persistencia)
http.response.status_codeEstado HTTP devueltoReconocimiento exitoso vs bloqueado; Las ráfagas de 4xx indican sondeo de licencias o fuerza bruta
user.idLlamar al ID de objeto de directorio del usuarioAtribución de identidad; pivotar hacia la otra actividad de ese usuario en LogInLogs / AuditLogs
user_agent.originalCadena completa de UA del llamadorYa sea que el llamador sea una biblioteca de Microsoft de primera parte, una herramienta de desarrollo (curl, Python aiohttp) o herramientas ofensivas conocidas
url.pathRuta de recursos (/usuarios, /políticas, /serviciosPrincipales, ...)Qué tipos de objetos de directorio se están tocando; La amplitud a través de caminos distintos indica enumeración masiva
azure.aadgraphactivitylogs.properties.app_idID de cliente OAuth que emitió el tokenYa sea que el tráfico provenga de un cliente legítimo de primera mano o de una vía de abuso tipo FOCI-swap
azure.aadgraphactivitylogs.properties.api_version1.5, 1.6, 1.61-interno, etc.Si el llamante está pidiendo campos solo internos (strongAuthenticationDetail, conjunto completo de CAP) a los que apunta específicamente la herramienta adversarial
azure.aadgraphactivitylogs.properties.actor_typeUsuario, Aplicación, ServicePrincipalLlamador humano vs principal de servicio / flujo solo de aplicación
azure.aadgraphactivitylogs.properties.roles / widsNombres de visualización de roles de directorio y GUIDs de plantillas de rol conocidas que posee el llamanteSi se está ejerciendo un rol privilegiado (Administrador Global, Administrador de Aplicaciones, etc.) en el momento de la llamada
azure.aadgraphactivitylogs.properties.scopesOAuth scope en el token que llamaQué licencias de directorio concede realmente el token al llamante
azure.aadgraphactivitylogs.properties.client_auth_methodCómo se autenticó el cliente (PRT, certificado, secreto, ...)Huellas dactilares para abuso de PRT, explotación de dispositivos por PRT o uso robado de credenciales de clientes
azure.aadgraphactivitylogs.properties.sign_in_activity_idID de correlación con el inicio de sesión de origenPivotar desde una llamada a un grafo AAD al evento de inicio de sesión que produjo el token de llamada
azure.aadgraphactivitylogs.properties.token_issued_atMarca de tiempo en la que se acuñó la fichaAnálisis de la antigüedad de los tokens; Las llamadas que circulan con un token emitido hace días pueden indicar abuso de token obsoleto o de token de actualización

Detección y prevención

Detección

El requisito previo para cualquier detección de grafos AAD es tener los logs en primer lugar. La categoría de diagnóstico AzureADGraphActivityLogs debe estar habilitada en Entra ID y enrutarla a un destino que puedas consultar (al menos un espacio de trabajo de Log Analytics, idealmente también reenviado a un hub de eventos para la ingestión de Elastic, como se describe en la sección de configuración anterior). Hasta que eso se haga, las llamadas descritas en esta publicación ocurren completamente fuera de cámara, y ninguna de las búsquedas de abajo se disparará.

Si ahora mismo no puedes hacer la ingesta en Elastic, activa la configuración de diagnóstico de todas formas y envía a Log Analytics. Los equivalentes KQL de las búsquedas a continuación son sencillos, y los datos se acumulan con retención incluso sin procesamiento adicional.

Prevención

No hay un único interruptor AAD Graph para todo el inquilino en el portal. El control real a la capa de aplicación es:

  • application.authenticationBehaviors.blockAzureADGraphAccess

Un Booleano por aplicación en el recurso de la aplicación (Microsoft Graph beta, documentación). Bloquear a gran escala significa revisar cada registro de la app y cambiarla manualmente o programáticamente. La propia retirada gradual de Microsoft lo está haciendo en su calendario, sea cual sea la inversión. Cuanto más avanza, menos superficie hay que defender.

Mientras tanto, los defensores pueden mover por los mismos ejes:

  • Audita aplicaciones en tu tenant que aún tengan tokens para graph.windows.net. Ponle blockAzureADGraphAccess = true en los que no lo necesiten. Cualquier cosa que siga dependiendo del AAD Graph se daña bruscamente, lo que hace que la automatización heredada que no sabías que tenías.

  • Aplica acceso condicional con Azure AD Graph como recurso objetivo. El principal de servicio Azure AD Graph (00000002-0000-0000-c000-000000000000) no aparece en el selector estándar de aplicaciones de CA, pero está cubierto por las políticas de Todos los recursos y es segmentable individualmente mediante el enfoque personalizado de filtro de atributos de seguridad. El cambio de aplicación de Microsoft del 2026 de marzo hace esto más práctico: los ámbitos de bajo privilegio (User.Read, People.Read, etc.) que antes se excluían automáticamente de la aplicación de CA ahora se tratan como acceso a AAD Graph, por lo que todas las políticas de recursos realmente los bloquean. CA evalúa en la emisión de tokens, así que los tokens ya válidos siguen funcionando hasta el vencimiento.

  • Aplica CA a los clientes FOCI en los que se apoya la herramienta adversaria (Microsoft Teams, Microsoft Office, OneDrive, Azure PowerShell, etc.). Exigir dispositivos gestionados y compatibles. La ruta de intercambio colapsa si el cliente subyacente no puede iniciar sesión.

  • Para los llamantes principales de servicio, Workload Identities Premium agrega CA con alcance a los principales de servicio. Las condiciones están limitadas a ubicación, riesgo de protección de identidad y contexto de autenticación; el único control de subvenciones es Bloquear. Útil para colapsar caminos externos y de contexto riesgoso, no para asignar un SP a aplicaciones en la nube específicas como hace la CA de usuario.

  • Desactiva el flujo de código del dispositivo para los usuarios que no lo necesiten. roadrecon auth --device-code es el camino de menor resistencia hacia toda la tubería anterior y es extremadamente común en el phishing OAuth.

Detección de comportamientos

Enviamos reglas de detección que cubren las formas de reconocimiento de AAD Graph documentadas arriba. Cada uno reside en el repositorio de reglas de detección Elastic y se ejecuta de forma nativa contra el flujo de datos analizado logs-azure.aadgraphactivitylogs-* .

Azure AD Graph Access with Suspicious User-Agent - KQL match rule. Se activa cuando AAD Graph recibe tráfico de cadenas de agente de usuario que coinciden con familias de herramientas ofensivas (Python, aiohttp, curl, Go-http-client, axios, AzureHound, BloodHound, AADIntenals, etc.). Una señal de base estable porque ningún componente de Microsoft de primera mano se identifica como alguno de estos, mientras que las herramientas predeterminadas sí. 

Azure AD Graph High 4xx Error Ratio del usuario - ES|Agregación QL. Se activa cuando un solo llamante produce una proporción inusualmente alta de respuestas 4xx frente a la gráfica AAD en una ventana corta. El uso de tokens de reconocimiento y fuerza bruta deja una cola de 403 y 404 mientras las herramientas recorren endpoints para los que no tienen licencia, piden IDs de objetos que no tienen o usan un ID de cliente no autorizado para AAD Graph. 

Acceso a grafos de Azure AD con cliente y usuario inusuales - regla KQL new_terms, severidad media. Se activa cuando aparece un par (cliente OAuth llamando, usuario iniciado sesión) en el Grafo AAD por primera vez en los 14 días anteriores. Detecta intercambios FOCI, tokens de actualización phishing canjeados por clientes que el usuario normalmente no usa y tokens robados usados por clientes desconocidos. Ignora aplicaciones de primera mano conocidas que se observaban comúnmente interactuando con Azure AD y que son propiedad backend de Microsoft.

Acceso a grafos de Azure AD con usuario inusual y ASN - regla de coincidencia KQL. Excluye las organizaciones comunes de Microsoft / AWS / GCP / Akamai / Cloudflare y señala el tráfico AAD Graph que se origina fuera de ese conjunto. Las herramientas adversariales suelen depender de ISP residenciales, proveedores VPS o redes de anonimización que producen una distribución ASN diferente a la de los llamantes legítimos de primera parte. Ajustable por inquilino ajustando la lista de ASN excluida.

Azure AD Graph Potential Enumeration (ROADrecon) - ES|Agregación QL, alta severidad. Requiere tanto un agente de usuario aiohttp como una ráfaga de 500+ solicitudes de grafo AAD desde una sola identidad. El comando gather de ROADrecon usa aiohttp por defecto y recorre todos los tipos de objetos de directorio, así que la combinación es esencialmente una huella digital de herramienta. Mayor severidad que la regla genérica de UA no Microsoft porque el requisito adicional de ráfaga elimina la clase de falso positivo desarrollador-prototipo.

Entra ID OAuth Device Code Sign-in to Azure AD Graph Enumeration - secuencia EQL, alta severidad. Se une a un inicio de sesión exitoso por código de dispositivo a la audiencia heredada de AAD Graph (00000002-0000-0000-c000-000000000000) en un dispositivo no gestionado, con enumeración de directorios contra graph.windows.net por el mismo usuario en un plazo de cinco minutos. El phishing por código de dispositivo consigue un token OAuth sin tocar la contraseña o MFA del usuario, por lo que las lecturas inmediatas de Graph de usuarios, responsables de servicio, aplicaciones, asignaciones de roles, políticas o detalles de inquilino bajo ese token son la identidad comprometida que está siendo controlada por el atacante. La secuencia cruzada de flujo de datos elimina la clase de falso positivo de un solo evento que llevan las otras reglas del grafo AAD.

Visibilidad del gráfico AAD: qué viene después

Durante la mayor parte de la última década, la actividad de los grafos de AAD fue el equivalente telemétrico de la materia oscura. Sabíamos que estaba ahí porque las herramientas adversarias seguían señalándolo, pero los clientes no tenían ningún flujo de diagnóstico al que suscribir ni registros que consultar. Microsoft Graph Activity Logs cerró la mitad de la diferencia cuando pasaron a ser GA en abril de 2024. AzureADGraphActivityLogs finalmente cerró la otra mitad a principios de 2026.

Ahora que existen los datos, el resto depende de nosotros. Agrega la nueva configuración de diagnóstico, apúntala a un hub de eventos, insiértela en tu pila, activa las detecciones (o crea la tuya propia) y ponte a monitorizar.

Las detecciones de esta publicación son un punto de partida. Una vez que tienes tráfico AAD Graph llegando a tu pila y una referencia de cómo es la normal en tu tenant, los mismos patrones se generalizan. Los legítimos usuarios de Microsoft de primera mano forman un grupo pequeño y reconocible, y cualquier cosa fuera de ese conjunto merece un análisis más detallado.

La actividad siempre estuvo ahí. La visibilidad por fin también.

¡Feliz búsqueda!

Referencias

A lo largo de la investigación anterior se hizo referencia a lo siguiente:

Acerca de Elastic Security Labs

Elastic Security Labs es la rama de inteligencia de amenazas de Elastic Security dedicada a generar un cambio positivo en el panorama de amenazas. Elastic Security Labs ofrece investigaciones públicas sobre amenazas emergentes con un análisis de objetivos estratégicos, operativos y tácticos de adversarios, para luego integrar esa investigación con las capacidades integradas de detección y respuesta de Elastic Security. Sigue a Elastic Security Labs en Twitter @elasticseclabs y consulta nuestra investigación en www.elastic.co/security-labs/.