Por Mauricio Payne, analista de seguridad de Bureau Veritas Cybersecurity
Comprometer la nube Azure a través de permisos API sensibles
Recientemente, investigadores de Cloudbrothers han encontrado una nueva e interesante forma de pasar de un entorno on-premise a un entorno Azure y obtener derechos de Global Admin. En este blog, le ofreceremos una demostración y explicación de este ataque. Además, se incluirán algunos pasos de mitigación para ayudarle a detectar y protegerse contra este ataque.
Demostración de la ruta de ataque
Los investigadores de Cloudbrothers descubrieron que un atacante que haya sido capaz de comprometer la cuenta AAD Sync utilizada por el servidor AD Connect puede escalar sus privilegios a administrador global explotando aplicaciones con permisos sensibles.
Esto es posible ya que la cuenta AAD Sync tiene los permisos 'microsoft.directory/applications/owners/update' y 'microsoft.directory/servicePrincipals/owners/update'. Lo que le permite actualizar los propietarios de las aplicaciones registradas.
Además, utilizando los permisos 'microsoft.directory/servicePrincipals/credentials/update ' esta cuenta podría añadir directamente credenciales a estas aplicaciones sin tener que añadirse primero a sí misma como propietaria.
Estas aplicaciones pueden entonces ser utilizadas para escalar privilegios si tienen los permisos correctos.
En este blog nos centraremos en dos de estos permisos sensibles ('RoleManagement.ReadWrite.Directory' y 'AppRoleAssignment.ReadWrite.All') y demostraremos la ruta de ataque que un atacante tendría que recorrer describiendo cada paso.
Visión general del ataque
Antes de empezar
Antes de empezar, es importante abordar algunas suposiciones que se hicieron para lograr este ataque.
- La primera es que se ha registrado una aplicación en Azure que contiene uno de los dos permisos sensibles mencionados anteriormente.
- La segunda suposición realizada es que se ha podido comprometer completamente el servidor que ejecuta AD Connect y se han podido volcar las credenciales de la cuenta AAD Sync. El volcado de las credenciales puede realizarse mediante varios métodos, por ejemplo utilizando el módulo PowerShell AADInternals. El uso de Get-AADIntSyncCredentials en el servidor de AD Connect devuelve las credenciales del usuario de AAD Sync:
El servidor de AD Connect devuelve las credenciales del usuario de AAD Sync
Una vez capturadas estas credenciales podemos pasar al ataque principal propiamente dicho. El primer paso es autenticarse en el inquilino como usuario de AAD Sync:
Autenticarse en el arrendatario como usuario de AAD Sync
Respuesta que contiene JWT
Equipados con este token JWT, ahora podemos realizar llamadas a la API Microsoft Graph y obtener una lista de todas las aplicaciones registradas en el Tenant. Este token JWT puede guardarse en una variable PowerShell que puede utilizarse como cabecera de autenticación:
$AuthHeader = @{Authorization = "Bearer <JWT>"}
De este modo, podremos realizar una solicitud al punto final beta/aplicaciones mediante PowerShell:
Invoke-RestMethod -Headers $AuthHeader -Uri "https://graph.microsoft.com/beta/applications/"
La siguiente imagen muestra la respuesta de la solicitud realizada al endpoint beta/applications que contiene todas las aplicaciones registradas.
Respuesta a la solicitud realizada al punto final beta/aplicaciones
Al examinar esta respuesta vemos mucha información relativa a las diferentes aplicaciones. Sin embargo, lo que nos importa en este ataque es el campo "appID". Estos Id deben guardarse en una lista ya que son necesarios para el siguiente paso del ataque. En este paso utilizaremos el appID para hacer una petición al Graph API y consultar qué principales de servicio pertenecen a esa aplicación.
A continuación podemos ver la respuesta de dicha solicitud que contiene el ID del service principal perteneciente a la aplicación con appID 8c3ffdc3-fe9d-47a2-9bbc-3bc49e486c43. Esta solicitud puede realizarse a través de PowerShell con el siguiente comando:
Invoke-RestMethod -Headers $AuthHeader -Uri "https://graph.microsoft.com/beta/servicePrincipals/?`$filter=(appid eq '<appID>')"
Respuesta con el ID del principal del servicio
Una vez que tenemos el ID de estos principales de servicio podemos buscar los permisos asignados a ellos. En concreto, estamos buscando un permiso con un appRoleID de "9e3f62cf-ca93-4989-b6ce- bf83c28f9fe8" que corresponde al rol RoleManagement .ReadWrite .Directory o el appRoleID de "06b708a9-e830-4db3-a914-8e69da51d44f" que corresponde al rol AppRoleAssignment.ReadWrite.All.
ROLEMANAGEMENT.READWRITE.DIRECTORY
El rol RoleManagement.ReadWrite. Directory otorga a la aplicación el permiso para concederse privilegios adicionales a sí misma, a otras aplicaciones o a cualquier usuario. Realizando la siguiente petición podemos obtener qué permisos tiene asignados el principal de servicio con id: "9e666f83-8520-4c65- a8e2-e929194839ea".
Invoke-RestMethod -Headers $AuthHeader -Uri "https://graph.microsoft.com/beta/servicePrincipals/<ServicePrincipalID>/appRoleAssignments"
En la imagen inferior podemos ver la respuesta a la petición realizada anteriormente. Observando la respuesta vemos el mencionado appRoleId, lo que hace que esta aplicación sea vulnerable a este ataque.
Respuesta que contiene appRoleID
Una vez que hayamos encontrado una aplicación que tenga establecido este rol, podemos añadir a nuestro usuario (en este caso el usuario de AAD Sync) como propietario de este servicio principal. En PowerShell la solicitud tendría el siguiente aspecto:
$Reference = @{ "@odata.id" = "https://graph.microsoft.com/beta/directoryObjects/" + <AAD Sync userID> } | ConvertTo-Json
Invoke-RestMethod -Method Post -Headers $AuthHeader -Uri "https://graph.microsoft.com/beta/servicePrincipals/<ServicePrincipalToTakeover>/owners/`$ref" - Body $Reference -ContentType "application/json" | Out-Null
La respuesta a esta solicitud tendría el siguiente aspecto
Respuesta al añadir un usuario como propietario
El siguiente paso consiste en añadir un nuevo secreto al principal del servicio que utilizaremos posteriormente para autenticarnos en el inquilino como esta aplicación vulnerable. Se realiza una solicitud POST a la Graph API que establece automáticamente una contraseña segura y la devuelve en el parámetro "secretText". Esto se hace con el siguiente comando PowerShell:
Invoke-RestMethod -Method Post -Headers $AuthHeader -Uri "https://graph.microsoft.com/beta/servicePrincipals/<ServicePrincipalToTakeover>/addPassword" -Body $Reference -ContentType "application/json"
Como puede verse a continuación, la API devuelve el textoSecreto:
Respuesta que contiene el nuevo secreto añadido
Utilizando el appID de la aplicación vulnerable como el "Client_Id" y el secreto recién añadido como el"Client_Secret", podemos autenticarnos en el tenant como este principal de servicio y recibir un nuevo token JWT.
Solicitud de API autenticándose como principal del servicio
APROLEASIGNACIÓN.LECTURAESCRITURA.TODO
El rol AppRoleAssignment.ReadWrite. All permite a la aplicación concederse privilegios adicionales a sí misma. Esto significa que podríamos conceder el rol RoleManagement.ReadWrite. Directory a la aplicación y obtener privilegios de administrador global. A continuación se puede ver una imagen en la que identificamos una aplicación vulnerable con este rol:
Una vez que hayamos identificado esta aplicación podemos añadirle un secreto que podemos utilizar para autenticarnos como la aplicación en el arrendatario Azure:
Como se ha visto anteriormente, la contraseña se devuelve como parámetro "secretText", que utilizaremos en combinación con el appID para autenticarnos en el tenant:
Esto devuelve un token JWT que cuando se descodifica como podemos ver sólo contiene el rol "AppRoleAssignment.ReadWrite.All":
Utilizando este token JWT como nuevo token de autorización podemos añadir el rol requerido a la aplicación. Para ello necesitamos conocer el appRoleID del rol que queremos añadir, el principalId, y el resourceId. La solicitud para añadir el rol RoleManagement.ReadWrite.Directory se puede realizar con los siguientes comandos PowerShell:
$params = @{
principalId = <servicePrincipalId>
resourceId = <resourceId>
appRoleId = "9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8"
} | ConvertTo-Json
Invoke-RestMethod -Method POST -Headers $AppAuthHeader -Uri "https://graph.microsoft.com/v1.0/servicePrincipals/ <servicePrincipalId>/appRoleAssignments" - Body $params -ContentType "application/json"
Respuesta a la adición de este papel
Ahora podemos autenticarnos como la aplicación una vez más utilizando la misma contraseña que habíamos añadido anteriormente. Al visualizar el token JWT recién generado podemos ver que nuestro nuevo rol se aplicó con éxito:
También se puede comprobar en el portal Azure visitando la aplicación:
AÑADIR USUARIO COMO ADMIN GLOBAL
El uso de este nuevo JWT nos permite realizar peticiones como principal del servicio. Como tiene el rol RoleManagement.ReadWrite.Directory nos permite asignar a un usuario el rol Global Admin. En PowerShell esto se hace actualizando la variable AppAuthHeader al nuevo token JWT y ejecutando los siguientes comandos:
$Reference = @{ "@odata.id" = "https://graph.microsoft.com/beta/directoryObjects/" + <UserIDToMakeGlobalAdmin>} | ConvertTo-Json
Invoke-RestMethod -Method Post -Headers $AppAuthHeader -Uri "https://graph.microsoft.com/beta/directoryRoles/roleTemplateId=62e90394-69f5-4237-9190- 012177145e10/members/`$ref" -Body $Reference -ContentType "application/json"
Mirando en el portal Azure podemos ver que nuestro usuario es ahora parte de los Administradores Globales:
MITIGACIONES
Cuando se trata de formas de mitigar este ataque no hay una respuesta clara. Sin embargo, hay ciertas acciones que se pueden tomar para ayudar a reducir la tasa de éxito de este ataque.
La primera y más obvia es limitar el uso de roles sensibles como RoleManagement.ReadWrite.Directory. En algunos casos estos roles serán necesarios, en estos escenarios lo mejor es vigilar de cerca estas aplicaciones y tener preparadas respuestas automatizadas en caso de comportamiento anómalo.
Además, el uso del acceso condicional reduciría la probabilidad de éxito de este ataque a través de Internet. Esto podría hacerse, por ejemplo, permitiendo únicamente el inicio de sesión en la cuenta de AAD Sync desde sus instalaciones. Cualquier irregularidad en este sentido podría utilizarse entonces para activar una alerta e informarle de un intento de inicio de sesión potencialmente malicioso. Sin embargo, como se ve en este ejemplo, un atacante que haya puesto en peligro el servidor de AD Connect puede saltarse estas políticas de acceso condicional realizando el ataque desde el servidor de AD Connect.
Además, deberían establecerse medidas de seguridad en el servidor AD Connect para supervisar y reducir los tipos de acciones que pueden realizarse en el servidor. Un ejemplo de ello podría ser bloquear el uso de herramientas como AADInternals.
La conclusión de estas mitigaciones es que no existe una única solución para este ataque. En su lugar, debería haber múltiples capas de defensa que detendrían a un atacante esperemos que incluso antes de que consiga acceder al servidor AD Connect.
Más información sobre este ataque en:
Sobre el autor
Mauricio Payne
Mauricio Payne es analista de seguridad en Bureau Veritas Cybersecurity. Estudió TIC y Software y se especializó en Ciberseguridad en la Fontys Hogescholen de Eindhoven. Desde su graduación trabaja en Bureau Veritas Cybersecurity donde se especializa en assessment de aplicaciones web y en la nube.
Más información
¿Tiene preguntas sobre este artículo o desea más información sobre cómo Bureau Veritas Cybersecurity puede ayudarle a aumentar su ciberresiliencia? Rellene el formulario y nos pondremos en contacto con usted en el plazo de un día laborable.
ACERCA DE LA CIBERSEGURIDAD
Bureau Veritas Cybersecurity es un expert líder en ciberseguridad. Nuestros clientes abarcan desde la administración y la sanidad hasta las finanzas y la industria en todo el mundo. Bureau Veritas Cybersecurity ofrece servicios técnicos, como assessment de vulnerabilidades, Penetration Testing y Red Teaming. También proporcionamos certificación para entornos IoT e industriales, así como auditorías, servicios forenses y formación de awareness. Nuestro objetivo es aumentar su ciberresiliencia.
Bureau Veritas Cybersecurity es una empresa de Bureau Veritas. Bureau Veritas (BV) es una empresa que cotiza en bolsa especializada en ensayos, inspección y certificación. BV fue fundada en 1828, cuenta con más de 80.000 empleados y está presente en 140 países. Bureau Veritas Cybersecurity es la piedra angular de la estrategia de ciberseguridad de Bureau Veritas.
¿Por qué elegir la ciberseguridad de Bureau Veritas?
Bureau Veritas Cybersecurity es su socio experto en ciberseguridad. Ayudamos a las organizaciones a identificar riesgos, reforzar sus defensas y cumplir con las normas y regulaciones de ciberseguridad. Nuestros servicios abarcan personas, procesos y tecnología, desde la formación en materia de concienciación y la ingeniería social hasta el asesoramiento en seguridad, el cumplimiento normativo y las pruebas de penetración.
Operamos en entornos de TI, TO e IoT, y damos soporte tanto a sistemas digitales como a productos conectados. Con más de 300 profesionales de la ciberseguridad en todo el mundo, combinamos una profunda experiencia técnica con una presencia global. Bureau Veritas Cybersecurity forma parte del Bureau Veritas Group, líder mundial en pruebas, inspección y certificación.