Loading
_ DESCIFRANDO CONEXIÓN SEGURA...

Unir inicios de sesión con cambios con join

5 tareas · 42 min · Principiante

Un cambio sospechoso casi nunca se entiende solo. Para saber si una persona que cambió un rol en el directorio entró de forma normal hay que cruzar el cambio (AuditLogs) con el inicio de sesión (SigninLogs), y para saber qué más hizo desde esa dirección hay que cruzar con AzureActivity. `join` une dos tablas por una clave. En la Clínica Veterinaria Mastranto, el 9 de marzo, un cambio de rol de madrugada lleva a un cruce con un inicio de sesión desde otro país. Aprendes qué clave elegir, por qué el tipo de join cambia el resultado y qué significa que una operación no tenga inicio de sesión. Todo es lectura del extracto, en UTC.

0 de 5 · 0%

Objetivo de la sala

Un cambio sospechoso casi nunca se entiende solo. Para saber si una persona que cambió un rol en el directorio entró de forma normal hay que cruzar el cambio (AuditLogs) con el inicio de sesión (SigninLogs), y para saber qué más hizo desde esa dirección hay que cruzar con AzureActivity. `join` une dos tablas por una clave. En la Clínica Veterinaria Mastranto, el 9 de marzo, un cambio de rol de madrugada lleva a un cruce con un inicio de sesión desde otro país. Aprendes qué clave elegir, por qué el tipo de join cambia el resultado y qué significa que una operación no tenga inicio de sesión. Todo es lectura del extracto, en UTC.

En AuditLogs, quién hizo el cambio está en InitiatedBy, una columna dynamic que guarda un objeto: {"user":{"userPrincipalName":"...","ipAddress":"..."}}. Para compararla con otra tabla hay que sacar los campos: InitiatedBy.user.userPrincipalName entra al objeto con puntos y tostring(...) lo convierte en texto, que es lo que join necesita para comparar. extend Actor = tostring(InitiatedBy.user.userPrincipalName) crea una columna con la cuenta.

Prueba la consulta que filtra OperationName == "Add member to role" (agregar a alguien a un rol) y deja la hora, la operación, la cuenta y la dirección. Es la mitad izquierda del cruce.

Responde para continuar

¿Desde qué dirección IP se hizo el cambio de membresía de rol del día?

Ver pista de ayuda

Escribe `AuditLogs | where OperationName == "Add member to role" | extend Actor = tostring(InitiatedBy.user.userPrincipalName), IP = tostring(InitiatedBy.user.ipAddress) | project TimeGenerated, OperationName, Actor, IP`.

join une las filas de dos tablas que comparten un valor, la clave. Se escribe join kind=inner (tabla2) on $left.ColumnaA == $right.ColumnaB, donde $left es la tabla que viene de la izquierda del join y $right la del paréntesis. Para unir por más de una columna se separan las condiciones con and.

Si no escribes kind=, KQL usa por defecto innerunique: antes de unir, deduplica la tabla izquierda por la clave, y solo queda una fila por cada valor distinto. Con kind=inner se conservan todas las filas que tienen pareja. Compara dos consultas que cuentan las operaciones hechas desde la dirección que inició sesión desde otro país. Sin kind=: AzureActivity | join (SigninLogs | where ResultType == "0" and Location != "CO" | project IPAddress, Location) on $left.CallerIpAddress == $right.IPAddress | count. Con kind=inner: la misma, escribiendo join kind=inner ( en lugar de join (.

Responde para continuar

Una consulta con join sin `kind=` devuelve una fila y la misma con `kind=inner` devuelve cuatro. ¿Qué explica la diferencia?

Ver pista de ayuda

Sin kind=, el sabor es innerunique: «inner con deduplicación de la tabla izquierda».

Unir solo por la cuenta trae todos los inicios de sesión de esa cuenta durante el día, no el que corresponde al cambio. En el extracto la cuenta tiene tres entradas correctas; unir por cuenta devuelve tres filas para un solo cambio y obliga a adivinar cuál era. Con la cuenta y la dirección como clave (on $left.Actor == $right.UserPrincipalName and $left.IP == $right.IPAddress) la unión señala la entrada que corresponde.

Una clave de unión demasiado floja produce filas de más que parecen evidencia y no lo son. Una clave demasiado estricta pierde las coincidencias. La lectura honesta dice con qué claves se unió y qué no prueba esa unión.

Responde para continuar

Al unir el cambio de rol con el inicio de sesión por cuenta y dirección, ¿qué código de país (Location) tiene esa entrada?

Ver pista de ayuda

Escribe `AuditLogs | where OperationName == "Add member to role" | extend Actor = tostring(InitiatedBy.user.userPrincipalName), IP = tostring(InitiatedBy.user.ipAddress) | join kind=inner (SigninLogs | where ResultType == "0" | project UserPrincipalName, IPAddress, SigninTime = TimeGenerated, Location) on $left.Actor == $right.UserPrincipalName and $left.IP == $right.IPAddress | project TimeGenerated, OperationName, Actor, IP, SigninTime, Location`.

kind=leftanti devuelve las filas de la tabla izquierda que NO tienen pareja en la derecha, y solo con las columnas de la izquierda. Aplicado a AzureActivity contra los inicios de sesión correctos, por dirección, muestra operaciones de gestión hechas desde direcciones sin ninguna entrada correcta registrada en SigninLogs.

Que una operación no tenga inicio de sesión en esa tabla no significa que sea ilegítima, y menos que sea un ataque. Antes de concluir hay que preguntarse qué puede explicarlo. Lee el resultado y fíjate en el nombre de la cuenta.

Responde para continuar

¿Qué cuenta aparece haciendo operaciones desde una dirección sin ningún inicio de sesión correcto en SigninLogs?

Ver pista de ayuda

Escribe `AzureActivity | join kind=leftanti (SigninLogs | where ResultType == "0") on $left.CallerIpAddress == $right.IPAddress | summarize Operaciones = count() by Caller, CallerIpAddress`.

La cuenta del resultado anterior es de servicio: hace copias programadas y no entra a una consola. SigninLogs recoge los inicios de sesión interactivos de personas; los inicios no interactivos y los de entidades de servicio se guardan en otras tablas de inicios de sesión del espacio. Por eso la ausencia en una tabla es una pregunta, no un hallazgo: falta mirar las otras tablas y comprobar con el responsable de la cuenta que esas copias son las esperadas.

Responde para continuar

Una operación de una cuenta de servicio no tiene inicio de sesión en SigninLogs. ¿Cuál es la lectura prudente?

Ver pista de ayuda

Una tabla sin la fila es una pregunta sobre dónde más buscar, no una conclusión.

Inicia sesión para registrar tus puntos y progreso en el ranking.

Whoami-Labs Pro

Whoami-Labs Pro utiliza cookies

Utilizamos cookies y almacenamiento local para el funcionamiento del sitio, seguridad de sesión y, si lo autorizas, analítica y marketing. Puedes aceptar, rechazar o personalizar. Política de Privacidad