☁️Entra IDApplicationsPermissionsMonitoring

Permisos Graph API Peligrosos de App Registration en Entra: Detección y Remediación

Directory.ReadWrite.All, Mail.ReadWrite, Files.ReadWrite.All y RoleManagement.ReadWrite.Directory pueden convertir una credencial de aplicación filtrada en control total de Global Administrator. Así funciona la escalada, cómo detectar las concesiones y cómo remediarlas.

Younes AZABARPor Younes AZABAR11 min de lectura
Permisos Graph API Peligrosos de App Registration en Entra: Detección y Remediación

Los permisos Graph API peligrosos de App Registration en Entra convierten un simple clic de consentimiento de administrador en una credencial permanente y válida en todo el tenant. Directory.ReadWrite.All, Mail.ReadWrite, Files.ReadWrite.All y RoleManagement.ReadWrite.Directory son permisos de aplicación (app-only) — concesiones que permiten a un service principal actuar en todo un tenant de Microsoft 365 sin usuario conectado y sin delimitación por objeto. Esta guía detalla lo que realmente permite cada permiso, una cadena de ataque documentada que los encadena hasta obtener el control total de Global Administrator, y cómo detectar y remediar estas concesiones.

Permisos Graph API Peligrosos de App Registration en Entra Explicados

Los cuatro son permisos de aplicación, también llamados permisos app-only. La propia documentación de Graph de Microsoft lo deja claro: los permisos de aplicación «funcionan en el escenario de acceso app-only, sin un usuario conectado presente», y la aplicación «puede acceder a cualquier dato asociado con el permiso». Un permiso delegado está limitado por lo que el usuario conectado ya puede ver; un permiso de aplicación no está limitado por nadie.

Los cuatro permisos requieren consentimiento de administrador, y Microsoft restringe quién puede concederlos a los roles Privileged Role Administrator y Global Administrator. Ese único clic de consentimiento — a menudo dado una sola vez, durante el onboarding, por quien estuviera presente en ese momento — es lo que convierte un App Registration en una concesión de acceso permanente, válida en todo el tenant, que nadie vuelve a revisar.

PermisoTipoLo que realmente permite (descripción de Microsoft)
Directory.ReadWrite.AllAplicaciónLeer y escribir datos de directorio — usuarios, grupos y más — sin usuario conectado. Microsoft clasifica este permiso en segundo lugar en privilegio global entre los permisos de Entra ID, justo detrás del permiso delegado más privilegiado.
Mail.ReadWriteAplicaciónCrear, leer, modificar y eliminar correo en todos los buzones del tenant, sin usuario conectado.
Files.ReadWrite.AllAplicaciónLeer, crear, modificar y eliminar todos los archivos de todas las colecciones de sitios, sin usuario conectado.
RoleManagement.ReadWrite.DirectoryAplicaciónLeer y escribir todos los datos de gestión de roles del directorio — incluida la activación de asignaciones de roles elegibles y la gestión de asignaciones de roles de Entra — sin usuario conectado.

Fuente: referencia de permisos de Microsoft Graph.

⚠️

⚠️ Advertencia: no son permisos oscuros que un atacante deba descubrir — son entradas estándar del selector de permisos de Graph, concedidas mediante el mismo cuadro de diálogo de consentimiento de administrador que cualquier otro. El peligro reside enteramente en el radio de impacto, no en el mecanismo.

Cómo funciona

Un permiso de aplicación se asocia a un service principal, la identidad local al tenant de un App Registration. Una vez concedido, el service principal se autentica con su propia credencial — un client secret o un certificado — mediante el flujo OAuth 2.0 de client credentials. El token de acceso resultante lleva el permiso en su reclamación (claim) roles, y Microsoft Graph aplica el acceso basándose únicamente en esa reclamación. No hay contexto de usuario al que recurrir, ni límite de consentimiento por recurso: una aplicación con Files.ReadWrite.All puede acceder a un archivo que nunca se le ha compartido, en un sitio con el que no tiene ninguna otra relación.

RoleManagement.ReadWrite.Directory pertenece a una categoría aún más reducida y peligrosa. La propia documentación de permisos de Microsoft señala una clase de «permisos que permiten conceder autorización» — permisos que dejan que una aplicación reparta privilegios adicionales a sí misma, a otras aplicaciones o a cualquier usuario — como algo que requiere especial cautela (referencia de permisos de Microsoft Graph). RoleManagement.ReadWrite.Directory es exactamente ese tipo de permiso para los roles de directorio de Entra: una aplicación que lo posee puede asignar cualquier rol integrado de Entra, incluido Global Administrator, a cualquier principal de seguridad — incluida ella misma.

La cadena de ataque: de una credencial filtrada a Global Administrator

