Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Hawk/Hawk.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@
'Get-HawkUserEntraIDSignInLog',
'Get-HawkTenantEntraIDAuditLog',
'Get-HawkTenantRiskyUsers',
'Get-HawkTenantRiskDetections'
'Get-HawkTenantRiskDetections',
'Get-HawkUserUALInboxRuleCreation',
'Get-HawkUserUALInboxRuleModification',
'Get-HawkUserUALInboxRuleRemoval'
# Cmdlets to export from this module
# CmdletsToExport = ''

Expand Down
6 changes: 6 additions & 0 deletions Hawk/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,9 @@
- Added log pull of user SharePoint Search activity to the User Investigation (Get-HawkUserSharePointSearchQuery)
- Added telemetry discloser on Readme and updated license
- Added AppInsight GUID

## 4.1 (2025-3-xx)

- Added Get-HawkUserUALInboxRuleCreation: Analyzes audit logs for inbox rules created by specific users
- Added Get-HawkUserUALInboxRuleModification: Analyzes audit logs for inbox rules modified by specific users
- Added Get-HawkUserUALInboxRuleRemoval: Analyzes audit logs for inbox rules removed by specific users
117 changes: 117 additions & 0 deletions Hawk/functions/User/Get-HawkUserUALInboxRuleCreation.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
Function Get-HawkUserUALInboxRuleCreation {
<#
.SYNOPSIS
Retrieves audit log entries for inbox rules that were historically created by or for a specific user.

.DESCRIPTION
This function queries the Microsoft 365 Unified Audit Log for inbox rule creation events
(New-InboxRule) associated with a specific user or set of users. It focuses on historical
record-keeping and identifying potentially suspicious rules that were created.

Key points:
- Displays creation events for inbox rules, including who created them and when.
- Flags created rules that appear suspicious (e.g., rules that forward externally, delete
messages, or filter based on suspicious keywords).
- Does not confirm whether the rules are currently active or still exist.

For current, active rules, use Get-HawkUserInboxRule instead.

This function is the user-specific counterpart to Get-HawkTenantAdminInboxRuleCreation.

.PARAMETER UserPrincipalName
Single UPN of a user, comma-separated list of UPNs, or array of objects that contain UPNs.
This parameter specifies which users' inbox rule creation events to investigate.

.OUTPUTS
File: Simple_User_Inbox_Rules_Creation_<user>.csv/.json
Path: \<User>
Description: Simplified view of created inbox rule events for the user.

File: User_Inbox_Rules_Creation_<user>.csv/.json
Path: \<User>
Description: Detailed audit log data for created inbox rules for the user.

File: _Investigate_User_Inbox_Rules_Creation_<user>.csv/.json
Path: \<User>
Description: A subset of historically created rules flagged as suspicious.

.EXAMPLE
Get-HawkUserUALInboxRuleCreation -UserPrincipalName user@contoso.com

Retrieves inbox rule creation events from the audit logs for user@contoso.com.

.EXAMPLE
Get-HawkUserUALInboxRuleCreation -UserPrincipalName (Get-Mailbox -Filter {CustomAttribute1 -eq "C-level"})

Retrieves inbox rule creation events for all users with CustomAttribute1 set to "C-level".

.LINK
Get-HawkTenantAdminInboxRuleCreation
Get-HawkUserInboxRule
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[array]$UserPrincipalName
)

# Check if Hawk object exists and is fully initialized
if (Test-HawkGlobalObject) {
Initialize-HawkGlobalObject
}

Test-EXOConnection
Send-AIEvent -Event "CmdRun"

# Verify our UPN input
[array]$UserArray = Test-UserObject -ToTest $UserPrincipalName

