The Azure log you probably didn’t know existed

June 11, 2024

We have the privilege of teaching people about incident response in the Microsoft cloud all over the world either virtually or at live events. The times we met people that knew of the existence of this log in Azure can be counted on one hand. Therefore we decided to write a blog about this special log. This log, often referred to as the Directory Activity Log or Tenant Activity Log, can be of importance during an incident response investigation.

In this blog post, we'll explore what this log is, how to access it, and why it can be very useful for incident response investigations.

Understanding the Directory Activity Log

The Directory Activity Log provides insights into actions that could affect the security posture of your organization. For instance, if a Global Administrator grants themselves extensive permissions over Azure resources, this is recorded in the log.

Discovering the Directory Activity Log

This log is somewhat hidden within the Azure interface. When viewing the Activity log, you have the option to switch between Activity and Directory Activity.

Activity vs Directory Activity

Generally, the Activity Log and Directory Activity Log serve similar purposes, but they operate at different scopes. The Activity Log is available at both the subscription and management group levels, providing detailed records of actions within those scopes. However, Azure offers an even higher scope known as the Tenant scope covered in the Directory Activity Log. While the resources managed at this level are limited, the activities logged here are still crucial for a complete overview.

By combining the Activity Log, which contains all subscription and management group actions, with the Directory Activity Log, which captures tenant level activities, you achieve full coverage of all available scopes in Azure. 

Acquisition

It's important to note that when working with Azure Activity Logs, when you retrieve Azure Activity Logs using the PowerShell cmdlet Get-AzActivityLog, you won't capture Directory Activity Logs. Currently, to acquire the Directory Activity Logs, you need to use a REST request or download the results as CSV in the Azure interface. Instructions and examples for the REST method are provided in Microsoft's official documentation. For those looking for an automated solution, there is a script available on GitHub that facilitates the acquisition of these logs.

The problem is that the CSV export doesn't contain all the details of an event, which is also the case for the 'normal' Activity log. Therefore we want to use the REST API to get the full details of each event. This functionality will be added to our very own Microsoft Extractor Suite very soon.

Analysis

So, why is this log relevant during an investigation? If a Global Administrator or User Access Administrator account is compromised, having this role in Entra ID alone does not grant permissions in Azure. However, both roles can elevate their access to full permissions over the entire Azure environment. This is achieved by granting themselves access over all subscriptions and management groups. This can be done through the "Access Management for Azure Resources" option available in the Entra ID blade of the Azure Portal.

When access is elevated, an entry is added to the Directory Activity Logs. Elevate access log entries do not appear in the standard activity logs, This can be identified by monitoring for the Operation name: 

  • Assigns the caller to User Access Administrator role

Another tactic a threat actor might employ is granting themselves or another user access to the Tenant Root Group. By default, every subscription added to an Entra ID tenant exists under the Tenant Root Management Group. 

Assigning a user, for example, Contributor access over this group will allow that user to access all resources within it. Fortunately, this can be detected in the Directory Activity Log by monitoring for the specific operation name:

  • Create role assignment

An example event which we can see in the portal when selecting JSON would look as follows (some data is modified):

