Jeder Tenant muss sich früher oder später der Frage stellen, wie Entra Delegierte versus Anwendungsberechtigungen in der Graph API zu bewerten sind: Welches der beiden Consent-Modelle ist tatsächlich sicherer, und wie erteilt man einer App das Minimum, das sie benötigt, ohne sie zu brechen? Die meisten Teams beantworten das aus dem Bauchgefühl — delegierte Berechtigungen „laufen als Benutzer" und wirken dadurch begrenzt; Anwendungsberechtigungen „laufen als App" und wirken dadurch gefährlich. Dieses Bauchgefühl liegt zur Hälfte richtig — und ausgerechnet die falsche Hälfte ist die, die niemand prüft.
Die Berechtigung, die einer App leise einen Fuß in jedes Postfach im Tenant verschafft, ist nicht zwingend eine Anwendungsberechtigung. Es kann eine delegierte Berechtigung sein, der ein Administrator im Namen der gesamten Organisation zugestimmt hat — und dieser Grant liegt in einer anderen Objektsammlung als die App-Rollen, sodass ein Review der Anwendungsberechtigungen ihn nie zurückliefert.
Entra Delegierte versus Anwendungsberechtigungen der Graph API, definiert
Microsofts Identity Platform dokumentiert zwei Zugriffsszenarien, und der Unterschied liegt darin, als wer die App agiert — nicht darin, wie viel Schaden sie anrichten kann.
Delegierter Zugriff bedeutet, dass ein Benutzer sich angemeldet hat und die Client-Anwendung die Ressource in seinem Namen aufruft. Microsoft ist bei der Obergrenze eindeutig: „Die Anwendung kann nicht auf mehr zugreifen, als der angemeldete Benutzer selbst zugreifen könnte." Eine App mit der delegierten Berechtigung Files.Read.All „kann nur Dateien lesen, auf die der Benutzer persönlich Zugriff hat." Delegierte Berechtigungen werden auch Scopes genannt, und das resultierende Grant-Objekt ist ein oAuth2PermissionGrant.
Anwendungszugriff (App-only) bedeutet, dass die Anwendung eigenständig agiert, ohne dass ein Benutzer angemeldet ist — Daemons, Backups, Automatisierung. Hier ist die Ressource selbst die Obergrenze: Eine App mit der Microsoft-Graph-Anwendungsberechtigung Files.Read.All „kann mit Microsoft Graph jede Datei im Tenant lesen." Anwendungsberechtigungen sind App-Rollen, das Grant-Objekt ist ein appRoleAssignment, und laut Microsofts eigener Vergleichstabelle kann nur ein Administrator ihnen zustimmen.
| Delegierte Berechtigungen | Anwendungsberechtigungen | |
|---|---|---|
| Zugriffskontext | Im Namen eines angemeldeten Benutzers | Ohne Benutzer |
| Wer kann zustimmen | Benutzer für ihre eigenen Daten; Administratoren für alle Benutzer | Nur ein Administrator |
| Consent-Methoden | Statisch (App-Registrierung) oder dynamisch (bei der Anmeldung angefordert) | Nur statisch |
| Andere Bezeichnungen | Scopes, OAuth2-Berechtigungs-Scopes | App-Rollen, App-only-Berechtigungen |
| Grant-Objekt | oAuth2PermissionGrant | appRoleAssignment |
Diese letzte Zeile ist das ganze Problem in einem Satz. Die beiden Berechtigungstypen leben in zwei unterschiedlichen Objektsammlungen. Ein Audit, das appRoleAssignments aufzählt, sieht nichts von der delegierten Seite — und umgekehrt: Die beiden Abfragen liefern disjunkte Mengen zurück, sodass ein Review, das nur eine davon ausführt, über die Hälfte der Angriffsfläche schweigt.
Die zwei Arten, wie Tenants das Consent-Modell falsch herum lesen
„Delegiert ist die sichere Variante"
Der Satz „die App kann nicht mehr als der Benutzer" ist wahr — und er trägt dabei ein Gewicht, das er nie tragen sollte.
Ein delegierter Grant trägt ein Feld consentType mit zwei möglichen Werten. Microsofts Referenz ist eindeutig: „AllPrincipals gibt die Autorisierung an, alle Benutzer zu impersonieren. Principal gibt die Autorisierung an, einen bestimmten Benutzer zu impersonieren." Wenn consentType gleich AllPrincipals ist, ist principalId null — der Grant ist an niemanden gebunden, weil er für alle gilt.
Ein tenant-weiter Admin-Consent für die delegierte Berechtigung Mail.ReadWrite bedeutet also nicht, dass die App die gesamte Mail lesen kann. Er bedeutet, dass die App vorab autorisiert ist, im Postfach jedes Benutzers, der sich bei ihr anmeldet, zu agieren — ohne Consent-Prompt, solange der Grant existiert. Die Grenze bleiben weiterhin die eigenen Rechte des angemeldeten Benutzers — aber die Population ist das gesamte Verzeichnis, und die Reibung, die einen Benutzer normalerweise innehalten und einen Consent-Bildschirm lesen lässt, fehlt.
Und wer meldet sich eigentlich bei internen Tools an? Wenn sich ein Global Administrator oder ein Exchange Administrator bei einer App authentifiziert, die eine tenant-weite delegierte Directory.ReadWrite.All-Berechtigung hält, erbt die App die Reichweite dieser Sitzung. Delegiert ist keine feste Obergrenze für Privilegien — es ist eine Obergrenze, die sich mit dem jeweils angemeldeten Benutzer mitbewegt.
„Anwendungsberechtigungen sind die mächtigen, also fordern wir die an"
Der spiegelbildliche Fehler. Microsofts eigene Portal-Anleitung stellt delegierte Berechtigungen zuerst vor und beschreibt Anwendungsberechtigungen als die Option für „dienst- oder daemonartige Anwendungen, die ohne Benutzerinteraktion bei Anmeldung oder Consent selbst auf eine Web-API zugreifen müssen" — und genau diese Beschreibung ist der Grund, warum Entwickler danach greifen. Ein Dienst, der eigentlich nur ein einziges freigegebenes Postfach lesen muss, hält am Ende Mail.Read für die gesamte Organisation, weil das die einzige Granularität ist, die Entra ID auf der Graph-Berechtigung selbst anbietet.
Microsofts Einführung zum delegierten Zugriff ist unmissverständlich, welches Szenario wohin gehört: Delegierter Zugriff ist „in der Regel eine schlechte Wahl für Szenarien, die ohne angemeldeten Benutzer laufen müssen, wie Automatisierung", während man „delegierten Zugriff immer dann verwenden sollte, wenn ein angemeldeter Benutzer mit seinen eigenen oder für ihn zugänglichen Ressourcen arbeiten soll." Der Fehlerfall in echten Tenants ist die Wahl nach Bequemlichkeit — je nachdem, was ohne Browser-Prompt authentifiziert — statt nach der Frage, welches Principal die Daten tatsächlich braucht.
⚠️ Warnung: Die beiden Fehler summieren sich. Ein Tenant, der sowohl tenant-weite delegierte Scopes als auch ungescopte Anwendungsberechtigungen übervergibt, hat zwei unabhängige, sich addierende Pfade zu denselben Daten — nachverfolgt an zwei unterschiedlichen Stellen.
Was ein tenant-weiter delegierter Grant einem Angreifer bringt
Delegierter Zugriff braucht für den Erfolg zwei unabhängige Autorisierungen, und Microsoft dokumentiert sie getrennt: Client-App-Autorisierung (der App wurde der Scope gewährt, der im scp-Claim des Tokens landet) und Benutzer-Autorisierung (die Ressource prüft die eigenen Rechte des angemeldeten Benutzers). Microsofts OneDrive-Beispiel macht die Matrix explizit — eine Anfrage schlägt fehl, wenn entweder der Scope fehlt oder der Benutzer keine Rechte am Objekt hat.
Ein Angreifer muss dieses Modell nicht brechen. Er muss nur beide Hälften gleichzeitig erfüllen, und ein tenant-weiter Grant liefert ihm die erste Hälfte kostenlos:
- Der Scope ist bereits gewährt. Bei
consentType = AllPrincipalsgibt es keinen Consent-Prompt zum Phishen und keinen Grant pro Benutzer, der erst erstellt werden müsste. Jedes Token, das die App für einen beliebigen Benutzer erhält, trägt den Scope. - Die Benutzer-Hälfte kommt mit dem Opfer. Was auch immer der kompromittierte oder gephishte Benutzer erreichen kann, kann die App jetzt über die API erreichen — genau das ist der Unterschied zwischen „dieses eine Postfach in Outlook lesen" und „es programmatisch in Maschinengeschwindigkeit durchzählen." Und diese Reichweite ist oft größer, als das Organigramm vermuten lässt — siehe überprivilegierte Service-Principal-Admin-Rollen.
- Der Widerruf sitzt nicht dort, wo man ihn erwartet. Microsofts eigene Anleitung merkt an, dass man im Entra Admin Center „Berechtigungen im Tab Benutzereinwilligung nicht über das Portal widerrufen kann." Delegierte Grants pro Benutzer müssen über Graph oder PowerShell entfernt werden.
Das ist dieselbe Consent-Oberfläche, die auch OAuth-Consent-Phishing missbraucht — nur dass hier gar kein Phishing nötig ist. Der Grant existiert bereits, erteilt von einem Administrator, meist vor Jahren, meist für ein Tool, das immer noch installiert ist.
Zwei verwandte Registrierungseigenschaften vergrößern den Explosionsradius zusätzlich. signInAudience auf AzureADMultipleOrgs gesetzt macht die Registrierung multi-tenant-fähig — „Benutzer mit einem geschäftlichen oder schulischen Microsoft-Konto in jedem beliebigen Microsoft-Entra-Tenant einer Organisation" können sich anmelden. Und Apps, die niemand mehr nutzt, behalten ihre Grants unbegrenzt: Das Objekt oAuth2PermissionGrant besitzt keine Ablaufeigenschaft, sodass nichts einen Grant von selbst altern lässt — eine stillgelegte Integration mit einem noch gültigen Secret und einem noch gültigen tenant-weiten Grant ist ein Credential, das nur darauf wartet, gefunden zu werden. Siehe auch Entra App-Registrierung: Zugangsdaten-Rotation und Secrets-Hygiene.
Erkennung
Führen Sie diese Abfragen gegen den eigenen Tenant aus. Für das Lesen der Anmeldeaktivität wird AuditLog.Read.All (least privileged) sowie eine der Rollen Reports Reader, Security Reader oder Security Administrator benötigt; für das Lesen und Widerrufen von Grants mindestens Cloud Application Administrator.
| Worauf zu achten ist | Wo | Signal |
|---|---|---|
| Tenant-weite delegierte Grants | oauth2PermissionGrants | consentType eq 'AllPrincipals' — gilt für jeden Benutzer |
| Delegierte Grants pro Benutzer | oauth2PermissionGrants | consentType eq 'Principal', im Portal nicht widerrufbar |
| Anwendungsberechtigungen | servicePrincipals/{id}/appRoleAssignments | Ungescopt, konstruktionsbedingt tenant-weit |
| Multi-Tenant-Registrierungen | applications | signInAudience eq 'AzureADMultipleOrgs' |
| Ruhende Apps | /beta/reports/servicePrincipalSignInActivities | lastSignInActivity älter als 90 Tage |
Beginnen Sie mit den Grants, die für alle gelten. consentType unterstützt $filter mit eq:
GET https://graph.microsoft.com/v1.0/oauth2PermissionGrants?$filter=consentType eq 'AllPrincipals'
Jedes Ergebnis liefert clientId (die Objekt-ID des Client-Service-Principals — nicht dessen appId), resourceId (die aufgerufene API) und scope, eine durch Leerzeichen getrennte Liste wie openid User.Read GroupMember.Read.All. Das Äquivalent in Microsoft Graph PowerShell:
Connect-MgGraph -Scopes "Directory.Read.All"
Get-MgOauth2PermissionGrant -All | Where-Object { $_.ConsentType -eq 'AllPrincipals' } |
Select-Object ClientId, ResourceId, Scope
Rufen Sie anschließend die andere Sammlung für denselben Service Principal ab, denn die obige delegierte Abfrage zeigt sie nie:
GET https://graph.microsoft.com/v1.0/servicePrincipals/{id}/oauth2PermissionGrants
GET https://graph.microsoft.com/v1.0/servicePrincipals/{id}/appRoleAssignments
Multi-Tenant-Registrierungen — signInAudience unterstützt $filter mit eq, ne und not:
GET https://graph.microsoft.com/v1.0/applications?$filter=signInAudience eq 'AzureADMultipleOrgs'
Für ruhende Apps ist die Sign-in-Aktivität von Service Principals eine Beta-API — Microsoft weist darauf hin, dass APIs unter /beta Änderungen unterliegen und nicht für den Produktionseinsatz unterstützt werden. Behandeln Sie das also als Audit-Input, nicht als Control, auf das Sie sich verlassen. Sie unterstützt $top, $filter und $orderby:
GET https://graph.microsoft.com/beta/reports/servicePrincipalSignInActivities
Import-Module Microsoft.Graph.Beta.Reports
Get-MgBetaReportServicePrincipalSignInActivity
Jeder Datensatz liefert lastSignInActivity sowie eine Aufschlüsselung, die zeigt, wie die App genutzt wird: delegatedClientSignInActivity (sie agiert für einen angemeldeten Benutzer) versus applicationAuthenticationClientSignInActivity (App-only, kein Benutzer). Diese Aufteilung ist der schnellste Weg, um eine App zu erwischen, die beide Berechtigungsarten hält, aber tatsächlich immer nur eine davon nutzt — und sie fließt direkt in die Erkennung von Anmeldeanomalien bei Service Principals ein.
Behebung
💡 Quick Win: Zählen Sie zuerst consentType eq 'AllPrincipals' auf und widerrufen Sie die Grants von Apps, für die niemand einen Owner benennen kann. Das ist der kürzeste Weg vom Audit zu einem reduzierten Explosionsradius.
- Stoppen Sie neuen Über-Consent an der Tür. Gehen Sie im Microsoft Entra Admin Center zu Identität > Anwendungen > Enterprise-Anwendungen > Consent und Berechtigungen > Benutzereinwilligungseinstellungen (Global Administrator für das Portal; Privileged Role Administrator ansonsten). Standardmäßig „dürfen alle Benutzer Anwendungen für Berechtigungen zustimmen, die keinen Administrator-Consent erfordern." Die beiden integrierten Richtlinien sind
microsoft-user-default-legacy(Benutzer-Consent für Apps erlauben — jede Berechtigung, die keinen Admin-Consent erfordert, jede App) undmicrosoft-user-default-low(Benutzer-Consent nur für Apps von verifizierten Herausgebern oder im eigenen Tenant registrierte Apps erlauben, und nur für Berechtigungen, die Sie als Low Impact klassifiziert haben). Programmatisch:
PATCH https://graph.microsoft.com/v1.0/policies/authorizationPolicy
{
"defaultUserRolePermissions": {
"permissionGrantPoliciesAssigned": [
"managePermissionGrantsForSelf.microsoft-user-default-low",
"managePermissionGrantsForOwnedResource.{other-current-policies}"
]
}
}
Lesen Sie zuerst die aktuelle authorizationPolicy aus und erhalten Sie bestehende ManagePermissionGrantsForOwnedResource.*-Einträge, sonst entfernen Sie stillschweigend das Self-Service-Consent für Entwickler. Kombinieren Sie das mit dem Admin-Consent-Workflow, damit Benutzer eine Prüfung anfordern können, statt in eine Sackgasse zu laufen, und prüfen Sie das zusammen mit den übrigen Tenant-Standardbenutzereinstellungen, die regeln, was Nicht-Administratoren erstellen dürfen.
⚠️ Warnung: Diese Einstellung zu ändern, behebt nur die Zukunft. Microsoft ist eindeutig: „Alle Aktualisierungen der Benutzereinwilligungseinstellungen wirken sich nur auf zukünftige Consent-Vorgänge für Anwendungen aus. Bestehende Consent-Grants bleiben unverändert." Die Richtlinie zu verschärfen widerruft keinen einzigen bestehenden Grant.
- Widerrufen Sie, was bereits existiert. Delegierte und Anwendungsberechtigungen werden über unterschiedliche Endpunkte entfernt:
DELETE https://graph.microsoft.com/v1.0/oAuth2PermissionGrants/{id}
DELETE https://graph.microsoft.com/v1.0/servicePrincipals/{resource-servicePrincipal-id}/appRoleAssignedTo/{appRoleAssignment-id}
Denken Sie an die Portal-Einschränkung: Der Tab Admin consent unterstützt den Widerruf in der UI, der Tab User consent nicht. Und Widerruf allein ist nicht dauerhaft — Microsoft merkt an, dass „das Widerrufen der aktuell erteilten Berechtigung Benutzer nicht daran hindert, den von der Anwendung angeforderten Berechtigungen erneut zuzustimmen." Sie müssen die Berechtigung außerdem aus dem entfernen, was die App anfordert, oder den Benutzer-Consent komplett blockieren.
- Scopen Sie Anwendungsberechtigungen, statt tenant-weite zu akzeptieren. Für Exchange-Workloads lässt RBAC for Applications Sie eine App-Rolle mit einem Ressourcen-Scope kombinieren, sodass
Mail.Readeine gefilterte Menge an Postfächern abdeckt statt aller. Die Zuweisung dieser Rollen erfordert Mitgliedschaft in der Rollengruppe Organization Management in Exchange Online sowie die Rolle Exchange Administrator in Microsoft Entra ID:
New-ServicePrincipal -AppId <appId> -ObjectId <servicePrincipalObjectId> -DisplayName "reporting-app"
New-ManagementScope -Name "Canadian users" -RecipientRestrictionFilter "CustomAttribute1 -eq '012332'"
New-ManagementRoleAssignment -App <servicePrincipalObjectId> -Role "Application Mail.Read" -CustomResourceScope "Canadian users"
Test-ServicePrincipalAuthorization -Identity "reporting-app" -Resource <targetMailbox> | Format-Table
Hier lauert eine Falle, in die fast jeder tappt. Microsofts FAQ stellt es klar: Berechtigungen aus den beiden Autoritäten bilden eine Vereinigung, keine Schnittmenge. „Wenn Ihr Service Principal Mail.Read in Microsoft Entra ID erteilt bekommen hat und Sie eine ressourcengescopte Mail.Read-Berechtigung in Application RBAC konfigurieren, ist es wichtig, die Zuweisung von Mail.Read aus Microsoft Entra ID zu entfernen. Andernfalls führt die Vereinigung ... zu keinem wirksamen Resource Scoping." In Exchange zu scopen, während der Entra-Grant bestehen bleibt, ändert nichts. Beachten Sie außerdem, dass Berechtigungsänderungen zwischen 30 Minuten und 2 Stunden gecacht werden (das Test-Cmdlet umgeht den Cache) und dass exklusive Management-Scopes den App-Zugriff nicht einschränken.
-
Deaktivieren Sie ruhende Registrierungen. Alles ohne
lastSignInActivityseit 90 Tagen ist ein Kandidat für Deaktivieren-dann-Löschen. Halten Sie diese Reihenfolge ein, damit Sie schnell wiederherstellen können, falls sich herausstellt, dass ein Quartalsjob davon abhängt. Das Löschen des Service Principals in Entra entfernt automatisch auch dessen Exchange-RBAC-Zuweisungen. -
Machen Sie das Review wiederkehrend, und decken Sie beide Sammlungen ab. Ein Review, das nur
appRoleAssignmentsliest, lässt einen Tenant durchgehen, dessen eigentliche Exposition ein fünf Jahre alterAllPrincipals-Grant ist. Betten Sie das in das umfassendere Entra-ID-Sicherheitsaudit ein, statt es als einmaliges Aufräumen zu behandeln — Consent-Grants haben kein Ablaufdatum, daher bleibt die Drift hier dauerhaft bestehen, bis jemand hinschaut.
Wie EtcSec das erkennt
EtcSecs Azure-Katalog deckt beide Hälften des Consent-Modells ab. APP_EXCESSIVE_DELEGATED kennzeichnet Anwendungen, die mehr delegierte Scopes halten, als ihre Funktion rechtfertigt, und APP_CONSENT_GRANTED_TENANT_WIDE deckt die AllPrincipals-Grants auf, die ein auf App-Rollen ausgerichtetes Berechtigungsreview übersieht. APP_USER_CONSENT_UNRESTRICTED und APP_ADMIN_CONSENT_NOT_REQUIRED prüfen die Tenant-Einstellungen, die diese Grants überhaupt erst akkumulieren lassen, während APP_MULTI_TENANT Registrierungen identifiziert, deren signInAudience über das eigene Verzeichnis hinausgeht, und APP_UNUSED_90_DAYS die Registrierungen auflistet, die noch lange, nachdem sie niemand mehr nutzt, aktive Grants halten.
Für die Anwendungsberechtigungs-Seite desselben Problems — konkret die App-Rollen Directory, Mail, Files und RoleManagement — siehe Entra App-Registrierung: gefährliche Graph-API-Berechtigungen und Azure App-Registrierungen: überprivilegierte Tenant-Apps.
ℹ️ Hinweis: EtcSec prüft bei jedem Entra-ID-Audit automatisch auf diese Fehlkonfigurationen. Führen Sie ein kostenloses Audit durch, um zu sehen, welche Ihrer App-Registrierungen heute tenant-weite Grants halten.
Quellen
- Overview of permissions and consent in the Microsoft identity platform
- Microsoft identity platform delegated access scenario
- Web API app registration and API permissions (delegated and application permissions in the portal)
- oAuth2PermissionGrant resource type (Microsoft Graph v1.0)
- List oAuth2PermissionGrants (Microsoft Graph v1.0)
- application resource type — signInAudience (Microsoft Graph v1.0)
- Configure how users consent to applications
- Review permissions granted to enterprise applications
- servicePrincipalSignInActivity resource type (Microsoft Graph beta)
- List servicePrincipalSignInActivities (Microsoft Graph beta)
- Role Based Access Control for Applications in Exchange Online
Entdecken Sie die Identity-Security-Seiten zu diesem Thema
