Cosa rende sovraprivilegiato un ruolo admin di service principal di Entra
Un ruolo admin di service principal di Entra sovraprivilegiato rispetto a ciò che la sua automazione fa realmente è una delle identità meno revisionate in Microsoft Entra ID — e una delle più pericolose, perché a differenza di un admin umano non deve mai superare l'MFA, raramente ha un owner del ciclo di vita, e spesso sopravvive al progetto che l'ha creata. Un service principal è l'identità locale al tenant di un'applicazione o di uno script: l'identità con cui Terraform, una pipeline CI/CD, o un'automazione personalizzata si autentica quando chiama Microsoft Graph. Assegnategli un ruolo admin di directory come Global Administrator, Privileged Role Administrator, o Application Administrator, e potrà fare tutto ciò che un admin umano in quel ruolo può fare — creare utenti, reimpostare credenziali, dare consenso a nuovi permessi, modificare l'Accesso Condizionale.
Vale la pena distinguere questo da un'esposizione correlata ma diversa. Un ruolo di directory (l'argomento di questo articolo) concede capacità amministrativa sull'intero tenant, assegnata tramite roleManagement/directory/roleAssignments. Un'assegnazione di ruolo applicativo (app role assignment) — i permessi Graph API delegati o applicativi come Directory.ReadWrite.All concessi tramite servicePrincipals/{id}/appRoleAssignedTo (Grant an appRoleAssignment for a service principal) — è un meccanismo distinto, limitato a una singola API di risorsa, ed è l'argomento trattato in Permessi Graph API Pericolosi App Registration di Entra. Un service principal può non avere nessuno dei due, uno dei due, o entrambi; questo articolo tratta del lato ruolo di directory di questa equazione.
Il problema del lato ruolo di directory è l'esposizione, non il ruolo in sé. Un service principal con un ruolo admin sovraprivilegiato resta attivo 24 ore su 24, si autentica in modo non interattivo con un client secret o un certificato, e — secondo le stesse indicazioni di Microsoft sul rischio delle workload identity — le workload identity «non possono eseguire l'autenticazione multifattore», «spesso non hanno un processo formale di ciclo di vita», e «devono memorizzare le proprie credenziali o segreti da qualche parte» (Securing workload identities with Microsoft Entra ID Protection). Anche l'applicazione obbligatoria dell'MFA di Microsoft Entra esplicitamente non raggiunge queste identità: Microsoft conferma che le workload identity «non sono interessate da nessuna delle due fasi» del rollout dell'MFA obbligatorio (Plan for mandatory Microsoft Entra multifactor authentication). Un segreto trapelato di un service principal con ruolo admin è una sessione admin trapelata, immune all'MFA.
Questa lacuna è raramente un singolo errore di configurazione. Di solito è un insieme di punti ciechi correlati che si sommano: il ruolo admin è più ampio di quanto serva all'automazione, nessuno possiede il service principal, disabilitarlo non rimuove davvero il permesso, e — sempre più spesso — l'identità che detiene il ruolo non è nemmeno nativa del vostro tenant.
Come nascono i service principal sovraprivilegiati
Permanente, non idoneo
Privileged Identity Management (PIM) permette che l'assegnazione di ruolo di un admin umano sia idonea — inattiva finché non la attiva, limitata nel tempo, e registrata. I service principal non possono usare questo modello: i ruoli di Microsoft Entra, i ruoli Azure e PIM per i gruppi possono concedere a un service principal solo un'assegnazione attiva, perché le assegnazioni idonee richiedono un passaggio di attivazione (approvazione, una richiesta MFA) che un'identità non interattiva non può eseguire (Eligible and time-bound role assignments in Azure RBAC). In pratica, ogni service principal con ruolo admin nel vostro tenant è un'assegnazione permanente per progettazione — non esiste una rete di sicurezza PIM che la limiti nel tempo, a meno che qualcuno non abbia impostato separatamente una scadenza dell'assegnazione.
Nessun owner
servicePrincipal.owners dovrebbe rispondere a «chi è responsabile di questo». Microsoft Graph lo espone come una collezione da popolare con una chiamata POST /servicePrincipals/{id}/owners $ref (servicePrincipal: Add owner) — ma nulla obbliga a popolarla alla creazione. Un service principal che emerge in una scansione delle assegnazioni di ruolo con una collezione owners vuota ha un ruolo admin di cui nessuno viene notificato, che nessuno rivede in fase di offboarding, e che nessuno può spiegare durante una chiamata di incidente.
Disabilitato ma ancora permissionato
accountEnabled su un service principal è un booleano che blocca l'accesso quando è impostato su false — «nessun utente può accedere a questa app, anche se vi è assegnato» (servicePrincipal resource type). Questo non tocca le assegnazioni di ruolo o di ruolo applicativo — rimuoverle è un'operazione distinta con un proprio cmdlet, Remove-MgServicePrincipalAppRoleAssignment (Microsoft Learn). Un team che «dismette» un'integrazione impostando accountEnabled su false e fermandosi lì lascia l'assegnazione di ruolo admin completamente intatta — riabilitare l'account, o un attaccante in grado di ripristinare quello stesso flag, ripristina istantaneamente l'accesso admin.
Da un'organizzazione esterna
Non tutti i service principal del vostro tenant sono stati creati da voi. Le app registration multi-tenant creano un service principal localmente mentre l'oggetto applicazione sottostante resta nel tenant di origine del vendor o del partner — registrato come appOwnerOrganizationId, che Microsoft Entra scrive anche nei dettagli aggiuntivi dell'evento di audit quando il service principal viene provisionato (Understand why a service principal was created in your tenant). Quando appOwnerOrganizationId non corrisponde all'ID del vostro tenant e quel service principal detiene anche un ruolo admin, avete delegato un accesso admin permanente a un'identità controllata da terzi — l'equivalente applicativo dell'esposizione cross-tenant degli account guest che la maggior parte dei team già monitora per gli account utente, ma quasi mai per le applicazioni.
Rilevamento
Estraete ogni assegnazione di ruolo di directory, poi incrociate quali principal sono service principal rispetto a utenti o gruppi — Get-MgRoleManagementDirectoryRoleAssignment non filtra da solo per tipo di principal, quindi risolvetelo con una ricerca su 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
La stessa query funziona direttamente contro Microsoft Graph senza il modulo PowerShell — utile per uno script eseguito al di fuori di una workstation con l'SDK Graph installato:
GET https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments?$filter=roleDefinitionId eq '{role-template-id}'
Ogni risultato restituisce un principalId; risolvetelo con GET /servicePrincipals/{id} per confermare il tipo di principal e recuperare accountEnabled, appOwnerOrganizationId, e — tramite GET /servicePrincipals/{id}/owners — la collezione owners nella stessa chiamata (List Microsoft Entra role assignments).
| Detector | Cosa verificare | Perché conta |
|---|---|---|
PA_SERVICE_PRINCIPAL_ADMIN / SP_HIGH_PRIVILEGE | Qualsiasi service principal sopra con un ruolo Global Administrator, Privileged Role Administrator, o un altro ruolo di alto livello | Accesso admin permanente, non in grado di MFA |
SP_NO_OWNER | OwnerCount -eq 0 su un service principal con ruolo assegnato | Nessun umano responsabile per revisionarlo o revocarlo |
SP_DISABLED_WITH_PERMISSIONS | AccountEnabled -eq $false ma l'assegnazione di ruolo si risolve ancora | Il permesso è sopravvissuto a quella che sembrava una dismissione |
SP_EXTERNAL_ORGANIZATION | AppOwnerOrganizationId presente e diverso dall'ID del vostro tenant | Ruolo admin detenuto da un'identità controllata da un'altra organizzazione |
Per l'evento di assegnazione stesso, filtrate i log di audit di Microsoft Entra sul servizio Core Directory e la categoria Role Management, poi cercate le voci di attività «Add member to role», limitando TargetResources al tipo ServicePrincipal per isolare le concessioni non umane da quelle degli utenti (Easily Manage Privileged Role Assignments in Microsoft Entra ID Using Audit Logs). Esportate questi log prima che scadano — la retention dei log di audit di Entra è breve di default e facile da perdere senza diagnostic settings configurati.
⚠️ Attenzione: AccountEnabled -eq $false su un service principal non è una remediation. Blocca l'accesso, non l'assegnazione di ruolo — trattate un service principal disabilitato con ruolo admin come ancora privilegiato finché non confermate che l'assegnazione stessa è stata rimossa.
Remediation
💡 Vittoria rapida: Eseguite una volta lo script di rilevamento sopra e date priorità a ogni risultato SP_NO_OWNER e SP_EXTERNAL_ORGANIZATION per primi — sono le due categorie che probabilmente nessun altro nel tenant sta già monitorando.
- Dimensionate correttamente il ruolo. Sostituite i ruoli admin ampi (Global Administrator, Privileged Role Administrator) con il ruolo integrato o personalizzato più ristretto che copra le chiamate Graph effettive dell'automazione — la maggior parte delle integrazioni necessita di Application Administrator o di un ruolo limitato a una risorsa, non di Global Administrator. Un service principal che si limita a provisionare utenti non necessita dello stesso ruolo di uno che gestisce l'Accesso Condizionale.
- Assegnate un owner.
POST /servicePrincipals/{id}/ownerscon un$refverso un ingegnere responsabile, così che l'assegnazione compaia nelle access review invece di emergere solo durante un incidente. - Rimuovete i permessi prima di disabilitare. Eseguite
Remove-MgServicePrincipalAppRoleAssignment(o l'equivalente rimozione del ruolo di directory) come parte del runbook di dismissione — non affidatevi solo aaccountEnabled: $false, e non considerate chiusa un'integrazione «disabilitata» finché l'assegnazione di ruolo stessa non è sparita. - Impostate una scadenza dove possibile. Poiché i service principal possono avere solo assegnazioni attive, usate l'opzione di data di fine dell'assegnazione al momento della concessione, così che un ruolo admin non diventi silenziosamente permanente per default.
- Vincolate le workload identity con l'Accesso Condizionale. Conditional Access for workload identities può bloccare l'accesso di un service principal single-tenant in base alla località o allo stato di rischio di Identity Protection — non forzerà l'MFA (i service principal non possono farlo), ma chiude parte della lacuna che l'MFA non può raggiungere.
- Rivedete i service principal di organizzazioni esterne secondo i loro meriti. Per ogni riscontro
SP_EXTERNAL_ORGANIZATIONcon un ruolo admin, confermate che il rapporto con il vendor sia ancora attuale e che il ruolo sia ancora giustificato — lo stesso scrutinio che applichereste a un account guest con accesso permanente, applicato a un'applicazione anziché a una persona.
Questo completa la revisione che la maggior parte dei team già esegue per l'accesso privilegiato umano — vedete Accesso Privilegiato Azure: Troppi Admin Globali e Come auditare la sicurezza di Microsoft Entra ID — ed è distinto, seppur correlato, dai permessi Graph API pericolosi sull'app registration stessa, che costituiscono un'esposizione separata dal ruolo di directory del service principal.
Come EtcSec rileva questo
L'audit Azure di EtcSec verifica PA_SERVICE_PRINCIPAL_ADMIN e SP_HIGH_PRIVILEGE su ogni assegnazione di ruolo di directory detenuta da un service principal, e segnala separatamente SP_NO_OWNER, SP_DISABLED_WITH_PERMISSIONS, e SP_EXTERNAL_ORGANIZATION così che le lacune di ownership, ciclo di vita e cross-tenant sopra descritte emergano come findings invece di richiedere una scansione PowerShell manuale ogni trimestre su ogni definizione di ruolo del tenant.
ℹ️ Nota: EtcSec verifica automaticamente questa vulnerabilità a ogni audit Azure. Eseguite un audit gratuito per verificare il vostro ambiente.
Esplora le pagine di identity security collegate a questo tema
