Skip to content

Commit c346d43

Browse files
praneeth-0000Copilotalexandair
authored
Feature 21955 - Manage the local administrators on Microsoft Entra joined devices (#708)
* rewrote the assessment logic as per new spec * added missing db param * removed old portal link * updated table header links * Updated db query for consistency Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fixed grammatical mistake in md file Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * added variable for portal link * updated license and table headers * used deviceLocalAdminRoleId in building portal link * handled empty string upn while displaying the output * used tenantid to build portal link * Fix markdown table formatting in Test-Assessment.ps1 * updated code to skip when intune license is present * Trigger validation with current main --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Aleksandar Nikolić <alexandair@live.com>
1 parent 8fb1284 commit c346d43

2 files changed

Lines changed: 88 additions & 18 deletions

File tree

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
When local administrators on Microsoft Entra joined devices aren't properly managed, threat actors with compromised credentials can execute device takeover attacks by removing organizational administrators and disabling the device's connection to Microsoft Entra. This lack of control results in complete loss of organizational control, creating orphaned assets that can't be managed or recovered.
1+
When local administrators on Microsoft Entra joined devices are not managed by the organization, threat actors who could compromise user accounts can execute device takeover attacks that result in permanent loss of organizational control. Threat actors can leverage compromised account credentials to perform account manipulation by removing all organizational administrators from the device’s local administrators, including the global administrators who normally retain management access. Once threat actors do that, they can modify user account control settings and disable the device's connection to Microsoft Entra, effectively severing the cloud management channel. This attack progression results in a complete device takeover where organizational global administrators lose all administrative pathways to regain control. The device becomes an orphaned asset that cannot be managed anymore.
22

33
**Remediation action**
44

5-
- [Manage the local administrators on Microsoft Entra joined devices](https://learn.microsoft.com/entra/identity/devices/assign-local-admin?wt.mc_id=zerotrustrecommendations_automation_content_cnl_csasci#manage-the-microsoft-entra-joined-device-local-administrator-role)
5+
- [Manage the local administrators on Microsoft Entra joined devices](https://learn.microsoft.com/en-us/entra/identity/devices/assign-local-admin)
66
<!--- Results --->
77
%TestResult%
8-

src/powershell/tests/Test-Assessment.21955.ps1

Lines changed: 86 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ function Test-Assessment-21955 {
77
[ZtTest(
88
Category = 'Devices',
99
ImplementationCost = 'Low',
10-
MinimumLicense = ('Free'),
10+
MinimumLicense = ('P1'),
1111
Pillar = 'Identity',
1212
RiskLevel = 'High',
1313
SfiPillar = 'Protect tenants and isolate production systems',
@@ -17,35 +17,106 @@ function Test-Assessment-21955 {
1717
UserImpact = 'Low'
1818
)]
1919
[CmdletBinding()]
20-
param()
20+
param(
21+
$Database
22+
)
2123

2224
Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose
2325

26+
# Check for Intune license, if present skip the test
27+
if (Get-ZtLicense Intune) {
28+
Add-ZtTestResultDetail -SkippedBecause NotApplicable
29+
return
30+
}
31+
32+
#region Data Collection
2433
$activity = 'Checking Manage the local administrators on Microsoft Entra joined devices'
25-
Write-ZtProgress -Activity $activity -Status 'Getting policy'
2634

27-
# Query device registration policy
28-
$policy = Invoke-ZtGraphRequest -RelativeUri 'policies/deviceRegistrationPolicy' -ApiVersion beta
35+
# Query role assignments from database
36+
Write-ZtProgress -Activity $activity -Status 'Getting role assignments'
37+
$deviceLocalAdminRoleId = '9f06204d-73c1-4d4c-880a-6edb90606fd8'
38+
39+
# Query database for assigned and eligible users/groups for this role
40+
$sql = "SELECT principalDisplayName, userPrincipalName, `"@odata.type`", principalId, privilegeType
41+
FROM vwRole
42+
WHERE roleDefinitionId = '$deviceLocalAdminRoleId';"
2943

30-
$enableGlobalAdmins = ${policy}?.azureADJoin?.localAdmins?.enableGlobalAdmins
44+
$roleAssignments = Invoke-DatabaseQuery -Database $Database -Sql $sql
3145

32-
$portalLink = 'https://entra.microsoft.com/#view/Microsoft_AAD_Devices/DevicesMenuBlade/~/DeviceSettings/menuId/Overview'
46+
Write-PSFMessage "Found $($roleAssignments.Count) role assignments for Azure AD Joined Device Local Administrator" -Level Verbose
3347

34-
$portalLinkMd = "[Global administrator role is added as local administrator on the device during Microsoft Entra join?]($portalLink)`n`n"
48+
# Separate assigned vs eligible
49+
$assignedMembers = $roleAssignments | Where-Object { $_.privilegeType -eq 'Permanent' }
50+
$eligibleMembers = $roleAssignments | Where-Object { $_.privilegeType -eq 'Eligible' }
51+
#endregion Data Collection
3552

36-
if ($enableGlobalAdmins) {
53+
#region Assessment Logic
54+
55+
if ($roleAssignments.Count -gt 0) {
3756
$passed = $true
38-
$testResultMarkdown = "Local administrators on Microsoft Entra joined devices are managed by the organization.`n`n"
39-
$testResultMarkdown += $portalLinkMd
40-
$testResultMarkdown += "- **Yes** → ✅"
57+
$testResultMarkdown = "Local administrators on Microsoft Entra joined devices are managed by the organization.`n`n%TestResult%"
4158
}
4259
else {
4360
$passed = $false
44-
$testResultMarkdown = "Local administrators on Microsoft Entra joined devices are not managed by the organization.`n`n"
45-
$testResultMarkdown += $portalLinkMd
46-
$testResultMarkdown += "- **No** → ❌"
61+
$testResultMarkdown = "Local administrators on Microsoft Entra joined devices are not managed by the organization.`n`n%TestResult%"
62+
}
63+
#endregion Assessment Logic
64+
65+
#region Report Generation
66+
67+
# Build detailed markdown
68+
# Get current tenant ID from context to build the portal link
69+
$resourceId = (Get-MgContext).TenantId
70+
$assignmentsPortalLink = "https://entra.microsoft.com/#view/Microsoft_Azure_PIMCommon/UserRolesViewModelMenuBlade/~/members/roleObjectId/$deviceLocalAdminRoleId/roleId/$deviceLocalAdminRoleId/roleTemplateId/$deviceLocalAdminRoleId/roleName/Microsoft%20Entra%20Joined%20Device%20Local%20Administrator/isRoleCustom~/false/resourceScopeId/%2F/resourceId/$resourceId"
71+
72+
$mdInfo = ''
73+
74+
if ($assignedMembers.Count -gt 0) {
75+
$mdInfo += "`n## [Active Microsoft Entra Joined Device Local Administrator assignments]($assignmentsPortalLink)`n`n"
76+
$mdInfo += "| Display name | UPN | Type | Assignment type |`n"
77+
$mdInfo += "| :----------- | :--- | :--- | :-------------- |`n"
78+
79+
foreach ($member in ($assignedMembers | Sort-Object -Property principalDisplayName)) {
80+
$objectType = if ($member.'@odata.type' -eq '#microsoft.graph.user') { 'User' } else { 'Group' }
81+
$upn = if ([string]::IsNullOrWhiteSpace($member.userPrincipalName)) { 'N/A' } else { $member.userPrincipalName }
82+
83+
$portalLink = if ($member.'@odata.type' -eq '#microsoft.graph.user') {
84+
"https://entra.microsoft.com/#view/Microsoft_AAD_UsersAndTenants/UserProfileMenuBlade/~/overview/userId/$($member.principalId)"
85+
} else {
86+
"https://entra.microsoft.com/#view/Microsoft_AAD_IAM/GroupDetailsMenuBlade/~/Overview/groupId/$($member.principalId)"
87+
}
88+
89+
$mdInfo += "| [$(Get-SafeMarkdown $member.principalDisplayName)]($portalLink) | $upn | $objectType | $($member.privilegeType) |`n"
90+
}
91+
}
92+
93+
if ($eligibleMembers.Count -gt 0) {
94+
$mdInfo += "`n## [Eligible Microsoft Entra Joined Device Local Administrator assignments]($assignmentsPortalLink)`n`n"
95+
$mdInfo += "| Display name | UPN | Type | Assignment type |`n"
96+
$mdInfo += "| :----------- | :--- | :--- | :-------------- |`n"
97+
98+
foreach ($member in ($eligibleMembers | Sort-Object -Property principalDisplayName)) {
99+
$objectType = if ($member.'@odata.type' -eq '#microsoft.graph.user') { 'User' } else { 'Group' }
100+
$upn = if ([string]::IsNullOrWhiteSpace($member.userPrincipalName)) { 'N/A' } else { $member.userPrincipalName }
101+
102+
$portalLink = if ($member.'@odata.type' -eq '#microsoft.graph.user') {
103+
"https://entra.microsoft.com/#view/Microsoft_AAD_UsersAndTenants/UserProfileMenuBlade/~/overview/userId/$($member.principalId)"
104+
} else {
105+
"https://entra.microsoft.com/#view/Microsoft_AAD_IAM/GroupDetailsMenuBlade/~/Overview/groupId/$($member.principalId)"
106+
}
107+
108+
$mdInfo += "| [$(Get-SafeMarkdown $member.principalDisplayName)]($portalLink) | $upn | $objectType | $($member.privilegeType) |`n"
109+
}
47110
}
48111

112+
if ($roleAssignments.Count -eq 0) {
113+
$mdInfo = "`n❌ No assigned or eligible users/groups found for the Microsoft Entra Joined Device Local Administrator role.`n"
114+
}
115+
116+
# Replace placeholder with detailed information
117+
$testResultMarkdown = $testResultMarkdown -replace '%TestResult%', $mdInfo
118+
#endregion Report Generation
119+
49120
$params = @{
50121
TestId = '21955'
51122
Status = $passed

0 commit comments

Comments
 (0)