foreach ($Object in $UserArray) {
[string]$User = $Object.UserPrincipalName

Out-LogFile "Initiating collection of inbox rule creation events for $User from the UAL." -Action

try {
# Build search command for unified audit log - specific to this user
$searchCommand = "Search-UnifiedAuditLog -RecordType ExchangeAdmin -Operations 'New-InboxRule' -UserIds $User"
[array]$NewInboxRules = Get-AllUnifiedAuditLogEntry -UnifiedSearch $searchCommand

if ($NewInboxRules.Count -gt 0) {
Out-LogFile ("Found " + $NewInboxRules.Count + " inbox rule creation events for $User in the audit logs.") -Information

# Process and output the results
$ParsedRules = $NewInboxRules | Get-SimpleUnifiedAuditLog

if ($ParsedRules) {
Out-LogFile "Writing parsed inbox rule creation data." -Action
$ParsedRules | Out-MultipleFileType -FilePrefix "Simple_User_Inbox_Rules_Creation" -csv -json -User $User
$NewInboxRules | Out-MultipleFileType -FilePrefix "User_Inbox_Rules_Creation" -csv -json -User $User

# Check for suspicious rules using the helper function
$SuspiciousRules = $ParsedRules | Where-Object {
$reasons = @()
Test-SuspiciousInboxRule -Rule $_ -Reasons ([ref]$reasons)
}

if ($SuspiciousRules) {
Out-LogFile "Found $($SuspiciousRules.Count) suspicious inbox rule creation events for $User." -Notice
Out-LogFile "Please verify this activity is legitimate." -Notice
$SuspiciousRules | Out-MultipleFileType -FilePrefix "_Investigate_User_Inbox_Rules_Creation" -csv -json -User $User -Notice
}
}
else {
Out-LogFile "Error: Failed to parse inbox rule audit data for $User." -isError
}
}
else {
Out-LogFile "No inbox rule creation events found in audit logs for $User." -Information
}
}
catch {
Out-LogFile "Error analyzing inbox rule creation for $User : $_" -isError
Write-Error -ErrorRecord $_ -ErrorAction Continue
}

Out-LogFile "Completed collection of inbox rule creation events for $User from the UAL." -Information
}
}
120 changes: 120 additions & 0 deletions Hawk/functions/User/Get-HawkUserUALInboxRuleModification.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
Function Get-HawkUserUALInboxRuleModification {
<#
.SYNOPSIS
Retrieves audit log entries for inbox rules that were historically modified by or for a specific user.

.DESCRIPTION
This function queries the Microsoft 365 Unified Audit Log for inbox rule modification events
(Set-InboxRule) associated with a specific user or set of users. It focuses on historical
changes to existing rules, helping identify suspicious modifications (e.g., forwarding to
external addresses, enabling deletion, or targeting sensitive keywords).

The logged events do not indicate how or where the modification took place, only that
an inbox rule was changed at a given time by a specific account.

Key points:
- Shows modification events for inbox rules, including who modified them and when.
- Flags modifications that may be suspicious based on predefined criteria.
- Does not indicate whether the rules are currently active or still exist.

For current, active rules, use Get-HawkUserInboxRule instead.

This function is the user-specific counterpart to Get-HawkTenantAdminInboxRuleModification.

.PARAMETER UserPrincipalName
Single UPN of a user, comma-separated list of UPNs, or array of objects that contain UPNs.
This parameter specifies which users' inbox rule modification events to investigate.

.OUTPUTS
File: Simple_User_Inbox_Rules_Modification_<user>.csv/.json
Path: \<User>
Description: Simplified view of inbox rule modification events for the user.

File: User_Inbox_Rules_Modification_<user>.csv/.json
Path: \<User>
Description: Detailed audit log data for modified inbox rules for the user.

File: _Investigate_User_Inbox_Rules_Modification_<user>.csv/.json
Path: \<User>
Description: A subset of historically modified rules flagged as suspicious.

.EXAMPLE
Get-HawkUserUALInboxRuleModification -UserPrincipalName user@contoso.com

Retrieves inbox rule modification events from the audit logs for user@contoso.com.

.EXAMPLE
Get-HawkUserUALInboxRuleModification -UserPrincipalName (Get-Mailbox -Filter {CustomAttribute1 -eq "C-level"})

Retrieves inbox rule modification events for all users with CustomAttribute1 set to "C-level".

.LINK
Get-HawkTenantAdminInboxRuleModification
Get-HawkUserInboxRule
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[array]$UserPrincipalName
)

