Jonathan Elkabas e Tomer Nahum

Nota do editor

Este cenário faz parte de uma série de exemplos que demonstram a utilização do EntraGoat, o nosso ambiente de simulação Entra ID. Pode ler uma visão geral do EntraGoat e o seu valor aqui.


Desconhecido e perigoso: Um Manual do Proprietário para a Administração Global

Começamos os nossos exemplos de utilização do EntraGoat com o Cenário 1, a que chamámos "Misowned and Dangerous": Um manual do proprietário para o administrador global. Este exercício prático mostra como a propriedade legítima do aplicativo no Microsoft Entra ID pode ser aproveitada para aumentar os privilégios e comprometer uma conta de administrador global, permitindo o controle completo do locatário.

Começando com uma conta de utilizador pouco privilegiada comprometida, o atacante descobre a propriedade de uma aplicação empresarial (service principal) à qual é atribuída uma função privilegiada.

Ao adicionar um segredo de cliente à entidade de serviço, o atacante entra na identidade da aplicação e, em seguida, utiliza a sua função para repor a palavra-passe do administrador e emitir um Passe de Acesso Temporário (TAP) para obter acesso interativo total ao portal do Azure.

Este cenário enfatiza as consequências reais da má gestão de aplicações e ilustra a diferença de comportamento, limites de acesso e exposição ao risco entre fluxos de autenticação delegados e apenas de aplicações.


Visão geral do caminho de ataque

  1. História do primeiro ponto de apoio: O atacante autentica-se como um utilizador financeiro comprometido (david.martinez) com credenciais roubadas.
  2. Enumeração: Usando cmdlets nativos do PowerShell e do Microsoft Graph, o atacante descobre que o usuário possui uma entidade de serviço chamada Finance Analytics Dashboard ao qual é atribuído o Privileged Authentication Administrator papel.
  3. Aumento de privilégios: O atacante adiciona um segredo de cliente à entidade proprietária do serviço e autentica-se utilizando credenciais apenas da aplicação, passando para uma identidade de entidade de serviço.
  4. Aquisição de conta: A partir do contexto só de aplicações com a função privilegiada, o atacante repõe a palavra-passe do Administrador Global ou adiciona um TAP para contornar a autenticação multifactor (MFA), depois inicia sessão interactivamente e recupera o sinalizador, confirmando o compromisso total do inquilino.

Fluxo de ataque

A Figura 1 mostra o fluxo deste ataque.

Figura 1. Fluxo de ataque que compromete uma conta de administrador global do EntraGoat

Por que razão é importante compreender a propriedade da aplicação?

Cada aplicação em Entra ID tem duas identidades distintas:

  1. Registo da aplicação, um objeto de definição global no inquilino de origem onde a aplicação foi originalmente criada. Este objeto contém as permissões (âmbitos) blueprint-OAuth2 da aplicação que a aplicação pode solicitar URIs de redireccionamento para fluxos de início de sessão, metadados de marca e editor, entre outros. Esta identidade não representa uma entidade de segurança ativa no inquilino por si só.
  2. Entidade de serviço, uma instância local da aplicação no locatário que actua como a sua identidade de segurança e impõe o controlo de acesso. Um principal de serviço é criado automaticamente quando um usuário no locatário registra um novo aplicativo, consente com um aplicativo externo e assim por diante. A identidade do principal de serviço é o que a Entra ID usa para atribuir funções, aplicar políticas e impor permissões. É também a identidade autenticada quando o aplicativo atua por conta própria (contexto somente de aplicativo).

A propriedade de aplicativos é um recurso administrativo legítimo. Este design suporta a administração descentralizada em grandes organizações, permitindo às equipas gerir as suas próprias aplicações empresariais. Ele permite que desenvolvedores, processos de automação e proprietários de serviços gerenciem o ciclo de vida e a configuração de seus aplicativos. No entanto, esse recurso se torna uma responsabilidade quando:

  • São atribuídas funções privilegiadas às aplicações
  • A propriedade é atribuída a utilizadores regulares sem governação
  • A higiene das credenciais é fraca ou não é monitorizada

