Problema
En entornos con Azure AD y Intune, la migración de MFA basada en códigos o notificaciones a Passkeys se promociona como una defensa contra phishing y robo de credenciales. Sin embargo, varios equipos reportan compromisos que siguen el mismo patrón que los ataques de session token theft (por ejemplo, EvilGinx). Un atacante logra iniciar sesión con una cuenta que tiene una política de Conditional Access (CA) que exige Passkey, pero la autenticación se completa de todos modos, a veces desde ubicaciones geográficas distintas y en pocos segundos. El síntoma típico es:
- Registro de un interrupted authentication (token robado) seguido de un successful sign‑in.
- La política de CA que debería bloquear accesos sospechosos no se dispara.
- Dispositivos móviles (iPhone, Outlook) aparecen como nuevos clientes autorizados sin requerir Passkey.
El problema no es exclusivo de un caso; es una combinación de debilidades en la cadena de confianza de Passkeys, configuraciones de CA incompletas y vectores de ataque que siguen usando tokens de sesión válidos.
Causa
1. Reutilización de tokens de sesión válidos
Los Passkeys solo protegen la fase de credential presentation. Si un atacante ya posee un access token o refresh token válido (obtenido mediante EvilGinx, malware en el navegador o extracción de cookies), puede usarlo para obtener un nuevo token de acceso sin volver a presentar la Passkey. Azure AD no vuelve a validar la Passkey mientras el token siga dentro de su ventana de validez.
2. Políticas de Conditional Access mal definidas
- Condiciones de ubicación: si la política usa rangos IP amplios o permite “trusted locations” que incluyen VPNs, los inicios de sesión desde diferentes países pueden pasar desapercibidos.
- Sign‑in risk: depende de la evaluación de riesgo de Microsoft Defender for Identity. Si el riesgo no se eleva (por ejemplo, porque el token fue emitido en un contexto “legítimo”), la política no se dispara.
- Exclusiones de cliente: a menudo se excluyen “legacy authentication” o “mobile apps” sin revisar que esas excepciones también omiten la exigencia de Passkey.
3. Registro de dispositivos móviles sin control de enrolamiento
Intune puede registrar automáticamente un dispositivo iOS cuando se instala Outlook o la app de Mail, creando un device object en Azure AD. Si la política de CA solo exige Passkey para “new sign‑ins” y no para “device registration”, el atacante puede añadir el dispositivo usando el token robado y luego autenticarse sin Passkey.
4. Falta de revocación de tokens comprometidos
Una vez detectado un token sospechoso, la mayoría de los equipos no revocan los refresh tokens existentes. Azure AD mantiene la validez del token hasta su expiración (por defecto 90 días), lo que permite que el atacante siga operando.
5. Configuración de Passkey sin “re‑authentication”
Algunas organizaciones habilitan Passkey solo en la primera autenticación y confían en la sesión prolongada. Si la política no fuerza re‑authentication después de un tiempo o de un cambio de IP, la sesión robada sigue siendo válida.
Solución
1. Reducir la vida útil de los tokens
Ajusta la política de Refresh token lifetime a un valor bajo (por ejemplo, 7 días) y habilita continuous access evaluation (CAE) para que Azure AD invalide tokens cuando cambie el contexto de riesgo.
az ad policy update --id <policy-id> --refresh-token-max-lifetime 7
2. Refuerza las condiciones de Conditional Access
- Ubicación: usa rangos IP estrictos y desactiva “trusted locations” para usuarios críticos.
- Riesgo de inicio de sesión: eleva el umbral a “high” y combina con sign‑in risk + device risk.
- Exclusiones: elimina excepciones de “mobile apps” y “legacy authentication” a menos que sea absolutamente necesario.
Ejemplo de política (JSON) que exige Passkey y re‑authentication cuando cambie la IP:
{
"grantControls": {
"operator": "OR",
"builtInControls": ["requirePasskey"]
},
"sessionControls": {
"signInFrequency": {
"value": 1,
"type": "days"
}
},
"conditions": {
"clientAppTypes": ["browser", "mobileAppsAndDesktopClients"],
"locations": {
"include": ["All"],
"exclude": ["Trusted"]
}
}
}
3. Obliga a re‑authentication con Passkey en cada nuevo dispositivo
Configura device enrollment restrictions para que cualquier registro de dispositivo requiera una Passkey. En Intune, habilita Require Multi‑Factor authentication to enroll devices y selecciona Passkey como método.
4. Implementa detección y revocación automática de tokens sospechosos
Utiliza Azure AD Identity Protection para crear una alerta cuando se detecte un sign‑in from a new location seguido de un successful sign‑in en menos de 5 minutos. Con una Logic App o Power Automate, revoca automáticamente los tokens del usuario:
az ad user sign-in revoke --id user@contoso.com
5. Monitorea la cadena de confianza de Passkeys
- Revisa los authentication methods de cada usuario (
Get-MgUserAuthenticationMethoden PowerShell) para confirmar que solo haya un Passkey registrado. - Desactiva Passkeys antiguos que no se usen y obliga a la rotación cada 90 días.
Get-MgUserAuthenticationMethod -UserId user@contoso.com | Where-Object {$_.OdataType -eq "#microsoft.graph.passwordAuthenticationMethod"} | Remove-MgUserAuthenticationMethod
6. Audita los logs de Azure AD
Busca patrones de interrupted authentication seguidos de success en menos de 10 minutos. Usa Kusto Query Language (KQL) en Log Analytics:
SigninLogs
| where ResultType == "0" and AuthenticationRequirement == "Passkey"
| summarize count() by UserPrincipalName, IPAddress, bin(TimeGenerated, 5m)
| where count_ > 1
Cuándo aplicar esta solución
- Síntomas: alertas de token theft, sesiones interrumpidas, accesos desde ubicaciones distintas en corto intervalo, dispositivos móviles inesperados en Azure AD.
- Entorno: organizaciones que usan Azure AD Conditional Access, Intune y Passkeys como factor principal de MFA.
- No aplica: entornos sin Azure AD (on‑prem AD puro) o donde la política de MFA no incluye Passkeys. En esos casos, la solución se reduce a reforzar MFA tradicional y revocar tokens.
Código
# Reduce refresh token lifetime a 7 días
az ad policy update --id <policy-id> --refresh-token-max-lifetime 7
# Revoca todos los tokens de un usuario comprometido
az ad user sign-in revoke --id user@contoso.com
# PowerShell: elimina métodos de autenticación obsoletos
Get-MgUserAuthenticationMethod -UserId user@contoso.com |
Where-Object {$_.OdataType -eq "#microsoft.graph.passwordAuthenticationMethod"} |
Remove-MgUserAuthenticationMethod
Verificación
- Prueba de expiración: inicia sesión, captura el refresh token y verifica que caduca después de 7 días usando
az account get-access-token. - Política de CA: intenta iniciar sesión desde una IP no incluida en la lista de “trusted locations”. Debería solicitar Passkey nuevamente.
- Registro de dispositivo: registra un iPhone nuevo sin Passkey. La política debe bloquear la inscripción y registrar un evento en SigninLogs.
- Detección de token theft: genera un inicio de sesión interrumpido con EvilGinx (prueba controlada) y confirma que la alerta de Logic App revoca los tokens.
Notas adicionales
- Sincronización de tiempo: los Passkeys dependen de la hora del dispositivo. Un reloj desincronizado puede causar fallos de validación que, paradójicamente, facilitan ataques de replay.
- Backup de Passkeys: si se permite la exportación de Passkeys a la nube, asegúrate de que el almacenamiento esté protegido con Azure Key Vault y políticas de acceso estrictas.
- Educación del usuario: muchos incidentes se reducen cuando los usuarios no aceptan notificaciones de “login approved” en dispositivos no reconocidos. Refuerza la cultura de “solo aprobar en dispositivos propios”.
- EvilGinx y similares: estos frameworks pueden capturar cookies de sesión incluso en navegadores que soportan Passkeys. La mitigación pasa por limitar la validez de la cookie y usar SameSite=Strict en la configuración de Azure AD App Registrations.
Con estos ajustes, la combinación de Passkeys, Conditional Access y una gestión activa de tokens reduce drásticamente la superficie de ataque y evita que un robo de sesión se convierta en un compromiso total.