From c7b0886a4672385d9ced4a059c36c365f4604c12 Mon Sep 17 00:00:00 2001 From: juliusperez1695 <150602855+juliusperez1695@users.noreply.github.com> Date: Mon, 13 Jan 2025 21:07:53 -0800 Subject: [PATCH 1/6] feature/233: Added User-specific audit for mailitems accessed --- .../User/Get-HawkMailItemsAccessed.ps1 | 62 +++++++++++++++++++ .../User/Start-HawkUserInvestigation.ps1 | 5 ++ 2 files changed, 67 insertions(+) create mode 100644 Hawk/functions/User/Get-HawkMailItemsAccessed.ps1 diff --git a/Hawk/functions/User/Get-HawkMailItemsAccessed.ps1 b/Hawk/functions/User/Get-HawkMailItemsAccessed.ps1 new file mode 100644 index 0000000..a09f82a --- /dev/null +++ b/Hawk/functions/User/Get-HawkMailItemsAccessed.ps1 @@ -0,0 +1,62 @@ +Function Get-HawkMailItemsAccessed { +<# +.SYNOPSIS + This will export MailboxItemsAccessed operations from the Unified Audit Log (UAL). Must be connected to Exchange Online + using the Connect-EXO or Connect-ExchangeOnline module. M365 E5 or G5 license is required for this function to work. + This telemetry will ONLY be availabe if Advanced Auditing is enabled for the M365 user. +.DESCRIPTION + Recent attacker activities have illuminated the use of the Graph API to read user mailbox contents. This will export + logs that will be present if the attacker is using the Graph API for such actions. Note: NOT all graph API actions against + a mailbox are malicious. Review the results of this function and look for suspicious access of mailbox items associated + with a specific user. +.PARAMETER UserIDs + Specific user(s) to be investigated +.EXAMPLE + Get-HawkMailItemsAccessed -UserIDs bsmith@contoso.com + Gets MailItemsAccess from Unified Audit Log (UAL) that corresponds to the User ID that is provided +.OUTPUTS + MailItemsAccessed.csv + +.LINK + https://www.microsoft.com/security/blog/2020/12/21/advice-for-incident-responders-on-recovery-from-systemic-identity-compromises/ + +.NOTES + "Operation Properties" and "Folders" will return "System.Object" as they are nested JSON within the AuditData field. + You will need to conduct individual log pull and review via PowerShell or other SIEM to determine values + for those fields. +#> + [CmdletBinding()] + param( + [Parameter(Mandatory=$true)] + [string[]]$UserIDs + ) + + BEGIN { + # Check if Hawk object exists and is fully initialized + if (Test-HawkGlobalObject) { + Initialize-HawkGlobalObject + } + Out-LogFile "Starting Unified Audit Log (UAL) search for 'MailItemsAccessed'" -Action + }#End Begin + + PROCESS { + $curr_idx = 0 + foreach($user in $UserIDs) { + if($curr_idx -eq 0) { + $UserList = $user + }else { + $UserList = "$UserList, $user" + } + $curr_idx += 1 + } + $MailboxItemsAccessed = Get-AllUnifiedAuditLogEntry -UnifiedSearch ("Search-UnifiedAuditLog -Operations 'MailItemsAccessed' -UserIds $UserList") + + $MailboxItemsAccessed | Select-Object -ExpandProperty AuditData | Convertfrom-Json | Out-MultipleFileType -FilePrefix "MailItemsAccessed" -csv -json + + }#End Process + + END{ + Out-Logfile "Completed exporting MailItemsAccessed logs" -Information + }#End End + +} \ No newline at end of file diff --git a/Hawk/functions/User/Start-HawkUserInvestigation.ps1 b/Hawk/functions/User/Start-HawkUserInvestigation.ps1 index d295c90..c9f3005 100644 --- a/Hawk/functions/User/Start-HawkUserInvestigation.ps1 +++ b/Hawk/functions/User/Start-HawkUserInvestigation.ps1 @@ -112,6 +112,11 @@ Out-LogFile "Running Get-HawkUserMessageTrace" -Action Get-HawkUserMessageTrace -User $User } + + if ($PSCmdlet.ShouldProcess("Running Get-HawkMailItemsAccessed for $User")) { + Out-LogFile "Running Get-HawkMailItemsAccessed" -Action + Get-HawkMailItemsAccessed -UserIDs $User + } if ($PSCmdlet.ShouldProcess("Running Get-HawkUserMobileDevice for $User")) { Out-LogFile "Running Get-HawkUserMobileDevice" -Action From ea076ba23ecd3a504fb3107d06071ce2515ea3e6 Mon Sep 17 00:00:00 2001 From: juliusperez1695 <150602855+juliusperez1695@users.noreply.github.com> Date: Tue, 14 Jan 2025 19:03:29 -0800 Subject: [PATCH 2/6] feature/233: Added Simple UAL output and error handling --- Hawk/Hawk.psd1 | 1 + Hawk/changelog.md | 1 + .../User/Get-HawkMailItemsAccessed.ps1 | 62 ------------- .../User/Get-HawkUserMailItemsAccessed.ps1 | 87 +++++++++++++++++++ .../User/Start-HawkUserInvestigation.ps1 | 6 +- 5 files changed, 92 insertions(+), 65 deletions(-) delete mode 100644 Hawk/functions/User/Get-HawkMailItemsAccessed.ps1 create mode 100644 Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 diff --git a/Hawk/Hawk.psd1 b/Hawk/Hawk.psd1 index 1589cd3..4b7bac5 100644 --- a/Hawk/Hawk.psd1 +++ b/Hawk/Hawk.psd1 @@ -83,6 +83,7 @@ 'Get-HawkTenantEntraIDAdmin', 'Get-HawkTenantEXOAdmin', 'Get-HawkTenantMailItemsAccessed', + 'Get-HawkUserMailItemsAccessed', 'Get-HawkTenantAppAndSPNCredentialDetail', 'Get-HawkTenantEntraIDUser', 'Get-HawkTenantDomainActivity', diff --git a/Hawk/changelog.md b/Hawk/changelog.md index 2f2aee0..3030106 100644 --- a/Hawk/changelog.md +++ b/Hawk/changelog.md @@ -95,4 +95,5 @@ - Implemented PROMPT tag to display to screen when prompting user - Added functionality to expand detect M365 license type to determine max log retention time - Added ability to expand search up to 365 days +- Added search of mail items accessed to the User Investigation (Get-HawkUserMailItemsAccessed) diff --git a/Hawk/functions/User/Get-HawkMailItemsAccessed.ps1 b/Hawk/functions/User/Get-HawkMailItemsAccessed.ps1 deleted file mode 100644 index a09f82a..0000000 --- a/Hawk/functions/User/Get-HawkMailItemsAccessed.ps1 +++ /dev/null @@ -1,62 +0,0 @@ -Function Get-HawkMailItemsAccessed { -<# -.SYNOPSIS - This will export MailboxItemsAccessed operations from the Unified Audit Log (UAL). Must be connected to Exchange Online - using the Connect-EXO or Connect-ExchangeOnline module. M365 E5 or G5 license is required for this function to work. - This telemetry will ONLY be availabe if Advanced Auditing is enabled for the M365 user. -.DESCRIPTION - Recent attacker activities have illuminated the use of the Graph API to read user mailbox contents. This will export - logs that will be present if the attacker is using the Graph API for such actions. Note: NOT all graph API actions against - a mailbox are malicious. Review the results of this function and look for suspicious access of mailbox items associated - with a specific user. -.PARAMETER UserIDs - Specific user(s) to be investigated -.EXAMPLE - Get-HawkMailItemsAccessed -UserIDs bsmith@contoso.com - Gets MailItemsAccess from Unified Audit Log (UAL) that corresponds to the User ID that is provided -.OUTPUTS - MailItemsAccessed.csv - -.LINK - https://www.microsoft.com/security/blog/2020/12/21/advice-for-incident-responders-on-recovery-from-systemic-identity-compromises/ - -.NOTES - "Operation Properties" and "Folders" will return "System.Object" as they are nested JSON within the AuditData field. - You will need to conduct individual log pull and review via PowerShell or other SIEM to determine values - for those fields. -#> - [CmdletBinding()] - param( - [Parameter(Mandatory=$true)] - [string[]]$UserIDs - ) - - BEGIN { - # Check if Hawk object exists and is fully initialized - if (Test-HawkGlobalObject) { - Initialize-HawkGlobalObject - } - Out-LogFile "Starting Unified Audit Log (UAL) search for 'MailItemsAccessed'" -Action - }#End Begin - - PROCESS { - $curr_idx = 0 - foreach($user in $UserIDs) { - if($curr_idx -eq 0) { - $UserList = $user - }else { - $UserList = "$UserList, $user" - } - $curr_idx += 1 - } - $MailboxItemsAccessed = Get-AllUnifiedAuditLogEntry -UnifiedSearch ("Search-UnifiedAuditLog -Operations 'MailItemsAccessed' -UserIds $UserList") - - $MailboxItemsAccessed | Select-Object -ExpandProperty AuditData | Convertfrom-Json | Out-MultipleFileType -FilePrefix "MailItemsAccessed" -csv -json - - }#End Process - - END{ - Out-Logfile "Completed exporting MailItemsAccessed logs" -Information - }#End End - -} \ No newline at end of file diff --git a/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 b/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 new file mode 100644 index 0000000..adf4f24 --- /dev/null +++ b/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 @@ -0,0 +1,87 @@ +Function Get-HawkUserMailItemsAccessed { +<# +.SYNOPSIS + This will export MailboxItemsAccessed operations from the Unified Audit Log (UAL). Must be connected to Exchange Online + using the Connect-EXO or Connect-ExchangeOnline module. M365 E5 or G5 license is required for this function to work. + This telemetry will ONLY be availabe if Advanced Auditing is enabled for the M365 user. +.DESCRIPTION + Recent attacker activities have illuminated the use of the Graph API to read user mailbox contents. This will export + logs that will be present if the attacker is using the Graph API for such actions. Note: NOT all graph API actions against + a mailbox are malicious. Review the results of this function and look for suspicious access of mailbox items associated + with a specific user. +.PARAMETER UserIDs + Specific user(s) to be investigated +.EXAMPLE + Get-HawkUserMailItemsAccessed -UserIDs bsmith@contoso.com + Gets MailItemsAccessed from Unified Audit Log (UAL) that corresponds to the User ID that is provided +.OUTPUTS + MailItemsAccessed_bsmith@contoso.com.csv + +.LINK + https://www.microsoft.com/security/blog/2020/12/21/advice-for-incident-responders-on-recovery-from-systemic-identity-compromises/ + +.NOTES + "Operation Properties" and "Folders" will return "System.Object" as they are nested JSON within the AuditData field. + You will need to conduct individual log pull and review via PowerShell or other SIEM to determine values + for those fields. +#> + [CmdletBinding()] + param( + [Parameter(Mandatory=$true)] + [array]$UserPrincipalName + ) + + BEGIN { + # Check if Hawk object exists and is fully initialized + if (Test-HawkGlobalObject) { + Initialize-HawkGlobalObject + } + Out-LogFile "Starting Unified Audit Log (UAL) search for 'MailItemsAccessed'" -Action + Test-EXOConnection + }#End Begin + + PROCESS { + + #Verify UPN input + [array]$UserArray = Test-UserObject -ToTest $UserPrincipalName + + foreach($UserObject in $UserArray) { + [string]$User = $UserObject.UserPrincipalName + try { + #Retrieve all audit data for mailitems accessed + $SearchCommand = "Search-UnifiedAuditLog -Operations 'MailItemsAccessed' -UserIds $User" + $MailboxItemsAccessed = Get-AllUnifiedAuditLogEntry -UnifiedSearch $SearchCommand + + if ($MailboxItemsAccessed.Count -gt 0){ + + #Define output directory path for user + $UserFolder = Join-Path -Path $Hawk.FilePath -ChildPath $User + + #Create user directory if it doesn't already exist + if (-not (Test-Path -Path $UserFolder)) { + New-Item -Path $UserFolder -ItemType Directory -Force | Out-Null + } + + #Compress raw data into more simple view + $MailboxItemsAccessedSimple = $MailboxItemsAccessed | Get-SimpleUnifiedAuditLog + + #Export both raw and simplistic views to specified user's folder + $MailboxItemsAccessed | Select-Object -ExpandProperty AuditData | Convertfrom-Json | Out-MultipleFileType -FilePrefix "MailItemsAccessed_$User" -User $User -csv -json + $MailboxItemsAccessedSimple | Out-MultipleFileType -FilePrefix "Simple_MailItemsAccessed_$User" -User $User -csv -json + } else { + Out-LogFile "Get-HawkUserMailItemsAccesed completed successfully" -Information + Out-LogFile "No items found for $User." -Information + } + } catch { + Out-LogFile "Error processing mail items accessed for $User : $_" -isError + Write-Error -ErrorRecord $_ -ErrorAction Continue + } + } + + }#End Process + + END{ + Out-Logfile "Completed exporting MailItemsAccessed logs" -Information + }#End End + +} \ No newline at end of file diff --git a/Hawk/functions/User/Start-HawkUserInvestigation.ps1 b/Hawk/functions/User/Start-HawkUserInvestigation.ps1 index c9f3005..c62e8f4 100644 --- a/Hawk/functions/User/Start-HawkUserInvestigation.ps1 +++ b/Hawk/functions/User/Start-HawkUserInvestigation.ps1 @@ -113,9 +113,9 @@ Get-HawkUserMessageTrace -User $User } - if ($PSCmdlet.ShouldProcess("Running Get-HawkMailItemsAccessed for $User")) { - Out-LogFile "Running Get-HawkMailItemsAccessed" -Action - Get-HawkMailItemsAccessed -UserIDs $User + if ($PSCmdlet.ShouldProcess("Running Get-HawkUserMailItemsAccessed for $User")) { + Out-LogFile "Running Get-HawkUserMailItemsAccessed" -Action + Get-HawkUserMailItemsAccessed -UserPrincipalName $User } if ($PSCmdlet.ShouldProcess("Running Get-HawkUserMobileDevice for $User")) { From 99113aa7cecb3008876ae9e2583f11f13d8a1e72 Mon Sep 17 00:00:00 2001 From: Jonathan Butler Date: Wed, 15 Jan 2025 16:41:36 -0500 Subject: [PATCH 3/6] Update comment based help to account for simple* files. --- Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 b/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 index adf4f24..1f73919 100644 --- a/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 +++ b/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 @@ -15,7 +15,8 @@ Function Get-HawkUserMailItemsAccessed { Get-HawkUserMailItemsAccessed -UserIDs bsmith@contoso.com Gets MailItemsAccessed from Unified Audit Log (UAL) that corresponds to the User ID that is provided .OUTPUTS - MailItemsAccessed_bsmith@contoso.com.csv + MailItemsAccessed_bsmith@contoso.com.csv /json + Simple_MailItemsAccessed.csv/json .LINK https://www.microsoft.com/security/blog/2020/12/21/advice-for-incident-responders-on-recovery-from-systemic-identity-compromises/ From 28b50360a7e8df1916ed47934cc582e6bc149991 Mon Sep 17 00:00:00 2001 From: Jonathan Butler Date: Wed, 15 Jan 2025 16:43:03 -0500 Subject: [PATCH 4/6] Add wait message for user. --- Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 b/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 index 1f73919..7179b87 100644 --- a/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 +++ b/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 @@ -38,6 +38,7 @@ Function Get-HawkUserMailItemsAccessed { Initialize-HawkGlobalObject } Out-LogFile "Starting Unified Audit Log (UAL) search for 'MailItemsAccessed'" -Action + Out-LogFile "Please be patient, this can take a while..." -Action Test-EXOConnection }#End Begin From 70cfc6e94e69685388feffe91c53bb14c915a210 Mon Sep 17 00:00:00 2001 From: Jonathan Butler Date: Wed, 15 Jan 2025 16:43:22 -0500 Subject: [PATCH 5/6] Add wait message for user. --- Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 b/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 index 7179b87..95717e7 100644 --- a/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 +++ b/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 @@ -38,7 +38,7 @@ Function Get-HawkUserMailItemsAccessed { Initialize-HawkGlobalObject } Out-LogFile "Starting Unified Audit Log (UAL) search for 'MailItemsAccessed'" -Action - Out-LogFile "Please be patient, this can take a while..." -Action + Out-LogFile "Please be patient, this can take a while..." -Information Test-EXOConnection }#End Begin From d4ecc089791daa7b4fc672de6789c166e7303865 Mon Sep 17 00:00:00 2001 From: Jonathan Butler Date: Wed, 15 Jan 2025 16:44:25 -0500 Subject: [PATCH 6/6] Update comment based help. --- Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 b/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 index 95717e7..3054fd5 100644 --- a/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 +++ b/Hawk/functions/User/Get-HawkUserMailItemsAccessed.ps1 @@ -9,10 +9,10 @@ Function Get-HawkUserMailItemsAccessed { logs that will be present if the attacker is using the Graph API for such actions. Note: NOT all graph API actions against a mailbox are malicious. Review the results of this function and look for suspicious access of mailbox items associated with a specific user. -.PARAMETER UserIDs +.PARAMETER UserPrincipalName Specific user(s) to be investigated .EXAMPLE - Get-HawkUserMailItemsAccessed -UserIDs bsmith@contoso.com + Get-HawkUserMailItemsAccessed -UserPrincipalName bsmith@contoso.com Gets MailItemsAccessed from Unified Audit Log (UAL) that corresponds to the User ID that is provided .OUTPUTS MailItemsAccessed_bsmith@contoso.com.csv /json