As entidades de serviço mal geridas permitem a adição de credenciais e o acesso apenas a aplicações, contornando controlos de identidade como o MFA e o acesso condicional.

Este passo a passo destaca por que os invasores priorizam o movimento lateral usando princípios de serviço em ambientes de nuvem modernos e por que os defensores devem entender a diferença entre contextos de segurança delegados e somente de aplicativo.


Como detetar e defender-se contra a utilização indevida da propriedade principal do serviço

Compreender e monitorar a propriedade do aplicativo não é opcional; é um controle de segurança fundamental em qualquer ambiente Entra ID. A propriedade do aplicativo concede a capacidade de gerenciar credenciais, configurar permissões e controlar efetivamente a identidade do aplicativo. Sem visibilidade da propriedade do aplicativo e das atribuições de permissão, os caminhos de escalonamento de privilégios permanecem ocultos tanto para os defensores quanto para os auditores.

Os defensores devem monitorizar e correlacionar:

  • Que aplicações existem no inquilino?
  • A quem pertencem?
  • Que permissões ou funções de diretório lhes são atribuídas?
  • Há algum utilizador sem privilégios que possua diretores de serviço com acesso elevado?
  • Que aplicações já não estão a ser utilizadas e podem ser desactivadas?

As soluções Semperis ajudam a colmatar as lacunas na compreensão destas questões com várias camadas de defesa, começando com indicadores de exposição (IOEs) e indicadores de compromisso (IOCs).

Esses indicadores detectam e alertam automaticamente sobre padrões perigosos e configurações incorretas - como políticas de autorização excessivamente permissivas para a configuração de aplicativos, não-administradores que possuem princípios de serviço privilegiados e linhas de base de segurança de aplicativos fracas.


Mergulho profundo no cenário: Apresentação passo a passo da solução

Vejamos os passos específicos a seguir para simular a utilização indevida da propriedade da aplicação e compreender em que condições permite o compromisso do Administrador Global.


Etapa 1: Ponto de apoio inicial

Começamos com o contexto de segurança de um analista financeiro, david.martinez (Figura 2) que introduziu as suas credenciais empresariais durante uma campanha de phishing.

Figura 2. Credenciais comprometidas de um utilizador pouco privilegiado

Utilizar o Connect-MgGraph cmdlet, autenticamos como o utilizador comprometido (Figura 3).

Figura 3. Iniciar sessão com as nossas credenciais roubadas

Para compreender as nossas capacidades actuais, começamos por inspecionar o contexto de segurança da sessão autenticada(Figura 4).

Figura 4. Contexto de segurança da sessão autenticada

Um método alternativo e bem conhecido para autenticar como um usuário Entra ID e obter um token de acesso JWT é aproveitar as ferramentas de automação, como o BARK1. O seguinte snippet do PowerShell demonstra como adquirir e usar um token de acesso via autenticação de nome de usuário/senha a partir da CLI:

      $userToken = Get-MSGraphTokenWithUsernamePassword -Username $UPN -Password $password -TenantID $tenantId
$userAccessToken = $userToken.access_token
$SecureToken = ConvertTo-SecureString $userAccessToken -AsPlainText -Force
Ligar-MgGraph -AccessToken $SecureToken

O BARK também inclui uma funcionalidade para descodificar o JWT resultante, expondo metadados detalhados da sessão, tais como permissões delegadas (scp), funções de diretório (wids), método de autenticação (amr), e informações do cliente (app_displayname), como Figura 5 espectáculos.

Figura 5. Metadados da sessão descodificados

Este passo de descodificação é particularmente útil para uma triagem rápida de privilégios. Por exemplo, se o token foi emitido para um utilizador com funções de diretório, o wids listaria diretamente os GUIDs das funções atribuídas, como a função de Administrador Global que Figura 6 mostra, sem exigir enumeração adicional da API do Graph.

