Skip to content

Commit 0946ffd

Browse files
committed
Add PIM fro Groups role setting enumeration and report
1 parent a163f6a commit 0946ffd

5 files changed

Lines changed: 1055 additions & 36 deletions

File tree

README.md

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ Findings are presented in interactive HTML reports to support efficient explorat
4646
- Azure Role Assignments
4747
- Conditional Access Policies
4848
- Administrative Units
49-
- PIM settings (for Entra Roles)
49+
- PIM settings:
50+
- PIM for Entra Roles
51+
- PIM for Groups (BroCi auth only)
5052

5153

5254
## ✅ Requirements
@@ -83,12 +85,12 @@ Use `-AuthFlow` to select the authentication flow.
8385

8486
| Auth Flow | Windows | Linux/macOS | Interactive Logins | Convenience | Parameter(s) | Notes |
8587
|-----------------------------|---------|-------|--------------------|-------------|--------------------------------------|-------|
86-
| BroCi | Yes | No | 1 | High | `-AuthFlow BroCi` *(default)* | Avoids reliance on legacy clients such as *Azure Active Directory PowerShell*. |
87-
| Auth Code Flow | Yes | No | 4 | Normal | `-AuthFlow AuthCode` | Standard non-BroCi auth code flow. |
88-
| Device Code Flow | Yes | Yes | 3 | Normal | `-AuthFlow DeviceCode` | Authentication can be completed on another device, but two Security Findings checks run with reduced depth. |
89-
| Auth Code + Manual Code Flow| Yes | Yes | 4 | Low-Normal | `-AuthFlow ManualCode` | Authentication can be completed on a different device or browser session. |
90-
| BroCi + Manual Code Flow | Yes | Yes | 1 | Low | `-AuthFlow BroCiManualCode` | Authorization code must be manually extracted from browser developer tools. |
91-
| BroCi with Token | Yes | Yes | 0 | Low | `-AuthFlow BroCiToken -BroCiToken "<refresh_token>"` | Refresh token must be obtained manually (e.g., from browser dev tools or another auth tool). |
88+
| BroCi | Yes | No | 1 | High | `-AuthFlow BroCi` *(default)* | Avoids reliance on legacy clients such as *Azure Active Directory PowerShell*. Supports all enumerations. |
89+
| Auth Code Flow | Yes | No | 4 | Normal | `-AuthFlow AuthCode` | Standard non-BroCi auth code flow. Does not generate the standalone `PIM (Groups)` settings report. |
90+
| Device Code Flow | Yes | Yes | 3 | Normal | `-AuthFlow DeviceCode` | Authentication can be completed on another device, but two Security Findings checks run with reduced depth. Does not generate the standalone `PIM (Groups)` settings report. |
91+
| Auth Code + Manual Code Flow| Yes | Yes | 4 | Low-Normal | `-AuthFlow ManualCode` | Authentication can be completed on a different device or browser session. Does not generate the standalone `PIM (Groups)` settings report. |
92+
| BroCi + Manual Code Flow | Yes | Yes | 1 | Low | `-AuthFlow BroCiManualCode` | Authorization code must be manually extracted from browser developer tools. Supports all enumerations.|
93+
| BroCi with Token | Yes | Yes | 0 | Low | `-AuthFlow BroCiToken -BroCiToken "<refresh_token>"` | Refresh token must be obtained manually (e.g., from browser dev tools or another auth tool). Supports all enumerations. |
9294

9395

