> For the complete documentation index, see [llms.txt](https://docs.forestall.io/forestall/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.forestall.io/forestall/edges/azure/az_storage_list_keys.md).

# AZ\_STORAGE\_LIST\_KEYS

## Summary

|                            |                                      |
| -------------------------- | ------------------------------------ |
| **Forestall ACL Alias**    | AZ\_STORAGE\_LIST\_KEYS              |
| **Azure Alias**            | Storage Account List Keys            |
| **Affected Object Types**  | Storage Accounts                     |
| **Exploitation Certainty** | Certain                              |
| **Severity**               | Critical                             |
| **Azure RBAC Roles**       | See **Built-In Role Coverage** below |

**Custom Role Actions:**

* `Microsoft.Storage/storageAccounts/listKeys/action`

## Built-In Role Coverage

The edge implementation maps the following Azure built-in roles to `AZ_STORAGE_LIST_KEYS`:

* Owner (`8e3af657-a8ff-443c-a75c-2fe8c4bcb635`)
* Contributor (`b24988ac-6180-42a0-ab88-20f7382dd24c`)
* App Compliance Automation Administrator (`0f37683f-2463-46b6-9ce7-9b788b988ba2`)
* Avere Contributor (`4f8fab4f-1852-4a58-a46a-8eaf358af14a`)
* Azure AI Administrator (`b78c5d69-af96-48a3-bf8d-a8b4d589de94`)
* Azure Local Migrate Execute Expert (`1cfa4eac-9a23-481c-a793-bfb6958e836c`)
* Azure Migrate Decide and Plan Expert (`7859c0b0-0bb9-4994-bd12-cd529af7d646`)
* Azure Migrate Execute Expert (`1cfa4eac-9a23-481c-a793-bfb6958e836b`)
* Azure Migrate Owner (`fd8ea4d5-6509-4db0-bada-356ab233b4fa`)
* Azure Red Hat OpenShift File Storage Operator (`0d7aedc0-15fd-4a67-a412-efad370c947e`)
* Azure Red Hat OpenShift Image Registry Operator (`8b32b316-c2f5-4ddf-b05b-83dacd2d08b5`)
* Azure Red Hat OpenShift Service Operator (`4436bae4-7702-4c84-919b-c4069ff25ee2`)
* DevTest Labs User (`76283e04-6283-4c54-8f91-bcf1374a3c64`)
* Disk Snapshot Contributor (`7efff54f-a5b4-42b5-a1c5-5411624893ce`)
* Log Analytics Contributor (`92aaf0da-9dab-42b6-94a3-d43ce8d16293`)
* Logic App Contributor (`87a39d53-fc1b-424a-814c-f7e04687dc9e`)
* Reader and Data Access (`c12c1c16-33a1-487b-954d-41c89c60f349`)
* SQL MI Migration Role (`1d335eef-eee1-47fe-a9e0-53214eba8872`)
* SQL VM Migration Role (`ae8036db-e102-405b-a1b9-bae082ea436d`)
* Storage Account Contributor (`17d1049b-9a84-46fb-8f53-869881c3d3ab`)
* Storage Account Key Operator Service Role (`81a9662b-bebf-436f-a333-f67b29880f12`)
* Virtual Machine Contributor (`9980e02c-c2be-4d73-94e8-173b1dc7cf3c`)
* VM Restore Operator (`dfce8971-25e3-42e3-ba33-6055438e3080`)

## Description

`AZ_STORAGE_LIST_KEYS` represents the ability to retrieve storage account keys for an Azure Storage Account. Storage account keys are shared secrets for the entire account; possession of either key grants broad data-plane access to blobs, queues, tables, and files unless network controls or service-level settings block the request.

This edge is critical because storage accounts often hold backups, application data, logs, deployment packages, and secrets. An attacker with the listed permissions can authenticate outside Azure RBAC by using a returned account key directly to read or modify storage data.

Related edges: [AZ\_STORAGE\_CONTRIBUTOR](https://docs.forestall.io/fsprotect/edges/azure/az_storage_contributor), [AZ\_STORAGE\_SAS\_GENERATE](https://docs.forestall.io/fsprotect/edges/azure/az_storage_sas_generate), [AZ\_STORAGE\_BLOB\_DATA\_READER](https://docs.forestall.io/fsprotect/edges/azure/az_storage_blob_data_reader), [AZ\_STORAGE\_BLOB\_DATA\_WRITER](https://docs.forestall.io/fsprotect/edges/azure/az_storage_blob_data_writer).

## Identification

### PowerShell (Az Module)

```powershell
Connect-AzAccount

$riskyActions = @(
    "Microsoft.Storage/storageAccounts/listKeys/action"
)

$riskyRoleIds = Get-AzRoleDefinition | Where-Object {
    $grantedActions = $_.Permissions | ForEach-Object { $_.Actions } | Where-Object { $_ }
    $blockedActions = $_.Permissions | ForEach-Object { $_.NotActions } | Where-Object { $_ }

    foreach ($riskyAction in $riskyActions) {
        $isGranted = $false
        $isBlocked = $false

        foreach ($grantedAction in $grantedActions) {
            # Handle wildcards: *, Microsoft.Storage/*, Microsoft.Storage/storageAccounts/*
            $pattern = "^" + [regex]::Escape($grantedAction).Replace("\*", ".*") + "$"
            if ($riskyAction -match $pattern) { $isGranted = $true }
        }

        foreach ($blockedAction in $blockedActions) {
            $pattern = "^" + [regex]::Escape($blockedAction).Replace("\*", ".*") + "$"
            if ($riskyAction -match $pattern) { $isBlocked = $true }
        }

        if ($isGranted -and -not $isBlocked) { return $true }
    }

    return $false
} | Select-Object -ExpandProperty Id -Unique

Get-AzRoleAssignment |
    Where-Object { $riskyRoleIds -contains $_.RoleDefinitionId } |
    Select-Object RoleDefinitionName, DisplayName, SignInName, ObjectType, Scope |
    Sort-Object Scope, RoleDefinitionName |
    Format-Table -AutoSize
```

### Azure Portal

1. Open **Azure Portal** -> target **Storage account**.
2. Go to **Access control (IAM)** -> **Role assignments**.
3. Review assignments for the built-in roles listed above and custom roles with the actions above.
4. Open **Activity log** and filter for key list operations.

## Exploitation

These examples are for authorized testing only.

### List Account Keys

```powershell
Connect-AzAccount

$keys = Get-AzStorageAccountKey -ResourceGroupName "<RGName>" -Name "<AccountName>"
$keys | Select-Object KeyName, Permissions, Value | Format-List
```

```bash
az storage account keys list \
    --resource-group "<RGName>" \
    --account-name "<AccountName>" \
    -o table
```

![List Account Keys az](https://3408039743-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FObpV44hoVkNmo5bFuVVL%2Fuploads%2Fgit-blob-9e327a6a8043419145f9964c53342d30292e94e5%2Fazure-az_storage_list_keys-list_keys.PNG?alt=media)

### Use a Retrieved Key to Read a Blob File

```bash
az storage container list \
    --account-name "<AccountName>" \
    --account-key "<AccountKey>" \
    -o table

az storage blob list \
    --account-name "<AccountName>" \
    --account-key "<AccountKey>" \
    --container-name "<ContainerName>" \
    -o table

az storage blob download \
    --account-name "<AccountName>" \
    --account-key "<AccountKey>" \
    --container-name "<ContainerName>" \
    --name "<BlobName>" \
    --file ".\\downloaded-blob"
```

![list keys, containers, blobsthen downloadfile az](https://3408039743-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FObpV44hoVkNmo5bFuVVL%2Fuploads%2Fgit-blob-0887cd6dfc1225c46cba6c28970b784a4f780ef4%2Fazure-az_storage_list_keys-list_keys_containers_blobs_download_file_az.PNG?alt=media)

## Mitigation

1. **Avoid key-based access** - prefer Microsoft Entra authorization for blob data and managed identities for applications.
2. **Restrict key-listing roles** - remove broad roles from storage scopes and avoid assigning **Storage Account Key Operator Service Role** unless strictly required.
3. **Disable shared key authorization where possible** - set **Allow storage account key access** to **Disabled** after confirming application compatibility.
4. **Rotate account keys** after suspected exposure and update dependent applications in a controlled sequence.
5. **Scope assignments narrowly** - avoid subscription-level or resource-group-level roles that include `listKeys`.

## Detection

Use the Azure Portal:

1. Open **Azure Portal** -> target **Storage account** -> **Activity log**.
2. Filter **Operation** for **List Storage Account Keys** or operations containing `listKeys`.
3. Review **Event initiated by**, **Timestamp**, **Resource**, **Status**, and **Caller IP address** for unexpected key access.
4. In **Diagnostic settings**, send Storage read/write logs and Activity Log events to Log Analytics or a SIEM.
5. Alert on key listing by non-break-glass principals and on key listing shortly before unusual blob, queue, table, or file activity.

## References

* [Azure Storage account keys](https://learn.microsoft.com/en-us/azure/storage/common/storage-account-keys-manage)
* [Prevent Shared Key authorization for an Azure Storage account](https://learn.microsoft.com/en-us/azure/storage/common/shared-key-authorization-prevent)
* [Azure built-in roles for Storage](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/storage)
* [`az storage account keys list`](https://learn.microsoft.com/en-us/cli/azure/storage/account/keys#az-storage-account-keys-list)