{
    "authorization": {
        "action": "Microsoft.Authorization/roleAssignments/write",
        "scope": "/providers/Microsoft.Management/managementGroups/12345678-9abc-def0-1234-56789abcdef0/providers/Microsoft.Authorization/roleAssignments/189668fa-bdfa-4281-8ff1-4554f3c10a4e"
    },
    "caller": "ExampleUser@example.com",
    "channels": "Operation",
    "claims": {
        "aud": "https://management.core.windows.net/",
        "iss": "https://sts.windows.net/12345678-9abc-def0-1234-56789abcdef0/",
        "iat": "1717660421",
        "nbf": "1717660421",
        "exp": "1717665855",
        "http://schemas.microsoft.com/claims/authnclassreference": "1",
        "aio": "AVQAq/8WAAAASQczYR3mQhOuBLpOH0M2jW+a0XRVygjYkizNlKcxewbushWxZvSKo39iDmMjvyHxkZCUxWsQH75dWz+i/pBNTVTAb/inE7KEjr3CmHxqHjc=",
        "http://schemas.microsoft.com/claims/authnmethodsreferences": "pwd",
        "appid": "c44b4083-3bb0-49c1-b47d-974e53cbdf3c",
        "appidacr": "2",
        "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname": "Admin",
        "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname": "Global",
        "groups": "11111111-2222-3333-4444-555566667777,88888888-9999-aaaa-bbbb-ccccdddddeee,ffffffff-aaaa-bbbb-cccc-ddddeeeeffff,11111111-aaaa-bbbb-cccc-555566667777,99999999-0000-1111-2222-333344445555",
        "idtyp": "user",
        "ipaddr": "192.0.2.1",
        "name": "Administrator",
        "http://schemas.microsoft.com/identity/claims/objectidentifier": "189668fa-bdfa-4281-8ff1-4554f3c10a4e",
        "puid": "100320016B077CE2",
        "rh": "0.AQwApYS14vNK7EScY-v6EuejHEZIf3kAutdPukPawfj2MBMMAHM.",
        "http://schemas.microsoft.com/identity/claims/scope": "user_impersonation",
        "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": "MRfXZULAK7K03aPhuYtmQMC7u1auhvAC8I-xydWmmi4",
        "http://schemas.microsoft.com/identity/claims/tenantid": "12345678-9abc-def0-1234-56789abcdef0",
        "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "ExampleUser@example.com",
        "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn": "ExampleUser@example.com",
        "uti": "rjflMwNAe0qSCkRZwptgAA",
        "ver": "1.0",
        "wids": "62e90394-69f5-4237-9190-012177145e10",
        "xms_tcdt": "1628605016"
    },
    "correlationId": "61f8bff8-87c7-4172-959a-bbeecc2bb756",
    "description": "",
    "eventDataId": "e8444172-8765-4479-a909-11e2e94abd3c",
    "eventName": {
        "value": "EndRequest",
        "localizedValue": "End request"
    },
    "category": {
        "value": "Administrative",
        "localizedValue": "Administrative"
    },
    "eventTimestamp": "2024-06-06T08:00:45.456107Z",
    "id": "/providers/Microsoft.Management/managementGroups/12345678-9abc-def0-1234-56789abcdef0/providers/Microsoft.Authorization/roleAssignments/189668fa-bdfa-4281-8ff1-4554f3c10a4e/events/e8444172-8765-4479-a909-11e2e94abd3c/ticks/638532576454561070",
    "level": "Informational",
    "operationId": "61f8bff8-87c7-4172-959a-bbeecc2bb756",
    "operationName": {
        "value": "Microsoft.Authorization/roleAssignments/write",
        "localizedValue": "Create role assignment"
    },
    "resourceGroupName": "",
    "resourceProviderName": {
        "value": "Microsoft.Authorization",
        "localizedValue": "Microsoft.Authorization"
    },
    "resourceType": {
        "value": "Microsoft.Authorization/roleAssignments",
        "localizedValue": "Microsoft.Authorization/roleAssignments"
    },
    "resourceId": "/providers/Microsoft.Management/managementGroups/12345678-9abc-def0-1234-56789abcdef0/providers/Microsoft.Authorization/roleAssignments/189668fa-bdfa-4281-8ff1-4554f3c10a4e",
    "status": {
        "value": "Succeeded",
        "localizedValue": "Succeeded"
    },
    "subStatus": {
        "value": "Created",
        "localizedValue": "Created (HTTP Status Code: 201)"
    },
    "submissionTimestamp": "2024-06-06T08:01:44Z",
    "subscriptionId": "",
    "tenantId": "12345678-9abc-def0-1234-56789abcdef0",
    "properties": {
        "statusCode": "Created",
        "serviceRequestId": null,
        "eventCategory": "Administrative",
        "entity": "/providers/Microsoft.Management/managementGroups/12345678-9abc-def0-1234-56789abcdef0/providers/Microsoft.Authorization/roleAssignments/189668fa-bdfa-4281-8ff1-4554f3c10a4e",
        "message": "Microsoft.Authorization/roleAssignments/write",
        "hierarchy": "12345678-9abc-def0-1234-56789abcdef0"
    },
    "relatedEvents": []
}

This log doesn’t provide all the necessary information. Based on this log, we know the following:

  • Caller: ExampleUser@example.com
  • IP Address: 192.0.2.1
  • Tenant ID: 12345678-9abc-def0-1234-56789abcdef0
  • Action: Microsoft.Authorization/roleAssignments/write
  • Operation Name: Create role assignment
  • Scope: /providers/Microsoft.Management/managementGroups/12345678-9abc-def0-1234-56789abcdef0/providers/Microsoft.Authorization/roleAssignments/189668fa-bdfa-4281-8ff1-4554f3c10a4e

Based on the scope, we know a role assignment was created with the name 189668fa-bdfa-4281-8ff1-4554f3c10a4e for the management group with ID 12345678-9abc-def0-1234-56789abcdef0. To find out which users have a role assignment on this group, you can use the following PowerShell command:

Get-AzRoleAssignment -Scope "/providers/Microsoft.Management/managementGroups/12345678-9abc-def0-1234-56789abcdef0" | Where-Object RoleAssignmentName -eq 189668fa-bdfa-4281-8ff1-4554f3c10a4e

As shown in the screenshot the user Korstiaan@bonacu.onmicrosoft.com was assigned the Contributor role over the root tenant management group.

Want to know more about incident response in Microsoft cloud environments join our live training at DEF CON or BlackHat or take it at your own pace via our OnDemand offering.