{"id":571,"date":"2024-03-04T13:21:45","date_gmt":"2024-03-04T12:21:45","guid":{"rendered":"https:\/\/sparrow365.de\/?p=571"},"modified":"2024-11-04T20:20:51","modified_gmt":"2024-11-04T19:20:51","slug":"du-brauchst-wahrscheinlich-kein-application-readwrite-all","status":"publish","type":"post","link":"https:\/\/sparrow365.de\/index.php\/2024\/03\/04\/du-brauchst-wahrscheinlich-kein-application-readwrite-all\/","title":{"rendered":"Du brauchst (wahrscheinlich) kein Application.ReadWrite.All"},"content":{"rendered":"<p>Als Microsoft den <strong>Midnight Blizzard-Angriff vom Januar<\/strong> zum ersten Mal <a href=\"https:\/\/msrc.microsoft.com\/blog\/2024\/01\/microsoft-actions-following-attack-by-nation-state-actor-midnight-blizzard\/\">bekannt gab<\/a> und ihre darauf folgende <a href=\"https:\/\/www.microsoft.com\/en-us\/security\/blog\/2024\/01\/25\/midnight-blizzard-guidance-for-responders-on-nation-state-attack\/\">tiefere Analyse ver\u00f6ffentlichte<\/a>, verfolgte ich den resultierenden Inhalt mit gro\u00dfem Interesse \u2013 <strong>Risiken, die von Enterprise Applikationen ausgehen<\/strong>, sind ein Herzensthema f\u00fcr mich.<\/p>\n<p>Wenn Sie Microsoft 365 auf einem vern\u00fcnftigen Niveau nutzen, werden Sie <strong><em>unweigerlich<\/em><\/strong> Enterprise Applikationen mit einem gro\u00dfen Umfang an Berechtigungen <strong>in Ihrem Tenant<\/strong> haben (denken Sie an Backup-L\u00f6sungen, Skriptautomatisierungen usw.) &#8211; deshalb sollten Sie die Entra ID Rolle <em>&quot;(Cloud) App Administrator&quot;<\/em> <strong>wie einen Globalen Administrator<\/strong> behandeln. Durch das Setzen von Anmeldeinformationen f\u00fcr Applikationen, k\u00f6nnen sie sich mit den zugeh\u00f6rigen APIs in dessen Namen verbinden und Privilegien nutzen, die Sie den Benutzern vielleicht nie gew\u00e4hrt h\u00e4tten. Das gilt auch f\u00fcr den Graph API Scope &quot;Application.ReadWrite.All&quot;.<\/p>\n<p>Da ich nichts zu den Hauptinteressenspunkten des Breach hinzuzuf\u00fcgen habe, <a href=\"https:\/\/jeffreyappel.nl\/pivot-via-oauth-applications-across-tenants-and-what-to-for-protection-with-microsoft-technology-midnight-blizzard\/\">lateral movement zwischen Tenants<\/a> durch Unternehmensanwendungen und wie man <a href=\"https:\/\/janbakker.tech\/a-love-story-about-role-based-access-control-for-applications-in-exchange-online-managed-identities-entra-id-admin-units-and-graph-api\/\">richtig API-Berechtigungen in Exchange Online erteilt<\/a>, werde ich diese Themen nicht erneut betrachten. Es gibt jedoch einen Bereich, in dem ich gerne mehr Informationen sehen w\u00fcrde &#8211; einmal in Ihrem <em>Tenant entdeckt<\/em>, ist es manchmal nicht einfach zu finden, wie man sich von <strong>hochprivilegierten API-Rollen befreit oder sie vermeidet<\/strong>. Ein solches Beispiel ist <a href=\"https:\/\/learn.microsoft.com\/en-us\/graph\/permissions-reference#applicationreadwriteall\">Application.ReadWrite.All<\/a>.<\/p>\n<p>Die gesamte Midnight Blizzard Angriffskette k\u00f6nnte direkt mit einem App-Besitzer der Multi-Tenant-App begonnen haben, aber es h\u00e4tte leicht eine Anwendung im Test-Mandanten mit dieser Berechtigung sein k\u00f6nnen, durch die der Angreifer zur Multi-Tenant-App wechselte (Microsoft ist hier\u00fcber nicht ganz klar).<\/p>\n<p>Schauen wir uns also einige Anwendungsf\u00e4lle an, bei denen der <strong>erste Reflex<\/strong> sein k\u00f6nnte, <strong>&quot;Application.ReadWrite.All&quot; zu verwenden, es aber bessere L\u00f6sungen gibt<\/strong>:<\/p>\n<blockquote>\n<p>Ich werde in meinen Demos PowerShell verwenden, aber da Graph eine REST-API ist, k\u00f6nnen Beispiele auf jede Programmiersprache mit Unterst\u00fctzung f\u00fcr HTTP-Anfragen \u00fcbertragen werden<br \/>\n<em>I hold these truths to be self evident: Delegierte Berechtigungen sind vorzuziehen gegen\u00fcber Anwendungsberechtigungen, und wenn Sie nur Read ben\u00f6tigen, verwenden Sie keinen ReadWrite Scope<\/em><\/p>\n<\/blockquote>\n<p><br class=\"\"><\/p>\n<h2>Allgemeine Konfigurationsverwaltung<\/h2>\n<p>Im Gro\u00dfteil der F\u00e4lle wollen wir nicht <strong>alle<\/strong> Anwendungen im Tenant verwalten, sondern nur eine begrenzte Auswahl. Beginnen wir mit einer Enterprise App, die ihre eigene Konfiguration verwalten m\u00f6chte.<\/p>\n<blockquote>\n<p>Denken Sie daran: In der Graph API sind <em>App Registrations<\/em> auf dem <strong>application<\/strong> Endpunkt, eine <em>Enterprise App<\/em> ist ein <strong>servicePrincipal<\/strong> &#8211; <a href=\"https:\/\/www.shankuehn.io\/post\/app-registration-vs-enterprise-applications\"><em>Kurze Zusammenfassung des Unterschieds<\/em><\/a><br \/>\nWenn ich es zu oft schreibe, k\u00f6nnte ich App Registrations als &quot;<strong>AppRegs<\/strong>&quot; und Enterprise Apps als &quot;<strong>EApps<\/strong>&quot; k\u00fcrzen.<\/p>\n<\/blockquote>\n<h3>Erster Versuch<\/h3>\n<p>Wenn wir uns die <a href=\"https:\/\/learn.microsoft.com\/en-us\/graph\/api\/application-update?view=graph-rest-1.0&amp;tabs=http#permissions\">Graph API Dokumentation<\/a> f\u00fcr die Verwaltung von App Registrations ansehen, k\u00f6nnen wir bereits eine potenzielle Option sehen (das Gleiche gilt f\u00fcr <a href=\"https:\/\/learn.microsoft.com\/en-us\/graph\/api\/serviceprincipal-update?view=graph-rest-1.0&amp;tabs=http#permissions\">Enterprise Apps<\/a>):<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/sparrow365.de\/wp-content\/uploads\/2024\/02\/4_ApplicationPATCHPermissions.png\" alt=\"DocumentedLeastPrivileges\" \/><\/p>\n<p>Also f\u00fcgen wir den Scope unserer App Registration hinzu, gew\u00e4hren die Berechtigungen auf der Enterprise App und sind fertig, richtig?<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/sparrow365.de\/wp-content\/uploads\/2024\/02\/5_AppPermissions.png\" alt=\"activeScopes\" \/><\/p>\n<p>Jetzt, da ich den Scope in meiner Graph Session habe, versuche ich, meine EApp so zu \u00e4ndern, dass ein Benutzer zugewiesen sein muss, bevor er sich anmelden kann:<br \/>\n<code>Invoke-MgGraphRequest &quot;PATCH&quot; &quot;https:\/\/graph.microsoft.com\/v1.0\/servicePrincipals(appId=&#039;$($graphConfig.clientID)&#039;)&quot; -Body @{ appRoleAssignmentRequired = $true }<\/code><\/p>\n<p><strong>Und werde prompt abgelehnt:<\/strong><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/sparrow365.de\/wp-content\/uploads\/2024\/02\/3_PatchYourself.png\" alt=\"ErrorMessageSelfPatch\" \/><\/p>\n<h3>Owner Rechte hinzuf\u00fcgen<\/h3>\n<p>Das ist logisch, wenn wir dar\u00fcber nachdenken. Wir haben der Enterprise App die Berechtigung gegeben, Anwendungen zu verwalten, die <strong>sie besitzt<\/strong>, aber <strong>wir besitzen nichts<\/strong> <a href=\"https:\/\/learn.microsoft.com\/en-us\/entra\/identity\/enterprise-apps\/overview-assign-app-owners\">(Hier klicken f\u00fcr Microsofts \u00dcbersicht \u00fcber Anwendungsbesitz)<\/a>. Wie k\u00f6nnen wir das also beheben? Zum Zeitpunkt des Verfassens (Feb. 2024) bietet das Entra Portal keine EApps an, wenn wir versuchen, einen Owner zu einer Enterprise App oder einer App Registration hinzuzuf\u00fcgen.<\/p>\n<p>Wenn wir uns jedoch mit dem <strong>delegierten<\/strong> Scope &quot;Application.ReadWrite.All&quot; als Benutzer mit mindestens Application Administrator (oder Owner) gegen die Graph API authentifizieren, k\u00f6nnen wir den notwendigen Besitz hinzuf\u00fcgen &#8211; ein Objekt kann sogar sich selbst besitzen.<\/p>\n<blockquote>\n<p>Denken Sie daran &#8211; Auch wenn Anmeldeinformationen auf der App Registration konfiguriert sind, <strong>h\u00e4lt die Enterprise App \/ der service Principal alle Berechtigungen im Tenant<\/strong><\/p>\n<p>Siehe auch die <a href=\"https:\/\/learn.microsoft.com\/en-us\/graph\/api\/serviceprincipal-post-owners?view=graph-rest-1.0&amp;tabs=http\">Microsoft Dokumentation zum Hinzuf\u00fcgen von Ownern zu Enterprise Apps<\/a><\/p>\n<\/blockquote>\n<pre><code class=\"language-powershell\"># Objekt-ID unserer EApp \u00fcber App \/ Client ID abrufen\n$enterpriseAppID    = ( Invoke-MgGraphRequest &quot;GET&quot; &quot;https:\/\/graph.microsoft.com\/v1.0\/servicePrincipals(appId=&#039;$($graphConfig.clientID)&#039;)?select=id&quot; ).id\n\n# Die EApp als ihren eigenen Owner hinzuf\u00fcgen\n$params = @{ &quot;@odata.id&quot; = &quot;https:\/\/graph.microsoft.com\/v1.0\/servicePrincipals\/$enterpriseAppID&quot; }\nInvoke-MgGraphRequest &quot;POST&quot; &quot;https:\/\/graph.microsoft.com\/v1.0\/servicePrincipals\/$enterpriseAppID\/owners\/`$ref&quot; -Body $params<\/code><\/pre>\n<p><br class=\"\"><\/p>\n<p>Versuchen wir es also erneut:<br \/>\n<code>Invoke-MgGraphRequest &quot;PATCH&quot; &quot;https:\/\/graph.microsoft.com\/v1.0\/servicePrincipals(appId=&#039;$($graphConfig.clientID)&#039;)&quot; -Body @{ appRoleAssignmentRequired = $true }<\/code><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/sparrow365.de\/wp-content\/uploads\/2024\/02\/6_UpdateAppRegSuccess.png\" alt=\"alt\" \/><\/p>\n<p><strong>Erfolg! Und wir k\u00f6nnen den gesamten Tenant von hier aus nicht \u00fcbernehmen, da wir nur eine Anwendung besitzen<\/strong> \ud83e\udd73<\/p>\n<p>Interessanterweise, obwohl wir Enterprise Apps nicht \u00fcber die UI als Owner hinzuf\u00fcgen k\u00f6nnen, sobald wir sie hinzugef\u00fcgt haben, sind sie sichtbar:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/sparrow365.de\/wp-content\/uploads\/2024\/02\/2_DisplayedOwners.png\" alt=\"PortalOwnerView\" \/><\/p>\n<p><br class=\"\"><\/p>\n<p>Wenn wir die Eigenschaften unserer App Registration \u00e4ndern m\u00fcssen, k\u00f6nnen wir auch dort Owner wie folgt hinzuf\u00fcgen:<\/p>\n<blockquote>\n<p>In diesem Beispiel verwende ich immer noch die App \/ Client ID der EApp, als die ich angemeldet bin, ersetzen Sie sie bei Bedarf<\/p>\n<p>Siehe auch die <a href=\"https:\/\/learn.microsoft.com\/en-us\/graph\/api\/application-post-owners?view=graph-rest-1.0&amp;tabs=http\">Microsoft Dokumentation zum Hinzuf\u00fcgen von Ownern zu App Registrations<\/a><\/p>\n<\/blockquote>\n<pre><code class=\"language-powershell\"># Die ID der EApp abrufen, die wir f\u00fcr das Management verwenden m\u00f6chten\n$enterpriseAppID    = (Invoke-MgGraphRequest &quot;GET&quot; &quot;https:\/\/graph.microsoft.com\/v1.0\/servicePrincipals(appId=&#039;$($graphConfig.clientID)&#039;)?select=id&quot;).id\n$appRegistrationID  = (Invoke-MgGraphRequest &quot;GET&quot; &quot;https:\/\/graph.microsoft.com\/v1.0\/applications(appId=&#039;$($graphConfig.clientID)&#039;)?select=id&quot;).id\n\n# Wir f\u00fcgen unsere EApp als den Owner der AppReg hinzu\n$params = @{ &quot;@odata.id&quot; = &quot;https:\/\/graph.microsoft.com\/v1.0\/servicePrincipals\/$enterpriseAppID&quot; }\nInvoke-MgGraphRequest &quot;POST&quot; &quot;https:\/\/graph.microsoft.com\/v1.0\/applications\/$appRegistrationID\/owners\/`$ref&quot; -Body $params<\/code><\/pre>\n<p><br class=\"\"><\/p>\n<p>Und wieder sind wir erfolgreich:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/sparrow365.de\/wp-content\/uploads\/2024\/02\/1_SuccessfullPatchOwnAppRegistration.png\" alt=\"appRegEditSuccess\" \/><\/p>\n<p><br class=\"\"><\/p>\n<h2>App Credentials verwalten<\/h2>\n<p>Einer der h\u00e4ufigsten Anfragen im Anwendungsmanagement ist wahrscheinlich, <strong>selbstverwaltung von Anmeldeinformationen<\/strong>. Das konsistente Ablaufen von Geheimnissen und Zertifikaten erfordert entweder eine genaue \u00dcberwachung oder, vorzugsweise, Automatisierung.<\/p>\n<p>Mit &quot;<strong>Application.ReadWrite.OwnedBy<\/strong>&quot; und unserer Enterprise App, die bereits im letzten Kapitel Owner an der App Registration erhalten hat, k\u00f6nnen wir Anmeldeinformationen aktualisieren &#8211; es handelt sich schlie\u00dflich nur um eine weitere Eigenschaft.<\/p>\n<h3>Secrets<\/h3>\n<blockquote>\n<p>Siehe auch die <a href=\"https:\/\/learn.microsoft.com\/en-us\/graph\/api\/application-update?view=graph-rest-1.0&amp;tabs=http\">Microsoft Dokumentation zum Aktualisieren von App Registrations<\/a><\/p>\n<\/blockquote>\n<pre><code class=\"language-powershell\">$appRegistrationID  = (Invoke-MgGraphRequest &quot;GET&quot; &quot;https:\/\/graph.microsoft.com\/v1.0\/applications(appId=&#039;$($graphConfig.clientID)&#039;)?select=id&quot;).id\n$params = @{\n    passwordCredential = @{\n        displayName = &quot;Secret$(get-date -f &quot;ddMMyy&quot;)&quot;\n    }\n}\n# Je nachdem, wo Sie das Geheimnis ben\u00f6tigen, ist es wahrscheinlich eine gute Idee, es so schnell wie m\u00f6glich dort abzulegen ;)\n$response = Invoke-MgGraphRequest POST &quot;https:\/\/graph.microsoft.com\/v1.0\/applications\/$appRegistrationID\/addPassword&quot; -Body $params<\/code><\/pre>\n<blockquote>\n<p><em>Wenn ich tats\u00e4chlich Secrets nutzen muss, bevorzuge ich, sie nur in SecureStrings zu speichern, da sie im Speicher besser gesch\u00fctzt sind:<\/em><br \/>\n<code>$secret = ConvertTo-SecureString $(Invoke-MgGraphRequest POST &quot;https:\/\/graph.microsoft.com\/v1.0\/applications\/$appRegistrationID\/addPassword&quot; -Body $params).secretText -AsPlainText -Force<\/code><\/p>\n<\/blockquote>\n<p>In unserer Antwort erhalten wir das secret als secretText, zusammen mit einigen Metadaten (denken Sie daran, es irgendwo zu speichern, sonst ist es f\u00fcr immer verloren):<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/sparrow365.de\/wp-content\/uploads\/2024\/02\/7_SecretMetadata.png\" alt=\"secretMetadata\" \/><\/p>\n<p>Wir k\u00f6nnen das Geheimnis auch in der UI sehen (nur nicht den Wert):<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/sparrow365.de\/wp-content\/uploads\/2024\/02\/8_SecretUI-e1709159393121.png\" alt=\"secretUI\" \/><\/p>\n<p><br class=\"\"><\/p>\n<h3>Keys \/ Zertifikate<\/h3>\n<p>Ich bin mir jedoch sicher, <strong>niemand ben\u00f6tigt noch Secrets<\/strong>. Sie sind einfach so viel <strong>schlechter als asymmetrische Authentifizierungsmethoden<\/strong>, also haben offensichtlich alle Anwendungen auf <strong>Zertifikate f\u00fcr die Authentifizierung umgestellt<\/strong>, nicht wahr? RICHTIG? Ein Mann darf tr\u00e4umen&#8230;<\/p>\n<p><a href=\"https:\/\/learn.microsoft.com\/en-us\/graph\/api\/application-addkey?view=graph-rest-1.0&amp;tabs=http#permissions\">Theoretisch br\u00e4uchten wir f\u00fcr Zertifikatrotation <strong>nicht mal<\/strong> &quot;<em>Application.ReadWrite.OwnedBy<\/em>&quot;<\/a> Berechtigungen, aber es ist <a href=\"https:\/\/learn.microsoft.com\/en-us\/answers\/questions\/587303\/access-token-missing-or-malformed-when-doing-addke\">mir nicht gelungen<\/a>, dies in PowerShell umzusetzen &#8211; ich werde zu dem Thema vermutlich sp\u00e4ter zur\u00fcck kehren oder w\u00fcrde mich sehr \u00fcber einen Hinweis auf eine funktionierende Implementierung in der <a href=\"https:\/\/learn.microsoft.com\/en-us\/answers\/questions\/587303\/access-token-missing-or-malformed-when-doing-addke\">offenen Q&amp;A-Frage<\/a> freuen&#8230;<\/p>\n<p>Da ich die <em>wirklich coole<\/em> L\u00f6sung (vorerst) nicht demonstrieren kann, habe ich nicht viel zur <a href=\"[https:\/\/learn.microsoft.com\/en-us\/graph\/applications-how-to-add-certificate?tabs=powershell]\">Microsoft Dokumentation<\/a> hinzuzuf\u00fcgen. Ich verwende jedoch das Zertifikat aus dem Zertifikatsspeicher:<\/p>\n<blockquote>\n<p>Beachten Sie, dass dieser Befehl auf der App Registration <strong>ALLE DERZEIT KONFIGURIERTEN ZERTIFIKATE ERSETZT<\/strong>.<\/p>\n<\/blockquote>\n<pre><code class=\"language-powershell\">$Certificate = Get-Item &quot;Cert:\\CurrentUser\\My\\$($graphConfig.newThumb)&quot; -ErrorAction Stop\n$params = @{\n    keyCredentials = @(\n        @{\n            type = &quot;AsymmetricX509Cert&quot;\n            usage = &quot;Verify&quot;\n            key = [convert]::ToBase64String($Certificate.GetRawCertData())\n            displayName = &quot;CN=20240228&quot;\n        }\n    )\n}\nInvoke-MgGraphRequest PATCH &quot;https:\/\/graph.microsoft.com\/v1.0\/applications(appId=&#039;$($graphConfig.clientID)&#039;)&quot; -Body $params<\/code><\/pre>\n<p><br class=\"\"><\/p>\n<h2>Skalieren<\/h2>\n<p>Wir haben nun ein gutes Verst\u00e4ndnis davon, wie wir einzelne Anwendungen verwalten k\u00f6nnen. Aber wie k\u00f6nnen wir unseren <strong>Scope erweitern<\/strong>? Es gibt Anwendungsf\u00e4lle, bei denen wir die Kontrolle \u00fcber viele Enterprise Apps \/ App Registrations behalten wollen <em>(ich werde ab jetzt <strong>&quot;Apps&quot;<\/strong> als Kurzform f\u00fcr beide verwenden)<\/em>.<\/p>\n<p>Denken Sie an Infrastructure as Code-L\u00f6sungen wie Terraform oder vielleicht haben wir ein Backup-System, das <a href=\"[https:\/\/learn.microsoft.com\/en-us\/graph\/throttling-limits]\">Graph API-Ratenlimits<\/a> umgehen m\u00f6chte, indem <a href=\"https:\/\/documentation.commvault.com\/commvault\/v11_sp20\/article?p=105598.htm\">mehr EApps erstellt werden<\/a>.<\/p>\n<p>Im Wesentlichen ben\u00f6tigen wir mindestens eine &quot;Manager&quot;-App und eine Reihe von &quot;Worker&quot;-Apps. Die <em>l\u00e4stige<\/em> L\u00f6sung w\u00e4re, im Voraus eine Reihe von Apps zu erstellen &#8211; und danach die <a href=\"#owner-rechte-hinzuf\u00fcgen\">Basis-Zuweisung der Owner<\/a> durchzuf\u00fchren. Nicht ideal, aber gl\u00fccklicherweise ist es viel einfacher &#8211; wenn wir &quot;<strong>Application.ReadWrite.OwnedBy<\/strong>&quot; auf unserer &quot;Head&quot;-App verwenden, k\u00f6nnen wir sie dann nutzen, um <strong>bei Bedarf Apps zu erstellen<\/strong>.<\/p>\n<blockquote>\n<p><em>Wir k\u00f6nnen auch den servicePrincipal-Endpoint aufrufen, um zugeh\u00f6rige Enterprise Apps zu erstellen, aber das sieht im Grunde gleich aus<\/em><\/p>\n<\/blockquote>\n<p><code>Invoke-MgGraphRequest POST &quot;https:\/\/graph.microsoft.com\/v1.0\/applications&quot; -body @{ displayName = &quot;CreatedByApp&quot; }<\/code><\/p>\n<p>Die ausf\u00fchrende Enterprise App wird <strong>automatisch als Owner<\/strong> der neuen App hinzugef\u00fcgt:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/sparrow365.de\/wp-content\/uploads\/2024\/02\/10createNewApps.png\" alt=\"newAppReg\" \/><\/p>\n<p><br class=\"\"><\/p>\n<p>Allerdings wird es eine Herausforderung sein, den \u00dcberblick \u00fcber all unsere Owner Verh\u00e4ltnisse zu behalten. Die L\u00f6sungen, die mir derzeit bekannt sind, sind den <strong>Aufbau einer Automatisierung<\/strong> basierend auf <a href=\"https:\/\/learn.microsoft.com\/en-us\/entra\/fundamentals\/custom-security-attributes-overview\">Custom Security Attributes<\/a> oder die Erstellung eines <strong>Tracking-Systems<\/strong> in <a href=\"https:\/\/learn.microsoft.com\/en-us\/graph\/extensibility-overview?tabs=http#directory-microsoft-entra-id-extensions\">directory extensions<\/a>. In jedem Fall sind dies keine gro\u00dfartigen Optionen &#8211; sind wir also dazu verdammt, entweder <strong>viel zu breite Berechtigungen<\/strong> zu vergeben oder zu versuchen, ein potenziell <strong>komplexes Netz von Besitzverh\u00e4ltnissen<\/strong> im Auge zu behalten?<\/p>\n<p><br class=\"\"><\/p>\n<h2>Die &quot;Beste&quot; Option<\/h2>\n<p>Wenn wir <strong>wirklich<\/strong> den Ansatz von &quot;least privilege&quot; verfolgen wollen, sind Graph API Scopes nicht der Weg. Im Kern sind Apps Entra ID Objekte, was <a href=\"https:\/\/learn.microsoft.com\/en-us\/entra\/identity\/role-based-access-control\/custom-enterprise-app-permissions\">custom roles<\/a> zu einer deutlich granulareren Option f\u00fcr das Berechtigungsmanagement macht. &quot;<strong>Application.ReadWrite.OwnedBy<\/strong>&quot; ist zuf\u00e4llig fast ein <strong>direkter Ersatz<\/strong> f\u00fcr das h\u00e4ufig verwendete &quot;<strong>Application.ReadWrite.All<\/strong>&quot;.<\/p>\n<blockquote>\n<p>OAuth Scopes haben den Vorteil, dass sie leicht zwischen Tenants \u00fcbertragbar sind &#8211; wenn eine Anwendung nur f\u00fcr Ihren Tenant erstellt wird, ist das kein stichhaltiges Argument, und wenn sie einer Multi-Tenant-App diese Rechte geben sollen m\u00fcssen sie dem Entwickler wirklich WIRKLICH vertrauen&#8230;<\/p>\n<\/blockquote>\n<p>Sobald wir uns die in Entra ID verf\u00fcgbaren Optionen anschauen, gibt es eine schmerzlich offensichtliche L\u00f6sung: F\u00fcr Benutzer, Gruppen und Ger\u00e4te k\u00f6nnen wir bereits <a href=\"https:\/\/learn.microsoft.com\/en-us\/entra\/identity\/role-based-access-control\/administrative-units\"><strong>Administrative Units<\/strong><\/a> erstellen. Diese erm\u00f6glichen das Einschr\u00e4nken von integrierten und benutzerdefinierten Rollen auf <strong>Teilbereiche eines Tenants<\/strong>, einschlie\u00dflich der Erstellung neuer Objekte innerhalb des Geltungsbereichs.<br \/>\nSomit h\u00e4tten wir eine leicht <strong>skalierbare und nachvollziehbare Sammlung<\/strong> von Apps.<br \/>\nLeider wird die Verwendung von AUs zur Verwaltung von Apps derzeit (M\u00e4rz 2024) von Microsoft <strong>nicht unterst\u00fctzt<\/strong>&#8230;<\/p>\n<p><br class=\"\"><\/p>\n<h2>Abschlie\u00dfende Worte<\/h2>\n<p>Bei Ihrer <a href=\"https:\/\/www.michev.info\/blog\/post\/5922\/reporting-on-entra-id-integrated-applications-service-principals-and-their-permissions\">n\u00e4chsten \u00dcberpr\u00fcfung der App-Berechtigungen<\/a> fragen Sie Entwickler, ob es m\u00f6glich w\u00e4re, <strong>weniger Berechtigungen<\/strong> zu verwenden. Denken Sie daran, dass <strong>Sicherheit oft sekund\u00e4r<\/strong> im Entwicklungsprozess ist. Fordern Sie die Behauptung &#8218;<em>wir brauchen das einfach<\/em>&#8218; heraus, indem Sie nach den spezifischen Anwendungsf\u00e4llen suchen, die abgedeckt werden m\u00fcssen &#8211; vielleicht gibt es L\u00f6sungen, die noch nicht in Betracht gezogen wurden.<\/p>\n<p>Andererseits, auch wenn ich erl\u00e4utere, wie wir <em>Application.ReadWrite.All<\/em> ersetzen k\u00f6nnen und sollten, ist dies nicht <em>immer<\/em> eine gute Idee. Wenn es ein System gibt, das 90% der Apps besitzt, rechtfertigt der <strong>Verwaltungsaufwand<\/strong> normalerweise nicht die geringf\u00fcgig erh\u00f6hte Sicherheit.<br \/>\nAu\u00dferdem, wenn Sie die Option von Entra ID benutzerdefinierten Rollen interessant finden, <strong>ist es nicht einfach<\/strong> zu verstehen, welche Entra ID Berechtigungen f\u00fcr eine bestimmte Graph-Operation notwendig sind &#8211; Sie m\u00fcssen bereit sein, ein wenig Trial and Error in Kauf zu nehmen.<\/p>\n<p><br class=\"\"><\/p>\n<p>Habe ich einen g\u00e4ngigen Anwendungsfall \u00fcbersehen oder m\u00f6chten Sie diskutieren, warum man <strong>Application.ReadWrite.All<\/strong> ben\u00f6tigen k\u00f6nnte? Ich m\u00f6chte Ihre E-Mail-Adresse nicht, also bitte <a href=\"https:\/\/www.linkedin.com\/posts\/julian-sperling-4bba72228_you-probably-dont-need-applicationreadwriteall-activity-7170393660268773377-wlmL?utm_source=share&amp;utm_medium=member_desktop\">diskutieren Sie in meinem zugeh\u00f6rigen LinkedIn-Post<\/a>.<\/p>\n<p>Wenn Sie an den Dingen interessiert sind, die ich mache, folgen Sie mir auf LinkedIn.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Als Microsoft den Midnight Blizzard-Angriff vom Januar zum ersten Mal bekannt gab und ihre darauf folgende tiefere Analyse ver\u00f6ffentlichte, verfolgte ich den resultierenden Inhalt mit gro\u00dfem Interesse \u2013 Risiken, die von Enterprise Applikationen ausgehen, sind ein Herzensthema f\u00fcr mich. Wenn Sie Microsoft 365 auf einem vern\u00fcnftigen Niveau nutzen, werden Sie unweigerlich Enterprise Applikationen mit einem&#8230; &raquo; <a class=\"read-more-link\" href=\"https:\/\/sparrow365.de\/index.php\/2024\/03\/04\/du-brauchst-wahrscheinlich-kein-application-readwrite-all\/\">weiterlesen<\/a><\/p>\n","protected":false},"author":2,"featured_media":562,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[24,48],"tags":[72,74,243,245,247,70,156,249,251,64,52,60,56,253,58,160,150,255],"class_list":["post-571","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-me-id","category-powershell","tag-aad","tag-aad-connect","tag-administrative-units-de","tag-application-readwrite-all-de","tag-application-readwrite-ownedby-de","tag-azure-ad","tag-best-practices","tag-custom-roles-de","tag-enterprise-app-ownership-de","tag-entra","tag-entra-id","tag-graph","tag-graph-api","tag-least-privilege-de","tag-microsoft-graph","tag-minimize-access","tag-overprivilege","tag-security-de"],"_links":{"self":[{"href":"https:\/\/sparrow365.de\/index.php\/wp-json\/wp\/v2\/posts\/571","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sparrow365.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sparrow365.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sparrow365.de\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sparrow365.de\/index.php\/wp-json\/wp\/v2\/comments?post=571"}],"version-history":[{"count":5,"href":"https:\/\/sparrow365.de\/index.php\/wp-json\/wp\/v2\/posts\/571\/revisions"}],"predecessor-version":[{"id":580,"href":"https:\/\/sparrow365.de\/index.php\/wp-json\/wp\/v2\/posts\/571\/revisions\/580"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sparrow365.de\/index.php\/wp-json\/wp\/v2\/media\/562"}],"wp:attachment":[{"href":"https:\/\/sparrow365.de\/index.php\/wp-json\/wp\/v2\/media?parent=571"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sparrow365.de\/index.php\/wp-json\/wp\/v2\/categories?post=571"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sparrow365.de\/index.php\/wp-json\/wp\/v2\/tags?post=571"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}