# Check if Hawk object exists and is fully initialized
if (Test-HawkGlobalObject) {
Initialize-HawkGlobalObject
}

Test-EXOConnection
Send-AIEvent -Event "CmdRun"

# Verify our UPN input
[array]$UserArray = Test-UserObject -ToTest $UserPrincipalName

foreach ($Object in $UserArray) {
[string]$User = $Object.UserPrincipalName

Out-LogFile "Initiating collection of inbox rule modification events for $User from the UAL." -Action

try {
# Build search command for unified audit log - specific to this user
$searchCommand = "Search-UnifiedAuditLog -RecordType ExchangeAdmin -Operations 'Set-InboxRule' -UserIds $User"
[array]$ModifiedInboxRules = Get-AllUnifiedAuditLogEntry -UnifiedSearch $searchCommand

if ($ModifiedInboxRules.Count -gt 0) {
Out-LogFile ("Found " + $ModifiedInboxRules.Count + " inbox rule modification events for $User in the audit logs.") -Information

# Process and output the results
$ParsedRules = $ModifiedInboxRules | Get-SimpleUnifiedAuditLog

if ($ParsedRules) {
Out-LogFile "Writing parsed inbox rule modification data." -Action
$ParsedRules | Out-MultipleFileType -FilePrefix "Simple_User_Inbox_Rules_Modification" -csv -json -User $User
$ModifiedInboxRules | Out-MultipleFileType -FilePrefix "User_Inbox_Rules_Modification" -csv -json -User $User

# Check for suspicious modifications using the helper function
$SuspiciousModifications = $ParsedRules | Where-Object {
$reasons = @()
Test-SuspiciousInboxRule -Rule $_ -Reasons ([ref]$reasons)
}

if ($SuspiciousModifications) {
Out-LogFile "Found $($SuspiciousModifications.Count) suspicious inbox rule modification events for $User." -Notice
Out-LogFile "Please verify this activity is legitimate." -Notice
$SuspiciousModifications | Out-MultipleFileType -FilePrefix "_Investigate_User_Inbox_Rules_Modification" -csv -json -User $User -Notice
}
}
else {
Out-LogFile "Error: Failed to parse inbox rule modification audit data for $User." -isError
}
}
else {
Out-LogFile "No inbox rule modification events found in audit logs for $User." -Information
}
}
catch {
Out-LogFile "Error analyzing inbox rule modifications for $User : $_" -isError
Write-Error -ErrorRecord $_ -ErrorAction Continue
}

Out-LogFile "Completed collection of inbox rule modification events for $User from the UAL." -Information
}
}
121 changes: 121 additions & 0 deletions Hawk/functions/User/Get-HawkUserUALInboxRuleRemoval.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
Function Get-HawkUserUALInboxRuleRemoval {
<#
.SYNOPSIS
Retrieves audit log entries for inbox rules that were removed by or for a specific user.

.DESCRIPTION
This function queries the Microsoft 365 Unified Audit Log for inbox rule removal events
(Remove-InboxRule) associated with a specific user or set of users. It focuses on
historical record-keeping and identifying when inbox rules were removed and by whom.

The logged events do not indicate the specific method or interface used to remove the rules,
only that a rule was removed at a given time by a specific account.

Key points:
- Displays removal events for inbox rules, including who removed them and when.
- Flags removals that might be suspicious (e.g., rules that were forwarding externally).
- Provides historical context for rule removals during investigations.

For current, active rules, use Get-HawkUserInboxRule instead.

This function is the user-specific counterpart to Get-HawkTenantAdminInboxRuleRemoval.

.PARAMETER UserPrincipalName
Single UPN of a user, comma-separated list of UPNs, or array of objects that contain UPNs.
This parameter specifies which users' inbox rule removal events to investigate.

.OUTPUTS
File: Simple_User_Inbox_Rules_Removal_<user>.csv/.json
Path: \<User>
Description: Simplified view of removed inbox rule events for the user.

File: User_Inbox_Rules_Removal_<user>.csv/.json
Path: \<User>
Description: Detailed audit log data for removed inbox rules for the user.

File: _Investigate_User_Inbox_Rules_Removal_<user>.csv/.json
Path: \<User>
Description: A subset of historically removed rules flagged as suspicious.

.EXAMPLE
Get-HawkUserUALInboxRuleRemoval -UserPrincipalName user@contoso.com

Retrieves inbox rule removal events from the audit logs for user@contoso.com.

.EXAMPLE
Get-HawkUserUALInboxRuleRemoval -UserPrincipalName (Get-Mailbox -Filter {CustomAttribute1 -eq "C-level"})

Retrieves inbox rule removal events for all users with CustomAttribute1 set to "C-level".

.LINK
Get-HawkTenantAdminInboxRuleRemoval
Get-HawkUserInboxRule
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[array]$UserPrincipalName
)

