Detection rules › YARA-L
YARA-L rules: 2u
AWS Privilege Escalation Using IAM Access Key
#Detect when a user creates a new access key for another user and escalates privileges using this newly created access key from the same IP.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence |
Telemetry Coverage
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule aws_privilege_escalation_using_iam_access_key {
meta:
author = "Google Cloud Security"
description = "Detect when a user creates a new access key for another user and escalates privileges using this newly created access key from the same IP."
rule_id = "mr_a28c56ea-b5e6-4e23-8cb8-f306587b832b"
rule_name = "AWS Privilege Escalation Using IAM Access Key"
mitre_attack_tactic = "Persistence"
mitre_attack_technique = "Cloud Account"
mitre_attack_url = "https://attack.mitre.org/techniques/T1136/003/"
mitre_attack_version = "v13.1"
type = "Alert"
data_source = "AWS CloudTrail"
platform = "AWS"
severity = "Low"
priority = "Low"
events:
$accesskey.metadata.vendor_name = "AMAZON"
$accesskey.metadata.product_name = "AWS CloudTrail"
$accesskey.metadata.product_event_type = "CreateAccessKey"
$accesskey.security_result.action= "ALLOW"
$accesskey.principal.user.user_display_name != $accesskey.target.user.userid
$accesskey.principal.user.userid = $p_userid
$accesskey.target.user.userid = $t_userid
$privesc.metadata.vendor_name = "AMAZON"
$privesc.metadata.product_name = "AWS CloudTrail"
//Same IP address and Access Key used
$accesskey.principal.ip = $privesc.principal.ip
$accesskey.target.resource.product_object_id = $privesc.additional.fields["accessKeyId"]
$accesskey.metadata.event_timestamp.seconds < $privesc.metadata.event_timestamp.seconds
match:
$p_userid over 1h
outcome:
$risk_score = max(35)
$mitre_attack_tactic = "Persistence"
$mitre_attack_technique = "Cloud Account"
$mitre_attack_technique_id = "T1136.003"
$event_count = count_distinct($privesc.metadata.id)
$network_http_user_agent = array_distinct($privesc.network.http.user_agent)
$principal_ip = array_distinct($privesc.principal.ip)
$principal_ip_country = array_distinct($privesc.principal.ip_geo_artifact.location.country_or_region)
$principal_ip_state = array_distinct($privesc.principal.ip_geo_artifact.location.state)
$principal_user_display_name = array_distinct($privesc.principal.user.user_display_name)
$dc_principal_user_display_name = count_distinct($privesc.principal.user.user_display_name)
$is_mfa_used = array_distinct($privesc.principal.user.attribute.labels["mfaAuthenticated"])
$target_resource_name = array_distinct($privesc.target.resource.name)
$target_resource_product_object_id = array_distinct($privesc.target.resource.product_object_id)
$product_event_types = array_distinct($privesc.metadata.product_event_type)
condition:
$accesskey and $privesc
}
YARA-L Rule Structure
Condition
Fires when at least one $accesskey event in the 1h window and at least one $privesc event in the 1h window.
Events
$accesskey
metadata.product_event_type = "CreateAccessKey"security_result.action = "ALLOW"principal.user.user_display_name cross_field_compare "accesskey.target.user.userid"principal.ip cross_field_compare "privesc.principal.ip"target.resource.product_object_id cross_field_compare "privesc.additional.fields["accessKeyId"]"
$privesc
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(35) |
event_count | count_distinct($privesc.metadata.id) |
network_http_user_agent | array_distinct($privesc.network.http.user_agent) |
principal_ip | array_distinct($privesc.principal.ip) |
principal_ip_country | array_distinct($privesc.principal.ip_geo_artifact.location.country_or_region) |
principal_ip_state | array_distinct($privesc.principal.ip_geo_artifact.location.state) |
principal_user_display_name | array_distinct($privesc.principal.user.user_display_name) |
dc_principal_user_display_name | count_distinct($privesc.principal.user.user_display_name) |
is_mfa_used | array_distinct($privesc.principal.user.attribute.labels["mfaAuthenticated"]) |
target_resource_name | array_distinct($privesc.target.resource.name) |
target_resource_product_object_id | array_distinct($privesc.target.resource.product_object_id) |
product_event_types | array_distinct($privesc.metadata.product_event_type) |
GCP GCE Image Open To Public
#Detect when GCP Compute Image is opened to public by adding allAuthenticatedUsers to the access policy.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Exfiltration |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| GCP | compute.images.setIamPolicy: Set image IAM policy |
Rule Body
// Copyright 2024 Google LLC. Licensed under Apache-2.0.
rule gcp_gce_image_open_to_public {
meta:
author = "Google Cloud Security"
description = "Detect when GCP Compute Image is opened to public by adding allAuthenticatedUsers to the access policy."
rule_id = "mr_4a1525be-9e17-41d6-ba67-a11058ee4d3c"
rule_name = "GCP GCE Image Open To Public"
mitre_attack_tactic = "Exfiltration"
mitre_attack_technique = "Transfer Data to Cloud Account"
mitre_attack_url = "https://attack.mitre.org/techniques/T1537/"
mitre_attack_version = "v14.1"
type = "Alert"
data_source = "GCP Cloud Audit"
platform = "GCP"
severity = "High"
priority = "High"
events:
$gcp.metadata.event_type = "USER_RESOURCE_UPDATE_PERMISSIONS"
$gcp.metadata.log_type = "GCP_CLOUDAUDIT"
$gcp.metadata.vendor_name = "Google Cloud Platform"
$gcp.metadata.product_event_type = "beta.compute.images.setIamPolicy"
$gcp.target.application = "compute.googleapis.com"
$gcp.security_result.action = "ALLOW"
any $gcp.target.resource.attribute.labels.value = "allAuthenticatedUsers"
$gcp.target.resource.resource_subtype = "gce_image"
outcome:
$risk_score = max(75)
$mitre_attack_tactic = "Exfiltration"
$mitre_attack_technique = "Transfer Data to Cloud Account"
$mitre_attack_technique_id = "T1537"
$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)
$principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state)
$principal_user_id = $gcp.principal.user.userid
$principal_user_display_name = $gcp.principal.user.user_display_name
$target_resource_name = $gcp.target.resource.name
$event_name = $gcp.metadata.product_event_type
$target_email_addresses = array_distinct($gcp.target.user.email_addresses)
condition:
$gcp
}
YARA-L Rule Structure
Condition
Fires when at least one $gcp event.
Events
$gcp
metadata.log_type = "GCP_CLOUDAUDIT"metadata.product_event_type = "beta.compute.images.setIamPolicy"target.application = "compute.googleapis.com"security_result.action = "ALLOW"target.resource.attribute.labels.value = "allAuthenticatedUsers"target.resource.resource_subtype = "gce_image"
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($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) |
principal_ip_state | array_distinct($gcp.principal.ip_geo_artifact.location.state) |
principal_user_id | $gcp.principal.user.userid |
principal_user_display_name | $gcp.principal.user.user_display_name |
target_resource_name | $gcp.target.resource.name |
event_name | $gcp.metadata.product_event_type |
target_email_addresses | array_distinct($gcp.target.user.email_addresses) |
Hunt for Office 365 group modification add member success
#Detects when a user is added to a group in Office 365.
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft 365 | Add member to 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_modification_add_member_success {
meta:
author = "Google Cloud Security"
description = "Detects when a user is added to a group in Office 365."
rule_id = "mr_254a5c85-b248-43b6-a9b2-5118d4c31abb"
rule_name = "Hunt for Office 365 group modification add member success"
type = "hunt"
platform = "azure"
data_source = "o365"
severity = "Low"
priority = "Low"
events:
$group.metadata.event_type = "GROUP_MODIFICATION"
$group.metadata.product_event_type = "Add member to 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)
//Used in match section so excluding here
//$principal_user_userid = array_distinct($app.principal.user.userid)
$group_name = array_distinct($group.target.group.group_display_name)
$group_guid = array_distinct($group.target.group.product_object_id)
$user_added = array_distinct($group.target.user.userid)
$user_count = count_distinct($group.target.user.userid)
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 member to 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($group.target.group.product_object_id) |
user_added | array_distinct($group.target.user.userid) |
user_count | count_distinct($group.target.user.userid) |
OneLogin Multiple Users Login Failures From The Same IP
#Detects multiple users login failures from a single IP.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access |
Rule Body
// Copyright 2024 Google LLC. Licensed under Apache-2.0.
rule onelogin_multiple_users_login_failures_from_the_same_ip {
meta:
author = "Google Cloud Security"
description = "Detects multiple users login failures from a single IP."
rule_id = "mr_8e302561-6fc5-430d-ae0c-bd285a0aec21"
rule_name = "OneLogin Multiple Users Login Failures From The Same IP"
mitre_attack_tactic = "Initial Access"
mitre_attack_technique = "Valid Accounts: Cloud Accounts"
mitre_attack_url = "https://attack.mitre.org/techniques/T1078/004/"
mitre_attack_version = "v15.1"
type = "Alert"
data_source = "OneLogin"
severity = "Medium"
priority = "Medium"
events:
$login.metadata.event_type = "USER_LOGIN"
$login.metadata.product_name = "ONELOGIN_SSO"
$login.metadata.vendor_name = "ONELOGIN"
$login.security_result.action = "BLOCK"
$login.metadata.product_event_type = "6" //user failed authentication
$login.principal.ip = $ip
match:
$ip over 1h
outcome:
$risk_score = max(35 +
// Unauthorized target geographies
if($login.target.ip_geo_artifact.location.country_or_region = "Cuba", 20) +
if($login.target.ip_geo_artifact.location.country_or_region = "Iran", 20) +
if($login.target.ip_geo_artifact.location.country_or_region = "North Korea", 20) +
if($login.target.ip_geo_artifact.location.country_or_region = "Russia", 20) +
if($login.target.ip_geo_artifact.location.country_or_region = "Syria", 20)
)
$mitre_attack_tactic = "Initial Access"
$mitre_attack_technique = "Valid Accounts: Cloud Accounts"
$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_userid = array_distinct($login.principal.user.userid)
$principal_user_user_display_name = array_distinct($login.principal.user.user_display_name)
$dc_principal_user_userid = count_distinct($login.principal.user.userid)
$metadata_description = array_distinct($login.metadata.description)
condition:
$login and $dc_principal_user_userid > 3
}
YARA-L Rule Structure
Condition
Fires when at least one $login event in the 1h window and $dc_principal_user_userid > 3.
Events
$login
security_result.action = "BLOCK"metadata.product_event_type = "6"
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(35 + if($login.target.ip_geo_artifact.location.country_or_region = "Cuba", 20) + if($login.target.ip_geo_artifact.location.country_or_region = "Iran", 20) + if($login.target.ip_geo_artifact.location.country_or_region = "North Korea", 20) + if($login.target.ip_geo_artifact.location.country_or_region = "Russia", 20) + if($login.target.ip_geo_artifact.location.country_or_region = "Syria", 20) ) |
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_userid | array_distinct($login.principal.user.userid) |
principal_user_user_display_name | array_distinct($login.principal.user.user_display_name) |
dc_principal_user_userid | count_distinct($login.principal.user.userid) |
metadata_description | array_distinct($login.metadata.description) |
sap break glass account login
#Alerts whenever a default SAP administrative account (e.g., SAP*, DDIC, TMSADM) logs into the system. These accounts should be locked and used only for emergency 'break-glass' scenarios
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access |
Telemetry Coverage
Rule Body
// Copyright 2026 Google LLC. Licensed under Apache-2.0.
rule sap_break_glass_account_login {
meta:
author = "Google Cloud Security"
description = "Alerts whenever a default SAP administrative account (e.g., SAP*, DDIC, TMSADM) logs into the system. These accounts should be locked and used only for emergency 'break-glass' scenarios"
severity = "Low"
tactic = "TA0001"
technique = "T1078"
events:
$e.metadata.log_type = "SAP_SECURITY_AUDIT"
(
$e.additional.fields["msg_1"] = /^AU1$|^AU5$/ or
$e.metadata.event_type = "USER_LOGIN"
)
$e.principal.user.userid = $userid
$userid = /^DDIC$|^EARLYWATCH$|^SAP\*$|^TMSADM$/ nocase
match:
$userid over 1h
outcome:
$event_count = count_distinct($e.metadata.id)
$risk_score = if($event_count < 10, 20, 40)
$vendor_name = array_distinct($e.metadata.vendor_name)
$product_name = array_distinct($e.metadata.product_name)
$product_severity = array_distinct($e.security_result.severity)
$event_description = array_distinct($e.metadata.description)
$victim_name = array_distinct($e.target.user.userid)
$adversary_name = array_distinct($e.principal.user.userid)
$result_time = min($e.metadata.event_timestamp.seconds)
condition:
$e
}
YARA-L Rule Structure
Condition
Fires when at least one $e event in the 1h window.
Events
$e
metadata.log_type = "SAP_SECURITY_AUDIT"additional.fields["msg_1"] matches "^AU1$|^AU5$"principal.user.userid matches "^DDIC$|^EARLYWATCH$|^SAP\*$|^TMSADM$"
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 |
|---|---|
event_count | count_distinct($e.metadata.id) |
risk_score | if($event_count < 10, 20, 40) |
vendor_name | array_distinct($e.metadata.vendor_name) |
product_name | array_distinct($e.metadata.product_name) |
product_severity | array_distinct($e.security_result.severity) |
event_description | array_distinct($e.metadata.description) |
victim_name | array_distinct($e.target.user.userid) |
adversary_name | array_distinct($e.principal.user.userid) |
result_time | min($e.metadata.event_timestamp.seconds) |
sap brute force rfc logon
#Identifies brute force attacks on SAP systems using RFC logons. Detects a single IP attempting to sign in to several systems or clients within a 1-hour interval, indicating potential credential stuffing or internal lateral movement.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Rule Body
// Copyright 2026 Google LLC. Licensed under Apache-2.0.
rule sap_brute_force_rfc_logon {
meta:
author = "Google Cloud Security"
description = "Identifies brute force attacks on SAP systems using RFC logons. Detects a single IP attempting to sign in to several systems or clients within a 1-hour interval, indicating potential credential stuffing or internal lateral movement."
severity = "Low"
tactic = "TA0001"
technique = "T1110"
events:
$e.metadata.log_type = "SAP_SECURITY_AUDIT"
$e.additional.fields["msg_1"] = /^AU6$|^CUZ$/
$ip = $e.principal.ip
$sid = $e.target.application
$client = $e.target.resource.attribute.labels["slgmand_1"]
match:
$ip over 1h
outcome:
$total_event_count = count($e.metadata.id)
$user_ids_attempted = array_distinct($e.principal.user.userid)
$systems_targeted = array_distinct($sid)
$clients_targeted = array_distinct($client)
$source_ip = array_distinct($ip)
$terminal_names = array_distinct($e.principal.hostname)
$report_names = array_distinct($e.principal.process.file.names)
condition:
#sid >= 2 or #client >= 2
}
YARA-L Rule Structure
Condition
Fires when $sid occurs at least 2 times in the 1h window or $client occurs at least 2 times in the 1h window.
Events
$e
metadata.log_type = "SAP_SECURITY_AUDIT"additional.fields["msg_1"] matches "^AU6$|^CUZ$"
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 |
|---|---|
total_event_count | count($e.metadata.id) |
user_ids_attempted | array_distinct($e.principal.user.userid) |
systems_targeted | array_distinct($sid) |
clients_targeted | array_distinct($client) |
source_ip | array_distinct($ip) |
terminal_names | array_distinct($e.principal.hostname) |
report_names | array_distinct($e.principal.process.file.names) |