Detection rules › YARA-L

Unauthorized KMS Decryption

Type
Alert
Author
Drew Pilarski - Tempus AI
Source
github.com/chronicle/detection-rules

Detects when a Key Management Service (KMS) decryption operation is carried out by a service account that's not in the allowlist. This behavior may indicate unauthorized access to information.

MITRE ATT&CK coverage

TacticTechniques
PersistenceNo specific technique

Event coverage

Rule body yaral

/*
 * Copyright 2025 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

rule gcp_kms_decryption_by_unexpected_service_account {
  meta:
    author = "Drew Pilarski - Tempus AI"
    description = "Detects when a Key Management Service (KMS) decryption operation is carried out by a service account that's not in the allowlist. This behavior may indicate unauthorized access to information."
    rule_id = "mr_90cd5b0d-60a7-4028-bc41-dce0947fbafd"
    rule_name = "Unauthorized KMS Decryption"
    reference = "Internal Security Policy" // Include link to your organization's internal documentation if available
    mitre_attack_tactic = "Persistence"
    mitre_attack_technique = "Valid Accounts: Cloud Accounts"
    type = "Alert"
    platform = "GCP"
    data_source = "Cloud Audit Logs"
    severity = "Medium"  // Adjust based on your risk assessment
    priority = "Medium"  // Adjust based on your incident response process

  events:
    $decrypt.metadata.product_name = "Google Cloud Platform"
    $decrypt.metadata.vendor_name = "Google Cloud Platform"

    // Generic KMS Key Pattern - Pick the relevant one to your environment
    re.regex($decrypt.target.resource.name, `^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$`)
    $decrypt.metadata.product_event_type = "Decrypt"
    not $decrypt.principal.user.email_addresses in %kms_decryption_service_account_allowlist

  outcome:
    $action = $decrypt.metadata.product_event_type
    $account_name = array_distinct($decrypt.principal.user.email_addresses)
    $mitre_attack_tactic = array_distinct("Persistence")
    $mitre_attack_technique = array_distinct("Valid Accounts: Cloud Accounts")
    $mitre_attack_technique_id = array_distinct("T1078.004")

  condition:
    $decrypt
}

Detection logic

Fires when at least one $decrypt event.

Events

$decrypt

  • target.resource.name matches "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$"
  • metadata.product_event_type = "Decrypt"
  • principal.user.email_addresses in "%kms_decryption_service_account_allowlist"

Outcome

Fields the detection emits on a match. $risk_score drives alerting; Chronicle surfaces the rest on the detection.

FieldExpression
action$decrypt.metadata.product_event_type
account_namearray_distinct($decrypt.principal.user.email_addresses)