A few weeks ago I thought that 0x00sec didn’t have enough Blue Team focused posts. Yet, detection of potential threats is incredibly important in any organization. Because Azure and Office 365 are widely used, I decided to start with this. I hope you will find it useful because unfortunately, there is a lack of good resources other than Microsoft when it comes to monitoring Azure with a SIEM and I had to spend many hours to study the logs and figure out what was relevant.

This is not a complete guide for all the products and services within Azure. I just don’t have enough spare time to do it all. But I think it’s a great starting point to monitor the commonly used services.

Most of the queries here are built for Splunk because of its increasing popularity as a SIEM. If you or your organization doesn’t use Splunk, you can convert them manually or try using Sigma. The queries are meant to be base searches that you can built on top of and customize to your needs.

Requirements for log ingestion

This depends on your SIEM. Most SIEM or log management platforms provide apps or connectors to easily ingest logs from Azure. For Splunk specifically, you will likely need the following apps:

Splunk Add-on for Microsoft Office 365

Splunk Add-on for Microsoft Cloud Services

Microsoft Office 365 Reporting Add-on for Splunk

If you’re using ArcSight, you’ll find the connectors on the ArcSight Marketplace.

If such app is not available for the solution you are using, you can script the pulling with the Azure API. The logs provided are in JSON format so the parsing should be easy.

The details on the integration for Azure activity logs can be found here in the integration column for each type of log. For Office 365 specifically, details can be found here.

Building a list of known attackers

Chances are that you are the target of password spray and bruteforce attacks. This is something that your organization can use to its advantage by building a list of “known attackers”. You can then use this list for:

Identifying other services targeted by the attackers

Succesful authentication from these sources to identify compromised account

Conduct intelligence gathering to determine if your organization is specifically targeted

A reliable way I found to build such list using Azure is to look for an unknown IP generating an account lockout on N distinct accounts. In the search below, I first start by looking for sources generating locked accounts and exclude the IP addresses that already exist in the list to avoid duplicates. Then, I run the iplocation command in Splunk to get the country and city of each one of them. Finally, I do a distinct count on the UserId field by ClientIP and the source IPs that locked 5 or more accounts are appended to the list.

sourcetype=o365:management:activity Operation=UserLoginFailed LogonError=IdsLocked `comment("Don`t include duplicates")` NOT [|inputlookup azure_ipv4_blacklist | fields ClientIP] | iplocation ClientIP | stats dc(UserId) as DistinctUsersLocked by ClientIP, Country, City | where DistinctUsersLocked >= 5 | fields ClientIP, Country, City | outputlookup append=t azure_ipv4_blacklist

Exchange Online

Users sending large amount of emails to external recipients

Attempts to detect potentially compromised hosts spamming external recipients. In large organization, this might generate multiple false-positive due to internal communications, mass mailing, etc so I recommend filtering by excluding some legitimate senders. The threshold can be modified in the where RecipientCount >= 100 part.

sourcetype=ms:o365:reporting:messagetrace RecipientAddress!="*@<yourdomain.tld>" | stats dc(RecipientAddress) by SenderAddress, Subject | rename dc(RecipientAddress) as RecipientCount | where RecipientCount >= 100 | sort - RecipientCount

Mail forwarding to external recipients

Email forwarding can be set up by both administrators and users. It’s very important to monitor these kind of events to detect insider threats. The difference is that administrators can set up new mail transport rules that affect one or multiple users within Exchange Online while users can only do it on their own mailbox from the Outlook client.

Forwarding to an external recipient by an administrator

Administrator using New-TransportRule cmdlet

sourcetype=o365:management:activity Workload=Exchange Operation="New-TransportRule" | eval kv=mvzip('Parameters{}.Name', 'Parameters{}.Value', "=") | mvexpand kv | rex field=kv "^(?<kv_key>[^=]+)=(?<kv_value>[^=]+)$" | eval {kv_key}=kv_value | search kv_key=RedirectMessageTo | rename kv_value as dest | search dest!="*@<yourdomain.tld>" | table _time, user, src, dest

Forwarding to an external recipient by a user

User using the Outlook client

Mailbox item deleted by a user other than a mailbox owner

Useful to monitor users with permissions on another user’s mailbox deleting items that could be sensitive or that shouldn’t be deleted in the first place.

index=azure sourcetype=o365:management:activity Workload=Exchange AND (Operation=HardDelete OR Operation=SoftDelete) | where MailboxOwnerUPN!=user | table _time, MailboxOwnerUPN, Operation, AffectedItems{}.ParentFolder.Path, AffectedItems{}.Subject, user

