DFIR-O365RC PowerShell module for Office 365 and Azure AD log collection

superior_hosting_service

DFIR

Module description

The DFIR-O365RC PowerShell module is a set of functions that allow the DFIR analyst to collect logs relevant for Office 365 Business Email Compromise investigations.

The logs are generated in JSON format and retrieved from two main data sources:

The two data sources can be queried from different endpoints:

Data source / EndpointHistoryPerformanceScopePre-requisites (OS or Azure)
Unified Audit Logs / Exchange Online PowerShell90 daysPoorAll Office 365 logs (Azure AD included)None
Unified Audit Logs / Office 365 Management API7 daysGoodAll Office 365 logs (Azure AD included)Azure App registration
Azure AD Logs / Azure AD PowerShell Preview30 daysGoodAzure AD sign-ins and audit events onlyWindows OS only
Azure AD Logs / MS Graph API30 daysGoodAzure AD sign-ins and audit events onlyNone

DFIR-O365RC is a forensic tool, its aim is not to monitor in real time your Office 365 infrastructure: Please use the Office 365 Management API if you want to analyze data in real time with a SIEM.

DFIR-O365RC will fetch data from:

  • Azure AD Logs using the MS Graph API because performance is good, history is 30 days and it works on PowerShell Core.
  • Unified Audit Logs using Exchange online PowerShell despite poor performance, history is 90 days and it works on PowerShell Core.

In case you are also investigating other Azure resources (IaaS, PaaS…) DFIR-O365RC can also fetch data from Azure Activity logs using the Azure Monitor RESTAPI. History is 90 days and it works on PowerShell Core.

As a result, DFIR-O365RC works also on Linux or Mac, as long as you have PowerShell Core and a browser in order to use device login.

Installation and pre-requisites

Clone the DFIR-O365RC repository. The tool works on PowerShell Desktop and PowerShell Core.

DFIR-O365 uses Jason Thompson’s MSAL.PS and Boe Prox’s PoshRSJob modules. To install them run the following commands:

Install-Module -Name MSAL.PS -RequiredVersion '4.21.0.1'
Install-Module -Name PoshRSJob -RequiredVersion '1.7.4.4'

If MSAL.PS module installation fails with the following message:

WARNING: The specified module ‘MSAL.PS’ with PowerShellGetFormatVersion ‘2.0’ is not supported by the current version of PowerShellGet. Get the latest version of the PowerShellGet module to install this module, ‘MSAL.PS’.

Update PowerShellGet with the following commands:

Install-PackageProvider Nuget -Force
Install-Module -Name PowerShellGet -Force

Once both modules are installed, launch a PowerShell prompt and locate your Powershell modules path with the following command:

PS> $env:PSModulePath

Copy the DFIR-O365RC directory in one of your modules path, for example on Windows:

  • %USERPROFILE%\Documents\WindowsPowerShell\Modules
  • %ProgramFiles%\WindowsPowerShell\Modules
  • %SYSTEMROOT%\system32\WindowsPowerShell\v1.0\Modules

Modules path examples on Linux:

  • /home/%USERNAME%/.local/share/powershell/Modules
  • /usr/local/share/powershell/Modules
  • /opt/microsoft/powershell/7/Modules

The DFIR-O365RC module is installed, restart the PowerShell prompt and load the module:

PS> Import-module DFIR-O365RC

Roles and license requirements

The user launching the tool should have the following roles:

  • Microsoft 365 role (portal.microsoft.com): Global reader
  • Exchange Online role (outlook.office365.com/ecp): View-Only Audit Logs

In order to retrieve Azure AD sign-ins logs with the MS Graph API you need at least one user with an Azure AD Premium P1 license. This license can be purchased at additional cost for a single user and is sometimes included in some license plans such as the Microsoft 365 Business Premium for small and medium-sized businesses.

If you need to retrieve also the Azure Activity logs you need the Log Analytics Reader role for the Azure subscription you are dumping the logs from.

Functions included in the module

The module has 6 functions:

Function nameData Source/HistoryPerformanceCompletenessDetails
Get-O365FullUnified audit logs/90 daysPoorAll unified audit logsA subset of logs per record type can be retrieved. Use only on a small tenant or a short period of time
Get-O365LightUnified audit logs/90 daysGoodA subset of unified audit logs onlyOnly a subset of operations considered of interest is retrieved.
Get-DefenderforO365Unified audit logs/90 daysGoodA subset of unified audit logs onlyRetrieves Defender for Office 365 related logs. Requires at least an E5 license or a license plan such as Microsoft Defender for Office 365 Plan or cloud app security
Get-AADLogsAzure AD Logs/30 daysGoodAll Azure AD logsGet tenant general information, all Azure sign-ins and audit logs. Azure AD sign-ins logs have more information than Azure AD logs retrieved via Unified audit logs.
Get-AADAppsAzure AD Logs/30 daysGoodA subset of Azure AD logs onlyGet Azure audit logs related to Azure applications and service principals only. The logs are enriched with application or service principal object information.
Get-AADDevicesAzure AD Logs/30 daysGoodA subset of Azure AD logs onlyGet Azure audit logs related to Azure AD joined or registered devices only. The logs are enriched with device object information.
Search-O365Unified audit logs/90 daysDepends on the queryA subset of unified audit logs onlySearch for activity related to a particular user, IP address or use the freetext query.
Get-AzRMActivityLogsAzure Activity logs/90 daysGoodAll Azure Activity logsGet all Azure activity logs for a given subscription or on every subscription the account running the function has access to

When querying Unified audit logs you are limited to 3 concurrent Exchange Online Powershell sessions. DFIR-O365RC will try to use all available sessions, please close any existing session before launching the log collection.

Each function as a comment based help which you can invoke with the get-help cmdlet.

#Display comment based help
PS> Get-help Get-O365Full
#Display comment based help with examples
PS> Get-help Get-O365Full -examples

Each function takes as a parameter a start date and an end date.

In order to retrieve Azure AD audit logs, sign-ins logs from the past 30 days and tenant information launch the following command:

$enddate = get-date
$startdate = $enddate.adddays(-30)
Get-AADLogs -startdate $startdate -enddate $enddate

In order to retrieve enriched Azure AD audit logs related to Azure applications and service principals from the past 30 days launch the following command:

$enddate = get-date
$startdate = $enddate.adddays(-30)
Get-AADApps -startdate $startdate -enddate $enddate

In order to retrieve enriched Azure AD audit logs related to Azure AD joined or registered devices from the past 30 days launch the following command:

$enddate = get-date
$startdate = $enddate.adddays(-30)
Get-AADDevices -startdate $startdate -enddate $enddate

In order to retrieve all unified audit logs considered of interest from the past 30 days, except those related to Azure AD, which were already retrieved by the first command, launch:

$enddate = get-date
$startdate = $enddate.adddays(-30)
Get-O365Light -startdate $startdate -enddate $enddate -Operationsset "AllbutAzureAD"

In order to retrieve all unified audit logs considered of interest in a time window between -90 days and -30 days from now launch the following command:

$enddate = (get-date).adddays(-30)
$startdate = (get-date).adddays(-90)
Get-O365Light -StartDate $startdate -Enddate $enddate -Operationsset All

If mailbox audit is enabled and you want also to retrieve Mailboxlogin operations you can use the dedicated switch, on large tenants beware of a 50.000 events per day limit retrieval.

Get-O365Light -StartDate $startdate -Enddate $enddate -Operationsset All -MailboxLogin $true

If there are users with Enterprise 5 licenses or if there is a Microsoft Defender for Office 365 Plan you can retrieve Microsoft Defender related logs with the following command:

$enddate = get-date
$startdate = $enddate.adddays(-90)
Get-DefenderforO365 -StartDate $startdate -Enddate $enddate

To retrieve all Exchange Online related records from the unified audit logs between Christmas eve and Boxing day, beware that performance might be poor on a large tenant:

$startdate = get-date "12/24/2020"
$enddate = get-date "12/26/2020"
Get-O365Full -StartDate $startdate -Enddate $enddate -RecordSet ExchangeOnly

You can use the search function to look for IP addresses, activity related to specific users or perfrom a freetext search in the unified audit logs:

$enddate = get-date
$startdate = $enddate.adddays(-90)
#Retrieve events using the Exchange online Powershell AppId
Search-O365 -StartDate $startdate -Enddate $enddate -FreeText "a0c73c16-a7e3-4564-9a95-2bdf47383716"

#Search for events related to the X.X.X.X and Y.Y.Y.Y IP adresses, argument is a string separated by comas.
Search-O365 -StartDate $startdate -Enddate $enddate -IPAddresses "X.X.X.X,Y.Y.Y.Y"

#Retrieve events related to users user1@contoso.com and user2@constoso.com , argument is a system.array object
Search-O365 -StartDate $startdate -Enddate $enddate -UserIds "user1@contoso.com", "user2@contoso.com"

