Skip to content

Commit

Permalink
Merge branch 'bugfix/dec-22-meet-up' of github.com:T0pCyber/hawk into…
Browse files Browse the repository at this point in the history
… bugfix/dec-22-meet-up
  • Loading branch information
jonnybottles committed Dec 22, 2024
2 parents 0b64ff1 + c6c6ad5 commit 8b6c1f7
Show file tree
Hide file tree
Showing 17 changed files with 980 additions and 349 deletions.
12 changes: 9 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

# ignore the settings folder and files for VSCode and PSS
# ignore the settings folder and files for VSCode and PSS
.vscode/*
*.psproj
*TempPoint*
Expand All @@ -19,4 +18,11 @@ Hawk/Hawk.psproj
TestResults/*

# ignore the publishing Directory
publish/*
publish/*

# Ignore all .csv, .json, .docx, and .xlsx files
*.csv
*.json
*.docx
*.doc
*.xlsx
7 changes: 5 additions & 2 deletions Hawk/Hawk.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,18 @@
'Get-HawkTenantInboxRules',
'Get-HawkTenantConsentGrant',
'Get-HawkTenantRBACChange',

'Get-HawkTenantAzureAppAuditLog',
'Get-HawkUserAuthHistory',
'Get-HawkUserConfiguration',
'Get-HawkUserEmailForwarding',
'Get-HawkUserInboxRule',
'Get-HawkUserMailboxAuditing',
'Search-HawkTenantActivityByIP',
'Search-HawkTenantEXOAuditLog',
'Get-HawkTenantAdminInboxRuleCreation',
'Get-HawkTenantAdminInboxRuleModification',
'Get-HawkTenantAdminInboxRuleRemoval',
'Get-HawkTenantAdminMailboxPermissionChange',
'Get-HawkTenantAdminEmailForwardingChange',
'Show-HawkHelp',
'Start-HawkTenantInvestigation',
'Start-HawkUserInvestigation',
Expand Down
1 change: 0 additions & 1 deletion Hawk/Resolving IP Locations

This file was deleted.

33 changes: 18 additions & 15 deletions Hawk/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,21 @@
- Removed Robust Cloud Command from build as it was not being used in the code base anymore
- Updated PowerShell API key in GitHub to fix build.yml issue where the Hawk would not publish to gallery on merge to main

## 3.2.3 (2024-12-09)

- **Migration to Microsoft Graph**: Replaced all AzureAD functionality with Microsoft Graph commands, including updates to functions like `Get-HawkTenantAppAndSPNCredentialDetails` (now using `Get-MgServicePrincipal` and `Get-MgApplication`).

- **Directory Role Management**: Updated `Get-HawkTenantAZAdmins` to use Microsoft Graph (`Get-MgRoleDefinition` and `Get-MgRoleAssignment`), renamed to `Get-HawkTenantEntraIDAdmin`, and enhanced output for better role tracking.

- **Consent Grant Updates**: Migrated `Get-HawkTenantConsentGrant` to Graph commands (`Get-MgOauth2PermissionGrant` and `Get-MgServicePrincipalAppRoleAssignment`), ensuring consistent output and backward compatibility.

- **Removed AzureAD Dependencies**: Eliminated AzureAD references in the Hawk.psd1 manifest and removed the deprecated `Test-AzureADConnection.ps1`. Updated manifest to rely solely on Microsoft Graph modules (v2.25.0).

- **Simplified Authentication**: Streamlined Graph API connections by removing unnecessary commands like `Select-MgProfile` and improving `Test-GraphConnection` for default behaviors.

- **Improved Logging and Naming**: Standardized log outputs (e.g., `AzureADUsers` to `EntraIDUsers`) and aligned function outputs with updated naming conventions.

- This release completes the migration to Microsoft Graph, fully deprecating AzureAD and aligning Hawk with modern Microsoft standards.
## 3.2.3 (2024-12-20)

- Replaced all AzureAD functionality with Microsoft Graph commands.
- Updated Get-HawkTenantAZAdmins to use Microsoft Graph.
- Migrated Get-HawkTenantConsentGrant to Graph commands.
- Removed AzureAD Dependencies: Eliminated AzureAD references in the Hawk.psd1 manifest and removed the deprecated Test-AzureADConnection.ps1.
- Simplified Authentication: Streamlined Graph API connections by removing unnecessary commands like Select-MgProfile and improving Test-GraphConnection.
- Improved Logging and Naming: Standardized log outputs (e.g., AzureADUsers to EntraIDUsers) and aligned function outputs with updated naming conventions.
- Removed Search-HawkTenantEXOAuditLog as it was deprecated and replaced with modern, modular functions, as listed below:
- Added Get-HawkTenantAdminInboxRuleModification, which retrieves audit log entries for inbox rules that were historically modified within the tenant.
- Added Get-HawkTenantAdminEmailForwardingChange, which retrieves audit log entries for email forwarding changes made within the tenant.
- Added Get-HawkTenantAdminInboxRuleCreation, which retrieves audit log entries for inbox rules that were historically created within the tenant.
- Added Get-HawkTenantAdminInboxRuleRemoval, which retrieves audit log entries for inbox rules that were removed within the tenant.
- Added Get-HawkTenantAdminMailboxPermissionChange, which retrieves audit log entries for mailbox permission changes within the tenant.
- Added internal helper function Test-SuspiciousInboxRule, which detects suspicious inbox rule patterns.
- Removed ability to detect RBAC Application Impersonation as this is being deprecated / removed in FEB 2025.
- Updated Out-Log file, adding -Information parameter for tagging prompts with INFO for status updates.
- Updated Out-Log file, modifying -Notice parameter for tagging prompts with INVESTIGATE in brackets instead of asterisks, for uniformity purposes.
216 changes: 216 additions & 0 deletions Hawk/functions/Tenant/Get-HawkTenantAdminEmailForwardingChange.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
Function Get-HawkTenantAdminEmailForwardingChange {
<#
.SYNOPSIS
Retrieves audit log entries for email forwarding changes made within the tenant.
.DESCRIPTION
This function queries the Microsoft 365 Unified Audit Log for events related to email
forwarding configuration changes (Set-Mailbox with forwarding parameters). It focuses on
tracking when and by whom forwarding rules were added or modified, helping identify potential
unauthorized data exfiltration attempts.
Key points:
- Monitors changes to both ForwardingAddress and ForwardingSMTPAddress settings
- Resolves recipient information for ForwardingAddress values
- Flags all forwarding changes for review as potential security concerns
- Provides historical context for forwarding configuration changes
.OUTPUTS
File: Simple_Forwarding_Changes.csv/.json
Path: \Tenant
Description: Simplified view of forwarding configuration changes.
File: Forwarding_Changes.csv/.json
Path: \Tenant
Description: Detailed audit log data for forwarding changes.
File: Forwarding_Recipients.csv/.json
Path: \Tenant
Description: List of unique forwarding destinations configured.
.EXAMPLE
Get-HawkTenantAdminEmailForwardingChange
Retrieves all email forwarding configuration changes from the audit logs within the specified
search window.
#>
[CmdletBinding()]
param()

# Test the Exchange Online connection to ensure the environment is ready for operations.
Test-EXOConnection
# Log the execution of the function for audit and telemetry purposes.
Send-AIEvent -Event "CmdRun"

# Initialize timing variables for status updates
$startTime = Get-Date
$lastUpdate = $startTime

# Log the start of the analysis process for email forwarding configuration changes.
Out-LogFile "Analyzing email forwarding configuration changes from audit logs" -Action

# Ensure the tenant-specific folder exists to store output files. If not, create it.
$TenantPath = Join-Path -Path $Hawk.FilePath -ChildPath "Tenant"
if (-not (Test-Path -Path $TenantPath)) {
New-Item -Path $TenantPath -ItemType Directory -Force | Out-Null
}

try {
# Define both operations and broader search terms to cast a wider net.
$searchCommand = @"
Search-UnifiedAuditLog -RecordType ExchangeAdmin -Operations @(
'Set-Mailbox',
'Set-MailUser',
'Set-RemoteMailbox',
'Enable-RemoteMailbox'
)
"@

# Fetch all specified operations from the audit log
[array]$AllMailboxChanges = Get-AllUnifiedAuditLogEntry -UnifiedSearch $searchCommand

# Log search completion time
Out-LogFile "Unified Audit Log search completed" -Information

Out-LogFile "Filtering results for forwarding changes..." -Action

# Enhanced filtering to catch more types of forwarding changes
[array]$ForwardingChanges = $AllMailboxChanges | Where-Object {
$auditData = $_.AuditData | ConvertFrom-Json
$parameters = $auditData.Parameters
($parameters | Where-Object {
$_.Name -in @(
'ForwardingAddress',
'ForwardingSMTPAddress',
'ExternalEmailAddress',
'PrimarySmtpAddress',
'RedirectTo', # Added from other LLM suggestion
'DeliverToMailboxAndForward', # Corrected parameter name
'DeliverToAndForward' # Alternative parameter name
) -or
# Check for parameter changes enabling forwarding
($_.Name -eq 'DeliverToMailboxAndForward' -and $_.Value -eq 'True') -or
($_.Name -eq 'DeliverToAndForward' -and $_.Value -eq 'True')
})
}

Out-LogFile "Completed filtering for forwarding changes" -Information

if ($ForwardingChanges.Count -gt 0) {
# Log the number of forwarding configuration changes found.
Out-LogFile ("Found " + $ForwardingChanges.Count + " change(s) to user email forwarding") -Information

# Write raw JSON data for detailed reference and potential troubleshooting.
$RawJsonPath = Join-Path -Path $TenantPath -ChildPath "Forwarding_Changes_Raw.json"
$ForwardingChanges | Select-Object -ExpandProperty AuditData | Out-File -FilePath $RawJsonPath

# Parse the audit data into a simpler format for further processing and output.
$ParsedChanges = $ForwardingChanges | Get-SimpleUnifiedAuditLog
if ($ParsedChanges) {
# Write the simplified data for quick analysis and review.
$ParsedChanges | Out-MultipleFileType -FilePrefix "Simple_Forwarding_Changes" -csv -json -Notice

# Write the full audit log data for comprehensive records.
$ForwardingChanges | Out-MultipleFileType -FilePrefix "Forwarding_Changes" -csv -json -Notice

# Initialize an array to store processed forwarding destination data.
$ForwardingDestinations = @()

Out-LogFile "Beginning detailed analysis of forwarding changes..." -Action
foreach ($change in $ParsedChanges) {
# Add a status update every 30 seconds
$currentTime = Get-Date
if (($currentTime - $lastUpdate).TotalSeconds -ge 30) {
Out-LogFile "Processing forwarding changes... ($($ForwardingDestinations.Count) destinations found so far)" -Action
$lastUpdate = $currentTime
}

$targetUser = $change.ObjectId

# Process ForwardingSMTPAddress changes if detected in the audit log.
if ($change.Parameters -match "ForwardingSMTPAddress") {
$smtpAddress = ($change.Parameters | Select-String -Pattern "ForwardingSMTPAddress:\s*([^,]+)").Matches.Groups[1].Value
if ($smtpAddress) {
# Add the SMTP forwarding configuration to the destinations array.
$ForwardingDestinations += [PSCustomObject]@{
UserModified = $targetUser
TargetSMTPAddress = $smtpAddress.Split(":")[-1].Trim() # Remove "SMTP:" prefix if present.
ChangeType = "SMTP Forwarding"
ModifiedBy = $change.UserId
ModifiedTime = $change.CreationTime
}
}
}

# Process ForwardingAddress changes if detected in the audit log.
if ($change.Parameters -match "ForwardingAddress") {
$forwardingAddress = ($change.Parameters | Select-String -Pattern "ForwardingAddress:\s*([^,]+)").Matches.Groups[1].Value
if ($forwardingAddress) {
try {
# Attempt to resolve the recipient details from Exchange Online.
$recipient = Get-EXORecipient $forwardingAddress -ErrorAction Stop

# Determine the recipient's type and extract the appropriate address.
$targetAddress = switch ($recipient.RecipientType) {
"MailContact" { $recipient.ExternalEmailAddress.Split(":")[-1] }
default { $recipient.PrimarySmtpAddress }
}

# Add the recipient forwarding configuration to the destinations array.
$ForwardingDestinations += [PSCustomObject]@{
UserModified = $targetUser
TargetSMTPAddress = $targetAddress
ChangeType = "Recipient Forwarding"
ModifiedBy = $change.UserId
ModifiedTime = $change.CreationTime
}
}
catch {
# Log a warning if the recipient cannot be resolved.
Out-LogFile "Unable to resolve forwarding recipient: $forwardingAddress" -Notice
# Add an unresolved entry for transparency in the output.
$ForwardingDestinations += [PSCustomObject]@{
UserModified = $targetUser
TargetSMTPAddress = "UNRESOLVED:$forwardingAddress"
ChangeType = "Recipient Forwarding (Unresolved)"
ModifiedBy = $change.UserId
ModifiedTime = $change.CreationTime
}
}
}
}
}


Out-LogFile "Completed processing forwarding changes" -Information

if ($ForwardingDestinations.Count -gt 0) {
# Log the total number of forwarding destinations detected.
Out-LogFile ("Found " + $ForwardingDestinations.Count + " forwarding destinations configured") -Information
# Write the forwarding destinations data to files for review.
$ForwardingDestinations | Out-MultipleFileType -FilePrefix "Forwarding_Recipients" -csv -json -Notice

# Log details about each forwarding destination for detailed auditing.
foreach ($dest in $ForwardingDestinations) {
Out-LogFile "Forwarding configured: $($dest.UserModified) -> $($dest.TargetSMTPAddress) ($($dest.ChangeType)) by $($dest.ModifiedBy) at $($dest.ModifiedTime)" -Notice
}
}
}
else {
# Log a warning if the parsing of audit data fails.
Out-LogFile "Error: Failed to parse forwarding change audit data" -Notice
}
}
else {
# Log a message if no forwarding changes are found in the logs.
Out-LogFile "No forwarding changes found in filtered results" -Information
Out-LogFile "Retrieved $($AllMailboxChanges.Count) total operations, but none involved forwarding changes" -Information
}
}
catch {
# Log an error if the analysis encounters an exception.
Out-LogFile "Error analyzing email forwarding changes: $($_.Exception.Message)" -Notice
Write-Error -ErrorRecord $_ -ErrorAction Continue
}
}

Loading

0 comments on commit 8b6c1f7

Please sign in to comment.