Public/Security.ps1
|
<# .SYNOPSIS Finds SendAs audit records in the Office 365 audit log. .DESCRIPTION This function searches the Office 365 audit log for SendAs events and enriches the data with information about the recipient type. .PARAMETER StartDate The start date for the audit log search. Defaults to 90 days ago. .PARAMETER EndDate The end date for the audit log search. Defaults to today. .PARAMETER ResultSize The maximum number of audit records to return. Defaults to 2000. .PARAMETER NoGridView If specified, the function will not display the results in a grid view. .PARAMETER ExportPath If specified, the function will export the results to a CSV file at the given path. .EXAMPLE Find-O365SendAsAuditRecord -ExportPath "C:\temp\SendAsAudit.csv" .NOTES You must be connected to Exchange Online before running this function. #> function Find-O365SendAsAuditRecord { [CmdletBinding()] param( [datetime]$StartDate = (Get-Date).AddDays(-90), [datetime]$EndDate = (Get-Date).AddDays(1), [int]$ResultSize = 2000, [switch]$NoGridView, [string]$ExportPath ) Write-Verbose "Populating Recipients Table..." $RecipientsTable = @{} try { $Recipients = Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails UserMailbox, SharedMailbox $Recipients.ForEach({ $RecipientsTable.Add([String]$_.PrimarySmtpAddress, $_.RecipientTypeDetails) }) $GroupMailboxes = Get-Mailbox -ResultSize Unlimited -GroupMailbox $GroupMailboxes.ForEach({ $RecipientsTable.Add([String]$_.PrimarySmtpAddress, $_.RecipientTypeDetails) }) } catch { Write-Warning "Can't find recipients. Make sure you are connected to Exchange Online." return } Write-Verbose "Finding audit records for Send As operations..." $Records = (Search-UnifiedAuditLog -StartDate $StartDate -EndDate $EndDate -Operations "SendAs" -ResultSize $ResultSize) if ($Records.Count -eq 0) { Write-Verbose "No audit records for Send As found." return } Write-Verbose "Processing $($Records.Count) Send As audit records..." $Report = [System.Collections.Generic.List[Object]]::new() ForEach ($Rec in $Records) { $AuditData = ConvertFrom-Json $Rec.Auditdata $MailboxType = $RecipientsTable.Item($AuditData.MailboxOwnerUPN) if ($MailboxType -eq "GroupMailbox") { $Reason = "Group Mailbox Send" } else { $Reason = "Delegate Send As" } if ($AuditData.UserId -eq "S-1-5-18") { $UserId = "Service Account" } else { $UserId = $AuditData.UserId } $ReportLine = [PSCustomObject]@{ TimeStamp = Get-Date($AuditData.CreationTime) -format g SentBy = $AuditData.MailboxOwnerUPN SentAs = $AuditData.SendAsUserSmtp Subject = $AuditData.Item.Subject User = $AuditData.UserId Action = $AuditData.Operation Reason = $Reason UserType = $AuditData.UserType LogonType = $AuditData.LogonType ClientIP = $AuditData.ClientIP MailboxType = $MailboxType ClientInfo = $AuditData.ClientInfoString Status = $AuditData.ResultStatus } $Report.Add($ReportLine) } $UserMailboxReport = $Report | Where-Object { $_.MailboxType -eq "UserMailbox" } if (-not $NoGridView) { $UserMailboxReport | Out-GridView } if ($ExportPath) { try { $Report | Export-Csv -NoTypeInformation -Path $ExportPath Write-Verbose "Report file saved to $ExportPath" } catch { Write-Warning "Failed to save report file to $ExportPath. Error: $_ " } } return $Report } <# .SYNOPSIS Generates a security scorecard for the tenant. .DESCRIPTION This function checks for a variety of security best practices and provides a report with a summary of the findings. .PARAMETER StaleAdminDays The number of days to check for stale admin sign-ins. .PARAMETER InactiveGuestDays The number of days to check for inactive guest users. .EXAMPLE Get-O365SecurityScorecard .NOTES You must be connected to the Microsoft Graph and Exchange Online with the appropriate scopes before running this function. #> function Get-O365SecurityScorecard { [CmdletBinding()] param( [int]$StaleAdminDays = 30, [int]$InactiveGuestDays = 30 ) Write-Verbose "Generating security scorecard..." $StaleAdmins = Get-O365StaleAdminSignIns -Days $StaleAdminDays $InactiveGuests = Get-O365InactiveGuestUsers -Days $InactiveGuestDays $UsersWithoutMFA = Get-O365UsersWithoutMFA $MailboxForwardingRules = Get-O365MailboxForwardingRules $UnsignedInServicePrincipals = Get-O365UnsignedInServicePrincipals $Scorecard = [PSCustomObject]@{ StaleAdmins = $StaleAdmins.Count InactiveGuests = $InactiveGuests.Count UsersWithoutMFA = $UsersWithoutMFA.Count MailboxForwardingRules = $MailboxForwardingRules.Count UnsignedInServicePrincipals = $UnsignedInServicePrincipals.Count } return $Scorecard } <# .SYNOPSIS Gets Conditional Access policies that are in "report-only" mode. .DESCRIPTION This function gets all Conditional Access policies in the tenant and filters for those that are in "report-only" mode. .EXAMPLE Get-O365ReportOnlyConditionalAccessPolicy .NOTES You must be connected to the Microsoft Graph with the 'Policy.Read.All' scope before running this function. #> function Get-O365ReportOnlyConditionalAccessPolicy { [CmdletBinding()] param() Write-Verbose "Finding report-only Conditional Access policies..." $Policies = Get-MgIdentityConditionalAccessPolicy $ReportOnlyPolicies = $Policies | Where-Object { $_.State -eq 'enabledForReportingButNotEnforced' } Write-Verbose "Found $($ReportOnlyPolicies.Count) report-only Conditional Access policies." return $ReportOnlyPolicies } |