To retrieve all Azure Activity logs the account has access to launch the following command, available subscriptions will be displayed:

$enddate = get-date
$startdate = $enddate.adddays(-90)
Get-AzRMActivityLogs -StartDate $startdate -Enddate $enddate

When using PowerShell Core the authentication process will require a device code, you will need to use the devicecode parameter and launch your browser, open the https://microsoft.com/devicelogin URL and enter the code provided by the following message:

PS> Get-O365Light -StartDate $startdate -Enddate $enddate -DeviceCode:$true
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code XXXXXXXX to authenticate.

Files generated

All files generated are in JSON format.

  • Get-AADApps creates a file named AADApps_%FQDN%.json in the azure_ad_apps folder where FQDN is the domain name part of the account used to collect the logs.
  • Get-AADDevices creates a file named AADDevices_%FQDN%.json in the azure_ad_devices folder.
  • Get-AADLogs creates folders named after the current date using the YYYY-MM-DD format in the azure_ad_signin folder, in each directory a file called AADSigninLog_%FQDN%_YYYY-MM-DD_HH-00-00.json is created for Azure AD sign-ins logs. A folder azure_ad_audit is also created and results are dumped in files named AADAuditLog_%FQDN%_YYYY-MM-DD.json for Azure AD audit logs. Finally a folder called azure_ad_tenant is created and the general tenant information written in a file named AADTenant_%FQDN%.json.
  • Get-AzRMActivityLogs creates folders named after the current date using the YYYY-MM-DD format in the azure_rm_activity folder, in each directory a file called AzRM_%FQDN%_%SubscriptionID%_YYYY-MM-DD_HH-00-00.json is created where %SubscriptionID% is the Azure subscription ID. A folder called azure_rm_subscriptions is created and each subscription information written in a file named AzRMsubscriptions_%FQDN%.json.
  • Get-O365Full creates folders named after the current date using the YYYY-MM-DD format in the O365_unified_audit_logs, in each directory a file called UnifiedAuditLog_%FQDN%_YYYY-MM-DD_HH-00-00.json is created.
  • Get-O365Light creates folders named after the current date using the YYYY-MM-DD format in the O365_unified_audit_logs, in each directory a file called UnifiedAuditLog_%FQDN%_YYYY-MM-DD.json is created.
  • Get-DefenderforO365 creates folders named after the current date using the YYYY-MM-DD format in the O365_unified_audit_logs, in each directory a file called UnifiedAuditLog_%FQDN%_YYYY-MM-DD_DefenderforO365.json is created.
  • Search-O365 creates folders named after the current date using the YYYY-MM-DD format in the O365_unified_audit_logs, in each directory a file called UnifiedAuditLog_%FQDN%YYYY-MM-DD%searchtype%.json is created, where searchtype can have the values “Freetext“, “IPAddresses” or “UserIds“.

Launching the various functions will generate a similar directory structure:

DFIR-O365_Logs
│   Get-AADApps.log
│   Get-AADDevices.log
│   Get-AADLogs.log
|   Get-AzRMActivityLogs
│   Get-DefenderforO365.log
│   Get-O365Light.log    
│   Search-O365.log
└───azure_ad_apps
│    │   AADApps_%FQDN%.json
└───azure_ad_audit
│    │   AADAuditLog_%FQDN%_YYYY-MM-DD.json
│    │   ...
└───azure_ad_devices
│    │   AADDevices_%FQDN%.json 
└───azure_ad_signin
│   │
│   └───YYYY-MM-DD
│       │   AADSigninLog_%FQDN%_YYYY-MM-DD_HH-00-00.json
│       │   ...
└───azure_ad_tenant
│    │   AADTenant_%FQDN%.json
└───azure_rm_activity
│   │
│   └───YYYY-MM-DD
│       │   AzRM_%FQDN%_%SubscriptionID%_YYYY-MM-DD_HH-00-00.json
│       │   ...
└───azure_rm_subscriptions
│    │   AzRMsubscriptions_%FQDN%.json
└───O365_unified_audit_logs
│   │
│   └───YYYY-MM-DD
│       │   UnifiedAuditLog_%FDQN%_YYYY-MM-DD.json
│       │   UnifiedAuditLog_%FQDN%_YYYY-MM-DD_freetext.json
│       │   UnifiedAuditLog_%FQDN%_YYYY-MM-DD_DefenderforO365.json
│       │   UnifiedAuditLog_%FQDN%_YYYY-MM-DD_HH-00-00.json
│       │   ...