Detection rules › YARA-L

YARA-L rules: 14

GCP Service Account Key Used From Multiple Countries

#
Severity
low
Type
Alert
Time window
1h
Match by
sa_key_id
Author
Google Cloud Security
Source
github.com/chronicle/detection-rules

Detects usage of service account key from multiple countries using Chronicle GeoIP enrichment.

MITRE ATT&CK Coverage

TacticTechniques
Credential Access

Rule Body

// Copyright 2024 Google LLC. Licensed under Apache-2.0.

 rule gcp_service_account_key_used_from_multiple_countries {

  meta:
    author = "Google Cloud Security"
    description = "Detects usage of service account key from multiple countries using Chronicle GeoIP enrichment."
    rule_id = "mr_dbc9cf09-7c2d-4c9e-b9d4-60df60f360a1"
    rule_name = "GCP Service Account Key Used From Multiple Countries"
    mitre_attack_tactic = "Credential Access"
    mitre_attack_technique = "Unsecured Credentials: Private Keys"
    mitre_attack_url = "https://attack.mitre.org/techniques/T1552/004/"
    mitre_attack_version = "v14.1"
    type = "Alert"
    data_source = "GCP Cloud Audit"
    platform = "GCP"
    severity = "Low"
    priority = "Low"

 events:
    $gcp.metadata.log_type = "GCP_CLOUDAUDIT"
    $gcp.security_result.action = "ALLOW"
    $gcp.principal.ip_geo_artifact.location.country_or_region != ""
    $gcp.principal.ip_geo_artifact.network.organization_name != /google/
    $gcp.security_result.detection_fields["key_id"] = $sa_key_id

  match:
    $sa_key_id over 1h

  outcome:
    $risk_score = max(35)
    $mitre_attack_tactic = "Credential Access"
    $mitre_attack_technique = "Unsecured Credentials: Private Keys"
    $mitre_attack_technique_id = "T1552.004"
    $event_count = count_distinct($gcp.metadata.id)
    $network_http_user_agent = array_distinct($gcp.network.http.user_agent)
    $principal_ip = array_distinct($gcp.principal.ip)
    $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region)
    $dc_principal_ip_country = count_distinct($gcp.principal.ip_geo_artifact.location.country_or_region)
    $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state)
    $principal_user_display_name = array_distinct($gcp.principal.user.user_display_name)
    $target_resource_name = array_distinct($gcp.target.resource.name)
    $sa_key_name = array_distinct($gcp.security_result.detection_fields["service_account_key_name"])

  condition:
    $gcp and $dc_principal_ip_country > 2
}

YARA-L Rule Structure

Condition

Fires when at least one $gcp event in the 1h window and $dc_principal_ip_country > 2.

Events

$gcp

  • metadata.log_type = "GCP_CLOUDAUDIT"
  • security_result.action = "ALLOW"
  • principal.ip_geo_artifact.location.country_or_region is not null
  • principal.ip_geo_artifact.network.organization_name matches "google"

Match and Correlation

Match key
$sa_key_id (security_result.detection_fields["key_id"])
Within
1h

Outcome

Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.

FieldExpression
risk_scoremax(35)
event_countcount_distinct($gcp.metadata.id)
network_http_user_agentarray_distinct($gcp.network.http.user_agent)
principal_iparray_distinct($gcp.principal.ip)
principal_ip_countryarray_distinct($gcp.principal.ip_geo_artifact.location.country_or_region)
dc_principal_ip_countrycount_distinct($gcp.principal.ip_geo_artifact.location.country_or_region)
principal_ip_statearray_distinct($gcp.principal.ip_geo_artifact.location.state)
principal_user_display_namearray_distinct($gcp.principal.user.user_display_name)
target_resource_namearray_distinct($gcp.target.resource.name)
sa_key_namearray_distinct($gcp.security_result.detection_fields["service_account_key_name"])

Google Workspace Alerts Aggregated By Severity

#
Type
Alert
Time window
1h
Match by
severity
Author
Google Cloud Security
Source
github.com/chronicle/detection-rules

Generates alerts based on Google Workspace alerts center and aggregates them based on severity.

Rule Body

// Copyright 2023 Google LLC. Licensed under Apache-2.0.