Esto no es una composición teórica de dos permisos peligrosos — es una técnica documentada. La investigación de Semperis (publicada como «EntraGoat Scenario 2») recorre exactamente esta ruta de escalada de principio a fin.

Paso 1 — Exposición de la credencial

Un atacante recupera un certificado codificado en base64 y una contraseña dejados en artefactos de un pipeline CI/CD.

Paso 2 — Atribución

La huella digital (thumbprint) del certificado se coteja con los metadatos keyCredentials.customKeyIdentifier de un service principal, lo que identifica a qué aplicación pertenece.

Paso 3 — Autenticación app-only

El atacante se autentica como el service principal mediante el flujo OAuth 2.0 de client credentials — sin solicitud de MFA, sin política de inicio de sesión de acceso condicional que satisfacer, porque no hay ningún inicio de sesión interactivo.

Paso 4 — Reconocimiento

El atacante inspecciona la reclamación roles del token y descubre que el service principal ya posee AppRoleAssignment.ReadWrite.All — un permiso que le permite asignar roles de aplicación de Graph a cualquier service principal, incluido él mismo.

Paso 5 — Autoescalada

Usando ese permiso, el atacante asigna RoleManagement.ReadWrite.Directory al mismo service principal.

Paso 6 — Asignación de rol

Con un token nuevo que lleva el nuevo permiso, el atacante añade el service principal al rol de directorio Global Administrator — una llamada tan simple como New-MgDirectoryRoleMemberByRef contra el ID de plantilla de rol conocido de Global Administrator (62e90394-69f5-4237-9190-012177145e10).

Paso 7 — Toma de control

Como los roles de directorio de Entra se evalúan dinámicamente en tiempo de ejecución en lugar de incorporarse en el token, el service principal es un Global Administrator con privilegios completos desde su siguiente llamada — a partir de ahí, el atacante puede restablecer la contraseña de cualquier administrador.

AppRoleAssignment.ReadWrite.All (ya poseída)
        |
        v
  asignar RoleManagement.ReadWrite.Directory a sí mismo
        |
        v
  añadir el service principal al rol Global Administrator
        |
        v
  restablecer la contraseña del admin objetivo -> toma de control total del tenant

🚨 Peligro: el paso 4 es lo que más pasan por alto los defensores. El resultado peligroso aquí no es un único permiso con exceso de privilegios — es la combinación. AppRoleAssignment.ReadWrite.All por sí solo permite a una aplicación conceder permisos de Graph a service principals; RoleManagement.ReadWrite.Directory por sí solo permite a una aplicación gestionar roles de directorio. Ninguna revisión detecta el par, a menos que alguien busque específicamente permisos que permiten conceder autorización.

Detección

Concentre la detección en el momento en que se concede un permiso peligroso y en el momento en que se usa para tocar roles de directorio — ambos se registran por defecto en el log de auditoría de Microsoft Entra, sin necesidad de ningún complemento premium.

IndicadorActividad del log de auditoríaQué filtrarFuente
Aplicación a la que se concedió un permiso de aplicación peligrosoAdd app role assignment to service principalTarget(s) = Microsoft Graph, AppRole.Value en Directory.ReadWrite.All, Mail.ReadWrite, Files.ReadWrite.All, RoleManagement.ReadWrite.DirectoryLog de auditoría de Entra (Categoría: ApplicationManagement)
Service principal añadido a un rol de directorio privilegiadoAdd member to role, Add eligible member to role, o Add scoped member to roleTipo de principal = service principal, rol = Global Administrator u otro rol privilegiadoLog de auditoría de Entra
Un administrador aprobó el consentimientoConsent to applicationConsentContext.IsAdminConsent = trueLog de auditoría de Entra
Consentimiento de usuario final a un scope de riesgoConsent to applicationConsentContext.IsAdminConsent = false, la aplicación solicita un scope de alto riesgoLog de auditoría de Entra

Esta es la propia guía documentada de Microsoft — vea Operaciones de seguridad de Microsoft Entra para aplicaciones, que además incluye detecciones de Microsoft Sentinel ya preparadas para exactamente este patrón «app role with sensitive access» y para ServicePrincipalAssignedPrivilegedRole.

Establecer una línea base de las concesiones existentes

Para establecer una línea base de lo que ya está concedido, consulte directamente las asignaciones de roles de aplicación existentes en lugar de esperar al próximo evento de auditoría:

# Enumerate service principals holding any of the four dangerous permissions
$dangerousRoleIds = @(
    "19dbc75e-c2e2-444c-a770-ec69d8559fc7", # Directory.ReadWrite.All
    "e2a3a72e-5f79-4c64-b1b1-878b674786c9", # Mail.ReadWrite
    "75359482-378d-4052-8f01-80520e7db3cd", # Files.ReadWrite.All
    "9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8"  # RoleManagement.ReadWrite.Directory
)
$graphSp = Get-MgServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'"
Get-MgServicePrincipalAppRoleAssignedTo -ServicePrincipalId $graphSp.Id -All |
    Where-Object { $_.AppRoleId -in $dangerousRoleIds }
