From 465e55ed2a252b8c467c9d1abbd76fa33d405cbd Mon Sep 17 00:00:00 2001 From: Henrik Piecha Date: Wed, 29 Jan 2025 14:20:06 +0100 Subject: [PATCH 1/3] added test where it validates if any app registration has tier-0 graph permissions assigned --- .../entra/Test-MtHighRiskAppPermissions.md | 53 +++ .../entra/Test-MtHighRiskAppPermissions.ps1 | 367 ++++++++++++++++++ .../Test-MtHighRiskAppPermissions.Tests.ps1 | 8 + 3 files changed, 428 insertions(+) create mode 100644 powershell/public/maester/entra/Test-MtHighRiskAppPermissions.md create mode 100644 powershell/public/maester/entra/Test-MtHighRiskAppPermissions.ps1 create mode 100644 tests/Maester/Entra/Test-MtHighRiskAppPermissions.Tests.ps1 diff --git a/powershell/public/maester/entra/Test-MtHighRiskAppPermissions.md b/powershell/public/maester/entra/Test-MtHighRiskAppPermissions.md new file mode 100644 index 00000000..69f4ef9a --- /dev/null +++ b/powershell/public/maester/entra/Test-MtHighRiskAppPermissions.md @@ -0,0 +1,53 @@ +Ensure no graph application has permissions with a risk of having a direct or indirect path to Global Admin and full tenant takeover. + +This test if any application has tier-0 graph permissions with a risk of having a direct or indirect path to Global Admin and full tenant takeover. + +Following is a shortened copy from [Application permissions - Tier 0: Family of Global Admins](https://github.com/emiliensocchi/azure-tiering/tree/main/Microsoft%20Graph%20application%20permissions#tier-0), Date: 20.01.2025 + +| Application permission | Path type | Known shortest path | +| --- | --- | --- | +| [AdministrativeUnit.ReadWrite.All](https://learn.microsoft.com/en-us/graph/permissions-reference#administrativeunitreadwriteall) | Indirect | When combined with other types of access allowing to reset user passwords, can remove a Global Admin from a [Restricted Management Administrative Unit (RMAU)](https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/admin-units-restricted-management) and take it over. | +| [Application.ReadWrite.All](https://learn.microsoft.com/en-us/graph/permissions-reference#applicationreadwriteall) | Indirect | Can impersonate any SP with more privileged application permissions granted for MS Graph, and impersonate it to escalate to Global Admin. | +| [Application.ReadWrite.OwnedBy](https://learn.microsoft.com/en-us/graph/permissions-reference#applicationreadwriteownedby) | Indirect | Same as [Application.ReadWrite.All](#application-readwrite-all), but the impersonation is limited to the SP(s) for which the compromised SP is an owner. | +| [AppRoleAssignment.ReadWrite.All](https://learn.microsoft.com/en-us/graph/permissions-reference#approleassignmentreadwriteall) | Indirect | Can assign the [RoleManagement.ReadWrite.Directory](#rolemanagement-readwrite-directory) permission to the compromised SP *without* requiring admin consent, and escalate to Global Admin. | +| [DeviceManagementConfiguration.ReadWrite.All](https://learn.microsoft.com/en-us/graph/permissions-reference#devicemanagementconfigurationreadwriteall) | Indirect | Can run arbitrary commands on the InTune-managed endpoint of a Global Administrator and steal their tokens to impersonate them. | +| [DeviceManagementRBAC.ReadWrite.All](https://learn.microsoft.com/en-us/graph/permissions-reference#devicemanagementrbacreadwriteall) | Indirect | Can assign InTune roles to a controlled user account, which allows running arbitrary commands on the InTune-managed endpoint of a Global Administrator and steal their tokens to impersonate them. | +| [Directory.ReadWrite.All](https://learn.microsoft.com/en-us/graph/permissions-reference#directoryreadwriteall) | Indirect | Can become member of a non-role-assignable user group with assigned privileged Azure permissions, and leverage Azure resources to escalate to Global Admin.
**Note**: can also acquire access to external solutions integrated with Entra ID via SSO, and providing access based on non-role-assignable group memberships. | +| [EntitlementManagement.ReadWrite.All](https://learn.microsoft.com/en-us/graph/permissions-reference#entitlementmanagementreadwriteall) | Indirect | Can update the assignment policy of an access package provisioning access to Global Admin, so that requesting the package without approval is possible from a controlled user account. | +| [Group.ReadWrite.All](https://learn.microsoft.com/en-us/graph/permissions-reference#groupreadwriteall) | Indirect | Same as [Directory.ReadWrite.All](#directory-readwrite-all). | +| [GroupMember.ReadWrite.All](https://learn.microsoft.com/en-us/graph/permissions-reference#groupmemberreadwriteall) | Indirect | Same as [Directory.ReadWrite.All](#directory-readwrite-all). | +| [Policy.ReadWrite.AuthenticationMethod](https://learn.microsoft.com/en-us/graph/permissions-reference#policyreadwriteauthenticationmethod) | Indirect | When combined with [UserAuthenticationMethod.ReadWrite.All](#userauthenticationmethod-readwrite-all), can enable the [Temporary Access Pass (TAP)](https://learn.microsoft.com/en-us/entra/identity/authentication/howto-authentication-temporary-access-pass) authentication method to help leveraging and follow the same path as that permission. | +| [Policy.ReadWrite.PermissionGrant](https://learn.microsoft.com/en-us/graph/permissions-reference#policyreadwritepermissiongrant) | Indirect | Can create a [permission grant policy](https://learn.microsoft.com/en-us/graph/api/permissiongrantpolicy-post-includes?view=graph-rest-1.0&tabs=http) for the compromised SP with the [RoleManagement.ReadWrite.Directory](https://learn.microsoft.com/en-us/graph/permissions-reference#rolemanagementreadwritedirectory) permission, and leverage that policy to follow the same path as that permission and escalate to Global Admin. | +| [PrivilegedAccess.ReadWrite.AzureADGroup](https://learn.microsoft.com/en-us/graph/permissions-reference#privilegedaccessreadwriteazureadgroup) | Direct | Can add a controlled user account as owner or member of a group with an active Global Admin assignment (i.e. can update the membership of role-assignable groups). | +| [PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup](https://learn.microsoft.com/en-us/graph/permissions-reference#privilegedeligibilityschedulereadwriteazureadgroup) | Indirect | Can make a controlled user account eligible to a group with an active Global Admin assignment, and activate the group membership to escalate to Global Admin. | +| [RoleAssignmentSchedule.ReadWrite.Directory](https://learn.microsoft.com/en-us/graph/permissions-reference#roleassignmentschedulereadwritedirectory) | Direct | Can assign the Global Admin role to a controlled user account, by creating an active PIM role assignment. | +| [RoleEligibilitySchedule.ReadWrite.Directory](https://learn.microsoft.com/en-us/graph/permissions-reference#roleeligibilityschedulereadwritedirectory) | Indirect | Can make a controlled user account eligible to the Global Admin role, and activate it to escalate to Global Admin. | +| [RoleManagement.ReadWrite.Directory](https://learn.microsoft.com/en-us/graph/permissions-reference#rolemanagementreadwritedirectory) | Direct | Can assign the Global Admin role to a controlled principal. | +| [RoleManagementPolicy.ReadWrite.AzureADGroup](https://learn.microsoft.com/en-us/graph/permissions-reference#rolemanagementpolicyreadwriteazureadgroup) | Indirect | Can remove group role assignment and activation constrains, such as MFA requirements or admin approval, to help leveraging [PrivilegedAccess.ReadWrite.AzureADGroup](#privilegedaccess-readwrite-azureadgroup), [PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup](#privilegedassignmentschedule-readwrite-azureadgroup) or [PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup](#privilegedeligibilityschedule-readwrite-azureadgroup), and follow the same path as those permissions in a tenant with strict PIM settings. | +| [RoleManagementPolicy.ReadWrite.Directory](https://learn.microsoft.com/en-us/graph/permissions-reference#rolemanagementpolicyreadwritedirectory) | Indirect | Can remove Entra role assignment and activation constrains, such as MFA requirements or admin approval, to help leveraging [RoleAssignmentSchedule.ReadWrite.Directory](#roleassignmentschedule-readwrite-directory) or [RoleEligibilitySchedule.ReadWrite.Directory](#roleeligibilityschedule-readwrite-directory), and follow the same path as those permissions in a tenant with strict PIM settings. | +| [User.DeleteRestore.All](https://learn.microsoft.com/en-us/graph/permissions-reference#userdeleterestoreall) | Direct | Can delete all user accounts in the tenant (making the latter unavailable), and ask for a ransomware to restore one of the break-glass accounts.
Note: this permission is "Global-Admin-like", as it affects the availability of the tenant in the same way as a Global Admin. | +| [User.EnableDisableAccount.All](https://learn.microsoft.com/en-us/graph/permissions-reference#userenabledisableaccountall) | Direct | When combined with [User.Read.All](https://learn.microsoft.com/en-us/graph/permissions-reference#userreadall), can disable all user accounts in the tenant (making the latter unavailable), and ask for a ransomware to re-enable one of the break-glass accounts.
Note: this permission is "Global-Admin-like", as it affects the availability of the tenant in the same way as a Global Admin. | +| [User.ReadWrite.All](https://learn.microsoft.com/en-us/graph/permissions-reference#userreadwriteall) | Indirect | Can edit sensitive properties of a controlled user account, such as "Employee ID" and "Department", to become member of a dynamic group with assigned privileged Azure permissions, and leverage Azure resources to escalate to Global Admin. | +| [User-PasswordProfile.ReadWrite.All](https://learn.microsoft.com/en-us/graph/permissions-reference#user-passwordprofilereadwriteall) | Indirect | Same as [Directory.ReadWrite.All](#directory-readwrite-all). | +| [UserAuthenticationMethod.ReadWrite.All](https://learn.microsoft.com/en-us/graph/permissions-reference#userauthenticationmethodreadwriteall) | Direct | Can generate a [Temporary Access Pass (TAP)](https://learn.microsoft.com/en-us/entra/identity/authentication/howto-authentication-temporary-access-pass) and take over any user account in the tenant.
Note: if TAP is not an enabled authentication method in the tenant, this path needs to be combined with [Policy.ReadWrite.AuthenticationMethod](#policy-readwrite-authenticationmethod) to be successful. | + +#### Remediation action: + +To check the applications permissions: +1. Navigate to Microsoft Entra admin center [https://entra.microsoft.com/](https://entra.microsoft.com/). +2. Click to expand **Applications** then select **App registrations**. +3. Select **All applications**. +4. Search for the application that you want to check and select the application. +5. Select **API permissions**. +6. Check the **Microsoft Graph** permissions. +7. Verify that **only authorized users** have access to this application and its secrets. + +#### Related links + +* [Microsoft 365 Admin Center](https://admin.microsoft.com) +* [Microsft Entra - App registrations](https://enappreg.cmd.ms/) +* [Application permissions - Tier 0: Family of Global Admins](https://github.com/emiliensocchi/azure-tiering/tree/main/Microsoft%20Graph%20application%20permissions#tier-0) +* [Microsoft Learn - Graph permissions](https://learn.microsoft.com/en-us/graph/permissions-reference) + + +%TestResult% \ No newline at end of file diff --git a/powershell/public/maester/entra/Test-MtHighRiskAppPermissions.ps1 b/powershell/public/maester/entra/Test-MtHighRiskAppPermissions.ps1 new file mode 100644 index 00000000..75c1c131 --- /dev/null +++ b/powershell/public/maester/entra/Test-MtHighRiskAppPermissions.ps1 @@ -0,0 +1,367 @@ +<# +.SYNOPSIS + Ensure no graph application has permissions with a risk of having a direct or indirect path to Global Admin and full tenant takeover. + +.DESCRIPTION + Applications that use Graph API permissions with a risk of having a direct or indirect path to Global Admin and full tenant takeover. + +.EXAMPLE + Test-MtHighRiskAppPermissions + + Returns true if no application has Tier-0 graph permissions + +.LINK + https://maester.dev/docs/commands/ + https://github.com/emiliensocchi/azure-tiering/tree/main/Microsoft%20Graph%20application%20permissions +#> +function Test-MtHighRiskAppPermissions { + [CmdletBinding()] + [OutputType([bool])] + param() + + if (-not (Test-MtConnection Graph)) { + Add-MtTestResultDetail -SkippedBecause NotConnectedGraph + return $null + } + + $allCriticalGraphPermissions = @( + [pscustomobject]@{ + Id='2f6817f8-7b12-4f0f-bc18-eeaf60705a9e'; + Name='PrivilegedAccess.ReadWrite.AzureADGroup'; + Type='Application'; + Path='Direct' + } + [pscustomobject]@{ + Id='32531c59-1f32-461f-b8df-6f8a3b89f73b'; + Name='PrivilegedAccess.ReadWrite.AzureADGroup'; + Type='Delegated' + Path='Direct' + } + [pscustomobject]@{ + Id='41202f2c-f7ab-45be-b001-85c9728b9d69'; + Name='PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup'; + Type='Application' + Path='Direct' + } + [pscustomobject]@{ + Id='06dbc45d-6708-4ef0-a797-f797ee68bf4b'; + Name='PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup'; + Type='Delegated' + Path='Direct' + } + [pscustomobject]@{ + Id='dd199f4a-f148-40a4-a2ec-f0069cc799ec'; + Name='RoleAssignmentSchedule.ReadWrite.Directory'; + Type='Application' + Path='Direct' + } + [pscustomobject]@{ + Id='8c026be3-8e26-4774-9372-8d5d6f21daff'; + Name='RoleAssignmentSchedule.ReadWrite.Directory'; + Type='Delegated' + Path='Direct' + } + [pscustomobject]@{ + Id='9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8'; + Name='RoleManagement.ReadWrite.Directory'; + Type='Application' + Path='Direct' + } + [pscustomobject]@{ + Id='d01b97e9-cbc0-49fe-810a-750afd5527a3'; + Name='RoleManagement.ReadWrite.Directory'; + Type='Delegated' + Path='Direct' + } + [pscustomobject]@{ + Id='eccc023d-eccf-4e7b-9683-8813ab36cecc'; + Name='User.DeleteRestore.All'; + Type='Application' + Path='Direct' + } + [pscustomobject]@{ + Id='4bb440cd-2cf2-4f90-8004-aa2acd2537c5'; + Name='User.DeleteRestore.All'; + Type='Delegated' + Path='Direct' + } + [pscustomobject]@{ + Id='3011c876-62b7-4ada-afa2-506cbbecc68c'; + Name='User.EnableDisableAccount.All'; + Type='Application' + Path='Direct' + } + [pscustomobject]@{ + Id='f92e74e7-2563-467f-9dd0-902688cb5863'; + Name='User.EnableDisableAccount.All'; + Type='Delegated' + Path='Direct' + } + [pscustomobject]@{ + Id='50483e42-d915-4231-9639-7fdb7fd190e5'; + Name='UserAuthenticationMethod.ReadWrite.All'; + Type='Application' + Path='Direct' + } + [pscustomobject]@{ + Id='b7887744-6746-4312-813d-72daeaee7e2d'; + Name='UserAuthenticationMethod.ReadWrite.All'; + Type='Delegated' + Path='Direct' + } + [pscustomobject]@{ + Id='5eb59dd3-1da2-4329-8733-9dabdc435916'; + Name='AdministrativeUnit.ReadWrite.All'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='7b8a2d34-6b3f-4542-a343-54651608ad81'; + Name='AdministrativeUnit.ReadWrite.All'; + Type='Delegated' + Path='Indirect' + } + [pscustomobject]@{ + Id='1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9'; + Name='Application.ReadWrite.All'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='bdfbf15f-ee85-4955-8675-146e8e5296b5'; + Name='Application.ReadWrite.All'; + Type='Delegated' + Path='Indirect' + } + [pscustomobject]@{ + Id='18a4783c-866b-4cc7-a460-3d5e5662c884'; + Name='Application.ReadWrite.OwnedBy'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='06b708a9-e830-4db3-a914-8e69da51d44f'; + Name='AppRoleAssignment.ReadWrite.All'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='84bccea3-f856-4a8a-967b-dbe0a3d53a64'; + Name='AppRoleAssignment.ReadWrite.All'; + Type='Delegated' + Path='Indirect' + } + [pscustomobject]@{ + Id='9241abd9-d0e6-425a-bd4f-47ba86e767a4'; + Name='DeviceManagementConfiguration.ReadWrite.All'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='0883f392-0a7a-443d-8c76-16a6d39c7b63'; + Name='DeviceManagementConfiguration.ReadWrite.All'; + Type='Delegated' + Path='Indirect' + } + [pscustomobject]@{ + Id='e330c4f0-4170-414e-a55a-2f022ec2b57b'; + Name='DeviceManagementRBAC.ReadWrite.All'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='0c5e8a55-87a6-4556-93ab-adc52c4d862d'; + Name='DeviceManagementRBAC.ReadWrite.All'; + Type='Delegated' + Path='Indirect' + } + [pscustomobject]@{ + Id='19dbc75e-c2e2-444c-a770-ec69d8559fc7'; + Name='Directory.ReadWrite.All'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='c5366453-9fb0-48a5-a156-24f0c49a4b84'; + Name='Directory.ReadWrite.All'; + Type='Delegated' + Path='Indirect' + } + [pscustomobject]@{ + Id='9acd699f-1e81-4958-b001-93b1d2506e19'; + Name='EntitlementManagement.ReadWrite.All'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='ae7a573d-81d7-432b-ad44-4ed5c9d89038'; + Name='EntitlementManagement.ReadWrite.All'; + Type='Delegated' + Path='Indirect' + } + [pscustomobject]@{ + Id='62a82d76-70ea-41e2-9197-370581804d09'; + Name='Group.ReadWrite.All'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='4e46008b-f24c-477d-8fff-7bb4ec7aafe0'; + Name='Group.ReadWrite.All'; + Type='Delegated' + Path='Indirect' + } + [pscustomobject]@{ + Id='dbaae8cf-10b5-4b86-a4a1-f871c94c6695'; + Name='GroupMember.ReadWrite.All'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='f81125ac-d3b7-4573-a3b2-7099cc39df9e'; + Name='GroupMember.ReadWrite.All'; + Type='Delegated' + Path='Indirect' + } + [pscustomobject]@{ + Id='29c18626-4985-4dcd-85c0-193eef327366'; + Name='Policy.ReadWrite.AuthenticationMethod'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='7e823077-d88e-468f-a337-e18f1f0e6c7c'; + Name='Policy.ReadWrite.AuthenticationMethod'; + Type='Delegated' + Path='Indirect' + } + [pscustomobject]@{ + Id='a402ca1c-2696-4531-972d-6e5ee4aa11ea'; + Name='Policy.ReadWrite.PermissionGrant'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='2672f8bb-fd5e-42e0-85e1-ec764dd2614e'; + Name='Policy.ReadWrite.PermissionGrant'; + Type='Delegated' + Path='Indirect' + } + [pscustomobject]@{ + Id='618b6020-bca8-4de6-99f6-ef445fa4d857'; + Name='PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='ba974594-d163-484e-ba39-c330d5897667'; + Name='PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup'; + Type='Delegated' + Path='Indirect' + } + [pscustomobject]@{ + Id='fee28b28-e1f3-4841-818e-2704dc62245f'; + Name='RoleEligibilitySchedule.ReadWrite.Directory'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='62ade113-f8e0-4bf9-a6ba-5acb31db32fd'; + Name='RoleEligibilitySchedule.ReadWrite.Directory'; + Type='Delegated' + Path='Indirect' + } + [pscustomobject]@{ + Id='b38dcc4d-a239-4ed6-aa84-6c65b284f97c'; + Name='RoleManagementPolicy.ReadWrite.AzureADGroup'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='0da165c7-3f15-4236-b733-c0b0f6abe41d'; + Name='RoleManagementPolicy.ReadWrite.AzureADGroup'; + Type='Delegated' + Path='Indirect' + } + [pscustomobject]@{ + Id='31e08e0a-d3f7-4ca2-ac39-7343fb83e8ad'; + Name='RoleManagementPolicy.ReadWrite.Directory'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='1ff1be21-34eb-448c-9ac9-ce1f506b2a68'; + Name='RoleManagementPolicy.ReadWrite.Directory'; + Type='Delegated' + Path='Indirect' + } + [pscustomobject]@{ + Id='741f803b-c850-494e-b5df-cde7c675a1ca'; + Name='User.ReadWrite.All'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='204e0828-b5ca-4ad8-b9f3-f32a958e7cc4'; + Name='User.ReadWrite.All'; + Type='Delegated' + Path='Indirect' + } + [pscustomobject]@{ + Id='cc117bb9-00cf-4eb8-b580-ea2a878fe8f7'; + Name='User-PasswordProfile.ReadWrite.All'; + Type='Application' + Path='Indirect' + } + [pscustomobject]@{ + Id='56760768-b641-451f-8906-e1b8ab31bca7'; + Name='User-PasswordProfile.ReadWrite.All'; + Type='Delegated' + Path='Indirect' + } + ) + + $return = $true + try { + $allApplications = Invoke-MtGraphRequest -RelativeUri "applications" + $allApplicationsWithGraph = $allApplications | Where-Object { $_.requiredResourceAccess.resourceAppId -eq "00000003-0000-0000-c000-000000000000"} + $allAssignedCriticalPermissions = @() + foreach ($app in $allApplicationsWithGraph) { + $allAppPermissions = $app.requiredResourceAccess.resourceAccess.id + foreach ($appPermission in $allAppPermissions) { + foreach ($criticalGraphPermission in $allCriticalGraphPermissions) { + if ($appPermission -eq $criticalGraphPermission.Id) { + $allAssignedCriticalPermissions += @( + [pscustomobject]@{ + ApplicationName = $app.displayName; + ApplicationId = $app.appId; + PermissionName = $criticalGraphPermission.Name; + PermissionType = $criticalGraphPermission.Type; + AttackPath = $criticalGraphPermission.Path + } + ) + $return = $false + } + } + } + } + + $result = "| ApplicationName | ApplicationId | PermissionName | PermissionType | AttackPath |`n" + $result += "| --- | --- | --- | --- | --- |`n" + foreach ($assignedCriticalPermission in $allAssignedCriticalPermissions) { + $result += "| $($assignedCriticalPermission.ApplicationName) | $($assignedCriticalPermission.ApplicationId) | $($assignedCriticalPermission.PermissionName) | $($assignedCriticalPermission.PermissionType) | $($assignedCriticalPermission.AttackPath) |`n" + } + + if ($return) { + $testResultMarkdown = "Well done. No graph application has permissions with a risk of having a direct or indirect path to Global Admin and full tenant takeover." + } else { + $testResultMarkdown = "At least one application has graph permissions with a risk of having a direct or indirect path to Global Admin and full tenant takeover.`n`n%TestResult%" + $testResultMarkdown = $testResultMarkdown -replace "%TestResult%", $result + } + Add-MtTestResultDetail -Result $result + } catch { + $return = $false + Write-Error $_.Exception.Message + } + return $return +} \ No newline at end of file diff --git a/tests/Maester/Entra/Test-MtHighRiskAppPermissions.Tests.ps1 b/tests/Maester/Entra/Test-MtHighRiskAppPermissions.Tests.ps1 new file mode 100644 index 00000000..f2f88bd9 --- /dev/null +++ b/tests/Maester/Entra/Test-MtHighRiskAppPermissions.Tests.ps1 @@ -0,0 +1,8 @@ +Describe "Roles and permissions" -Tag "All", "Entra", "Graph" { + It "Ensure no graph application has permissions with a risk of having a direct or indirect path to Global Admin and full tenant takeover." -Tag "MS.AAD.9.0" { + $result = Test-MtHighRiskAppPermissions + if ($null -ne $result) { + $result | Should -Be $true -Because "no graph application has permissions with a risk of having a direct or indirect path to Global Admin and full tenant takeover." + } + } +} \ No newline at end of file From 14dc43a9731b40ffbcf2e52aa18ea61e6fc1242e Mon Sep 17 00:00:00 2001 From: Henrik <35952834+HenrikPiecha@users.noreply.github.com> Date: Wed, 5 Feb 2025 15:50:32 +0100 Subject: [PATCH 2/3] Update Test-MtHighRiskAppPermissions.md Corrected grammar issue. -> "This test 'checks' if any application..." --- .../public/maester/entra/Test-MtHighRiskAppPermissions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/powershell/public/maester/entra/Test-MtHighRiskAppPermissions.md b/powershell/public/maester/entra/Test-MtHighRiskAppPermissions.md index 69f4ef9a..8988421d 100644 --- a/powershell/public/maester/entra/Test-MtHighRiskAppPermissions.md +++ b/powershell/public/maester/entra/Test-MtHighRiskAppPermissions.md @@ -1,6 +1,6 @@ Ensure no graph application has permissions with a risk of having a direct or indirect path to Global Admin and full tenant takeover. -This test if any application has tier-0 graph permissions with a risk of having a direct or indirect path to Global Admin and full tenant takeover. +This test checks if any application has tier-0 graph permissions with a risk of having a direct or indirect path to Global Admin and full tenant takeover. Following is a shortened copy from [Application permissions - Tier 0: Family of Global Admins](https://github.com/emiliensocchi/azure-tiering/tree/main/Microsoft%20Graph%20application%20permissions#tier-0), Date: 20.01.2025 @@ -50,4 +50,4 @@ To check the applications permissions: * [Microsoft Learn - Graph permissions](https://learn.microsoft.com/en-us/graph/permissions-reference) -%TestResult% \ No newline at end of file +%TestResult% From 4c5f312aacf9efb74ba7f67e30d759d6c9b895d3 Mon Sep 17 00:00:00 2001 From: Henrik <35952834+HenrikPiecha@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:12:50 +0100 Subject: [PATCH 3/3] Update Test-MtHighRiskAppPermissions.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added conceptional description for valid use-cases into test description: "There are several use cases where Tier-0 permissions with an indirect attack path are required. For example, Maester itself requires the permission “RoleEligibilitySchedule.ReadWrite.Directory” to properly validate the PIM assignments. Nevertheless, an administrator should question the use of these permissions and check whether less critical permissions are also sufficient. Applications that are provided by third-party vendors that do have Tier-0 permissions with direct or indirect attack paths should strictly be questioned and monitored. " --- .../public/maester/entra/Test-MtHighRiskAppPermissions.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/powershell/public/maester/entra/Test-MtHighRiskAppPermissions.md b/powershell/public/maester/entra/Test-MtHighRiskAppPermissions.md index 8988421d..cb4dbf28 100644 --- a/powershell/public/maester/entra/Test-MtHighRiskAppPermissions.md +++ b/powershell/public/maester/entra/Test-MtHighRiskAppPermissions.md @@ -2,7 +2,10 @@ Ensure no graph application has permissions with a risk of having a direct or in This test checks if any application has tier-0 graph permissions with a risk of having a direct or indirect path to Global Admin and full tenant takeover. -Following is a shortened copy from [Application permissions - Tier 0: Family of Global Admins](https://github.com/emiliensocchi/azure-tiering/tree/main/Microsoft%20Graph%20application%20permissions#tier-0), Date: 20.01.2025 +Note:\ +There are several use cases where Tier-0 permissions with an indirect attack path are required. For example, Maester itself requires the permission “RoleEligibilitySchedule.ReadWrite.Directory” to properly validate the PIM assignments. Nevertheless, an administrator should question the use of these permissions and check whether less critical permissions are also sufficient. Applications that are provided by third-party vendors that do have Tier-0 permissions with direct or indirect attack paths should strictly be questioned and monitored. + +Following is a shortened copy from [Application permissions - Tier 0: Family of Global Admins](https://github.com/emiliensocchi/azure-tiering/tree/main/Microsoft%20Graph%20application%20permissions#tier-0), Date: 20.01.2025: | Application permission | Path type | Known shortest path | | --- | --- | --- |