This is already the third blog I’m writing about the scenario where Azure AD Global Admin elevates access from the Azure AD to all Azure subscriptions connected to the tenant. The earlier posts are found from the links below:
- Build detection in Defender for Cloud Apps (former Cloud App Security). Usable when your organization is using 3rd party SIEM such as IBM QRadar or Splunk
- Send Defender for Cloud Apps ‘Activity Log’ data with Azure Logic Apps to Sentinel and build detection with KQL
The ultimate solution would be to monitor the activity in Microsoft Sentinel and, in this blog post, I demonstrate how to achieve this by integrating MDA and Azure Sentinel natively, without any 3rd party solution such as Logic Apps.
The Latest Updates in Microsoft 365 Defender Data Connector in Sentinel
This is possible to achieve because of the latest updates on Microsoft Sentinel ‘M365 Defender’ data connector. Ingesting raw data through Defender for Cloud Apps (MDA), Defender for O365 (MDO), Defender for Identity (MDI) through the M365D data connector has seen the daylight. It means that you are able to fetch raw data, such as MDA activity log, without creating Logic Apps to do the data ingestion & parsing.
Setting up the Scene
In the past, monitoring of the ‘Elevate Access’ activity by Global Admin has been a tricky operation because it has been possible only with Microsoft Defender for Cloud Apps (MDA).
A few weeks ago, Fabian Bader highlighted that activity event is nowadays found in Azure Management Group logs (I highly recommend reading the blog (Azure Dominance Paths), it has awesome content). The only problem is that export diagnostics through the Azure portal are not available at the time of writing. It might be that it’s possible to configure diagnostic settings through API but I didn’t test it for now.
There are many articles about how Azure AD Global Admin can elevate access to Azure Root Management Group (User Access Administrator) and I’m not covering the elevation process here. If you want to get familiar with the concept I recommend starting from here.
By default, Global Admin doesn’t have access to Azure resources. Azure AD and Azure resources are secured independently from one another but there might be a reason when this operation needs to be done (if not part of the attack), according to Microsoft (docs.microsoft.com):
- Regain access to an Azure subscription or management group when a user has lost access
- Grant another user or yourself access to an Azure subscription or management group
- See all Azure subscriptions or management groups in an organization
- Allow an automation app (such as an invoicing or auditing app) to access all Azure subscriptions or management groups
Permission granted is the User Access Administrator role in Azure at the root scope (/). With this role, the user will get access to any subscription or management group in the directory.
Worth mentioning is that User Access Administrator role assignments can be removed using Azure PowerShell, Azure CLI, or the REST API.
In general, the removal part has been updated last year. The permissions cannot be removed from the portal but when the admin changes the toggle option to “no”, permissions are removed from the root management group.
Send Defender for Cloud Apps (MDA) Activity Log Data to Azure Sentinel
As we all know, the development pace in the cloud is staggering and existing solutions are evolving all the time. Earlier, you needed to use Azure Logic Apps to get MDA ‘Activity Log’ data from the MDA API and send it to Azure Log Analytics API that’s the underlying log repository in Microsoft Sentinel.
- An alternative solution was to use Log Collector with MDA SIEM agent and pull data to log collector and then push to Log Analytics.
Now, with an improved integration mechanism between ‘Microsoft 365 Defender’ & ‘Microsoft Defender for Cloud Apps’ you can get the MDA Activity Log data from all connected sources to Microsoft Sentinel if you are using:
- Microsoft 365 data connector
- You are ingesting raw data from ‘Defender for Cloud Apps’
Microsoft Defender for Cloud Apps (MDA)
As mentioned before, the elevated access action is not monitored anywhere on the Azure side by native logging capabilities such as Azure Monitor, Azure Activity Logs, or Azure AD logs.
- Exception – nowadays, the activity is found from the Azure root management group activity log.
In the last years, I have seen a few cases where MDA receives richer information from Azure management API than other tools and for that reason, it can be used as a detection tool in these rare cases.
In the case where a custom alert policy is used in MDA to detect the scenario, an alert is found from the alert list.
Microsoft 365 Defender
Enhanced integration between Microsoft Defender for Cloud Apps (MDA) & Microsoft 365 Defender (M365D) means that events from all data sources (which are connected to MDA with API connector) are found from M365D.
For example, in my environment, I can find events related to O365, Azure, AWS, DropBox, ServiceNow, and Google Cloud Platform are ingested to M365D. If Microsoft Sentinel & M365D integration is in place, the same data is found from Microsoft Sentinel.
Advanced Hunting Query
The query I used to filter out the elevate access action. Azure Application Id is 12260 and critical data is found inside the ‘raw data’ column that contains event information from the source application or service in JSON format.
CloudAppEvents | where ApplicationId == '12260' and Application == 'Microsoft Azure' | where ActionType has 'ElevateAccess Microsoft.Authorization' | project AccountDisplayName, IPAddress, CountryCode, ActivityObjects, RawEventData.authorization, RawEventData.operationName, RawEventData.properties
When data arrives in Azure Log Analytics I can leverage Azure Sentinel Analytics rules and create incidents based on the data. Even though, MDA already creates alerts based on this activity, with Azure Sentinel there is more granularity for rule creation and possibilities to investigate (+hunt) the activities performed by the actor from a varied range of services.
If everything works as expected, when Global Admin elevates access to Azure Root Management Group and all subscriptions underneath it the following actions will take place:
- MDA receives the event data from Azure Management API and logs the activity to the Activity Log
- The event is synced from MDA to M365D
- The event is synced from M365D to Microsoft Sentinel
The Analytic Rule
In the custom rule, which is based on the activity log data ingestion through native integration, I search for Microsoft.Authorization/elevateAccess/action activity where ‘roleAssignmentScope == “/”’.
The KQL query below does the trick. I added ‘extend’ to contain details from the ‘RawEventData’ column to get more relevant data to the incident for the investigation.
CloudAppEvents | where ApplicationId == '12260'and Application == 'Microsoft Azure' | where parse_json(tostring(parse_json(tostring(RawEventData.authorization)).evidence)).roleDefinitionId == "b21f0835cd464e508cf8e297ff563cb1" | where RawEventData.operationName == "Microsoft.Authorization/elevateAccess/action" | where parse_json(tostring(parse_json(tostring(RawEventData.authorization)).evidence)).roleAssignmentScope == "/" | where parse_json(tostring(parse_json(tostring(RawEventData.authorization)).evidence)).roleAssignmentId == "b507cd211c194747a82e1c2e8584c6da" | extend ClientIPAddress = parse_json(tostring(RawEventData.httpRequest)).clientIpAddress | extend RoleAssignmentScope = parse_json(tostring(parse_json(tostring(RawEventData.authorization)).evidence)).roleAssignmentScope | extend RoleAssignmentId = parse_json(tostring(parse_json(tostring(RawEventData.authorization)).evidence)).roleAssignmentId
When the incident is created it contains critical information that can be used to verify the user, IP address information, and the scope of the permissions. As you can see from the investigation graph, there are a lot of suspicious activities from this IP address. From the first picture, you can see a slight difference between the incidents, one is from MDA and one is created by Sentinel based on raw data (see detection source).
In the analytics rule, I added custom details to contain the permission scope from the raw data to help the investigation.
Based on tests made in the demo environment the following latencies were identified. Times on the table below have a dependency on how the analytics rule is configured in Sentinel (query thresholds).
|Azure AD||Global Admin elevates access to the root management group||7:22PM|
|MDA/MDCA/MCAS||Receives the event from Azure Management API||7:27PM|
|M365 Defender||Receives the event from MDCA||7:28PM|
|Sentinel||Receives the event||7:29PM|
|Sentinel||Creates an incident (depends on schedule)||7:34PM|
A few considerations that came into my mind when writing this:
- The same end result can be achieved by using only Microsoft Defender for Cloud Apps. For example, if you have 3rd party SIEM in place I recommend creating a custom policy in MDA and integrating MDA with 3rd party SIEM such as Splunk & QRadar.
- If Microsoft Sentinel is used in your environment there might be a scenario where you could end up in the situation where you have AWS events from both, the native Sentinel data connector and through M365D raw data. So, pay attention to the data connectors in different security solutions to avoid extra expenses in data ingestion (for example AWS & GCP).
Hope this helps!