Excessive Secret or Key Retrieval from Azure Key Vault

Last updated 23 days ago on 2025-07-10
Created 23 days ago on 2025-07-10

About

Identifies excessive secret or key retrieval operations from Azure Key Vault. This rule detects when a user principal retrieves secrets or keys from Azure Key Vault multiple times within a short time frame, which may indicate potential abuse or unauthorized access attempts. The rule focuses on high-frequency retrieval operations that deviate from normal user behavior, suggesting possible credential harvesting or misuse of sensitive information.
Tags
Domain: CloudDomain: StorageDomain: IdentityData Source: AzureData Source: Azure Platform LogsData Source: Azure Key VaultUse Case: Threat DetectionUse Case: Identity and Access AuditTactic: Credential AccessLanguage: esql
Severity
medium
Risk Score
43
MITRE ATT&CK™

Credential Access (TA0006)(opens in a new tab or window)

False Positive Examples
Service accounts or applications that frequently access Azure Key Vault for configuration or operational purposes may trigger this rule. Automated scripts or processes that retrieve secrets or keys for legitimate purposes, such as secret rotation or application configuration, may also lead to false positives. Security teams performing routine audits or assessments that involve retrieving keys or secrets from Key Vaults may trigger this rule if they perform multiple retrievals in a short time frame.
License
Elastic License v2(opens in a new tab or window)

Definition

Integration Pack
Prebuilt Security Detection Rules
Related Integrations

azure(opens in a new tab or window)

Query
FROM logs-azure.platformlogs-* METADATA _id, _index

// Filter for Azure Key Vault read operations
| WHERE event.dataset == "azure.platformlogs"
  AND event.action IN (
    "VaultGet",
    "KeyGet",
    "KeyList",
    "KeyListVersions",
    "KeyGetDeleted",
    "KeyListDeleted",
    "SecretGet",
    "SecretList",
    "SecretListVersions",
    "SecretGetDeleted",
    "SecretListDeleted",
    "CertificateGet",
    "CertificateList",
    "CertificateListVersions",
    "CertificateGetDeleted",
    "CertificateListDeleted",
    "CertificatePolicyGet",
    "CertificateContactsGet",
    "CertificateIssuerGet",
    "CertificateIssuersList"
  )

// Truncate timestamps into 1-minute windows
| EVAL Esql.time_window.date_trunc = DATE_TRUNC(1 minute, @timestamp)

// Aggregate identity, geo, resource, and activity info
| STATS
    Esql.azure.platformlogs.identity.claim.upn.values = VALUES(azure.platformlogs.identity.claim.upn),
    Esql.azure.platformlogs.identity.claim.upn.count_unique = COUNT_DISTINCT(azure.platformlogs.identity.claim.upn),
    Esql.azure.platformlogs.identity.claim.appid.values = VALUES(azure.platformlogs.identity.claim.appid),
    Esql.azure.platformlogs.identity.claim.objectid.values = VALUES(azure.platformlogs.identity.claim.objectid),

    Esql.source.ip.values = VALUES(source.ip),
    Esql.geo.city.values = VALUES(geo.city_name),
    Esql.geo.region.values = VALUES(geo.region_name),
    Esql.geo.country.values = VALUES(geo.country_name),
    Esql.network.as_org.values = VALUES(source.as.organization.name),

    Esql.event.actions.values = VALUES(event.action),
    Esql.event.count = COUNT(*),
    Esql.event.action.count_distinct = COUNT_DISTINCT(event.action),
    Esql.azure.resource.name.count_distinct = COUNT_DISTINCT(azure.resource.name),
    Esql.azure.resource.name.values = VALUES(azure.resource.name),
    Esql.azure.platformlogs.result_type.values = VALUES(azure.platformlogs.result_type),
    Esql.cloud.region.values = VALUES(cloud.region),

    Esql.agent.name.values = VALUES(agent.name),
    Esql.azure.subscription_id.values = VALUES(azure.subscription_id),
    Esql.azure.resource_group.values = VALUES(azure.resource.group),
    Esql.azure.resource_id.values = VALUES(azure.resource.id)

BY Esql.time_window.date_trunc, azure.platformlogs.identity.claim.upn

// Keep relevant fields
| KEEP
    Esql.time_window.date_trunc,
    Esql.azure.platformlogs.identity.claim.upn.values,
    Esql.azure.platformlogs.identity.claim.upn.count_unique,
    Esql.azure.platformlogs.identity.claim.appid.values,
    Esql.azure.platformlogs.identity.claim.objectid.values,
    Esql.source.ip.values,
    Esql.geo.city.values,
    Esql.geo.region.values,
    Esql.geo.country.values,
    Esql.network.as_org.values,
    Esql.event.actions.values,
    Esql.event.count,
    Esql.event.action.count_distinct,
    Esql.azure.resource.name.count_distinct,
    Esql.azure.resource.name.values,
    Esql.azure.platformlogs.result_type.values,
    Esql.cloud.region.values,
    Esql.agent.name.values,
    Esql.azure.subscription_id.values,
    Esql.azure.resource_group.values,
    Esql.azure.resource_id.values

// Filter for suspiciously high volume of distinct Key Vault reads by a single actor
| WHERE Esql.azure.platformlogs.identity.claim.upn.count_unique == 1 AND Esql.event.count >= 10 AND Esql.event.action.count_distinct >= 2

| SORT Esql.time_window.date_trunc DESC

Install detection rules in Elastic Security

Detect Excessive Secret or Key Retrieval from Azure Key Vault in the Elastic Security detection engine by installing this rule into your Elastic Stack.

To setup this rule, check out the installation guide for Prebuilt Security Detection Rules(opens in a new tab or window).