Figura 6. O UID de Administrador Global revelado

No entanto, este passo a passo evita depender de ferramentas ou abstrações de terceiros. Todas as etapas de enumeração e exploração são executadas usando o PowerShell nativo e chamadas diretas à API do Graph para garantir que cada fase do caminho do ataque seja totalmente transparente e tecnicamente explicada.

NOTA: Por defeito, todos os utilizadores autenticados no Entra ID podem consultar os dados básicos do perfil de outros utilizadores e atributos como extensionAttribute1–15 não são classificadas como sensíveis. Como resultado, o sinalizador armazenado no perfil do administrador pode tecnicamente ser recuperado imediatamente com a seguinte consulta da API:

      $uri = "https://graph.microsoft.com/v1.0/users/EntraGoat-admin-s1@334brf.onmicrosoft.com?`$select=onPremisesExtensionAttributes"
$response = Invoke-MgGraphRequest -Uri $uri -Method GET
$response.onPremisesExtensionAttributes.extensionAttribute1

Este comportamento é intencional. O objetivo do EntraGoat não é ocultar o sinalizador, mas ensinar técnicas realistas de escalonamento de privilégios em ambientes Entra ID. É possível recuperar o sinalizador por meio de uma chamada direta à API; mas o objetivo real é escalar privilégios, acessar o portal do Azure como usuário administrador e visualizar o sinalizador na interface do usuário - demonstrando controle total sobre uma identidade de administrador global. A bandeira é um artefacto gamificado, não o objetivo principal.

      Invoke-MgGraphRequest -Uri 'https://graph.microsoft.com/v1.0/me?$select=id,userPrincipalName,onPremisesExtensionAttributes' |
    Select-Object @{n='UPN';e={$_.userPrincipalName}},
                  @{n='Id';e={$_.id}},
                  @{n='Flag';e={$_.onPremisesExtensionAttributes.extensionAttribute1}}

Etapa 2: Enumeração

Como este é o primeiro cenário da série EntraGoat, vamos percorrer o processo de enumeração e destacar as técnicas fundamentais de escalonamento de privilégios. Em nossos outros cenários, assumiremos essa linha de base e nos concentraremos diretamente no caminho principal do ataque, ignorando as etapas de reconhecimento no estilo CTF.

Com acesso inicial a david.martinezSe o sistema de segurança estiver comprometido, começamos a procurar caminhos para o aumento de privilégios. A nossa primeira tarefa é compreender o acesso que a identidade comprometida tem.

Começamos por verificar se o utilizador tem alguma função de diretório atribuída(Figura 7).

Figura 7. Verificação das funções do utilizador

O Get-MgRoleManagementDirectoryRoleAssignment não revela funções privilegiadas, confirmando que david.martinez não tem acesso elevado por defeito. De seguida, analisamos as associações de grupos (Figura 8).

Figura 8. Ver os membros do grupo do nosso utilizador

O utilizador faz apenas parte do grupo de inquilinos predefinido, que é atribuído a cada utilizador Entra ID para serviços de colaboração como o SharePoint ou o Teams. Nenhum caminho de escalonamento de privilégios aqui também.

Também verificamos se david.martinez possui quaisquer grupos, uma vez que os proprietários de grupos podem adicionar-se a si próprios como membros e herdar os privilégios do grupo (tais como funções atribuídas). Esta verificação também retorna vazio (Figura 9).

Figura 9. Verificação da propriedade do grupo do nosso utilizador

No entanto, a consulta da propriedade principal do serviço apresenta um resultado(Figura 10).

Figura 10. Descoberta de que o nosso utilizador possui um serviço principal

david.martinez possui o mandante do serviço Finance Analytics Dashboard. Isto é importante porque os proprietários da entidade de serviço podem gerir credenciais - incluindo a adição de novos segredos para autenticar como entidade de serviço.

