Skip Navigation
Get a Demo
 
 
 
 
 
 
 
 
 
Resources Blog Threat detection

Cloud coverage: Detecting an email payroll diversion attack

Whether it’s in the cloud or on prem, there’s an abundance of useful Exchange telemetry that defenders can use to detect suspicious email activity like payroll diversion schemes.

Justin Schoenfeld Zach Diehl
Originally published . Last modified .

Email inboxes contain a treasure trove of valuable information and email addresses are among the most critical identifiers in the corporate world. Wresting control of a victim’s inbox not only offers an adversary access to untold amounts of sensitive information but also the ability to impersonate legit user accounts and carry out a multitude of other malicious activities. Therefore, it’s no surprise that adversaries commonly target email systems and that defenders prioritize securing them.

Whether it’s hosted locally or (as is more-than-likely) in the cloud, email accounts are practically endpoints that require hardening and layered defense mechanisms. As we can see in the MITRE ATT&CK Cloud Matrix for Office365, adversaries are capable of performing all the necessary tactics the security industry is familiar with. Although the techniques and procedures may be quite different, the concepts remain the same.

MITRE ATT&CK Cloud Matrix for Office365

Saving [REDACTED]’s paycheck

We’ve got a group of Office 365 detection analytics that are designed to catch suspicious and malicious email activity. While it doesn’t necessarily include a email component, we’ve encountered attempted payroll diversion fraud over the years that follows some variation of the following pattern: the adversary compromises an email account and abuses their access in an attempt to update that user’s direct deposit information by corresponding via email with payroll department, forwarding relevant correspondence into a rarely used folder to evade notice, and eventually—if successful—routing the legitimate user’s paycheck into the criminal’s bank account.

In this post, we’re going to use real-world examples to dig into some of the post-compromise behaviors that typically correspond with this kind of attack. We’ll show you some of the relevant Microsoft 365 and Azure Active Directory artifacts contained in the Unified Audit Log (UAL), which is Microsoft’s data source for forensic investigations. Lastly, we’ll provide some tips on how you can detect, investigate, and respond to these sorts of compromises.

The initial lead

The initial investigative points often come from Office 365 detection analytics looking for email rules that copy or move email messages to rarely used folders—such as the “Archive” folder. Once an adversary triggers that detection analytic, our product presents our detection engineering team with a summarized event that, at a high-level, details the following:

User victim@example.com, logged in from IP X.X.X.X, created an email rule named “……….” that moves emails sent from person alice@example.com to the Archive folder

Some initial “tinfoil-hat” thoughts typically come to mind when reviewing an event like this:

  • Does this user normally login from this IP?
    • Can we use Geo-IP info for additional context?
  • Does this user normally create inbox rules?
  • What else occurred within this user’s login session?
  • Any suspicious audit logs pre-date this event?
  • What else did the user do after this rule was created?
    • Any emails sent?
    • Any sensitive emails accessed?
    • Were any other email rules created?
  • What does alice@example.com from the rule condition do within the organization?

The detection logic underlying that type of event assumes the user’s email account has been compromised based on how rare it is for that destination folder (the “archive” folder in this case) to be used in email rules, let alone the relative scarcity of email forwarding rules in the first place. It’s also common in these sorts of attacks for the adversary to log in from an atypical IP or location.

To slice and dice Microsoft’s UALs, we forward them into Splunk and use its visualization feature to plot users’ previous login activity, with the goal of spotting deviations over the last 14 days:

suspicious event timeline

The above chart shows successful logins stemming from either Microsoft Exchange and Azure Active Directory for the victim of an attempted payroll diversion attack we detected. The spike in the chart isn’t terribly alarming on its own, but it’s noteworthy because it’s directly correlated with the time of one of our suspicious email rule events. Worth noting: in this particular case, additional context on these IPs didn’t show any scenarios indicating “impossible travel.”

Most of the successful logins occur from within the legitimate user’s expected geographic region—and none came from abroad.

To learn more about the spike, we generally create a timeline and start pivoting around the data for additional leads. Developing a timeline of behavior is important to help narrow down or expand the scope of our investigations. Figuring out what the user did in a given login session is typically a good starting point.

Quick (sort of) primer on UAL Pivoting

