Detection rules › Panther

GCP KMS Key Version Disabled or Destroyed

Status
Experimental
Severity
informational
Log types
GCP.AuditLog
Tags
GCP, Google Cloud KMS, Defense Evasion:Impair Defenses, Impact:Data Encrypted for Impact, Ransomware
Reference
https://cloud.google.com/kms/docs/key-states
Source
github.com/panther-labs/panther-analysis

Detects when a KMS key version is disabled, scheduled for destruction, or destroyed. Disabling or destroying KMS key versions can be used to deny access to encrypted data—a ransomware tactic where attackers disable keys to prevent victims from accessing their data.

MITRE ATT&CK coverage

Rules detecting the same action

Other rules on this platform that filter on the same API call or operation.

Rule body yaml

AnalysisType: rule
Filename: gcp_kms_erase_key.py
RuleID: "GCP.KMS.EraseKey"
DisplayName: "GCP KMS Key Version Disabled or Destroyed"
Enabled: true
Status: Experimental
LogTypes:
  - GCP.AuditLog
Tags:
  - GCP
  - Google Cloud KMS
  - Defense Evasion:Impair Defenses
  - Impact:Data Encrypted for Impact
  - Ransomware
Reports:
  MITRE ATT&CK:
    - TA0005:T1562
    - TA0040:T1486
Severity: Info
Description: >
  Detects when a KMS key version is disabled, scheduled for destruction, or destroyed.
  Disabling or destroying KMS key versions can be used to deny access to encrypted data—a
  ransomware tactic where attackers disable keys to prevent victims from accessing their data.
Runbook: |
  1. Query GCP Audit logs for all KMS key operations by the principal email in the 24 hours before and after this alert
  2. Check if the source IP is associated with known cloud provider IP ranges, VPN endpoints, or matches the user's typical access patterns
  3. Search for other KMS key state changes (disabled, destroyed) across different keys in the same project in the past 6 hours
  4. Identify which GCS buckets or other resources use this KMS key for encryption and assess data access impact
  5. Look for other alerts related to ransomware indicators (e.g., bulk operations, unusual encryption activity) from this project in the past 7 days
Reference: https://cloud.google.com/kms/docs/key-states
SummaryAttributes:
  - severity
  - p_any_ip_addresses
  - p_any_emails
