Group collections from O365 with PowerShell

If you’re working in or responding to an O365 environment, there’s plenty of opportunities where you need to search and collect from multiple O365 custodians at the same time. While the experience of the Security & Compliance Center has improved over the years, I still find it inefficient for creating larger collections – especially when each custodian has to be searched for and added one at a time.

I created a handful of PowerShell scripts that automate the creation of searches for a group of custodians (provided via .txt file). I’ve used these methods countless times for both eDiscovery and IR cases.

There are different scripts to address the collection of:

  • O365 Mailbox – will capture email, calendar, tasks, contacts, MS Teams*.
  • Microsoft Teams – either for a single custodian or for a group.
  • Microsoft OneDrive – collect the O365 OneDrive for Business for a group of custodians.
  • When Legal says “get it all” – All O365 mailbox contents, including Teams, and OneDrive.

Once the collection has been generated you will still need to log on to https://protection.office.com to retrieve the search results.

Prerequisites:

  • ExchaneOnlineManagment PowerShell Module
  • Microsoft.Online.SharePoint.PowerShell Module

O365 Mailbox Collections: MSExchangeGroupSearch.ps1

<# MS Exchange Security & Compliance Search 
version 2.0
https://github.com/dwmetz/Axiom-PowerShell
Author: @dwmetz
Function:
    Collect an O365 mailbox search for group of custodians.
    Note this script requires previous installation of the ExchangeOnlineManagement PowerShell module
    See https://docs.microsoft.com/en-us/powershell/exchange/connect-to-scc-powershell?view=exchange-ps for more information.
      
This PowerShell script will prompt you for the following information:
    * Your user credentials                                          
    * The pathname for the text file that contains a list of user email addresses
    * The name of the Content Search that will be created
    * The search query string
The script will then:
    * Create and start a Content Search using the above information

Updates:
    17.November.2022 - updated ExchangeOnlineManagement connection, Security & Compliance Center (IPPSSession)

#>
# New Auth
Import-module ExchangeOnlineManagement
Connect-IPPSSession
# Get other required information
$inputfile = read-host "Enter the file name of the text file that contains the email addresses for the users you want to search"
$searchName = Read-Host "Enter the name for the new search"
$searchQuery = Read-Host "[Optional] Enter the search query you want to use"
$emailAddresses = Get-Content $inputfile | Where-Object {$_ -ne ""}  | ForEach-Object{ $_.Trim() }
Write-Host "Creating and starting the search"
$search = New-ComplianceSearch -Name $searchName -ExchangeLocation $emailAddresses -ContentMatchQuery $searchQuery
# Finally, start the search and then display the status
if($search)
{
    Start-ComplianceSearch $search.Name
    Get-ComplianceSearch $search.Name
} 
Write-Host "Search initiated"-ForegroundColor Blue
Write-Host "Proceed to https://protection.office.com/ to download the results."-ForegroundColor Blue

O365 Mailboxes and OneDrives: MS-ExchangeODGroupSearch.ps1

Note: you will get 2 authentication prompts as you are logging on to Security & Compliance Center as well as the Sharepoint Admin panel.

<# MS Exchange & OneDrive Security & Compliance Search 
version 2.0
https://github.com/dwmetz/Axiom-PowerShell
Author: @dwmetz

Function: This script will generate a Security and Compliance Search to capture O365 Email and OneDrive for a list of custodians.

This PowerShell script will prompt you for the following information:
    * Your user credentials                                          
    * The pathname for the text file that contains a list of user email addresses
    * The name of the Content Search that will be created
    * The search query string (optional. mastering the search query cmd is a dark art.)
 The script will then:
    * Find the OneDrive for Business site for each user in the text file
    * Create and start a Content Search using the above information
#>
Import-module ExchangeOnlineManagement
Import-Module Microsoft.Online.SharePoint.PowerShell
Connect-SPOService -Credential $creds -Url https://magdev-admin.sharepoint.com -ModernAuth $true -AuthenticationUrl https://login.microsoftonline.com/organizations
Connect-IPPSSession
# Get other required information
$script:inputfile = read-host "Enter the file name of the text file that contains the email addresses for the users you want to search"
$searchName = Read-Host "Enter the name for the new search"
$tempDir = "C:\Temp"
New-Item $tempDir\ODUrls.txt
ForEach ($emailAddress in Get-Content $script:inputfile)
{
    $OneDriveURL = Get-SPOSite -IncludePersonalSite $true -Limit all -Filter "Owner -like $emailAddress" | Select-Object -ExpandProperty Url 
    if ($null -ne $OneDriveURL){ 
        Add-content $tempDir\ODUrls.txt $OneDriveURL
        Write-Host "$emailAddress => $OneDriveURL"
    } else {
        Write-Warning "Could not locate OneDrive for $emailAddress"
    }
}
$emailAddresses = Get-Content $inputfile | Where-Object {$_ -ne ""}  | ForEach-Object{ $_.Trim() }
$urls = Get-Content $tempDir\ODUrls.txt | Where-Object {$_ -ne ""}  | ForEach-Object{ $_.Trim() }
Write-Host "Creating and starting the search"
# Collect OneDrive & Email
$search = New-ComplianceSearch -Name $searchName -ExchangeLocation $emailAddresses -SharePointLocation $urls -ContentMatchQuery $searchQuery
# Finally, start the search and then display the status
if($search)
{
    Start-ComplianceSearch $search.Name
    Get-ComplianceSearch $search.Name
} 
Remove-Item $tempDir\ODUrls.txt

