|
| 1 | +function Invoke-CIPPStandardDisableExchangeOnlinePowerShell { |
| 2 | + <# |
| 3 | + .FUNCTIONALITY |
| 4 | + Internal |
| 5 | + .COMPONENT |
| 6 | + (APIName) DisableExchangeOnlinePowerShell |
| 7 | + .SYNOPSIS |
| 8 | + (Label) Disable Exchange Online PowerShell for non-admin users |
| 9 | + .DESCRIPTION |
| 10 | + (Helptext) Disables the ability for non-admin users to use Exchange Online PowerShell. Only administrators will be able to use PowerShell to connect to Exchange Online. |
| 11 | + (DocsDescription) Disables the ability for non-admin users to use Exchange Online PowerShell. This helps prevent attackers from using PowerShell to run malicious commands, access file systems, registry, and distribute ransomware throughout networks. Only administrators will be able to use PowerShell to connect to Exchange Online, aligning with a least privileged access approach to security. |
| 12 | + .NOTES |
| 13 | + CAT |
| 14 | + Exchange Standards |
| 15 | + TAG |
| 16 | + "CIS" |
| 17 | + "PowerShell" |
| 18 | + "Security" |
| 19 | + ADDEDCOMPONENT |
| 20 | + IMPACT |
| 21 | + Medium Impact |
| 22 | + ADDEDDATE |
| 23 | + 2025-06-19 |
| 24 | + POWERSHELLEQUIVALENT |
| 25 | + Get-User -ResultSize Unlimited -Filter 'RemotePowerShellEnabled -eq $true' | ForEach-Object { Set-User -Identity $_.Identity -RemotePowerShellEnabled $false } |
| 26 | + RECOMMENDEDBY |
| 27 | + "CIS" |
| 28 | + "CIPP" |
| 29 | + UPDATECOMMENTBLOCK |
| 30 | + Run the Tools\Update-StandardsComments.ps1 script to update this comment block |
| 31 | + .LINK |
| 32 | + https://docs.cipp.app/user-documentation/tenant/standards/list-standards |
| 33 | + #> |
| 34 | + |
| 35 | + param($Tenant, $Settings) |
| 36 | + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'DisableExchangeOnlinePowerShell' |
| 37 | + |
| 38 | + try { |
| 39 | + |
| 40 | + $AdminUsers = (New-GraphGetRequest -uri 'https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments?$expand=principal' -tenantid $Tenant).principal.userPrincipalName |
| 41 | + $UsersWithPowerShell = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-User' -Select 'userPrincipalName, identity, remotePowerShellEnabled' | Where-Object { $_.RemotePowerShellEnabled -eq $true -and $_.userPrincipalName -notin $AdminUsers } |
| 42 | + $PowerShellEnabledCount = ($UsersWithPowerShell | Measure-Object).Count |
| 43 | + $StateIsCorrect = $PowerShellEnabledCount -eq 0 |
| 44 | + } catch { |
| 45 | + $ErrorMessage = Get-CippException -Exception $_ |
| 46 | + Write-LogMessage -API 'Standards' -tenant $tenant -message "Could not check Exchange Online PowerShell status. $($ErrorMessage.NormalizedError)" -sev Error |
| 47 | + $StateIsCorrect = $null |
| 48 | + } |
| 49 | + |
| 50 | + if ($Settings.remediate -eq $true) { |
| 51 | + if ($PowerShellEnabledCount -gt 0) { |
| 52 | + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Started disabling Exchange Online PowerShell for $PowerShellEnabledCount users." -sev Info |
| 53 | + |
| 54 | + $Request = $UsersWithPowerShell | ForEach-Object { |
| 55 | + @{ |
| 56 | + CmdletInput = @{ |
| 57 | + CmdletName = 'Set-User' |
| 58 | + Parameters = @{Identity = $_.Identity; RemotePowerShellEnabled = $false } |
| 59 | + } |
| 60 | + } |
| 61 | + } |
| 62 | + |
| 63 | + $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray @($Request) |
| 64 | + $SuccessCount = 0 |
| 65 | + $BatchResults | ForEach-Object { |
| 66 | + if ($_.error) { |
| 67 | + $ErrorMessage = Get-NormalizedError -Message $_.error |
| 68 | + Write-Host "Failed to disable Exchange Online PowerShell for $($_.target). Error: $ErrorMessage" |
| 69 | + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to disable Exchange Online PowerShell for $($_.target). Error: $ErrorMessage" -sev Error |
| 70 | + } else { |
| 71 | + $SuccessCount++ |
| 72 | + } |
| 73 | + } |
| 74 | + |
| 75 | + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Successfully disabled Exchange Online PowerShell for $SuccessCount out of $PowerShellEnabledCount users." -sev Info |
| 76 | + } else { |
| 77 | + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Exchange Online PowerShell is already disabled for all non-admin users' -sev Info |
| 78 | + } |
| 79 | + } |
| 80 | + |
| 81 | + if ($Settings.alert -eq $true) { |
| 82 | + if ($StateIsCorrect -eq $true) { |
| 83 | + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Exchange Online PowerShell is disabled for all non-admin users.' -sev Info |
| 84 | + } else { |
| 85 | + Write-StandardsAlert -message "Exchange Online PowerShell is enabled for $PowerShellEnabledCount users" -object @{UsersWithPowerShellEnabled = $PowerShellEnabledCount } -tenant $tenant -standardName 'DisableExchangeOnlinePowerShell' -standardId $Settings.standardId |
| 86 | + Write-LogMessage -API 'Standards' -tenant $tenant -message "Exchange Online PowerShell is enabled for $PowerShellEnabledCount users." -sev Info |
| 87 | + } |
| 88 | + } |
| 89 | + |
| 90 | + if ($Settings.report -eq $true) { |
| 91 | + $state = $StateIsCorrect ?? @{UsersWithPowerShellEnabled = $PowerShellEnabledCount } |
| 92 | + Set-CIPPStandardsCompareField -FieldName 'standards.DisableExchangeOnlinePowerShell' -FieldValue $state -TenantFilter $Tenant |
| 93 | + Add-CIPPBPAField -FieldName 'ExchangeOnlinePowerShellDisabled' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant |
| 94 | + } |
| 95 | +} |
0 commit comments