Vamos verificar se o Finance Analytics Dashboard o responsável pelo serviço tem quaisquer permissões atribuídas (Figura 11).

Figura 11. Verificação das permissões atribuídas ao diretor de serviço

Nenhum está configurado. Em seguida, verificamos se existem funções de diretório atribuídas ao mesmo(Figura 12).

Figura 12. Verificação das funções de diretório do principal de serviço

Vemos uma atribuição de função, mas ela é representada apenas por um GUID. Cada função interna da Entra ID é representada por um GUID, que é global e o mesmo em todos os locatários da Entra ID. É possível visualizar todas as funções internas oficiais e seus GUIDs aqui.

Para resolver o GUID para um nome de função legível por humanos, podemos canalizar a saída de Get-MgRoleManagementDirectoryRoleAssignment para Get-MgRoleManagementDirectoryRoleDefinition (Figura 13), que traduzirá cada ID de função atribuído para o nome de apresentação correspondente.

Figura 13. Revelar o nome de apresentação de uma função

Privileged Authentication Administrator é uma função altamente sensível no Entra ID. Permite ao titular gerir métodos de autenticação para todos os utilizadores, incluindo a reposição de definições de MFA, a configuração de opções de início de sessão FIDO2 e sem palavra-passe e a modificação de políticas-chave que regem a forma como os utilizadores se autenticam. É por isso que um atacante, agindo como seu proprietário, certamente desejaria adicionar um segredo de cliente a ele e usá-lo para influenciar a conta de Administrador Global.

NOTA: Se você acompanhou de perto a fase de enumeração, provavelmente notou a verbosidade e o esforço manual necessários ao usar cmdlets nativos do Microsoft Graph. (E se tivéssemos 5[0] aplicativos Entra em vez de 1?) Essa é uma das principais limitações de depender exclusivamente de ferramentas nativas. Os comandos geralmente retornam dados de baixo nível (como GUIDs) que exigem consultas adicionais para serem resolvidos em informações significativas.

É exatamente por isso que muitas estruturas de enumeração automatizam estes processos. Elas abstraem as consultas repetitivas e simplificam o resultado, permitindo uma análise mais rápida dos privilégios e a tomada de decisões. Por exemplo, para melhorar a usabilidade, podemos escrever funções de wrapper simples, como Find-OwnedServicePrincipals e Get-ServicePrincipalRoles que foram concebidos para automatizar a descoberta de propriedade de SP e resolver atribuições de funções de diretório de forma mais eficiente:

      function Find-OwnedServicePrincipals {
    param([string]$UserId)
    
    # Get all service principals in tenant
    $allSPs = Get-MgServicePrincipal -All
    Write-Host "Found $($allSPs.Count) service principals in tenant"
    
    $ownedSPs = @()
    $checkCount = 0
    
    # Check ownership of each service principal
    foreach ($sp in $allSPs) {
        $checkCount++
        if ($checkCount % 50 -eq 0) {
            Write-Host "Checked $checkCount/$($allSPs.Count) service principals..."
        }
        
        try {
            $owners = Get-MgServicePrincipalOwner -ServicePrincipalId $sp.Id -ErrorAction SilentlyContinue
            if ($owners) {
                foreach ($owner in $owners) {
                    if ($owner.Id -eq $UserId) {
                        $ownedSPs += $sp
                        Write-Host "OWNED SERVICE PRINCIPAL FOUND!" -ForegroundColor Red
                        Write-Host "   Name: $($sp.DisplayName)" -ForegroundColor Yellow
                        Write-Host "   SP ID: $($sp.Id)" -ForegroundColor Yellow
                        Write-Host "   App ID: $($sp.AppId)" -ForegroundColor Yellow
                        break
                    }
                }
            }
        } catch {
            continue
        }
    }
    return $ownedSPs
}

