Rules/APP-006.risky-delegated-grants.psd1
|
@{ Id = 'APP-006' Title = 'No risky delegated consent grants' Area = 'ConsentGrants' Severity = 'Medium' References = @( 'https://learn.microsoft.com/defender-cloud-apps/investigate-risky-oauth' ) Rationale = 'Delegated grants with write access to mail or files plus offline_access are the classic footprint of illicit consent-grant attacks - durable API access in user context, invisible to password resets.' Remediation = 'Review the flagged grants (who consented, is the app known?) and revoke unexpected ones; restrict future user consent (see ID-005).' Test = { param($Snapshot) $riskyScopes = @('Mail.ReadWrite', 'Mail.Send', 'MailboxSettings.ReadWrite', 'Files.ReadWrite.All', 'Sites.ReadWrite.All', 'Directory.ReadWrite.All', 'Contacts.ReadWrite', 'Notes.ReadWrite.All') $hits = [System.Collections.Generic.List[object]]::new() $microsoftSkipped = 0 foreach ($grant in @($Snapshot.ConsentGrants.delegatedGrants)) { $scopeTokens = @(([string]$grant.scope) -split '\s+' | Where-Object { $_ }) $matched = @($scopeTokens | Where-Object { $riskyScopes -contains $_ }) if ($matched.Count -eq 0) { continue } # Microsoft first-party apps (SharePoint, Photos, ...) get broad # scopes as normal platform behavior - not consent-grant risk. if ($grant.PSObject.Properties['_tlIsMicrosoftApp'] -and $grant._tlIsMicrosoftApp) { $microsoftSkipped++ continue } $clientLabel = $(if ($grant.PSObject.Properties['_tlClientName'] -and $grant._tlClientName) { $grant._tlClientName } else { $grant.clientId }) $hits.Add(("{0}: {1} ({2})" -f $clientLabel, ($matched -join ', '), $grant.consentType)) } $notes = @() if ($microsoftSkipped -gt 0) { $notes = @("$microsoftSkipped Microsoft first-party grant(s) with broad scopes skipped as expected platform behavior.") } if ($hits.Count -gt 0) { New-TLRuleResult -Status Fail -Evidence (@($hits | Select-Object -First 15) + $notes) } else { New-TLRuleResult -Status Pass -Evidence (@("No risky third-party delegated scopes across {0} consent grants." -f @($Snapshot.ConsentGrants.delegatedGrants).Count) + $notes) } } } |