Table of Contents
Exchange Online Makes It Easier to Identify Problematic Sessions
Anything that helps Office 365 tenant administrators to track attempted or actual hacks is a good thing. Microsoft’s January 4 post telling us that Exchange Online mailbox and admin audit records now include a session identifier is an example of a small but useful change. I don’t need to repeat the description of what the change is as that ground has been well covered by the original post and the many duplicates that invariably appear to repeat the information given by Microsoft. But what hasn’t been explained is how to use the session identifier in a practical sense. Let’s try here.
Office 365 Audit Log
The first thing to know is that Exchange mailbox auditing must be enabled for any records to be captured. Auditing is enabled by default for Exchange Online, but it’s always wise to check. The second thing is that a tenant must also enable the ingestion of records from workloads into the Office 365 audit log. This is a one-time action.
Once enabled, audit data from Exchange flows into the audit log. Records show up roughly 15 minutes after an event happens. The delay is because of the need to gather data and pass the records through the normalization process to transform Exchange data into Office 365 audit data before ingestion into the log.
Audit records remain in the audit log for 90 days (for accounts with Office 365 E3 licenses) or 365 days (for those with Office 365 E5 licenses). Once the retention period elapses, Office 365 removes the audit records from the log. If you want to keep audit data for longer, you need to invest in a third-party product such as Quadrotech’s Radar for Security and Audit.
Looking for Audit Records
You can use the Audit log search functionality in the Microsoft 365 Compliance Center to look for Exchange activity, and then examine details of the records. As shown below, the session identifier is among the properties revealed when you click the More information link when viewing an audit record.

Understanding AuditData
Many of the interesting properties captured in an Office 365 audit record, including the session identifier, are held in a JSON-formatted property called AuditData. It’s difficult to track all the actions that occur within a specific session using the SCC interface and the better approach is to use the Search-UnifiedAuditLog cmdlet to find relevant records and examine what they hold.
However, because the session identifier is tucked away within the AuditData property, we must convert the JSON data before we can look at the session identifier. The Search-UnifiedAuditLog cmdlet includes a SessionId parameter, but it has no relevance here as it does not filter records based on the Exchange session identifier.
Extracting and Reporting Audit Events
The process to start tracing the events belonging to a session are therefore:
- Find the audit records for the relevant period and filter them to extract the events generated by Exchange.
- Extract the information held in the AuditData property for each record.
- Report what we find.
This PowerShell code is based on an example found in the reporting and auditing chapter in the Office 365 for IT Pros eBook. You’ll notice that some of the MailboxLogin records have no session identifiers. This is because these are PowerShell sessions that use basic authentication to connect rather than sessions generated by Exchange clients like OWA or Outlook. Only sessions that use modern authentication have their session identifiers recorded.
[array]$Records = (Search-UnifiedAuditLog -StartDate 4-Jan-2019 -EndDate 5-Jan-2019 -ResultSize 1000 | ? {$_.RecordType -like "*Exchange*"}) If ($Records.Count -eq 0) { Write-Host "No Exchange audit records found." } Else { Write-Host "Processing" $Records.Count "Exchange audit records..." $Report = @() ForEach ($Rec in $Records) { $AuditData = ConvertFrom-Json $Rec.Auditdata $ReportLine = [PSCustomObject]@{ TimeStamp = $AuditData.CreationTime User = $AuditData.UserId Action = $AuditData.Operation Status = $AuditData.ResultStatus SessionId = $AuditData.SessionId Mailbox = $AuditData.MailboxOwnerUPN } $Report += $ReportLine }} $Report | Sort SessionId, TimeStamp | Format-Table Timestamp, User, Action, Status, SessionId -AutoSize TimeStamp User Action Status SessionId --------- ---- ------ ------ --------- 2019-01-04T09:18:02 Administrator@office365itpros.com MailboxLogin Succeeded 2019-01-04T18:12:46 Administrator@office365itpros.com MailboxLogin Succeeded 2019-01-04T18:39:51 Tony.Redmond@office365itpros.com MailboxLogin Succeeded 1229a1b9-61fc-46f4-960a-84323c91cfc2 2019-01-04T18:49:48 Kim.Akers@office365itpros.com MailboxLogin Succeeded 1f6d382a-a2d2-4875-a6d1-264120f4392e 2019-01-04T18:51:35 James.Ryan@office365itpros.com MailboxLogin Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:51:55 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:52:33 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:52:33 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:52:34 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:52:35 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:54:47 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:57:22 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:57:22 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:57:37 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T19:00:15 James.Ryan@office365itpros.com SendAs Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T15:36:51 Tony.Redmond@office365itpros.com MailboxLogin Succeeded 85808ea9-a43d-4221-9338-584c4717f740
Our code works, but it outputs events from all the Exchange sessions in the chosen period. We can improve things a tad by filtering out anything but the records belonging to the session we need to examine. It’s easy to do this by adding a prompt to allow the user to input a session identifier (if they’re smart, they will cut and paste this from a record displayed by the compliance center).
$Session = (Read-Host "What session id to look for")
And now we adjust the code to process the records so that we only output those for the chosen identifier.
If ($Records.Count -eq 0) { Write-Host "No Exchange audit records found." } Else { Write-Host "Processing" $Records.Count "Exchange audit records..." $Report = @() ForEach ($Rec in $Records) { $AuditData = ConvertFrom-Json $Rec.Auditdata If ($AuditData.SessionId -eq $Session) { $ReportLine = [PSCustomObject]@{ TimeStamp = $AuditData.CreationTime User = $AuditData.UserId Action = $AuditData.Operation Status = $AuditData.ResultStatus SessionId = $AuditData.SessionId Mailbox = $AuditData.MailboxOwnerUPN } $Report += $ReportLine} }}
The output now includes only the records for the chosen session, sorted in time order:
TimeStamp User Action Status SessionId --------- ---- ------ ------ --------- 2019-01-04T18:51:35 James.Ryan@office365itpros.com MailboxLogin Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:51:55 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:52:33 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:52:33 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:52:34 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:52:35 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:54:47 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:57:22 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:57:22 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T18:57:37 James.Ryan@office365itpros.com HardDelete Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91 2019-01-04T19:00:15 James.Ryan@office365itpros.com SendAs Succeeded 7ea5da96-dbc6-4f86-8b1d-1f16b6278f91
It’s pretty clear from the audit log that someone logged into the James Ryan account performed a series of hard deletes (permanent removal of mailbox items) in quick succession followed by a mail send. Now we know what happened, we can look at the individual audit records to discover which items were removed from the mailbox. That takes a little more work, but it’s relatively easy because we have the relevant audit records that contain the information.
For more information about the Office 365 audit log and many practical examples of how to use it to generate reports about different tenant activities, see the reporting and auditing chapter in the Office 365 for IT Pros eBook.