function Get-ServicePrincipalRoles {
    param([object]$ServicePrincipal)
    
    Write-Host "Checking roles for: $($ServicePrincipal.DisplayName)"
    
    # Check directory role assignments for the SP
    $roleAssignments = Get-MgRoleManagementDirectoryRoleAssignment -Filter "principalId eq '$($ServicePrincipal.Id)'" -ErrorAction SilentlyContinue
    $roles = @()
    
    if ($roleAssignments) {
        foreach ($assignment in $roleAssignments) {
            $roleDefinition = Get-MgRoleManagementDirectoryRoleDefinition -UnifiedRoleDefinitionId $assignment.RoleDefinitionId
            $roles += $roleDefinition
            Write-Host "   Role: $($roleDefinition.DisplayName)" -ForegroundColor Cyan
        }
    } else {
        Write-Host "   No directory roles assigned"
    }
    
    return $roles
}

Agora, para descobrir todos os princípios de serviço pertencentes ao utilizador comprometido e enumerar as suas funções atribuídas, podemos simplesmente executar Find-OwnedService Principals, como Figura 14 espectáculos.

Figura 14. Descoberta de mandantes de serviços próprios

Etapa 3: Pivotar para o contexto do responsável pelo serviço

Esta etapa destaca o principal motivo pelo qual criamos este cenário e o posicionamos em primeiro lugar na série: As entidades de serviço moldam o cenário de escalonamento de privilégios na Entra ID. O movimento lateral para o contexto de segurança de uma entidade de serviço e sua utilização para realizar operações privilegiadas é uma técnica fundamental com a qual todo defensor, atacante e pesquisador que trabalha com o Entra ID deve estar familiarizado.

Vamos adicionar um segredo de cliente ao ficheiro Finance Analytics Dashboard para estabelecer um acesso backdoor e autenticar-se como SP:

      $secretDescription = "EntraGoat-Secret-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
$passwordCredential = @{
    DisplayName = $secretDescription
    EndDateTime = (Get-Date).AddYears(1)
}

$newSecret = Add-MgServicePrincipalPassword -ServicePrincipalId $SP.Id -PasswordCredential $passwordCredential

# Guardar os detalhes do segredo adicionado
$clientSecret = $newSecret.SecretText

Em seguida, desligue a sessão do utilizador atual com Disconnect-MgGraphconstruir as credenciais do cliente e autenticar utilizando a identidade do responsável pelo serviço através de Connect-MgGraph:

      $secureSecret = ConvertTo-SecureString -String $clientSecret -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $SP.AppId, $secureSecret
Connect-MgGraph -TenantId $tenantId -ClientSecretCredential $credential

E, de facto, agora estamos autenticados como os Finance Analytics Dashboard chefe de serviço (Figura 15).

Figura 15. Demonstração da autenticação como entidade de serviço

O Get-MgContext revela informações sobre como a sessão atual do Microsoft Graph é autenticada, o que determina diretamente o contexto de segurança, o nível de acesso e o modelo de permissão que é aplicado. Vamos nos concentrar nos campos AuthType e TokenCredentialType uma vez que expõem a semântica de identidade central na Entra ID.

Depois de se autenticar como david.martinez, estes valores apareceram como:

      AuthType : Delegado
TokenCredentialType : InteractiveBrowser

Isto indica uma sessão delegada, em que o token emitido representa uma identidade de utilizador. O acesso é regido pelas funções atribuídas ao utilizador e pelas permissões delegadas, e todas as operações são executadas em nome do utilizador. O contexto da sessão está limitado àquilo a que a identidade do utilizador tem acesso, uma vez que herda políticas de Acesso Condicional, imposição de MFA e restrições PIM.

