Detection rules › YARA-L
YARA-L rules: 24
Google Workspace Password Policy Changed
#Identifies when Google Workspace password policy is changed. Security teams can monitor for changes to password policy configuration that may weaken the organization's security posture.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence |
Telemetry Coverage
Rules Detecting the Same Action
These rules filter on the same operation.
- Application Removed from Blocklist in Google Workspace (Elastic)
- Google Workspace Bitlocker Setting Disabled (Elastic)
- Google Workspace Gmail Routing or Forwarding Rule Created or Modified (Elastic)
- Google Workspace Marketplace Allowlist Configuration (YARA-L)
- Google Workspace Password Policy Modified (Elastic)
- Google Workspace Restrictions for Marketplace Modified to Allow Any App (Elastic)
- GSuite Workspace Gmail Pre-Delivery Message Scanning Disabled (Panther)
- GSuite Workspace Gmail Security Sandbox Disabled (Panther)
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule google_workspace_password_policy_changed {
meta:
author = "Google Cloud Security"
description = "Identifies when Google Workspace password policy is changed. Security teams can monitor for changes to password policy configuration that may weaken the organization's security posture."
rule_id = "mr_fd63a810-800a-4c55-97d2-080fc8a0e567"
rule_name = "Google Workspace Password Policy Changed"
mitre_attack_tactic = "Persistence"
mitre_attack_technique = "Account Manipulation"
mitre_attack_url = "https://attack.mitre.org/techniques/T1098/"
mitre_attack_version = "v13.1"
type = "Alert"
data_source = "Workspace Activity"
severity = "Low"
priority = "Low"
events:
$ws.metadata.vendor_name = "Google Workspace"
$ws.metadata.product_name = "admin"
($ws.metadata.product_event_type = "CREATE_APPLICATION_SETTING" or
$ws.metadata.product_event_type = "CHANGE_APPLICATION_SETTING")
$ws.security_result.category_details = "APPLICATION_SETTINGS"
$ws.target.resource.name = /Password Management/
$ws.principal.user.email_addresses = $email
match:
$email over 1h
outcome:
$risk_score = max(35)
$mitre_attack_tactic = "Persistence"
$mitre_attack_technique = "Account Manipulation"
$mitre_attack_technique_id = "T1098"
$event_count = count_distinct($ws.metadata.id)
$principal_ip = array_distinct($ws.principal.ip)
$principal_country = array_distinct($ws.principal.ip_geo_artifact.location.country_or_region)
$principal_state = array_distinct($ws.principal.ip_geo_artifact.location.state)
$principal_user_emails = array_distinct($ws.principal.user.email_addresses)
$principal_user_id = array_distinct($ws.principal.user.userid)
$target_application =array_distinct($ws.target.application)
$password_policies =array_distinct($ws.target.resource.name)
condition:
$ws
}
YARA-L Rule Structure
Condition
Fires when at least one $ws event in the 1h window.
Events
$ws
metadata.product_event_typeis one of:CREATE_APPLICATION_SETTINGCHANGE_APPLICATION_SETTING
security_result.category_details = "APPLICATION_SETTINGS"target.resource.name matches "Password Management"
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($ws.metadata.id) |
principal_ip | array_distinct($ws.principal.ip) |
principal_country | array_distinct($ws.principal.ip_geo_artifact.location.country_or_region) |
principal_state | array_distinct($ws.principal.ip_geo_artifact.location.state) |
principal_user_emails | array_distinct($ws.principal.user.email_addresses) |
principal_user_id | array_distinct($ws.principal.user.userid) |
target_application | array_distinct($ws.target.application) |
password_policies | array_distinct($ws.target.resource.name) |
MITRE ATT&CK T1110.003 RW Windows Password Spray
#Detect repeated authentication failure with multiple users indicative of a password spray attack.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Telemetry Coverage
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule rw_windows_password_spray_T1110_003 {
meta:
author = "Google Cloud Security"
description = "Detect repeated authentication failure with multiple users indicative of a password spray attack."
rule_id = "mr_5d6c9686-992f-4caf-bf1b-2fec05925c49"
rule_name = "MITRE ATT&CK T1110.003 RW Windows Password Spray"
type = "alert"
data_source = "microsoft windows events"
tactic = "TA0006"
technique = "T1110.003"
platform = "Windows"
severity = "Medium"
priority = "Medium"
events:
$login.metadata.event_type = "USER_LOGIN"
$login.metadata.vendor_name = "Microsoft"
$login.principal.hostname = $hostname
$login.target.user.userid = $user
$login.security_result.action = "BLOCK"
match:
$hostname over 30m
outcome:
$risk_score = 65
$event_count = count_distinct($login.metadata.id)
$user_login_threshold = 10
$target_user_distinct_count = count_distinct($user)
$target_user_count = count($user)
$tlp = array_distinct("amber")
// 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($login.principal.hostname)
$principal_ip = array_distinct($login.principal.ip)
$target_hostname = array_distinct($login.target.hostname)
$src_hostname = array_distinct($login.src.hostname)
$target_ip = array_distinct($login.target.ip)
$principal_user_userid = array_distinct($login.principal.user.userid)
$target_user_userid = array_distinct($login.target.user.userid)
$principal_resource_name = array_distinct($login.principal.resource.name)
$target_resource_name = array_distinct($login.target.resource.name)
$target_url = array_distinct($login.target.url)
condition:
#user > 10
}
YARA-L Rule Structure
Condition
Fires when $user occurs more than 10 times in the 30m window.
Events
$login
security_result.action = "BLOCK"
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($login.metadata.id) |
user_login_threshold | 10 |
target_user_distinct_count | count_distinct($user) |
target_user_count | count($user) |
tlp | array_distinct("amber") |
principal_ip | array_distinct($login.principal.ip) |
target_hostname | array_distinct($login.target.hostname) |
src_hostname | array_distinct($login.src.hostname) |
target_ip | array_distinct($login.target.ip) |
principal_user_userid | array_distinct($login.principal.user.userid) |
target_user_userid | array_distinct($login.target.user.userid) |
principal_resource_name | array_distinct($login.principal.resource.name) |
target_resource_name | array_distinct($login.target.resource.name) |
target_url | array_distinct($login.target.url) |
OneLogin Application Password Revealed
#Detects when a user revealed another user's application password.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
References
Rule Body
// Copyright 2024 Google LLC. Licensed under Apache-2.0.
rule onelogin_application_password_revealed {
meta:
author = "Google Cloud Security"
description = "Detects when a user revealed another user's application password."
rule_id = "mr_785c2d0e-067e-4ad6-a27b-91d0af644718"
rule_name = "OneLogin Application Password Revealed"
reference = "https://onelogin.service-now.com/kb_view_customer.do?sysparm_article=KB0010598"
mitre_attack_tactic = "Credential Access"
mitre_attack_technique = "Unsecured Credentials"
mitre_attack_url = "https://attack.mitre.org/techniques/T1552/"
mitre_attack_version = "v15.1"
type = "Alert"
data_source = "OneLogin"
severity = "High"
priority = "High"
events:
$password.metadata.event_type = "USER_RESOURCE_ACCESS"
$password.metadata.product_name = "ONELOGIN_SSO"
$password.metadata.vendor_name = "ONELOGIN"
$password.principal.user.userid != $password.target.user.userid //different users
$password.metadata.product_event_type = "240" //actor_user revealed password to an app for user
$password.principal.user.userid = $userid
match:
$userid over 1h
outcome:
$risk_score = max(75)
$mitre_attack_tactic = "Credential Access"
$mitre_attack_technique = "Unsecured Credentials"
$principal_ip = array_distinct($password.principal.ip)
$principal_ip_country = array_distinct($password.principal.ip_geo_artifact.location.country_or_region)
$principal_ip_state = array_distinct($password.principal.ip_geo_artifact.location.state)
$principal_user_userid = array_distinct($password.principal.user.userid)
$principal_user_user_display_name = array_distinct($password.principal.user.user_display_name)
$target_user_userid = array_distinct($password.target.user.userid)
$target_user_user_display_name = array_distinct($password.target.user.user_display_name)
$target_application = array_distinct($password.target.application)
condition:
$password
}
YARA-L Rule Structure
Condition
Fires when at least one $password event in the 1h window.
Events
$password
principal.user.userid cross_field_compare "password.target.user.userid"metadata.product_event_type = "240"
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) |
principal_ip | array_distinct($password.principal.ip) |
principal_ip_country | array_distinct($password.principal.ip_geo_artifact.location.country_or_region) |
principal_ip_state | array_distinct($password.principal.ip_geo_artifact.location.state) |
principal_user_userid | array_distinct($password.principal.user.userid) |
principal_user_user_display_name | array_distinct($password.principal.user.user_display_name) |
target_user_userid | array_distinct($password.target.user.userid) |
target_user_user_display_name | array_distinct($password.target.user.user_display_name) |
target_application | array_distinct($password.target.application) |
Suspicious Certreq Command to Download
#Detects a suspicious certreq execution taken from the LOLBAS examples, which can be abused to download (small) files
Known False Positives
- Unlikely
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
References
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 1: Process creation |
| Security-Auditing | Event ID 4688: A new process has been created. |
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule suspicious_certreq_command_to_download {
meta:
author = "Christian Burkard (Nextron Systems)"
description = "Detects a suspicious certreq execution taken from the LOLBAS examples, which can be abused to download (small) files"
reference = "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/process_creation/proc_creation_win_lolbin_susp_certreq_download.yml"
license = "https://github.com/SigmaHQ/Detection-Rule-License/blob/main/LICENSE.Detection.Rules.md"
rule_name = "Suspicious Certreq Command to Download"
sigma_uuid = "4480827a-9799-4232-b2c4-ccc6c4e9e12b"
sigma_status = "test"
rule_id = "mr_c615e9f9-ded5-40ff-a571-7564b67da2e0"
tactic = "TA0011"
technique = "T1105"
type = "Detection"
data_source = "Sysmon"
platform = "Windows"
severity = "High"
priority = "High"
false_positives = "Unlikely"
events:
$process.metadata.event_type = "PROCESS_LAUNCH"
(
re.regex($process.target.process.file.full_path, `\\certreq\.exe$`) nocase or
$process.src.process.file.full_path = "certreq.exe" nocase
)
(
strings.contains(strings.to_lower($process.target.process.command_line), " -post ") and
strings.contains(strings.to_lower($process.target.process.command_line), " -config ") and
strings.contains(strings.to_lower($process.target.process.command_line), " http") and
strings.contains(strings.to_lower($process.target.process.command_line), " c:\\windows\\win.ini ")
)
$process.principal.hostname = $hostname
match:
$hostname over 5m
outcome:
//example usage of specifying test user and hostname to adjust risk score
$risk_score = max(if($process.principal.user.userid = "user" and $process.principal.hostname = "hostname", 0, 15))
$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_specfic_process_id = array_distinct($process.principal.process.product_specific_process_id)
$principal_process_parent_process_product_specfic_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_specfic_process_id = array_distinct($process.target.process.product_specific_process_id)
$principal_user_userid = array_distinct($process.principal.user.userid)
$log_type = array_distinct(strings.concat($process.metadata.log_type,"/",$process.metadata.product_event_type))
condition:
$process
}
YARA-L Rule Structure
Condition
Fires when at least one $process event in the 5m window.
Events
$process
target.process.file.full_path matches "\\certreq\.exe$"src.process.file.full_path = "certreq.exe"target.process.command_line contains " -post "target.process.command_line contains " -config "target.process.command_line contains " http"target.process.command_line contains " c:\windows\win.ini "
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(if($process.principal.user.userid = "user" and $process.principal.hostname = "hostname", 0, 15)) |
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_specfic_process_id | array_distinct($process.principal.process.product_specific_process_id) |
principal_process_parent_process_product_specfic_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_specfic_process_id | array_distinct($process.target.process.product_specific_process_id) |
principal_user_userid | array_distinct($process.principal.user.userid) |
log_type | array_distinct(strings.concat($process.metadata.log_type,"/",$process.metadata.product_event_type)) |
WHOIS Expired Domain Accessed
#Example usage of WHOIS data, detecting an executable file download from a domain that's recently expired
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule whois_expired_domain_accessed {
meta:
author = "Google Cloud Security"
description = "Example usage of WHOIS data, detecting an executable file download from a domain that's recently expired"
rule_id = "mr_7b487c4f-cbf9-4b11-8b25-632ada3f90a3"
rule_name = "WHOIS Expired Domain Accessed"
type = "alert"
tags = "whois"
data_source = "zscalar"
severity = "Low"
priority = "Low"
events:
$access.metadata.event_type = "NETWORK_HTTP"
$access.target.hostname = $hostname
// join access event to entity graph to use WHOIS data
$whois.graph.entity.domain.name = $hostname
// Whois domains provided by GCTI Feed
$whois.graph.metadata.entity_type = "DOMAIN_NAME"
$whois.graph.metadata.vendor_name = "WHOIS"
$whois.graph.metadata.product_name = "WHOISXMLAPI Simple Whois"
$whois.graph.metadata.source_type = "GLOBAL_CONTEXT"
// Filter out domains without expiration time
$whois.graph.entity.domain.expiration_time.seconds > 0
// Domain expired before the event
$whois.graph.entity.domain.expiration_time.seconds < $access.metadata.event_timestamp.seconds
match:
$hostname over 1h
outcome:
$risk_score = 20
$event_count = count_distinct($access.metadata.id)
//added to populate alert graph with additional context
$principal_hostname = array_distinct($access.principal.hostname)
// Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results
//$target_hostname = array_distinct($access.target.hostname)
$principal_process_pid = array_distinct($access.principal.process.pid)
$principal_process_command_line = array_distinct($access.principal.process.command_line)
$principal_process_file_sha256 = array_distinct($access.principal.process.file.sha256)
$principal_process_file_full_path = array_distinct($access.principal.process.file.full_path)
$principal_process_product_specific_process_id = array_distinct($access.principal.process.product_specific_process_id)
$principal_process_parent_process_product_specific_process_id = array_distinct($access.principal.process.parent_process.product_specific_process_id)
$target_process_pid = array_distinct($access.target.process.pid)
$target_process_command_line = array_distinct($access.target.process.command_line)
$target_process_file_sha256 = array_distinct($access.target.process.file.sha256)
$target_process_file_full_path = array_distinct($access.target.process.file.full_path)
$target_process_product_specific_process_id = array_distinct($access.target.process.product_specific_process_id)
$target_process_parent_process_product_specific_process_id = array_distinct($access.target.process.parent_process.product_specific_process_id)
$principal_user_userid = array_distinct($access.principal.user.userid)
$target_user_userid = array_distinct($access.target.user.userid)
$target_url = array_distinct($access.target.url)
condition:
$access and $whois
}
YARA-L Rule Structure
Condition
Fires when at least one $access event in the 1h window and $whois matches entity context.
Events
$access
$whois
graph.metadata.entity_type = "DOMAIN_NAME"graph.metadata.vendor_name = "WHOIS"graph.metadata.product_name = "WHOISXMLAPI Simple Whois"graph.metadata.source_type = "GLOBAL_CONTEXT"graph.entity.domain.expiration_time.seconds > "0"graph.entity.domain.expiration_time.seconds cross_field_compare "access.metadata.event_timestamp.seconds"
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 | 20 |
event_count | count_distinct($access.metadata.id) |
principal_hostname | array_distinct($access.principal.hostname) |
principal_process_pid | array_distinct($access.principal.process.pid) |
principal_process_command_line | array_distinct($access.principal.process.command_line) |
principal_process_file_sha256 | array_distinct($access.principal.process.file.sha256) |
principal_process_file_full_path | array_distinct($access.principal.process.file.full_path) |
principal_process_product_specific_process_id | array_distinct($access.principal.process.product_specific_process_id) |
principal_process_parent_process_product_specific_process_id | array_distinct($access.principal.process.parent_process.product_specific_process_id) |
target_process_pid | array_distinct($access.target.process.pid) |
target_process_command_line | array_distinct($access.target.process.command_line) |
target_process_file_sha256 | array_distinct($access.target.process.file.sha256) |
target_process_file_full_path | array_distinct($access.target.process.file.full_path) |
target_process_product_specific_process_id | array_distinct($access.target.process.product_specific_process_id) |
target_process_parent_process_product_specific_process_id | array_distinct($access.target.process.parent_process.product_specific_process_id) |
principal_user_userid | array_distinct($access.principal.user.userid) |
target_user_userid | array_distinct($access.target.user.userid) |
target_url | array_distinct($access.target.url) |