Using Exchange Session Identifiers in Audit Log Records

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.

Viewing details of an audit record in the Office 365 Audit log
The session identifier in an Office 365 audit record as viewed through the SCC

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:

  1. Find the audit records for the relevant period and filter them to extract the events generated by Exchange.
  2. Extract the information held in the AuditData property for each record.
  3. 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.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.