rule google_workspace_alerts_aggregated_by_severity {

  meta:
    author = "Google Cloud Security"
    description = "Generates alerts based on Google Workspace alerts center and aggregates them based on severity."
    rule_id = "mr_311cc4ab-627b-43a1-a744-8d7aa5e44fbf"
    rule_name = "Google Workspace Alerts Aggregated By Severity"
    type = "Alert"
    data_source = "Workspace Alerts"

  events:
    $ws.metadata.vendor_name = "Google Workspace"
    $ws.metadata.product_name = "Google Workspace Alerts"
    $ws.security_result.severity = $severity

  match:
    $severity over 1h

  outcome:
    $risk_score = max(30 +
        if($ws.security_result.severity = "LOW", 10)+
        if($ws.security_result.severity = "MEDIUM", 30)+
        if($ws.security_result.severity = "HIGH", 50)
    )
    $event_count = count_distinct($ws.metadata.id)
    $event_type = array_distinct($ws.metadata.event_type)
    $product_event_type = array_distinct($ws.metadata.product_event_type)
    $security_category_details = array_distinct($ws.security_result.category_details)
    $security_category = array_distinct($ws.security_result.category)
    $security_investigation_tool_link = array_distinct($ws.security_result.detection_fields["security_investigation_tool_link"])
    $security_summary = array_distinct($ws.security_result.summary)
    $alert_severity = array_distinct($ws.security_result.severity)

  condition:
    $ws
}

YARA-L Rule Structure

Condition

Fires when at least one $ws event in the 1h window.

Events

$ws

No field filters (binds the event for correlation only).

Match and Correlation

Match key
$severity (security_result.severity)
Within
1h

Outcome

Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.

FieldExpression
risk_scoremax(30 + if($ws.security_result.severity = "LOW", 10)+ if($ws.security_result.severity = "MEDIUM", 30)+ if($ws.security_result.severity = "HIGH", 50) )
event_countcount_distinct($ws.metadata.id)
event_typearray_distinct($ws.metadata.event_type)
product_event_typearray_distinct($ws.metadata.product_event_type)
security_category_detailsarray_distinct($ws.security_result.category_details)
security_categoryarray_distinct($ws.security_result.category)
security_investigation_tool_linkarray_distinct($ws.security_result.detection_fields["security_investigation_tool_link"])
security_summaryarray_distinct($ws.security_result.summary)
alert_severityarray_distinct($ws.security_result.severity)

Google Workspace File Shared From Google Drive To Free Email Domain

#
Severity
high
Type
Alert
Author
Google Cloud Security
Source
github.com/chronicle/detection-rules

Identifies when a user shares a file on Google Drive with a free email domain, which may indicate data exfiltration.

MITRE ATT&CK Coverage

TacticTechniques
Exfiltration

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

// Copyright 2023 Google LLC. Licensed under Apache-2.0.

rule google_workspace_file_shared_from_google_drive_to_free_email_domain {

    meta:
      author = "Google Cloud Security"
      description = "Identifies when a user shares a file on Google Drive with a free email domain, which may indicate data exfiltration."
      rule_id = "mr_054c422b-2a42-4dde-b937-e80d063f65e7"
      rule_name = "Google Workspace File Shared From Google Drive To Free Email Domain"
      mitre_attack_tactic = "Exfiltration"
      mitre_attack_technique = "Exfiltration Over Web Service"
      mitre_attack_url = "https://attack.mitre.org/techniques/T1567/"
      mitre_attack_version = "v13.1"
      type = "Alert"
      data_source = "Workspace Activity"
      severity = "High"
      priority = "High"

    events:
      $ws.metadata.vendor_name = "Google Workspace"
      $ws.metadata.product_name = "drive"

      (
          $ws.metadata.product_event_type = "change_user_access" or
          $ws.metadata.product_event_type = "change_document_visibility" or
          $ws.metadata.product_event_type = "change_document_access_scope" or
          $ws.metadata.product_event_type = "change_acl_editors"
      )

      // File shared externally with free email domains
      $ws.target.resource.attribute.labels["visibility"] = "shared_externally"
      $ws.target.user.email_addresses = /.*@gmail\.com|.*@aol\.com|.*@ymail\.com|.*@ymail\.com|.*@hotmail\.com|.*@outlook\.com|.*@icloud\.com/

    outcome:
      $risk_score = max(75)
      $mitre_attack_tactic = "Exfiltration"
      $mitre_attack_technique = "Exfiltration Over Web Service"
      $mitre_attack_technique_id = "T1567"
      $event_count = count_distinct($ws.metadata.id)
      $product_event_type = array_distinct($ws.metadata.product_event_type)
      $userid = array_distinct($ws.principal.user.userid)
      $doc_type = array_distinct($ws.src.resource.attribute.labels["doc_type"])
      $owner = array_distinct($ws.target.resource.attribute.labels["owner"])
      $target_emails = array_distinct($ws.target.user.email_addresses)
      $doc_name = array_distinct($ws.target.resource.name)
      $doc_id = array_distinct($ws.target.resource.product_object_id)

    condition:
      $ws
  }