OneDrive

Users sharing OneDrive items with individuals outside of the organizations

This is self-explanatory and can be useful to detect individuals voluntarily sharing confidential information with external party or typo mistakes. Here too, a list of trusted third-party (partners, subsidiaries, etc) emails could be useful to filter out the noise.

index=azure sourcetype=o365:management:activity Workload=OneDrive Operation=AddedToSecureLink TargetUserOrGroupName!="*@<organization.tld>" | stats count by _time, UserId, ObjectId, Operation, TargetUserOrGroupName

Azure Active Directory

A note on MFA and legacy authentication

Azure allows legacy authentication using ActiveSync. That means that even if you have MFA enforced in Azure across your organization, as long as legacy authentication is enabled, MFA is useless against successful bruteforcing, password spraying or authentication to a mailbox with a compromised account.

Locked accounts

Identifies locked accounts from existing users. I say existing, because oddly, Azure detects and locks non-existing accounts (I’m not kidding) which explain the exclusion of unknown actor IDs in the "Actor{}.ID"!="Unknown" part. Removing this would return many false-positive as it would include any locks for accounts that don’t exist in your organization.

sourcetype=o365:management:activity Workload=AzureActiveDirectory Operation=UserLoginFailed LogonError=IdsLocked "Actor{}.ID"!="Unknown" | iplocation ClientIP | stats count by UserId, ClientIP, Country, City, ResourceName | sort - count

Succesful authentication without the use of MFA from a blacklisted IP

This is where the blacklist from earlier can be useful. You can detect compromised accounts using a blacklist of known attackers of your own or using threat intelligence feeds.

sourcetype=o365:management:activity NOT "OAuth2" AND Operation=UserLoggedIn LogonError!=UserAccountNotFound [| inputlookup <blacklist_lookup> | fields <ip_field> | rename <ip_field> as ClientIP] | table _time, UserId, ClientIP

If using Splunk Enterprise Security, you can replace the |inputlookup command part and use the ip_intel macro instead to match on the threat intel aggregated in Splunk.

sourcetype=o365:management:activity Workload=AzureActiveDirectory Operation=UserLoggedIn LogonError!=UserAccountNotFound [| `ip_intel` | search threat_collection=ip_intel ip!="" | fields ip | rename ip as ClientIP] NOT "OAuth2"

Users with a high count of failed MFA challenges

That one can be noisy because the integration with some products can be very buggy. Otherwise, it’s very useful to detect accounts for which the password was compromised but the authentication failed because MFA was enabled. It’s really up to you and your knowledge of your environment to define the threshold and what is a high count. If you happen to have multiple offices or remote users, I strongly suggest excluding a list of known legitimate public IPs to reduce the noise.

sourcetype=o365:management:activity LogonError=UserStrongAuthClientAuthNRequiredInterrupt | stats count by user, ClientIP | where count >= 10

eDiscovery

eDiscovery is a very sensitive feature, part of the Security & Compliance Center. It can be used to search anything in an indiviual account or all user accounts in your organization. While that seems creepy (and it is, which is why its use should be monitored), it is extremely useful for acquiring evidence in legal cases.

Compliance search started or exported

Anytime actions such as an eDiscovery compliance search is ran, it should be reported and validated by whoever is responsible for overseeing legal cases or HR in your company, due to the sensitivity of the information.

sourcetype=o365:management:activity Workload=SecurityComplianceCenter Operation=AlertTriggered Category=ThreatManagement Name="eDiscovery search started or exported" `comment("Use regex to re-write the user field with the user name that triggered the alert. Otherwise, the user appearing by default is 'SecurityComplianceAlerts'")` | rex "(?<user>[\w\-\.][email protected][\w\-]+\.+[\w\-]{2,4})" | `map_notable_fields`

Compliance search requesting the deletion of items

Legitimate most of the time (i.e. removing phishing emails from users mailboxes), it can also be used to remove incriminating evidence. Pay a particular attention to the -PurgeType argument shown in the logs as a HardDelete indicates permanent removal.

sourcetype=o365:management:activity Workload=SecurityComplianceCenter "New-ComplianceSearchAction" "-Purge"

As important as eDiscovery searches is monitoring users added as administrator in Security & Compliance Center.

sourcetype=o365:management:activity Workload=SecurityComplianceCenter "Add-eDiscoveryCaseAdmin"

Conclusion

I hope this will help you getting start. Feel free to message me privately here or on Twitter if you need any help or have any questions. You can also email me at [email protected]

Edit: Added a section on log ingestion and change the format of the queries so they are easier to read.