The chart above utilizes the following operations, which denote a login in the audit logs for each of the respective log origins:

 

WorkloadOperation
Workload:

AzureActiveDirectory

Operation:

UserLoggedIn

Workload:

Exchange

Operation:

MailboxLogin

What follows are a pair of examples illustrating the log data you would see from a UserLoggedIn and MailboxLogin operation.

Exchange MailboxLogin log sample

{
  "CreationTime": "2022-01-01T00:00:00",
  "Id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "Operation": "MailboxLogin",
  "OrganizationId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "RecordType": 2,
  "ResultStatus": "Succeeded",
  "UserKey": "XXXXXXXXXXXXXXXX",
  "UserType": 0,
  "Version": 1,
  "Workload": "Exchange",
  "ClientIP": "X.X.X.X",
  "UserId": "victim@example.com",
  "ClientIPAddress": "X.X.X.X",
  "ClientInfoString": "Client=/owa/; Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0000.100 Safari/500.00 Edg/100.0.0000.00",
  "ExternalAccess": false,
  "InternalLogonType": 0,
  "LogonType": 0,
  "LogonUserSid": "S-1-5-21-XXXXXXXXXX-XXXXXXXXX-XXXXXXXXXX-XXXXXXXX",
  "MailboxGuid": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "MailboxOwnerSid": "S-1-5-21-XXXXXXXXXX-XXXXXXXXX-XXXXXXXXXX-XXXXXXXX",
  "MailboxOwnerUPN": "victim@example.com",
  "OrganizationName": "example.com",
  "OriginatingServer": "XXXXXXXXXXXX",
  "SessionId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}

Azure Active Directory UserLoggedIn log sample

{
  "CreationTime": "2022-01-01T00:00:00",
  "Id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "Operation": "UserLoggedIn",
  "OrganizationId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "RecordType": 15,
  "ResultStatus": "Success",
  "UserKey": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "UserType": 0,
  "Version": 1,
  "Workload": "AzureActiveDirectory",
  "ClientIP": "X.X.X.X",
  "ObjectId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "UserId": "victim@example.com",
  "AzureActiveDirectoryEventType": 1,
  "ExtendedProperties": [
    {
      "Name": "ResultStatusDetail",
      "Value": "Redirect"
    },
    {
      "Name": "UserAgent",
      "Value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0000.100 Safari/500.00 Edg/100.0.0000.00"
    },
    {
      "Name": "RequestType",
      "Value": "OAuth2:Authorize"
    }],
  "ModifiedProperties": [],
  "Actor": [
    {
      "ID": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
      "Type": 0
    },
    {
      "ID": "victim@example.com",
      "Type": 5
    }],
  "ActorContextId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "ActorIpAddress": "X.X.X.X",
  "InterSystemsId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "IntraSystemId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "SupportTicketId": "",
  "Target": [
    {
      "ID": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
      "Type": 0
    }],
  "TargetContextId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "ApplicationId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "DeviceProperties": [
    {
      "Name": "OS",
      "Value": "Windows 10"
    },
    {
      "Name": "BrowserType",
      "Value": "Edge"
    },
    {
      "Name": "IsCompliantAndManaged",
      "Value": "False"
    },
    {
      "Name": "SessionId",
      "Value": " "
    }],
  "ErrorNumber": "0" }

A pivot point is a piece of data that can expand or narrow down the scope of an investigation. Audit logs that stem from the Cloud may be totally new to defenders, particularly as cloud security research expands and as organizations invest more in cloud system visibility. Some of the fields we’re about to discuss may be new to those who are less familiar with cloud data, but they offer fantastic context that help us see the bigger picture when responding to incidents.

IP addresses in the audit logs overlap slightly between Exchange and Azure. Microsoft documentation explains how they are different and where you can find them, including the following table:

 

WorkloadParameterAPI notes
Workload:

Exchange

Parameter:API notes:

The IP address of the device that was used when the operation was logged. The IP address is displayed in either an IPv4 or IPv6 address format.

Workload:

AzureActiveDirectory + Exchange

Parameter:API notes:

The IP address of the device that was used when the activity was logged. The IP address is displayed in either an IPv4 or IPv6 address format.

For some services, the value displayed in this property might be the IP address for a trusted application (for example, Office on the web apps) calling into the service on behalf of a user and not the IP address of the device used by person who performed the activity.

Also, for Azure Active Directory-related events, the IP address isn’t logged and the value for the ClientIP property is null.

Workload:

AzureActiveDirectory

Parameter:API notes:

The actor’s IP address in IPV4 or IPV6 address format.

The IPs mainly help us understand if there might be other victim email accounts within the organization or other customer environments. Although easily changeable by the adversary, it’s a simple pivot point. Enriching the IP with context like geolocation, known vpn/proxy/tor services, ISP, and fraud activity helps detection engineers decide to pursue or ignore potential leads.

Another great field for targeting suspicious adversary behavior within a given logon period is the Session ID. These can be found in the SessionId field of the Exchange logs, but within AzureActiveDirectory they’re an embedded value found in the DeviceProperties JSON blob, as seen in the UserLoggedIn example above. Pivoting on Session ID is not a new concept and is also applied with endpoint telemetry to help develop timelines of adversary activity. In the example attack we’re about to return to, the adversary had one single logon session that we’ll use to follow their exact actions.

The ApplicationId, or AppID, helps identify what service the attackers targeted or logged into. This ID value is a unique representation of a Microsoft 365 resource in which defenders can use the CloudAppEvents table within Microsoft Defender for Cloud Apps to query for more detailed information on the application. While custom or third-party applications will have unique IDs, first-party Microsoft services have standard IDs that can be correlated to identify activity related to Microsoft services. The Application ID in our case was 00000002-0000-0ff1-ce00-000000000000, which Microsoft clearly defines as “Office 365 Exchange Online” in their catalog of commonly used Applications.

Lastly, the User Agent can help scope incidents, but is not necessarily considered a high-fidelity indicator since, these tend to have a large overlap with devices using the same browser and operating system versions. The User Agent is listed as the ClientInfoString in Exchange logs but in Azure Active Directory they’re found within the ExtendedProperties JSON, also seen in our log example listed above. In this particular investigation, the User Agent was pretty fruitful, as it was uniquely found within this one session.

Back to the attack

The following is a timeline of the adversary’s activity from our example detection, which we’ll detail further and use to explore relevant audit log telemetry.

Attack timeline elapsing 12 minutes

It’s usually a good idea to open the aperture on an investigation like this to figure out if there are any suspicious logs that preexist overtly malicious activity. You can do this by turning off operations or specific Session ID filters. Doing so in incidents like this often reveals failed logon attempts. The AppId field in the following example informs us that the failed logons occurred from the Office Home application. The following Exchange log shows relevant information about the failed logon:

{
  "CreationTime": "2022-01-01T00:00:00",
  "Id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "Operation": "UserLoginFailed",
  "OrganizationId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "RecordType": 15,
  "ResultStatus": "Success",
  "UserKey": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "UserType": 0,
  "Version": 1,
  "Workload": "AzureActiveDirectory",
  "ClientIP": "X.X.X.X",
  "ObjectId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "UserId": “victim@example.com",
  "AzureActiveDirectoryEventType": 1,
  "ExtendedProperties": [
    {
      "Name": "ResultStatusDetail",
      "Value": "Success"
    },
    {
      "Name": "UserAgent",
      "Value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0000.100 Safari/500.00 Edg/100.0.0000.00"
    },
    {
      "Name": "UserAuthenticationMethod",
      "Value": "16"
    },
    {
      "Name": "RequestType",
      "Value": "Login:login"
    }
  ],
  "ModifiedProperties": [],
  "Actor": [
    {
      "ID": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
      "Type": 0
    },
    {
      "ID": "victim@example.com",
      "Type": 5
    }],
  "ActorContextId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "ActorIpAddress": "X.X.X.X",
  "InterSystemsId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "IntraSystemId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "SupportTicketId": "",
  "Target": [
    {
      "ID": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
      "Type": 0
    }],
  "TargetContextId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "ApplicationId": "4765445b-32c6-49b0-83e6-1d93765276ca",
  "DeviceProperties": [
    {
      "Name": "OS",
      "Value": "Windows 10"
    },
    {
      "Name": "BrowserType",
      "Value": "Edge"
    },
    {
      "Name": "IsCompliantAndManaged",
      "Value": "False"
    },
    {
      "Name": "SessionId",
      "Value": "victim@example.com"
    }],
  "ErrorNumber": "53003",
  "LogonError": "BlockedByConditionalAccess"
}

Note: the LogonError field suggests that the logon attempt was blocked because of a custom configuration

We can now inspect the audit logs further for any operations that came in after the initial spike of logon activity. Using the SessionID acquired from the successful login we previously identified, we can then modifying our Splunk search to show all Exchange and Azure Active Directory operations associated with that SessionID that occurred with 15 minutes:

Audit logs

From this list we can see the New-InboxRule operation that initially tipped our Detection Engineering team off to unusual activity—as well as the Set-InboxRule operation that was used to modify the rule that was created. We can also see a large number of MailItemsAccessed, Create, Send, and Move operations. Let’s dive into each of these operations.

The Create operation is interesting. According to Microsoft, this event should not have been logged because creating, sending, or receiving a message isn’t audited. In our case, this does not appear to be true. This log shows that Outlook created a new entry in the “\Drafts” folder of the user mailbox within the same logon session that created the abnormal email rule. We can also see the subject of the email: “Direct Deposit Update”. More to come on that…

 {
  AppId: 00000002-0000-0ff1-ce00-000000000000
   ClientIP: X.X.X.X
   ClientIPAddress: X.X.X.X
   ClientInfoString: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0000.100 Safari/500.00 Edg/100.0.0000.00;
   CreationTime: 2022-01-01T00:00:00
   ExternalAccess: false
   InternalLogonType: 0
   Item: {
     Id: FolderID
     InternetMessageId: <MessageID>
     IsRecord: false
     ParentFolder: {
       Id: FolderID
       Path: \Drafts
     }
     SizeInBytes: 2555
     Subject: Direct Deposit Update
   }
   LogonType: 0
   MailboxOwnerUPN: victim@example.com
   Operation: Create
   OrganizationName: example.com
   
   RecordType: 2
   ResultStatus: Succeeded
   SessionId: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
   UserId: victim@example.com
   Workload: Exchange
}

 

Send operations are generated when a user sends, replies to, or forwards an email message. In order to log this activity, the user must have an active Office 365 or Microsoft 365 E5 license applied to their account. Unfortunately this event does not provide who the message was sent to. To identify who the email was sent to, we use the InternetMessageId field to track the email in Exchange via the Get-MessageTrackingLog PowersShell module.

 

{
   AppId: 00000002-0000-0ff1-ce00-000000000000
   ClientIP: X.X.X.X
   ClientIPAddress: X.X.X.X
   ClientInfoString: Client=OWA;Action=ViaProxy
   CreationTime: 2022-01-01T00:00:00
   ExternalAccess: false
   InternalLogonType: 0
   Item: {
     Id: FolderID
     InternetMessageId: <MessageID>
     ParentFolder: {
       Id: FolderID
       Path: \Drafts
     }
     SizeInBytes: XXXX
     Subject: Direct Deposit Update
   }
   LogonType: 0
   MailboxOwnerUPN: victim@example.com
   Operation: Send
   OrganizationName: example.com

   RecordType: 2
   ResultStatus: Succeeded
   SessionId: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
   UserId:victim@example.com
   Workload: Exchange
}

After the Send operation, we also noticed the actor moved the email they sent from the “Sent Items” folder to the “Archive” folder. Move operations simply log when a message is moved from one folder to another. Within this event, there are three nested fields that will help identify what was moved, where it was moved from, and where it was moved to. The fields of interest are AffectedItems, DestFolder and Folder. The AffectedItems field will provide information on the message that was moved. The DestFolder tells where the message went and the Folder field tells you where it was moved from.

{
   AffectedItems: [
     {
       InternetMessageId: <MessageID>
       ParentFolder: {
         Id: FolderID
         Path: \Sent Items
       }
       Subject: Direct Deposit Update
     }
   ]
   AppId: 00000002-0000-0ff1-ce00-000000000000
   ClientIP: X.X.X.X
   ClientIPAddress: X.X.X.X
   ClientInfoString: Client=OWA;Action=ViaProxy
   CreationTime: 2022-01-01T00:00:00
   CrossMailboxOperation: false
   DestFolder: {
     Id: FolderID
     Path: \Archive
   }
   ExternalAccess: false
   Folder: {
     Id: FolderID
     Path: \Sent Items
   }
   InternalLogonType: 0
   LogonType: 0
   MailboxOwnerUPN: victim@example.com
   Operation: Move
   OrganizationName: example.com

   RecordType: 3
   ResultStatus: Succeeded
   SessionId: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
   UserId: victim@example.com
   Workload: Exchange
}

 

Now let’s talk about  MailItemsAccessed. This operation tells us that within this logon session, a number of emails were actually accessed. To generate these logs, like the Send operation, the user must have an active Office 365 or Microsoft 365 E5 license. Within this operation, there is a key piece of information we need to identify: the access type that generated the log. There are two access methods that can be logged within MailItemsAccessed: sync and bind.

Sync logs indicate that an Outlook desktop client or other Exchange ActiveSync compatible client was used to synchronize messages between Exchange and the Client device. Sync logs only provide the mailbox folder that was synced. If you see an adversary sync a user’s inbox, you must assume that ALL emails in that user’s inbox are compromised. The same is true for any other folder within the user’s mailbox.

Bind logs work slightly differently than sync logs. They log individually accessed messages. Bind events will be generated for protocols such as POP, IMAP, EWS and REST. Within the log we can see the specific emails that were accessed based on their InternetMessageId. However, bind logs collect telemetry two minutes at a time, so a single bind log can show that multiple messages have been accessed. Another thing to note about bind logs is that they can be throttled. Throttling occurs when more than 1,000 MailItemsAccess logs are generated in less than 24 hours. Throttling is denoted in the log under the IsThrottled field.

There are a number of JSON blobs within one of these logs that contain the interesting information we need to identify what access type was used and the folders and messages accessed. The Folders blob will provide the mailbox folders that were accessed for both bind and sync logs, but bind logs will also have a FolderItems blob that contains the information for individual messages that were accessed. The OperationCount field provides the number of accessed items contained in the log (remember that MailItemsAccess rolls a 2-minute window of activity into a single log). Finally, the OperationProperties blob tells us the access type and indicates if the log is being throttled. In this particular case, we had 141 MailItemsAccessed logs resulting in the actor accessing over 1,500 emails in less than 20 minutes.

Note: we’re continuing to research why 141 logs were generated in this case, as Microsoft’s documentation seems to suggest that this activity ought to have been aggregated in a single audit record.

{ [-]
   AppId: 00000002-0000-0ff1-ce00-000000000000
   ClientIPAddress: X.X.X.X
   ClientInfoString: Client=OWA;Action=ViaProxy
   CreationTime: 2022-01-01T00:00:00
   ExternalAccess: false
   Folders: [
     {
       FolderItems: [
         {
           InternetMessageId: <MessageID>
         }
       ]
       Id: FolderID
       Path: \Drafts
     }
     {
       FolderItems: [
         { 
           InternetMessageId: <MessageID>
         }
         {
           InternetMessageId: <MessageID>
         }
         {
           InternetMessageId: <MessageID>
         }
         {
           InternetMessageId: <MessageID>
         }
       ]
       Id: FolderID
       Path: \Sent Items
     }
   ]
   InternalLogonType: 0
   LogonType: 0
   MailboxOwnerUPN: victim@example.com
   Operation: MailItemsAccessed
   OperationCount: 5
   OperationProperties: [
     {
       Name: MailAccessType
       Value: Bind
     }
     {
       Name: IsThrottled
       Value: False
     }
   ]
   OrganizationName: victim@example.com

   RecordType: 50
   ResultStatus: Succeeded
   SessionId: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
   UserId: victim@example.com
   Workload: Exchange
}

Not a minute to spare

This example attack spanned just 12 minutes, and while no one lost their paycheck in this case, it shows just how fast an adversary can go from compromised email account to potential theft.

In the end though, Microsoft’s various tools and log sources provide a valuable array of telemetry that security teams can use to observe, detect, and prevent suspicious email forwarding rules.

 

The Trainman’s Guide to overlooked entry points in Microsoft Azure

 

Inside the 2024 Threat Detection Report

 

Better know a data source: Files

 

Why adversaries have their heads in the cloud

Subscribe to our blog

 
 
Back to Top