9496
#### Use BroCi flow (default, Beta / Windows only)
@@ -163,8 +165,8 @@ By default, official Microsoft enterprise applications are excluded from the ass
163165
```
164166

165167
#### Skip PIM for Groups Assessment
166-
Use the `-SkipPimForGroups` switch to skip the enumeration of PIM assignments for groups.
167-
This skips the additional authentication needed to access PIM for Groups data.
168+
Use the `-SkipPimForGroups` switch to skip PIM-for-Groups precollection and enrichment.
169+
This also skips the standalone `PIM (Groups)` settings report.
168170
```powershell
169171
.\run_EntraFalcon.ps1 -SkipPimForGroups
170172
```
@@ -213,9 +215,12 @@ This skips the additional authentication needed to access PIM for Groups data.
213215
### Conditional Access Policies (Details Section)
214216
![alt text](/images/caps_details.png)
215217

216-
### PIM Role Settings
218+
### PIM Role Settings (Entra)
217219
![alt text](/images/pim_settings.png)
218220

221+
### Agent Identities
222+
![alt text](/images/agent_identities.png)
223+
219224
### Enumeration Summary
220225
![alt text](/images/enumeration_overview.png)
221226

@@ -661,7 +666,6 @@ When BroCi authentication is used, only one interactive login occurs.
661666
|74658136-14ec-4630-ad9b-26e160ff0fc6|Non-Interactive|797f4846-ba00-4fd7-ba43-dac1f8f63013|Retrieve Azure IAM role assignment data|
662667

663668
When BroCi is enabled, EntraFalcon also queries `api.azrbac.mspim.azure.com` for PIM for Groups.
664-
665669
### Details
666670
For data collection, the tool sends multiple requests to the Microsoft Graph API and, optionally, the Azure ARM API—one or more per object. Where possible, it leverages the Graph Batch endpoint to reduce the number of individual requests and improve efficiency.
667671

modules/check_Groups.psm1

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ function Invoke-CheckGroups {
5151
}
5252
}
5353

54-
5554
#Function to create transitive members
5655
function Get-TransitiveMembers {
5756
param (
@@ -434,6 +433,7 @@ function Invoke-CheckGroups {
434433

435434
Write-Host "[*] Getting all group memberships"
436435
$GroupMembers = @{}
436+
$DirectActiveMemberCountById = @{}
437437
$BatchSize = 10000
438438
$ChunkCount = [math]::Ceiling($GroupsTotalCount / $BatchSize)
439439

@@ -458,8 +458,11 @@ function Invoke-CheckGroups {
458458

459459
# Store results
460460
foreach ($item in $Response) {
461-
if ($item.response.value) {
462-
$GroupMembers[$item.id] = @($item.response.value)
461+
$groupResponseId = [string]$item.id
462+
$directMembers = @($item.response.value)
463+
$DirectActiveMemberCountById[$groupResponseId] = $directMembers.Count
464+
if ($directMembers.Count -gt 0) {
465+
$GroupMembers[$groupResponseId] = $directMembers
463466
}
464467
}
465468
}
@@ -508,9 +511,13 @@ function Invoke-CheckGroups {
508511
# Send Batch request and create a hashtable
509512
$RawResponse = (Send-GraphBatchRequest -AccessToken $GLOBALmsGraphAccessToken.access_token -Requests $Requests -BetaAPI -UserAgent $($GlobalAuditSummary.UserAgent.Name) -QueryParameters @{'$select' = 'id,userType,onPremisesSyncEnabled'})
510513
$GroupOwnersRaw = @{}
514+
$DirectActiveOwnerCountById = @{}
511515
foreach ($item in $RawResponse) {
512-
if ($item.response.value -and $item.response.value.Count -gt 0) {
513-
$GroupOwnersRaw[$item.id] = $item.response.value
516+
$groupResponseId = [string]$item.id
517+
$directOwners = @($item.response.value)
518+
$DirectActiveOwnerCountById[$groupResponseId] = $directOwners.Count
519+
if ($directOwners.Count -gt 0) {
520+
$GroupOwnersRaw[$groupResponseId] = $directOwners
514521
}
515522
}
516523

@@ -663,6 +670,9 @@ function Invoke-CheckGroups {
663670
$owneruser = [System.Collections.Generic.List[psobject]]::new()
664671
$ownersp = [System.Collections.Generic.List[psobject]]::new()
665672
$baseOwnerUserDetails = [System.Collections.Generic.List[psobject]]::new()
673+
$groupIdKey = [string]$group.Id
674+
$DirectActiveMemberCount = if ($null -ne $DirectActiveMemberCountById -and $DirectActiveMemberCountById.ContainsKey($groupIdKey)) { [int]$DirectActiveMemberCountById[$groupIdKey] } else { 0 }
675+
$DirectActiveOwnerCount = if ($null -ne $DirectActiveOwnerCountById -and $DirectActiveOwnerCountById.ContainsKey($groupIdKey)) { [int]$DirectActiveOwnerCountById[$groupIdKey] } else { 0 }
666676

667677
# Process group members
668678
if ($TransitiveMembersRaw.ContainsKey($group.Id)) {
@@ -1352,6 +1362,8 @@ function Invoke-CheckGroups {
13521362
MemberSpDetails = $memberSpDetails
13531363
Devices = $memberdevices.count
13541364
DevicesDetails = $memberdevices
1365+
DirectActiveMembers = $DirectActiveMemberCount
1366+
DirectActiveOwners = $DirectActiveOwnerCount
13551367
DirectOwners = @($owneruser).count + @($ownersp).count + @($OwnerGroup).count
13561368
NestedOwners = 0 #Will be adjusted in port-processing
13571369
OwnerUserDetails = $owneruser
@@ -2644,6 +2656,8 @@ $headerHtml = @"
26442656
Warnings = $group.Warnings
26452657
EntraRolePrivilegedCount = $group.EntraRolePrivilegedCount
26462658
InheritedHighValue = $group.InheritedHighValue
2659+
DirectActiveMembers = $group.DirectActiveMembers
2660+
DirectActiveOwners = $group.DirectActiveOwners
26472661
DirectOwners = $group.DirectOwners
26482662
NestedOwners = $group.NestedOwners
26492663
}

0 commit comments

Comments
 (0)