O Que Torna um Service Principal do Entra com Função de Admin Privilegiada em Excesso
Um service principal do Entra com privilégios de admin excessivos para o que sua automação realmente faz é uma das identidades menos revisadas no Microsoft Entra ID — e uma das mais perigosas, porque, ao contrário de um admin humano, ele nunca precisa passar por MFA, raramente tem um owner de ciclo de vida e frequentemente sobrevive ao projeto que o criou. Um service principal é a identidade local do tenant para um aplicativo ou script: é como o Terraform, um pipeline de CI/CD ou uma automação personalizada se autentica ao chamar o Microsoft Graph. Dê a um deles uma função de admin de diretório como Administrador Global, Privileged Role Administrator ou Application Administrator, e ele poderá fazer tudo o que um admin humano nessa função também faria — criar usuários, redefinir credenciais, consentir com novas permissões, modificar o Conditional Access.
Vale separar isso de uma exposição relacionada, mas diferente. Uma função de diretório (o tema deste artigo) concede capacidade administrativa em todo o tenant, atribuída via roleManagement/directory/roleAssignments. Uma atribuição de função de app — as permissões delegadas ou de aplicativo do Graph API, como Directory.ReadWrite.All, concedidas via servicePrincipals/{id}/appRoleAssignedTo (Grant an appRoleAssignment for a service principal) — é um mecanismo separado, restrito a uma única API de recurso, e é o assunto abordado em permissões perigosas do Graph API em registros de aplicativo. Um service principal pode não ter nenhuma, ter uma ou ter as duas; este artigo trata do lado da função de diretório dessa equação.
O problema do lado da função de diretório é a exposição, não a função em si. Um service principal com função de admin superprivilegiada fica ativo 24/7, se autentica de forma não interativa com um client secret ou certificado — e, segundo a própria orientação da Microsoft sobre risco de identidades de carga de trabalho, identidades de carga de trabalho "não conseguem realizar autenticação multifator", "muitas vezes não têm um processo formal de ciclo de vida" e "precisam armazenar suas credenciais ou secrets em algum lugar" (Securing workload identities with Microsoft Entra ID Protection). A aplicação obrigatória de MFA do Microsoft Entra também explicitamente não alcança essas identidades: a Microsoft confirma que identidades de carga de trabalho "não são afetadas por nenhuma das duas fases" do rollout obrigatório de MFA (Plan for mandatory Microsoft Entra multifactor authentication). Um secret vazado de um service principal com função de admin é uma sessão de admin vazada e imune a MFA.
Essa lacuna raramente é uma única má configuração. Geralmente é um conjunto de pontos cegos relacionados que se somam: a função de admin é mais ampla do que a automação precisa, ninguém é dono do service principal, desativá-lo não remove de fato a permissão e — cada vez mais — a identidade que detém a função nem sequer é nativa do seu tenant.
Como Surgem os Service Principals com Privilégios Excessivos
Permanente, Não Elegível
O Privileged Identity Management (PIM) permite que a atribuição de função de um admin humano seja elegível — inativa até que ele a ative, limitada no tempo e registrada em log. Service principals não conseguem usar esse modelo: funções do Microsoft Entra, funções do Azure e PIM para grupos só podem conceder a um service principal uma atribuição ativa, porque atribuições elegíveis exigem uma etapa de ativação (aprovação, desafio de MFA) que uma identidade não interativa não consegue realizar (Eligible and time-bound role assignments in Azure RBAC). Na prática, todo service principal com função de admin no seu tenant é uma atribuição permanente por design — não existe uma rede de segurança do PIM que a limite no tempo, a menos que alguém tenha definido separadamente uma expiração para a atribuição.
Sem Owner
servicePrincipal.owners deveria responder "quem é responsável por isso". O Microsoft Graph expõe essa coleção, que é preenchida com uma chamada POST /servicePrincipals/{id}/owners $ref (servicePrincipal: Add owner) — mas nada obriga que ela seja preenchida na criação. Um service principal que aparece em uma varredura de atribuições de função com a coleção de owners vazia tem uma função de admin sobre a qual ninguém é notificado, que ninguém revisa no offboarding e que ninguém consegue explicar em uma call de incidente.
Desativado, Mas Ainda com Permissões
accountEnabled em um service principal é um booleano que bloqueia o login quando definido como false — "nenhum usuário consegue fazer login neste app, mesmo que esteja atribuído a ele" (servicePrincipal resource type). Ele não afeta atribuições de função ou de função de app — removê-las é uma operação separada, com seu próprio cmdlet, Remove-MgServicePrincipalAppRoleAssignment (Microsoft Learn). Uma equipe que "desativa" uma integração apenas alternando accountEnabled para false e parando por aí deixa a atribuição da função de admin totalmente intacta — reativar a conta, ou um atacante capaz de reverter essa mesma flag, restaura o acesso de admin instantaneamente.
De uma Organização Externa
Nem todo service principal no seu tenant foi criado por você. Registros de aplicativo multi-tenant criam um service principal localmente, enquanto o objeto de aplicativo subjacente permanece no tenant de origem do fornecedor ou parceiro — registrado como appOwnerOrganizationId, que o Microsoft Entra também grava nos detalhes adicionais do evento de auditoria quando o service principal é provisionado (Understand why a service principal was created in your tenant). Quando appOwnerOrganizationId não corresponde ao ID do seu próprio tenant e esse service principal também detém uma função de admin, você delegou acesso de admin permanente a uma identidade controlada por terceiros — o equivalente, para aplicativos, da exposição de convidados entre tenants que a maioria das equipes já acompanha para contas de usuário, mas quase nunca para aplicativos.
Detecção
Colete todas as atribuições de função de diretório e cruze quais principals são service principals e quais são usuários ou grupos — Get-MgRoleManagementDirectoryRoleAssignment não filtra por tipo de principal sozinho, então resolva isso com uma consulta a Get-MgServicePrincipal (List Microsoft Entra role assignments):
Connect-MgGraph -Scopes "RoleManagement.Read.Directory","Application.Read.All"
$roles = Get-MgRoleManagementDirectoryRoleDefinition
$spAssignments = foreach ($role in $roles) {
Get-MgRoleManagementDirectoryRoleAssignment -Filter "roleDefinitionId eq '$($role.Id)'" |
ForEach-Object {
$sp = Get-MgServicePrincipal -ServicePrincipalId $_.PrincipalId -ErrorAction SilentlyContinue
if ($sp) {
[pscustomobject]@{
ServicePrincipal = $sp.DisplayName
RoleAssigned = $role.DisplayName
AccountEnabled = $sp.AccountEnabled
OwnerCount = (Get-MgServicePrincipalOwner -ServicePrincipalId $sp.Id).Count
AppOwnerOrgId = $sp.AppOwnerOrganizationId
}
}
}
}
$spAssignments | Format-Table -AutoSize
A mesma consulta funciona diretamente contra o Microsoft Graph, sem o módulo do PowerShell — útil para um script rodando fora de uma workstation com o Graph SDK instalado:
GET https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments?$filter=roleDefinitionId eq '{role-template-id}'
Cada resultado retorna um principalId; resolva-o via GET /servicePrincipals/{id} para confirmar o tipo de principal e obter accountEnabled, appOwnerOrganizationId e — via GET /servicePrincipals/{id}/owners — a coleção de owners na mesma chamada (List Microsoft Entra role assignments).
| Detector | O que verificar | Por que importa |
|---|---|---|
PA_SERVICE_PRINCIPAL_ADMIN / SP_HIGH_PRIVILEGE | Qualquer service principal acima com Administrador Global, Privileged Role Administrator ou outra função de alto nível | Acesso de admin permanente e incapaz de MFA |
SP_NO_OWNER | OwnerCount -eq 0 em um service principal com função de admin | Nenhum humano responsável para revisar ou revogar |
SP_DISABLED_WITH_PERMISSIONS | AccountEnabled -eq $false, mas a atribuição de função ainda é resolvida | A permissão sobreviveu ao que parecia ser uma desativação |
SP_EXTERNAL_ORGANIZATION | AppOwnerOrganizationId presente e diferente do ID do seu próprio tenant | Função de admin nas mãos de uma identidade controlada por outra organização |
Para o próprio evento de atribuição, filtre os logs de auditoria do Microsoft Entra pelo serviço Core Directory e pela categoria Role Management, e procure entradas de atividade "Add member to role", restringindo TargetResources ao tipo ServicePrincipal para isolar concessões não humanas das concessões a usuários (Easily Manage Privileged Role Assignments in Microsoft Entra ID Using Audit Logs). Exporte esses logs antes que expirem — a retenção dos logs de auditoria do Entra é curta por padrão e é fácil perder o histórico sem diagnostic settings configurados.
⚠️ Aviso: AccountEnabled -eq $false em um service principal não é uma correção. Isso interrompe o login, não a atribuição de função — trate um service principal desativado com função de admin como ainda privilegiado até confirmar que a própria atribuição foi removida.
Correção
💡 Vitória Rápida: Execute o script de detecção acima uma vez e priorize primeiro cada resultado SP_NO_OWNER e SP_EXTERNAL_ORGANIZATION — essas são as duas categorias que provavelmente ninguém mais no tenant já está observando.
- Ajuste a função ao tamanho certo. Substitua funções de admin amplas (Administrador Global, Privileged Role Administrator) pela função interna ou personalizada mais restrita que cubra as chamadas do Graph que a automação realmente faz — a maioria das integrações precisa de Application Administrator ou de uma função limitada a um recurso, não de Administrador Global. Um service principal que só provisiona usuários não precisa da mesma função que um que gerencia o Conditional Access.
- Atribua um owner.
POST /servicePrincipals/{id}/ownerscom um$refpara um engenheiro responsável, para que a atribuição apareça em access reviews em vez de só surgir durante um incidente. - Remova as permissões antes de desativar. Execute
Remove-MgServicePrincipalAppRoleAssignment(ou a remoção equivalente da função de diretório) como parte do runbook de descomissionamento — não confie apenas emaccountEnabled: $false, e não considere uma integração "desativada" encerrada até que a própria atribuição de função tenha sido removida. - Defina uma expiração quando possível. Como service principals só podem manter atribuições ativas, use a opção de data de término da atribuição no momento da concessão, para que uma função de admin não se torne permanente silenciosamente.
- Restrinja identidades de carga de trabalho com Conditional Access. O Conditional Access para identidades de carga de trabalho pode bloquear o login de um service principal single-tenant por localização ou estado de risco do Identity Protection — ele não força MFA (service principals não conseguem fazer isso), mas fecha parte da lacuna que o MFA não alcança.
- Revise os service principals de organizações externas individualmente. Para cada resultado
SP_EXTERNAL_ORGANIZATIONcom função de admin, confirme que a relação com o fornecedor continua válida e que a função ainda se justifica — o mesmo escrutínio que você aplicaria a uma conta de convidado com acesso permanente, aplicado a um aplicativo em vez de a uma pessoa.
Isso complementa a revisão que a maioria das equipes já faz para o acesso privilegiado humano — veja Gerenciamento de Acesso Privilegiado no Azure: Riscos sem PIM e Como Auditar a Segurança do Microsoft Entra ID — e é distinto, mas relacionado, das permissões perigosas do Graph API no próprio registro de aplicativo, que é uma exposição separada da função de diretório do service principal.
Como o EtcSec Detecta Isso
A auditoria Azure do EtcSec verifica PA_SERVICE_PRINCIPAL_ADMIN e SP_HIGH_PRIVILEGE em cada atribuição de função de diretório mantida por um service principal, e sinaliza separadamente SP_NO_OWNER, SP_DISABLED_WITH_PERMISSIONS e SP_EXTERNAL_ORGANIZATION, para que as lacunas de ownership, ciclo de vida e cross-tenant descritas acima apareçam como findings em vez de exigir uma varredura manual em PowerShell a cada trimestre sobre cada definição de função no tenant.
ℹ️ Nota: O EtcSec verifica automaticamente essa vulnerabilidade em toda auditoria Azure. Execute uma auditoria gratuita para verificar seu ambiente.
Explore as paginas de identidade que sustentam este tema