Em contrapartida, um contexto apenas de aplicação, como um contexto iniciado por uma entidade de serviço que utiliza credenciais de cliente (AppId + Secret + TenantId) funciona como uma identidade não-humana. Qualquer cliente (script, trabalho em segundo plano, daemon) usando essas credenciais pode autenticar como o aplicativo e invocar APIs do Microsoft Graph com base em suas permissões de aplicativo, independentemente do contexto do usuário. As políticas de Acesso Condicional, MFA e PIM não são aplicáveis ou impostas neste fluxo.

Esta distinção é fundamental na conceção da segurança da identidade e explica porque é que o comportamento da API, os âmbitos de acesso e os privilégios de token diferem nos mesmos cmdlets, dependendo do contexto da sessão.

E, como seria de esperar, esta distinção tem um grande impacto na superfície de ataque e no potencial de abuso. Os fluxos delegados são limitados pelo contexto do utilizador, enquanto os fluxos só de aplicações funcionam com confiança ao nível do serviço e, frequentemente, com limites de privilégios mais amplos e menos controlados. Para os atacantes, comprometer o segredo ou o certificado de uma aplicação resulta frequentemente num acesso persistente e com privilégios elevados que contorna os mecanismos de aplicação centrados na identidade.


Passo 4: Tomada de controlo da conta - iniciar sessão como administrador global

Agora que nos autenticámos como uma identidade com o Privileged Authentication Administrator temos a possibilidade de repor as palavras-passe (Figura 16) para qualquer utilizador no locatário, incluindo o Administrador Global.

Figura 16: Repor a palavra-passe do administrador

Com este nível de acesso, também podemos atribuir um TAP(Figura 17) como método de autenticação, permitindo-nos contornar o MFA e iniciar sessão diretamente no portal do Azure:

Figura 17. Atribuição de um TAP para autenticação

De seguida, iniciamos a sessão com a TAP(Figura 18).

Figura 18. Iniciar sessão com o novo TAP

De seguida, recuperamos a bandeira do cenário(Figura 19).

Figura 19. A bandeira é capturada

Uma vez terminado o cenário, executamos o script de limpeza para restaurar o locatário EntraGoat ao seu estado original(Figura 20).

Figura 20. A limpeza do EntraGoat prepara-nos para o nosso próximo cenário

Este cenário demonstra como configurações aparentemente legítimas e comuns, como a atribuição da propriedade de uma aplicação a um utilizador padrão, podem abrir a porta a um compromisso total do inquilino quando emparelhadas com funções privilegiadas.

Ao tirar partido da propriedade de uma entidade de serviço, os atacantes podem aumentar os privilégios, contornar as defesas centradas no utilizador, como a MFA e o Acesso Condicional, e, em última análise, obter acesso de Administrador Global através de um fluxo apenas de aplicações.

Esse exercício ressalta a importância crítica de uma forte governança em torno das permissões de aplicativos, da propriedade da entidade de serviço e das atribuições de função. Nos ambientes de nuvem modernos, as entidades de serviço são frequentemente o elo mais fraco, e compreender o seu modelo de identidade dupla, os limites de acesso e o potencial de abuso é essencial tanto para os atacantes como para os defensores.

O Cenário 1 do EntraGoat estabelece as bases para uma maior exploração - e para os nossos próximos cenários. Por isso, continuem a piratear!


Aceite o seu próximo desafio EntraGoat

Nota final

  1. https://github.com/BloodHoundAD/BARK

Declaração de exoneração de responsabilidade

Este conteúdo é fornecido apenas para fins educacionais e informativos. Destina-se a promover a consciencialização e a correção responsável das vulnerabilidades de segurança que possam existir nos sistemas que possui ou que está autorizado a testar. O uso não autorizado dessas informações para fins maliciosos, exploração ou acesso ilegal é estritamente proibido. A Semperis não endossa ou tolera qualquer atividade ilegal e se isenta de qualquer responsabilidade decorrente do uso indevido do material. Além disso, a Semperis não garante a exatidão ou a integridade do conteúdo e não assume qualquer responsabilidade por quaisquer danos resultantes da sua utilização.