MS One Drive: MSOneDriveSearch.ps1

Note: you will get 2 authentication prompts as you are logging on to Security & Compliance Center as well as the Sharepoint Admin panel.

<# MS OneDrive Security & Compliance Search 
version 2.0
https://github.com/dwmetz/Axiom-PowerShell
Author: @dwmetz
Function:

Function: This script will generate a Security and Compliance Search to capture OneDrive for a list of custodians.

This PowerShell script will prompt you for the following information:
    * Your user credentials                                          
    * The pathname for the text file that contains a list of user email addresses
    * The name of the Content Search that will be created
    * The search query string (optional. mastering the search query cmd is a dark art.)
 The script will then:
    * Find the OneDrive for Business site for each user in the text file
    * Create and start a Content Search using the above information
#>
Import-module ExchangeOnlineManagement
Import-Module Microsoft.Online.SharePoint.PowerShell
Connect-SPOService -Credential $creds -Url https://magdev-admin.sharepoint.com -ModernAuth $true -AuthenticationUrl https://login.microsoftonline.com/organizations
Connect-IPPSSession
# Get other required information
$script:inputfile = read-host "Enter the file name of the text file that contains the email addresses for the users you want to search"
$searchName = Read-Host "Enter the name for the new search"
$tempDir = "C:\Temp"
New-Item $tempDir\ODUrls.txt
ForEach ($emailAddress in Get-Content $script:inputfile)
{
    $OneDriveURL = Get-SPOSite -IncludePersonalSite $true -Limit all -Filter "Owner -like $emailAddress" | Select-Object -ExpandProperty Url 
    if ($null -ne $OneDriveURL){ 
        Add-content $tempDir\ODUrls.txt $OneDriveURL
        Write-Host "$emailAddress => $OneDriveURL"
    } else {
        Write-Warning "Could not locate OneDrive for $emailAddress"
    }
}
$urls = Get-Content $tempDir\ODUrls.txt | Where-Object {$_ -ne ""}  | ForEach-Object{ $_.Trim() }
# Collect OneDrive 
$search = New-ComplianceSearch -Name $searchName -SharePointLocation $urls -ContentMatchQuery $searchQuery
# Finally, start the search and then display the status
if($search)
{
    Start-ComplianceSearch $search.Name
    Get-ComplianceSearch $search.Name
} 
Remove-Item $tempDir\ODUrls.txt

*Microsoft Teams

There are 2 scripts here for Microsoft Teams. Note – by default a Mailbox .pst file that contains Teams data, will not show that Teams data when the .pst is viewed with Outlook. Magnet AXIOM easily parses the Teams content, whether integrated as part of a mailbox collection, or from collections where just MS Teams data is captured.

MS Teams – single custodian: MSTeamsSearch.ps1

<# MS Teams Security & Compliance Search 
version 2.0
https://github.com/dwmetz/Axiom-PowerShell
Author: @dwmetz
Function:
    Collect an O365 mailbox search for MS Teams communications.
    Note this script requires previous installation of the ExchangeOnlineManagement PowerShell module
    See https://docs.microsoft.com/en-us/powershell/exchange/connect-to-scc-powershell?view=exchange-ps for more information.
    
Updates:
    25.October.2022 - updated ExchangeOnlineManagement connection, Security & Compliance Center (IPPSSession)
    
#>
    Import-module ExchangeOnlineManagement
    Connect-ExchangeOnline
    [string]$aname = Read-Host -Prompt 'Enter your account name'
    Connect-IPPSSession -UserPrincipalName $aname
    [string]$name = Read-Host -Prompt 'Enter a name for the search'
    [string]$email = Read-Host -Prompt 'Enter the users email address'
    new-compliancesearch -name $name -ExchangeLocation $email -ContentMatchQuery 'kind=microsoftteams','ItemClass=IPM.Note.Microsoft.Conversation','ItemClass=IPM.Note.Microsoft.Missed','ItemClass=IPM.Note.Microsoft.Conversation.Voice','ItemClass=IPM.Note.Microsoft.Missed.Voice','ItemClass=IPM.SkypeTeams.Message'
    Start-ComplianceSearch $name
    Get-ComplianceSearch $name
    Write-Host "Search initiated."-ForegroundColor Cyan
    Write-Host "Proceed to https://protection.office.com/ to download the results."-ForegroundColor Cyan

