-
Notifications
You must be signed in to change notification settings - Fork 0
/
38-Get-ExchangeMessageContentSearch.ps1
251 lines (217 loc) · 12 KB
/
38-Get-ExchangeMessageContentSearch.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# Bitpusher
# \`._,'/
# (_- -_)
# \o/
# The Digital
# Fox
# https://theTechRelay.com
# https://github.com/bitpusher2k
#
# Get-ExchangeMessageContentSearch.ps1 - By Bitpusher/The Digital Fox
# v2.8 last updated 2024-05-12
# Script to walk through usual content search steps for dealing with spam/phishing messages:
# * Search for messages by sender & subject
# * Export preview report
# * Export message contents
# * Purge messages
#
# Usage:
# powershell -executionpolicy bypass -f .\Get-ExchangeMessageContentSearch.ps1 -OutputPath "Default" -UserIds "compromisedaccount@contoso.com" -DaysAgo "5" -Subject "Phishing Message"
#
# Run with already existing connection to M365 tenant through
# PowerShell modules.
#
# Uses ExchangePowerShell (IPPS) commands.
#
#comp #m365 #security #bec #script #irscript #powershell #contentsearch #export #message #purge #content #search
#Requires -Version 5.1
[CmdletBinding()]
param(
[string]$OutputPath,
[string]$UserIds,
[int]$DaysAgo,
[string]$Subject,
[datetime]$StartDate,
[datetime]$EndDate,
[string]$Encoding = "utf8bom" # "ascii","ansi","bigendianunicode","unicode","utf8","utf8","utf8NoBOM","utf32"
)
if ($PSVersionTable.PSVersion.Major -eq 5 -and ($Encoding -eq "utf8bom" -or $Encoding -eq "utf8nobom")) { $Encoding = "utf8" }
$date = Get-Date -Format "yyyyMMddHHmmss"
## If OutputPath variable is not defined, prompt for it
if (!$OutputPath) {
Write-Output ""
$OutputPath = Read-Host "Enter the output base path, e.g. $($env:userprofile)\Desktop\Investigation (default)"
If ($OutputPath -eq '') { $OutputPath = "$($env:userprofile)\Desktop\Investigation" }
Write-Output "Output base path will be in $OutputPath"
} elseif ($OutputPath -eq 'Default') {
Write-Output ""
$OutputPath = "$($env:userprofile)\Desktop\Investigation"
Write-Output "Output base path will be in $OutputPath"
}
## If OutputPath does not exist, create it
$CheckOutputPath = Get-Item $OutputPath -ErrorAction SilentlyContinue
if (!$CheckOutputPath) {
Write-Output ""
Write-Output "Output path does not exist. Directory will be created."
mkdir $OutputPath
}
## Get Primary Domain Name for output subfolder
$PrimaryDomain = Get-AcceptedDomain | Where-Object Default -EQ $true
$DomainName = $PrimaryDomain.DomainName
$CheckSubDir = Get-Item $OutputPath\$DomainName -ErrorAction SilentlyContinue
if (!$CheckSubDir) {
Write-Output ""
Write-Output "Domain sub-directory does not exist. Sub-directory `"$DomainName`" will be created."
mkdir $OutputPath\$DomainName
}
Write-Output "You are signed in as:"
$CurrentUser = (Get-ConnectionInformation).UserPrincipalName[1]
$CurrentUser
# https://www.nextpoint.com/ediscovery-blog/ediscovery-keyword-search-examples/
# ((From:Dave recipients:Sue) OR (From:Sue recipients:Dave) OR (From:Dave recipients:Mike) OR (From:Mike recipients:Dave)) received:"This month"
# (c:c)(subjecttitle=“The Care Employment Opportunity”)(sent=2023-10-30..2023-10-31)
# Connect-IPPSSession
# Enable-OrganizationCustomization
Write-Output ""
Write-Output "Current users with Mailbox Search permissions are:"
Get-ManagementRoleAssignment -Role "Mailbox Search" -GetEffectiveUsers -Delegating $false | Select-Object EffectiveUserName, RoleAssigneeName, AssignmentMethod, DistinguishedName | Format-Table
Get-ManagementRoleAssignment -Role "Mailbox Search" -GetEffectiveUsers -Delegating $true | Select-Object EffectiveUserName, RoleAssigneeName, AssignmentMethod, DistinguishedName | Format-Table
Write-Output ""
Write-Output "Current users with eDiscovery Case Admin (eDiscovery Administrator) permissions are:"
Get-eDiscoveryCaseAdmin | Select-Object WindowsLiveID, Alias, DisplayName, PrimarySmtpAddress, DistinguishedName | Format-Table
Write-Output ""
Write-Output "Additional objects often configured with with eDiscovery permissions:"
# Get-RoleGroupMember -Identity "eDiscovery Manager"
try { Get-RoleGroupMember -Identity "eDiscovery Manager" -ErrorAction stop | Select-Object EffectiveUserName, DisplayName, Name, DistinguishedName, guid } catch { Write-Output "object eDiscovery Manager not found" }
try { Get-RoleGroupMember -Identity eDiscoveryManager -ErrorAction stop | Select-Object EffectiveUserName, DisplayName, Name, DistinguishedName, guid } catch { Write-Output "object eDiscoveryManager not found" }
try { Get-RoleGroupMember -Identity Reviewer -ErrorAction stop | Select-Object EffectiveUserName, DisplayName, Name, DistinguishedName, guid } catch { Write-Output "object Reviewer not found" }
try { Get-RoleGroupMember -Identity ComplianceAdministrator -ErrorAction stop | Select-Object EffectiveUserName, DisplayName, Name, DistinguishedName, guid } catch { Write-Output "object ComplianceAdministrator not found" }
Write-Output ""
Write-Output "If your username is included in the above manager/admin permissions you can continue. Otherwise: Ctrl+c, update permissions (https://compliance.microsoft.com/compliancecenterpermissions), sign-out, sign-in, and try again..."
Write-Output "`nOr use these commands from PoswerShell:"
Write-Output "Add-RoleGroupMember `"eDiscovery Manager`" -Member $CurrentUser; Get-RoleGroupMember -Identity `"eDiscovery Manager`""
Write-Output "Add-eDiscoveryCaseAdmin $CurrentUser; Get-eDiscoveryCaseAdmin"
Write-Output "."
Write-Output "."
## If UserIds variable is not defined, prompt for it
if (!$UserIds) {
Write-Output ""
$UserIds = Read-Host 'Enter the email address of the spam message source to be searched for/purged (leave blank to search all senders)'
if (!$UserIds) {
$UserIds = "Any Sender"
Write-Output "Will search content for ANY sender - Use with caution."
}
}
if (!$DaysAgo) {
Write-Output ""
$DaysAgo = Read-Host 'Enter how many days back to search (default 5)'
if ($DaysAgo -eq '') { $DaysAgo = "5" }
}
if ($DaysAgo -gt 90) { $DaysAgo = "90" }
if (!$Subject) {
Write-Output ""
$Subject = Read-Host 'Enter partial or complete subject of the malicious message to search for (required - escape apostrophies and quote marks with backtick or possibly backslash)'
if (!$Subject) {
Write-Output "Subject line required. Exiting"
exit
}
}
$StartDate = (Get-Date).AddDays(- $DaysAgo)
$EndDate = (Get-Date).AddDays(1)
# (Get-ConnectionInformation).UserPrincipalName
# Add-RoleGroupMember "eDiscovery Manager" -Member "user@domain.com"
# (Remove-RoleGroupMember "eDiscovery Manager" -Member "user@domain.com")
# Get-eDiscoveryCaseAdmin
# Add-eDiscoveryCaseAdmin me@example.com
# Add-RoleGroupMember -Identity "eDiscovery Manager" -Member me@example.com
Write-Output "."
Write-Output "."
$SearchName = "Suspicious email search $date"
if ($UserIds -eq "Any Sender") {
$Query = "sent>=" + $StartDate + " AND (subject:" + $Subject + ")"
} else {
$Query = "From:" + $UserIds + " AND sent>=" + $StartDate + " AND (subject:" + $Subject + ")"
}
Write-Output "Starting content search - `"$SearchName`""
Write-Output "New-ComplianceSearch -name `"$SearchName`" -ExchangeLocation all -ContentMatchQuery $Query`n"
New-ComplianceSearch -Name "$SearchName" -ExchangeLocation all -ContentMatchQuery $Query
# $Search=New-ComplianceSearch -Name "Remove Phishing Message" -ExchangeLocation All -ContentMatchQuery '(Received:4/13/2016..4/14/2016) AND (Subject:"Action required")'
# $Search=New-ComplianceSearch -Name "Remove Phishing Message" -ExchangeLocation All -ContentMatchQuery '(c:c)(from=greg@aefresno.com)(sent=2023-10-29..2023-11-29)'
Start-ComplianceSearch -Identity $SearchName
# $SearchStatus = Get-ComplianceSearch -Identity $SearchName
# Get-ComplianceSearch -Identity $SearchName | FL
$Continue = ""
while ($Continue -ne "Y") {
$OperationStatus = Get-ComplianceSearch -Identity "$SearchName"
# $OperationStatus
$OperationStatus.Name
$OperationStatus.ContentMatchQuery
# $OperationStatus.CreatedTime
# $OperationStatus.JobStartTime
# $OperationStatus.JobEndTime
$OperationStatus.Status
$Continue = Read-Host "`nIf the search status above is 'Completed' enter 'Y' to continue and export a preview. Press enter to refresh status"
}
Write-Output "."
Write-Output "."
Write-Output "Starting preview export - `"$SearchName`""
Write-Output "New-ComplianceSearchAction -SearchName `"$SearchName`" -Preview`n"
New-ComplianceSearchAction -SearchName "$SearchName" -Preview
Write-Output "If there is an error above about `"A parameter cannot be found that matches parameter name 'Preview'`" you need to add the eDiscovery manager or admin role to your account and sign out/sign in again."
Write-Output "Go to https://compliance.microsoft.com/contentsearchv2 in Edge to manage through admin center."
$Continue = ""
while ($Continue -ne "Y") {
$OperationStatus = Get-ComplianceSearchAction -Identity "$($SearchName)_Preview"
# $OperationStatus
$OperationStatus.Name
# $OperationStatus.CreatedTime
# $OperationStatus.JobStartTime
# $OperationStatus.JobEndTime
$OperationStatus.Status
$Continue = Read-Host "`nIf the preview status above is 'Completed' enter 'Y' to continue and save the report. Press enter to refresh status"
}
Write-Output "Exporting content search preview results..."
$Results = (Get-ComplianceSearchAction "$($SearchName)_Preview" -Details).Results -replace '{', "`"Location`",`"Sender`",`"Subject`",`"Type`",`"Size`",`"ReceivedTime`",`"DataLink`"`r`n" -replace '}' -replace 'Location: ', '"' -replace '; Sender: ', '","' -replace '; Subject: ', '","' -replace '; Type: ', '","' -replace '; Size: ', '","' -replace '; Received Time: ', '","' -replace '; Data Link: ', '","' -replace ",`r`n", "`"`r`n" | Out-File "$OutputPath\$DomainName\ContentSearchResults_$($date).csv"
Invoke-Item "$OutputPath\$DomainName"
Write-Output "."
Write-Output "."
$Continue = ""
while ($Continue -ne "Y") {
$Continue = Read-Host "Enter 'Y' to continue with content search export. Press Ctrl+c to exit script now"
}
Write-Output "New-ComplianceSearchAction -SearchName `"$SearchName`" -Export"
New-ComplianceSearchAction -SearchName "$SearchName" -Export
$OperationStatus = Get-ComplianceSearchAction -Identity "$($SearchName)_Export"
$OperationStatus.Name
$OperationStatus.Status
Write-Output "Opening Edge browser window so content search export can be retrieved and reviewed..."
Write-Output "https://compliance.microsoft.com/contentsearchv2?viewid=export"
Start-Process msedge.exe -ArgumentList "https://compliance.microsoft.com/contentsearchv2?viewid=export"
# Start-Process msedge.exe -ArgumentList "https://compliance.microsoft.com/contentsearchv2?viewid=export -inprivate" # Use this string to open private window if Edge is not the browser being used for M365 management
Write-Output "Sign-in with the account that started this content search, click `"Export`". When the export is 'Completed' retrieve the messages using `"Download results`" and the Export Key."
Write-Output "."
Write-Output "."
$Continue = ""
while ($Continue -ne "Y") {
$Continue = Read-Host "Enter 'Y' to continue with *PURGE* (SoftDelete) of all messages found though this content search from all mailboxes. Press Ctrl+c to exit script now"
}
$Continue = ""
while ($Continue -ne "YES") {
$Continue = Read-Host "*** Are you sure you are ready to PURGE all messages found through content search `"$SearchName`" from all mailboxes? Enter 'YES' to continue. Press Ctrl+c to exit script now"
}
if ($Continue -eq "YES") {
Write-Output "PURGING messages found through `"$SearchName`""
Write-Output "New-ComplianceSearchAction -SearchName `"$SearchName`" -Purge -PurgeType SoftDelete"
New-ComplianceSearchAction -SearchName "$SearchName" -Purge -PurgeType SoftDelete
# New-ComplianceSearchAction -SearchName $SearchName -Purge -PurgeType HardDelete
Get-ComplianceSearchAction -Identity "$($SearchName)_Purge"
$Continue = ""
while ($Continue -ne "Y") {
$OperationStatus = Get-ComplianceSearchAction -Identity "$($SearchName)_Purge"
# $OperationStatus
$OperationStatus.Status
$Continue = Read-Host "`nIf the purge status above is 'Completed' enter 'Y' to continue. Press enter to refresh status"
}
}
Write-Output "`nDone! Check output path for results."
exit