YARA-L Rule Structure

Condition

Fires when at least one $ws event.

Events

$ws

  • metadata.product_event_type is one of:
    • change_user_access
    • change_document_visibility
    • change_document_access_scope
    • change_acl_editors
  • target.resource.attribute.labels["visibility"] = "shared_externally"
  • target.user.email_addresses matches ".*@gmail\.com|.*@aol\.com|.*@ymail\.com|.*@ymail\.com|.*@hotmail\.com|.*@outlook\.com|.*@icloud\.com"

Outcome

Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.

FieldExpression
risk_scoremax(75)
event_countcount_distinct($ws.metadata.id)
product_event_typearray_distinct($ws.metadata.product_event_type)
useridarray_distinct($ws.principal.user.userid)
doc_typearray_distinct($ws.src.resource.attribute.labels["doc_type"])
ownerarray_distinct($ws.target.resource.attribute.labels["owner"])
target_emailsarray_distinct($ws.target.user.email_addresses)
doc_namearray_distinct($ws.target.resource.name)
doc_idarray_distinct($ws.target.resource.product_object_id)

O365 Recently Created Entra ID User Assigned Roles

#
Severity
medium
Type
alert
Time window
90m
Match by
userid
Author
Google Cloud Security
Source
github.com/chronicle/detection-rules

Detects when a user is created in Entra ID and assigned roles within a defined time window.

MITRE ATT&CK Coverage

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

// Copyright 2023 Google LLC. Licensed under Apache-2.0.

rule o365_recently_created_entra_id_user_assigned_roles {

  meta:
    author = "Google Cloud Security"
    description = "Detects when a user is created in Entra ID and assigned roles within a defined time window."
    rule_id = "mr_c0406a96-4ed1-4dd2-9629-aa5a2c881222"
    rule_name = "O365 Recently Created Entra ID User Assigned Roles"
    tactic = "TA0003"
    technique = "T1098.003"
    assumption = "The list msgraph_watchlist_roles is populated with role names, ie Application Administrator"
    type = "alert"
    platform = "azure"
    data_source = "o365"
    severity = "Medium"
    priority = "Medium"

  events:
    (
        $create.metadata.event_type = "USER_CREATION" and
        $create.metadata.product_event_type = "Add user." and
        $create.metadata.product_name = "Office 365" and
        $create.security_result.action = "ALLOW" and
        $create.target.user.userid = $userid
    )
    $create.metadata.event_timestamp.seconds < $role.metadata.event_timestamp.seconds
    (
        $role.metadata.event_type = "USER_UNCATEGORIZED" and
        $role.metadata.product_event_type = "Add member to role." and
        $role.metadata.product_name = "Office 365" and
        $role.security_result.action = "ALLOW" and
        //The reference list msgraph_watchlist_roles matches on the role name. List contents example row: Global Administrator //manage all aspects of Azure AD and Microsoft services that use Azure AD identities 62e90394-69f5-4237-9190-012177145e10
        //If you wanted to detect on specific roles, they could be added to a reference list and the following line uncommented
        //$role.target.resource.attribute.roles.name in %msgraph_watchlist_roles and
        $role.target.user.userid = $userid
    )

  match:
    $userid over 90m

  outcome:
    $risk_score = max(if($role.target.resource.attribute.roles.name = /Administrator/ nocase, 85, 35))
    $security_summary = array_distinct($role.security_result.summary)
    $user_agent = array_distinct($role.network.http.user_agent)
    $assigned_role = array_distinct($role.target.resource.attribute.roles.name)
    //added to populate alert graph with additional context
    $principal_user_userid = array_distinct($create.principal.user.userid)
    $target_user_userid = array_distinct($create.target.user.userid)

  condition:
    $create and $role
}

YARA-L Rule Structure

Condition

Fires when at least one $create event in the 90m window and at least one $role event in the 90m window.

Events

$create USER_CREATION

  • metadata.product_event_type = "Add user."
  • security_result.action = "ALLOW"

$role USER_UNCATEGORIZED

  • metadata.product_event_type = "Add member to role."
  • security_result.action = "ALLOW"

Match and Correlation

Order
$create before $role
Match key
$userid (target.user.userid)
Within
90m

Outcome

Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.

FieldExpression
risk_scoremax(if($role.target.resource.attribute.roles.name = /Administrator/ nocase, 85, 35))
security_summaryarray_distinct($role.security_result.summary)
user_agentarray_distinct($role.network.http.user_agent)
assigned_rolearray_distinct($role.target.resource.attribute.roles.name)
principal_user_useridarray_distinct($create.principal.user.userid)
target_user_useridarray_distinct($create.target.user.userid)

Back to all YARA-L rules