Detection rules › YARA-L
YARA-L rules: 2i
AWS KMS Key Disabled Or Scheduled For Deletion
#Detect when a KMS (Key Management Service) key is disabled or scheduled for deletion.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Impact |
Telemetry Coverage
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule aws_kms_key_disabled_or_scheduled_for_deletion {
meta:
author = "Google Cloud Security"
description = "Detect when a KMS (Key Management Service) key is disabled or scheduled for deletion."
rule_id = "mr_b1947fef-7b98-4c10-8303-d6c9c032d84e"
rule_name = "AWS KMS Key Disabled Or Scheduled For Deletion"
mitre_attack_tactic = "Impact"
mitre_attack_technique = "Data Destruction"
mitre_attack_url = "https://attack.mitre.org/techniques/T1485/"
mitre_attack_version = "v13.1"
type = "Alert"
data_source = "AWS CloudTrail"
platform = "AWS"
severity = "High"
priority = "High"
events:
$cloudtrail.metadata.vendor_name = "AMAZON"
$cloudtrail.metadata.product_name = "AWS CloudTrail"
$cloudtrail.metadata.product_event_type = "DisableKey" or $cloudtrail.metadata.product_event_type = "ScheduleKeyDeletion"
$cloudtrail.security_result.action = "ALLOW"
outcome:
$risk_score = max(75)
$mitre_attack_tactic = "Impact"
$mitre_attack_technique = "Data Destruction"
$mitre_attack_technique_id = "T1485"
$event_count = count_distinct($cloudtrail.metadata.id)
$network_http_user_agent = $cloudtrail.network.http.user_agent
$principal_ip = array_distinct($cloudtrail.principal.ip)
$principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region)
$principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state)
$principal_user_display_name = $cloudtrail.principal.user.user_display_name
$recipient_aws_account_id = $cloudtrail.additional.fields["recipientAccountId"]
$aws_region = $cloudtrail.principal.location.name
$target_resource_name = $cloudtrail.target.resource.name
$target_resource_product_object_id = $cloudtrail.target.resource.product_object_id
condition:
$cloudtrail
}
YARA-L Rule Structure
Condition
Fires when at least one $cloudtrail event.
Events
$cloudtrail
metadata.product_event_type = "DisableKey" or "ScheduleKeyDeletion"security_result.action = "ALLOW"
Outcome
Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.
| Field | Expression |
|---|---|
risk_score | max(75) |
event_count | count_distinct($cloudtrail.metadata.id) |
network_http_user_agent | $cloudtrail.network.http.user_agent |
principal_ip | array_distinct($cloudtrail.principal.ip) |
principal_ip_country | array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) |
principal_ip_state | array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) |
principal_user_display_name | $cloudtrail.principal.user.user_display_name |
recipient_aws_account_id | $cloudtrail.additional.fields["recipientAccountId"] |
aws_region | $cloudtrail.principal.location.name |
target_resource_name | $cloudtrail.target.resource.name |
target_resource_product_object_id | $cloudtrail.target.resource.product_object_id |
GCTI Remote Access Tools
#Alert process and file create events that are associated with hashes from the GCTI Remote Access Tool list
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
Telemetry Coverage
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule gcti_remote_access_tools {
meta:
author = "Google Cloud Security"
description = "Alert process and file create events that are associated with hashes from the GCTI Remote Access Tool list"
rule_id = "mr_d838d64d-4a6f-4999-a895-0b5771d02aa6"
rule_name = "GCTI Remote Access Tools"
tactic = "TA0011"
technique = "T1219"
type = "alert"
tags = "rat"
data_source = "crowdstrike, microsoft sysmon, microsoft defender atp"
severity = "High"
priority = "High"
events:
// find a process launch event
($process.metadata.event_type = "PROCESS_LAUNCH" or $process.metadata.event_type = "PROCESS_MODULE_LOAD" or $process.metadata.event_type = "PROCESS_UNCATEGORIZED" or $process.metadata.event_type = "FILE_CREATION")
$process.target.process.file.sha256 != ""
$process.target.process.file.sha256 = $rat_hash
$process.principal.hostname = $hostname
// join graph and event hashes
$gcti.graph.entity.file.sha256 = $rat_hash
// look for files identified as likely remote access tools
$gcti.graph.metadata.entity_type = "FILE"
$gcti.graph.metadata.vendor_name = "Google Cloud Threat Intelligence"
$gcti.graph.metadata.product_name = "GCTI Feed"
$gcti.graph.metadata.source_type = "GLOBAL_CONTEXT"
$gcti.graph.metadata.threat.threat_feed_name = "Remote Access Tools"
match:
$hostname over 5m
outcome:
$risk_score = 65
$event_count = count_distinct($process.metadata.id)
// added to populate alert graph with additional context
// Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results
//$principal_hostname = array_distinct($process.principal.hostname)
$principal_process_pid = array_distinct($process.principal.process.pid)
$principal_process_command_line = array_distinct($process.principal.process.command_line)
$principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256)
$principal_process_file_full_path = array_distinct($process.principal.process.file.full_path)
$principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id)
$principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id)
$target_process_pid = array_distinct($process.target.process.pid)
$target_process_command_line = array_distinct($process.target.process.command_line)
$target_process_file_sha256 = array_distinct($process.target.process.file.sha256)
$target_process_file_full_path = array_distinct($process.target.process.file.full_path)
$target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id)
$target_process_parent_process_product_specific_process_id = array_distinct($process.target.process.parent_process.product_specific_process_id)
$target_file_full_path = array_distinct($process.target.file.full_path)
$principal_user_userid = array_distinct($process.principal.user.userid)
$target_resource_name = array_distinct($process.target.resource.name)
condition:
$process and $gcti
}
YARA-L Rule Structure
Condition
Fires when at least one $process event in the 5m window and $gcti matches entity context.
Events
$gcti
graph.metadata.entity_type = "FILE"graph.metadata.vendor_name = "Google Cloud Threat Intelligence"graph.metadata.product_name = "GCTI Feed"graph.metadata.source_type = "GLOBAL_CONTEXT"graph.metadata.threat.threat_feed_name = "Remote Access Tools"
$process
target.process.file.sha256 is not null
Match and Correlation
Outcome
Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.
| Field | Expression |
|---|---|
risk_score | 65 |
event_count | count_distinct($process.metadata.id) |
principal_process_pid | array_distinct($process.principal.process.pid) |
principal_process_command_line | array_distinct($process.principal.process.command_line) |
principal_process_file_sha256 | array_distinct($process.principal.process.file.sha256) |
principal_process_file_full_path | array_distinct($process.principal.process.file.full_path) |
principal_process_product_specific_process_id | array_distinct($process.principal.process.product_specific_process_id) |
principal_process_parent_process_product_specific_process_id | array_distinct($process.principal.process.parent_process.product_specific_process_id) |
target_process_pid | array_distinct($process.target.process.pid) |
target_process_command_line | array_distinct($process.target.process.command_line) |
target_process_file_sha256 | array_distinct($process.target.process.file.sha256) |
target_process_file_full_path | array_distinct($process.target.process.file.full_path) |
target_process_product_specific_process_id | array_distinct($process.target.process.product_specific_process_id) |
target_process_parent_process_product_specific_process_id | array_distinct($process.target.process.parent_process.product_specific_process_id) |
target_file_full_path | array_distinct($process.target.file.full_path) |
principal_user_userid | array_distinct($process.principal.user.userid) |
target_resource_name | array_distinct($process.target.resource.name) |
Hunt for Office 365 group creation success
#Detects when a group is created in Office 365.
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft 365 | Add group. |
Rules Detecting the Same Action
These rules filter on the same operation.
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule o365_group_creation_success {
meta:
author = "Google Cloud Security"
description = "Detects when a group is created in Office 365."
rule_id = "mr_d35822fd-c121-46eb-a232-772f8c1290bd"
rule_name = "Hunt for Office 365 group creation success"
type = "hunt"
platform = "azure"
data_source = "o365"
severity = "Low"
priority = "Low"
events:
$group.metadata.event_type = "GROUP_CREATION"
$group.metadata.product_event_type = "Add group."
$group.metadata.product_name = "Office 365"
$group.metadata.vendor_name = "Microsoft"
$group.security_result.action = "ALLOW"
$group.principal.user.userid = $user
match:
$user over 5m
outcome:
$risk_score = 35
$event_count = count_distinct($group.metadata.id)
$user_agent = array_distinct($group.network.http.user_agent)
$security_summary = array_distinct($group.security_result.summary)
$target_application = array_distinct($group.target.application)
//$principal_user_userid = array_distinct($group.principal.user.userid)
$group_name = array_distinct($group.target.group.group_display_name)
$group_guid = array_distinct(re.replace($group.security_result.detection_fields["target_2"], `^Group_`, ""))
condition:
$group
}
YARA-L Rule Structure
Condition
Fires when at least one $group event in the 5m window.
Events
$group
metadata.product_event_type = "Add group."security_result.action = "ALLOW"
Match and Correlation
Outcome
Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.
| Field | Expression |
|---|---|
risk_score | 35 |
event_count | count_distinct($group.metadata.id) |
user_agent | array_distinct($group.network.http.user_agent) |
security_summary | array_distinct($group.security_result.summary) |
target_application | array_distinct($group.target.application) |
group_name | array_distinct($group.target.group.group_display_name) |
group_guid | array_distinct(re.replace($group.security_result.detection_fields["target_2"], `^Group_`, "")) |
O365 OneDrive Anonymous File Accessed
#Anonymous links can be used to export files from OneDrive. While this isn't always a sign of malicious activity, some organizations do not support the use of anonymous links because of the risk of data leakage. This rule detects when anonymous links are used to access files from OneDrive.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Exfiltration |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft 365 | FileAccessed |
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule o365_onedrive_anonymous_file_accessed {
meta:
author = "Google Cloud Security"
description = "Anonymous links can be used to export files from OneDrive. While this isn't always a sign of malicious activity, some organizations do not support the use of anonymous links because of the risk of data leakage. This rule detects when anonymous links are used to access files from OneDrive."
rule_id = "mr_f713e2b0-31b1-4165-8764-59a5e2c5eabc"
rule_name = "O365 OneDrive Anonymous File Accessed"
tactic = "TA0010"
technique = "T1048.002"
type = "hunt"
platform = "azure"
data_source = "o365"
severity = "Medium"
priority = "Medium"
events:
$file.metadata.event_type = "USER_RESOURCE_ACCESS"
$file.metadata.product_event_type = "FileAccessed"
$file.metadata.product_name = "Office 365"
$file.metadata.vendor_name = "Microsoft"
(
$file.principal.user.userid = /^urn:spo:anon#/ or
$file.principal.user.userid = "anonymous"
)
$file.principal.ip = $ip
match:
$ip over 5m
outcome:
$risk_score = 35
$event_count = count_distinct($file.metadata.id)
$referral_url = array_distinct($file.network.http.referral_url)
$user_agent = array_distinct($file.network.http.user_agent)
$principal_application = array_distinct($file.principal.application)
$principal_ip = array_distinct($file.principal.ip) //IP is a Microsoft IP address not the individual who accessed the file
$target_application = array_distinct($file.target.application)
$principal_user_userid = array_distinct($file.principal.user.userid)
$target_file_full_path = array_distinct($file.target.file.full_path)
$target_url = array_distinct($file.target.url)
condition:
$file
}
YARA-L Rule Structure
Condition
Fires when at least one $file event in the 5m window.
Events
$file
metadata.product_event_type = "FileAccessed"principal.user.userid matches "^urn:spo:anon#"principal.user.userid = "anonymous"
Match and Correlation
Outcome
Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.
| Field | Expression |
|---|---|
risk_score | 35 |
event_count | count_distinct($file.metadata.id) |
referral_url | array_distinct($file.network.http.referral_url) |
user_agent | array_distinct($file.network.http.user_agent) |
principal_application | array_distinct($file.principal.application) |
principal_ip | array_distinct($file.principal.ip) |
target_application | array_distinct($file.target.application) |
principal_user_userid | array_distinct($file.principal.user.userid) |
target_file_full_path | array_distinct($file.target.file.full_path) |
target_url | array_distinct($file.target.url) |
OneLogin OTP Bruteforce Attack
#Detects a successful login after multiple failed OTP intents
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
References
Rule Body
// Copyright 2024 Google LLC. Licensed under Apache-2.0.
rule onelogin_otp_brute_force_attack {
meta:
author = "Google Cloud Security"
description = "Detects a successful login after multiple failed OTP intents"
rule_id = "mr_cc37e0cf-c8c5-4e46-be0e-b2b992775500"
rule_name = "OneLogin OTP Bruteforce Attack"
reference = "https://www.onelogin.com/blog/brute-force-attacks"
mitre_attack_tactic = "Credential Access"
mitre_attack_technique = "Brute Force"
mitre_attack_url = "https://attack.mitre.org/techniques/T1110/"
mitre_attack_version = "v15.1"
type = "Alert"
data_source = "OneLogin"
severity = "High"
priority = "High"
events:
$failed_otp.metadata.event_type = "USER_RESOURCE_ACCESS"
$failed_otp.metadata.product_name = "ONELOGIN_SSO"
$failed_otp.metadata.vendor_name = "ONELOGIN"
$failed_otp.metadata.product_event_type = "1002" //failed otp challenge
$failed_otp.principal.user.userid = $userid
$success_otp.metadata.event_type = "USER_LOGIN"
$success_otp.metadata.product_name = "ONELOGIN_SSO"
$success_otp.metadata.vendor_name = "ONELOGIN"
$success_otp.metadata.product_event_type = "1400" //User verified otp device
$success_otp.principal.user.userid = $userid
$login.metadata.event_type = "USER_LOGIN"
$login.metadata.product_name = "ONELOGIN_SSO"
$login.metadata.vendor_name = "ONELOGIN"
$login.metadata.product_event_type = "5" //User logged into onelogin
$login.principal.user.userid = $userid
$failed_otp.metadata.event_timestamp.seconds <= $success_otp.metadata.event_timestamp.seconds
$success_otp.metadata.event_timestamp.seconds <= $login.metadata.event_timestamp.seconds
match:
$userid over 15m
outcome:
$risk_score = max(75)
$mitre_attack_tactic = "Credential Access"
$mitre_attack_technique = "Brute Force"
$target_user_agent = array_distinct($login.network.http.user_agent)
$principal_ip = array_distinct($login.principal.ip)
$principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region)
$principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state)
$principal_user_user_display_name = array_distinct($login.principal.user.user_display_name)
$target_user_userid = array_distinct($login.target.user.userid)
$otp_device_name = array_distinct($success_otp.additional.fields["otp_device_name"])
$otp_device_id = array_distinct($success_otp.principal.asset_id)
condition:
#failed_otp >= 4 and $success_otp and $login
}
YARA-L Rule Structure
Condition
Fires when $failed_otp occurs at least 4 times in the 15m window and at least one $success_otp event in the 15m window and at least one $login event in the 15m window.
Events
$failed_otp
metadata.product_event_type = "1002"
$success_otp
metadata.product_event_type = "1400"
$login
metadata.product_event_type = "5"
Match and Correlation
Outcome
Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.
| Field | Expression |
|---|---|
risk_score | max(75) |
target_user_agent | array_distinct($login.network.http.user_agent) |
principal_ip | array_distinct($login.principal.ip) |
principal_ip_country | array_distinct($login.principal.ip_geo_artifact.location.country_or_region) |
principal_ip_state | array_distinct($login.principal.ip_geo_artifact.location.state) |
principal_user_user_display_name | array_distinct($login.principal.user.user_display_name) |
target_user_userid | array_distinct($login.target.user.userid) |
otp_device_name | array_distinct($success_otp.additional.fields["otp_device_name"]) |
otp_device_id | array_distinct($success_otp.principal.asset_id) |
sap hanadb user admin actions
#Detects administrative user management (Create/Alter/Drop) and schema deletion within SAP HANA DB.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence |
Rule Body
// Copyright 2026 Google LLC. Licensed under Apache-2.0.
rule sap_hanadb_user_admin_actions {
meta:
author = "Google Cloud Security"
description = "Detects administrative user management (Create/Alter/Drop) and schema deletion within SAP HANA DB."
severity = "Medium"
tactic = "TA0003"
technique = "T1136"
events:
$e.metadata.log_type = "SAP_HANA_AUDIT"
$statement = $e.additional.fields["executed_statement"]
(
$statement = /CREATE USER/ nocase or
$statement = /ALTER USER/ nocase or
$statement = /DROP USER/ nocase or
$statement = /DROP SCHEMA/ nocase
)
$user = $e.principal.user.userid
match:
$user over 30m
outcome:
$risk_score = max(70)
$principal_user = array_distinct($user)
$target_user = array_distinct($e.target.user.userid)
$executed_statements = array_distinct($statement)
$system_id = array_distinct($e.target.resource.attribute.labels["system_id"])
$db_name = array_distinct($e.target.resource.name)
condition:
$e
}
YARA-L Rule Structure
Condition
Fires when at least one $e event in the 30m window.
Events
$e
metadata.log_type = "SAP_HANA_AUDIT"additional.fields["executed_statement"] matches "CREATE USER"additional.fields["executed_statement"] matches "ALTER USER"additional.fields["executed_statement"] matches "DROP USER"additional.fields["executed_statement"] matches "DROP SCHEMA"
Match and Correlation
Outcome
Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.
| Field | Expression |
|---|---|
risk_score | max(70) |
principal_user | array_distinct($user) |
target_user | array_distinct($e.target.user.userid) |
executed_statements | array_distinct($statement) |
system_id | array_distinct($e.target.resource.attribute.labels["system_id"]) |
db_name | array_distinct($e.target.resource.name) |