Tests:
  - Name: KMS Key Version Disabled
    ExpectedResult: true
    Log:
      {
        "protoPayload":
          {
            "at_sign_type": "type.googleapis.com/google.cloud.audit.AuditLog",
            "authenticationInfo":
              {
                "oauthInfo":
                  {
                    "oauthClientId": "111111111111-abcdefghijklmnopqrstuvwxyz123456.apps.googleusercontent.com",
                  },
                "principalEmail": "denethor@lotr.com",
                "principalSubject": "user:denethor@lotr.com",
              },
            "authorizationInfo":
              [
                {
                  "granted": true,
                  "permission": "cloudkms.cryptoKeyVersions.update",
                  "permissionType": "ADMIN_WRITE",
                  "resource": "projects/test-project/locations/us/keyRings/test-keyring/cryptoKeys/test-key/cryptoKeyVersions/1",
                  "resourceAttributes":
                    {
                      "name": "projects/test-project/locations/us/keyRings/test-keyring/cryptoKeys/test-key/cryptoKeyVersions/1",
                      "service": "google.cloud.kms",
                      "type": "cloudkms.googleapis.com/CryptoKeyVersion",
                    },
                },
              ],
            "metadata": {},
            "methodName": "UpdateCryptoKeyVersion",
            "request":
              {
                "@type": "type.googleapis.com/google.cloud.kms.v1.UpdateCryptoKeyVersionRequest",
                "at_sign_type": "type.googleapis.com/google.cloud.kms.v1.UpdateCryptoKeyVersionRequest",
                "cryptoKeyVersion":
                  {
                    "name": "projects/test-project/locations/us/keyRings/test-keyring/cryptoKeys/test-key/cryptoKeyVersions/1",
                    "state": "DISABLED",
                  },
                "updateMask": "state",
              },
            "requestMetadata":
              {
                "callerIP": "1.2.3.4",
                "callerIp": "1.2.3.4",
                "callerSuppliedUserAgent": "google-cloud-sdk gcloud/548.0.0 command/gcloud.kms.keys.versions.disable",
                "destinationAttributes": {},
                "requestAttributes":
                  { "auth": {}, "time": "2025-12-15T15:40:47.296683147Z" },
              },
            "resourceLocation": { "currentLocations": ["us"] },
            "resourceName": "projects/test-project/locations/us/keyRings/test-keyring/cryptoKeys/test-key/cryptoKeyVersions/1",
            "serviceName": "cloudkms.googleapis.com",
            "status": {},
          },
        "insertId": "abc123def456",
        "logName": "projects/test-project/logs/cloudaudit.googleapis.com%2Factivity",
        "receiveTimestamp": "2025-12-15 15:40:48.642133512",
        "resource":
          {
            "labels":
              {
                "crypto_key_id": "test-key",
                "crypto_key_version_id": "1",
                "key_ring_id": "test-keyring",
                "location": "us",
                "project_id": "test-project",
              },
            "type": "cloudkms_cryptokeyversion",
          },
        "severity": "NOTICE",
        "timestamp": "2025-12-15 15:40:47.284488263",
      }
  - Name: KMS Key Version Enabled
    ExpectedResult: false
    Log:
      {
        "protoPayload":
          {
            "at_sign_type": "type.googleapis.com/google.cloud.audit.AuditLog",
            "authenticationInfo":
              { "principalEmail": "denethor@lotr.com" },
            "methodName": "UpdateCryptoKeyVersion",
            "request":
              {
                "@type": "type.googleapis.com/google.cloud.kms.v1.UpdateCryptoKeyVersionRequest",
                "cryptoKeyVersion":
                  {
                    "name": "projects/test-project/locations/us/keyRings/test-keyring/cryptoKeys/test-key/cryptoKeyVersions/1",
                    "state": "ENABLED",
                  },
                "updateMask": "state",
              },
            "resourceName": "projects/test-project/locations/us/keyRings/test-keyring/cryptoKeys/test-key/cryptoKeyVersions/1",
            "serviceName": "cloudkms.googleapis.com",
            "status": {},
          },
        "resource":
          {
            "labels": { "project_id": "test-project" },
            "type": "cloudkms_cryptokeyversion",
          },
        "timestamp": "2025-12-15 15:40:47.284488263",
      }
  - Name: KMS Key Version Destroyed
    ExpectedResult: true
    Log:
      {
        "protoPayload":
          {
            "at_sign_type": "type.googleapis.com/google.cloud.audit.AuditLog",
            "authenticationInfo":
              { "principalEmail": "user@example.com" },
            "methodName": "DestroyCryptoKeyVersion",
            "request":
              {
                "@type": "type.googleapis.com/google.cloud.kms.v1.UpdateCryptoKeyVersionRequest",
                "cryptoKeyVersion":
                  {
                    "name": "projects/test-project/locations/us/keyRings/test-keyring/cryptoKeys/test-key/cryptoKeyVersions/1",
                  },
              },
            "resourceName": "projects/test-project/locations/us/keyRings/test-keyring/cryptoKeys/test-key/cryptoKeyVersions/1",
            "serviceName": "cloudkms.googleapis.com",
            "status": {},
          },
        "resource":
          {
            "labels": { "project_id": "test-project" },
            "type": "cloudkms_cryptokeyversion",
          },
        "timestamp": "2025-12-15 15:40:47.284488263",
      }

Detection logic

Condition

protoPayload.serviceName eq "cloudkms.googleapis.com"
protoPayload.methodName eq "DestroyCryptoKeyVersion" or (protoPayload.methodName eq "UpdateCryptoKeyVersion" and protoPayload.request.updateMask eq "state" and protoPayload.request.cryptoKeyVersion.state in ["DISABLED", "DESTROY_SCHEDULED", "DESTROYED"])

Indicators

Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.

FieldKindValues
protoPayload.methodNameeq
  • DestroyCryptoKeyVersion
  • UpdateCryptoKeyVersion
protoPayload.request.cryptoKeyVersion.statein
  • DESTROYED
  • DESTROY_SCHEDULED
  • DISABLED
protoPayload.request.updateMaskeq
  • state
protoPayload.serviceNameeq
  • cloudkms.googleapis.com

Output fields

Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.

FieldSource
actorprotoPayload.authenticationInfo.principalEmail
kms_key_versionprotoPayload.resourceName
new_stateprotoPayload.request.cryptoKeyVersion.state
source_ipprotoPayload.requestMetadata.callerIp
projectresource.labels.project_id
key_ringresource.labels.key_ring_id
crypto_keyresource.labels.crypto_key_id
nameprotoPayload.request.cryptoKeyVersion.name