# Check if Hawk object exists and is fully initialized
if (Test-HawkGlobalObject) {
Initialize-HawkGlobalObject
}

Test-EXOConnection
Send-AIEvent -Event "CmdRun"

# Verify our UPN input
[array]$UserArray = Test-UserObject -ToTest $UserPrincipalName

foreach ($Object in $UserArray) {
[string]$User = $Object.UserPrincipalName

Out-LogFile "Initiating collection of inbox rule removal events for $User from the UAL." -Action

try {
# Build search command for unified audit log - specific to this user
$searchCommand = "Search-UnifiedAuditLog -RecordType ExchangeAdmin -Operations 'Remove-InboxRule' -UserIds $User"
[array]$RemovedInboxRules = Get-AllUnifiedAuditLogEntry -UnifiedSearch $searchCommand

if ($RemovedInboxRules.Count -gt 0) {
Out-LogFile ("Found " + $RemovedInboxRules.Count + " inbox rule removal events for $User in the audit logs.") -Information

# Process and output the results
$ParsedRules = $RemovedInboxRules | Get-SimpleUnifiedAuditLog

if ($ParsedRules) {
# Output simple format for easy analysis
$ParsedRules | Out-MultipleFileType -FilePrefix "Simple_User_Inbox_Rules_Removal" -csv -json -User $User

# Output full audit logs for complete record
$RemovedInboxRules | Out-MultipleFileType -FilePrefix "User_Inbox_Rules_Removal" -csv -json -User $User

# Check for suspicious removals using the helper function
$SuspiciousRemovals = $ParsedRules | Where-Object {
$reasons = @()
Test-SuspiciousInboxRule -Rule $_ -Reasons ([ref]$reasons)
}

if ($SuspiciousRemovals) {
Out-LogFile "Found $($SuspiciousRemovals.Count) suspicious inbox rule removal events for $User." -Notice
Out-LogFile "Please verify this activity is legitimate." -Notice
$SuspiciousRemovals | Out-MultipleFileType -FilePrefix "_Investigate_User_Inbox_Rules_Removal" -csv -json -User $User -Notice
}
}
else {
Out-LogFile "Error: Failed to parse inbox rule removal audit data for $User." -isError
}
}
else {
Out-LogFile "No inbox rule removal events found in audit logs for $User." -Information
}
}
catch {
Out-LogFile "Error analyzing inbox rule removals for $User : $_" -isError
Write-Error -ErrorRecord $_ -ErrorAction Continue
}

Out-LogFile "Completed collection of inbox rule removal events for $User from the UAL." -Information
}
}
Loading