Public/Get-IOOverPrivilegedApps.ps1
|
function Get-IOOverPrivilegedApps { <# .SYNOPSIS Flags applications with high-privilege Microsoft Graph permissions. .EXAMPLE Get-IOOverPrivilegedApps .EXAMPLE Get-IOOverPrivilegedApps -ToCsv "over-privileged.csv" #> [CmdletBinding()] param( [string[]]$CustomHighPrivilegeRoles, [string]$ToCsv ) $cmdName = $MyInvocation.MyCommand.Name Write-IOLog 'Scanning for apps with high-privilege API permissions...' -Level Info -Component $cmdName $dangerousRoles = if ($CustomHighPrivilegeRoles) { $CustomHighPrivilegeRoles } else { $script:HighPrivilegeRoles } $results = [System.Collections.Generic.List[PSCustomObject]]::new() # Resolve MS Graph SP to get role ID -> name mapping $graphSps = Invoke-IOGraphRequest -Uri "v1.0/servicePrincipals?`$filter=appId eq '$($script:MsGraphAppId)'&`$select=id,appRoles" if (-not $graphSps -or $graphSps.Count -eq 0) { throw "Microsoft Graph service principal not found in tenant." } $graphSp = $graphSps[0] $roleMap = @{} foreach ($role in $graphSp.appRoles) { $roleMap[$role.id] = $role.value } # Scan all service principals of type Application $sps = Invoke-IOGraphRequest -Uri "v1.0/servicePrincipals?`$filter=servicePrincipalType eq 'Application'&`$select=id,displayName,appId" $total = ($sps | Measure-Object).Count $counter = 0 if ($total -eq 0) { Export-IOResult -Data @() -ToCsv $ToCsv -CommandName $cmdName return } try { foreach ($sp in $sps) { $counter++ if ($counter % 50 -eq 0) { Write-Progress -Activity 'Evaluating app permissions' -Status "$counter / $total" -PercentComplete (($counter / $total) * 100) } try { $assignments = Invoke-IOGraphRequest -Uri "v1.0/servicePrincipals/$($sp.id)/appRoleAssignments?`$select=appRoleId,resourceId,resourceDisplayName" -NoPagination -SkipConnectionCheck } catch { continue } foreach ($assignment in $assignments) { $roleName = $roleMap[$assignment.appRoleId] if (-not $roleName) { $roleName = $assignment.appRoleId } if ($roleName -in $dangerousRoles) { $results.Add([PSCustomObject]@{ ApplicationName = $sp.displayName ApplicationId = $sp.appId ObjectId = $sp.id Permission = $roleName ResourceApp = $assignment.resourceDisplayName RiskLevel = if ($roleName -match 'ReadWrite\.All|FullControl|RoleManagement') { 'Critical' } else { 'High' } }) } } } } finally { Write-Progress -Activity 'Evaluating app permissions' -Completed } $sorted = $results | Sort-Object RiskLevel, ApplicationName Export-IOResult -Data $sorted -ToCsv $ToCsv -CommandName $cmdName } |