ℹ️

ℹ️ Nota: AppRoleAssignment.ReadWrite.All — el permiso que hizo posible el paso 5 de la cadena de ataque — merece auditarse por separado, independientemente de los cuatro permisos anteriores. Cualquier service principal que lo posea puede concederse a sí mismo cualquier otra cosa de esta tabla.

Vigile también los logs de actividad de Microsoft Graph en busca de un service principal que de repente empiece a llamar a /roleManagement/directory/roleAssignments o /servicePrincipals/{id}/appRoleAssignedTo — endpoints que una integración normal (sincronización de correo, de archivos, de directorio) no tiene ningún motivo para tocar.

Remediación

💡

💡 Consejo: ejecute hoy mismo la consulta de PowerShell anterior. Cualquier service principal que posea RoleManagement.ReadWrite.Directory y no sea una integración de PIM o gobernanza documentada y en uso activo debería revocarse de inmediato — este permiso prácticamente no tiene ningún uso legítimo fuera de las herramientas de gobernanza de identidades.

  1. Clasifique los cuatro permisos como de alto impacto. En Entra ID > Enterprise applications > Consent and permissions > Permission classifications, marque Directory.ReadWrite.All, Mail.ReadWrite, Files.ReadWrite.All y RoleManagement.ReadWrite.Directory como high impact para que los usuarios normales nunca puedan consentirlos, incluso si el consentimiento de usuario está habilitado por lo demás (Configurar cómo los usuarios consienten aplicaciones).
  2. Enrute todo lo demás a través del flujo de consentimiento de administrador. Habilite el flujo de consentimiento de administrador para que un usuario bloqueado pueda solicitar una revisión en lugar de que la solicitud desaparezca en silencio — pero combínelo con el paso 1, ya que este flujo solo importa si los usuarios no pueden simplemente autoconsentirse y evitarlo.
  3. Prefiera permisos más acotados. Mail.ReadWrite y Files.ReadWrite.All suelen tener un alcance excesivo para lo que la integración realmente hace — una política de acceso de aplicaciones puede restringir Mail.ReadWrite a buzones específicos en lugar de a todos los del tenant, y el consentimiento específico de recurso puede reducir el acceso a archivos por debajo de Files.ReadWrite.All.
  4. Trate la credencial como un secreto Tier 0. Cada uno de estos permisos es tan seguro como el certificado o client secret que lo protege — vea Rotación de Secretos de App Registration en Entra para saber qué aspecto tienen en la práctica los secretos «obsoletos» y «sobrecompartidos», y nunca deje uno en un artefacto de CI/CD como describe la investigación de Semperis.
  5. Restrinja incluso desde dónde puede autenticarse el service principal. El acceso condicional para identidades de carga de trabajo aplica políticas de ubicación y riesgo de inicio de sesión a las autenticaciones de service principals contra Microsoft Graph, y la evaluación continua de acceso para identidades de carga de trabajo revoca un token casi en tiempo real si la señal de riesgo cambia durante la sesión.
  6. Vuelva a ejecutar el informe de consentimientos concedidos a aplicaciones de forma periódica, no solo durante el onboarding — una auditoría de consentimientos otorgados saca a la luz permisos que nadie recuerda haber aprobado, y un permiso que estaba justificado hace dos reorganizaciones rara vez lo sigue estando.
  7. Incorpore las asignaciones de roles de service principals a su revisión de acceso privilegiado, junto con las asignaciones PIM humanas — un service principal en Global Administrator es exactamente tan peligroso como un Global Admin humano permanente, y CVE-2025-55241 recuerda cuánto alcance tiene ese único rol.

Cómo lo detecta EtcSec

La auditoría de Entra ID de EtcSec verifica exactamente esta exposición: APP_DANGEROUS_PERMISSION_DIR, APP_DANGEROUS_PERMISSION_MAIL, APP_DANGEROUS_PERMISSION_FILES y APP_DANGEROUS_PERMISSION_ROLE marcan cada uno un service principal que posee alguno de los cuatro permisos anteriores, y APP_CONSENT_GRANTED_TENANT_WIDE marca los consentimientos concedidos a todos los usuarios del tenant en lugar de a un grupo acotado.

ℹ️

ℹ️ Nota: EtcSec comprueba automáticamente esta vulnerabilidad en cada auditoría de Azure/Entra. Ejecute una auditoría gratuita para ver cuáles de sus App Registrations ya poseen alguno de estos permisos.

Explore las páginas de identidad que apoyan este tema