MS Teams – group of custodians: MSTeamsGroupSearch.ps1

<# MS Teams (Group) Security & Compliance Search 
version 1.0
https://github.com/dwmetz/Axiom-PowerShell
Author: @dwmetz
Function:
    Collect MS Teams for group of custodians in O365.
    Note this script requires previous installation of the ExchangeOnlineManagement PowerShell module
    See https://docs.microsoft.com/en-us/powershell/exchange/connect-to-scc-powershell?view=exchange-ps for more information.
      
This PowerShell script will prompt you for the following information:
    * Your user credentials                                          
    * The pathname for the text file that contains a list of user email addresses

The script will then:
    * Create and start a Content Search using the above information

Updates:
    17.November.2022 - ExchangeOnlineManagement connection, Security & Compliance Center (IPPSSession)

#>
# New Auth
Import-module ExchangeOnlineManagement
Connect-IPPSSession
# Get other required information
$inputfile = read-host "Enter the file name of the text file that contains the email addresses for the users you want to search"
$searchName = Read-Host "Enter the name for the new search"
$emailAddresses = Get-Content $inputfile | Where-Object {$_ -ne ""}  | ForEach-Object{ $_.Trim() }
Write-Host "Creating and starting the search"
$search = New-ComplianceSearch -Name $searchName -ExchangeLocation $emailAddresses -ContentMatchQuery 'kind=microsoftteams','ItemClass=IPM.Note.Microsoft.Conversation','ItemClass=IPM.Note.Microsoft.Missed','ItemClass=IPM.Note.Microsoft.Conversation.Voice','ItemClass=IPM.Note.Microsoft.Missed.Voice','ItemClass=IPM.SkypeTeams.Message'
# Finally, start the search and then display the status
if($search)
{
    Start-ComplianceSearch $search.Name
    Get-ComplianceSearch $search.Name
} 
Write-Host "Search initiated."-ForegroundColor Cyan
Write-Host "Proceed to https://protection.office.com/ to download the results."-ForegroundColor Cyan

All of the scripts above can be downloaded from my Axiom-PowerShell GitHub repo. You can grab all the scripts at once by going to the latest releases file.

Mal-Hash – interacting with Virus Total API via PowerShell

Virus Total started in 2004 as a free service to analyze files and URLs for malicious behavior. In 2012 Virus Total (VT) was acquired by Google. Virus Total can provide a boon of information for the nascent investigator, though OpSec should remain a concern.

It’s rare to be in a security class where Virus Total is mentioned and not be warned about submitting the file hash vs. submitting the file itself. Often the suspect file, (i.e. ‘companyXYZ_invoice.doc) could contain information that has been customized to the target, you or your company. You’d don’t need to be a big-game target. Often these files are distributed like mass marketing. The copy YOU receive may have information that traces back to you. The bad guys use Virus Total too you see – and if they see that companyXYZ_invoice.doc was submitted (or companyABC_invoice.doc, company123… etc.), it could tip them off as to who is on to them.

The preferred method of submission is to use the file hash. This value is unique* (insert debate about MD5 hash collisions) to the file and is safer to use as a reference to search for. Virus Total supports MD5, SHA1 and SHA256 hashes for lookup.

Virus Total has both free and Enterprise plans available. Registration gives you access to an API key that you can use to interact with VT. The free accounts are limited in the number of API queries you can submit. If you’re working on a project at enterprise scale, chances are you’ll need the license to do so to support the number of queries.

Mal-Hash is a PowerShell script that utilizes the Virus Total API to interact with VT from the command-line. Your API key is kept in a file separate from the script. When you invoke the script, you point it to a file to analyze.

Mal-Hash.ps1

You can either type the path in manually or you can drag and drop the file onto the PowerShell window and the path will auto populate.

Path of file to analyze

The script uses the Get-FileHash PowerShell command to get the MD5, SHA1 and SHA256 hash of the file. The script then (referencing your API key for the lookup), submits the MD5 (by default) hash to Virus Total. The results of the query are displayed back to the PowerShell instance and are also recorded to a text file.

You can get Mal-Hash.ps1 from my GitHub here. As always, feel free to fork the project and contribute back to the code. Learning is a constant process.