This blog post is part twenty of the "Hunting with Splunk: The Basics" series. The cloud is coming and how you choose to handle that may define your career in the coming months. One thing that's here today is Azure Active Directory. Not only does it power the authentication of Office 365 and Azure, but it also can be used for NON-cloud assets like Windows 10 workstations. Hopefully this acts as a good introduction DFIR/hunting concepts for Azure AD and doesn't leave you hanging with Novell-esque knowlege gaps. – Ryan Kovar
In our previous missive about Microsoft Cloud services, I discussed Microsoft Office 365 and some of the valuable fields that could be used for hunting. This post will pivot a bit to Azure. Azure is well known as a service that allows customers to create virtual machines, however, it can also be used for more exciting things like Active Directory. That's right; you can run Active Directory natively in the Azure cloud. When you authenticate to Office 365, it's actually using Azure Active Directory in the backend! You may not have access until you pay for it. :-)
In this blog post, we'll discuss what logs from Azure AD look like and what you can do with them. If you're looking for a blog on Azure VM events...keep waiting.
In Splunklandia today (because this can change literally in an afternoon), Azure AD logs come into Splunk looking something like this:
sourcetype=ms:aad* | stats count by sourcetype
Pretty simple, right? Two different sourcetypes: “audit” and “signin.” Perhaps surprisingly, they do exactly what they say on the tin. Audit gives you information about activities around user accounts. Signin tells you… when… users…. sign in.
The "ms:aad:audit" sourcetype audits the "changes" made to the Azure Active Directory (A.A.D… get it?). This is where you can find the user changes, updates to groups, removals of users/groups, and much more. The search below shows some key fields that I have found to be consistently useful: activityOperationType, activity, targets{}userPrincipalName, and actor.userPrincipalname.
sourcetype="ms:aad:audit" activity=*user* | stats VALUES(activityOperationType) VALUES(targets{}.userPrincipalName) count by actor.userPrincipalName
Field |
Description |
activity |
This is the nice description of what's happening, like "Reset user Password" or "Add user." |
activityOperationType |
Provides a short one-word value for what occurred in the event. "Add" or "Delete." Could be a group, could be a user. You will need to check "activity" or one of the Byzantine numeric codes in the log to find out. |
actor.userPrincipalName |
“Actor” is always the user “acting” upon Azure Active Directory. It's the user performing the action. |
targets{}.userPrincipalName |
"Target" is who is "acted" upon. This is the user that was an "Add" or who had an "Update." |
Now, you're probably looking at that long JSON blob of a log that Azure AD generates, looking at my above search/minimal data output and saying "is that it? Is that REALLY all I need from "ms:aad:audit?" Well… yes. I mean, don't get me wrong, there's lots more useful information in there like targets{}.isPrivileged and targets{}modifiedProperties{}.name but honestly, those are all things to dig into yourself. They don't always get populated, and they're really all derivatives of the finding above. If you really disagree, let me know and we'll add to this post!
That's right—Azure AD sign-in events. Basically, anything in the Microsoft Azure AD that signs in gets logged here. These logs (by comparison, much easier than Azure Audit… less nested JSON) are much easier to deal with. There are a variety of useful fields, but take a peek at this search first:
sourcetype="ms:aad:signin" | stats VALUES(loginStatus) VALUES(userPrincipalName) VALUES(location*) VALUES(ipAddress) by appDisplayName
You'll notice that we can see the status of the login attempt (loginStatus), the username who attempted to log in (userPrinicipalName), the IP address (ipAddress) that the attempt came from, and finally the locations that Microsoft has identified the login was attempted from. Here's a quick breakdown of the fields I have found primarily useful:
Field |
Description |
userPrinicipalName |
The username attempting to log in. |
loginStatus |
The Success or Failure of the login attempt. |
appDisplayName |
The name of the Microsoft Cloud Application that was accessed. |
ipAddress |
The IP address the access occurred from. |
location.* |
Several different “locations” available from Microsoft including city, country, and state. |
deviceInformation |
Information about the device that attempted to log in. Similar to a user agent. |
failureReason |
If the attempt to log in was a "Failure," this provides a good description of why the login was rejected. |
Much like Office 365 logs, there's much more functionality in the Azure logs than what we've outlined here. Take this as an introduction and dig as deep into your Azure logs as you can; if you find something of use, please let me know!
As always, Happy Hunting! :-)
The Splunk platform removes the barriers between data and action, empowering observability, IT and security teams to ensure their organizations are secure, resilient and innovative.
Founded in 2003, Splunk is a global company — with over 7,500 employees, Splunkers have received over 1,020 patents to date and availability in 21 regions around the world — and offers an open, extensible data platform that supports shared data across any environment so that all teams in an organization can get end-to-end visibility, with context, for every interaction and business process. Build a strong data foundation with Splunk.