Detection rules › YARA-L

YARA-L rules: 24

Google Workspace Password Policy Changed

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

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

TacticTechniques
Persistence

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_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_type is one of:
    • CREATE_APPLICATION_SETTING
    • CHANGE_APPLICATION_SETTING
  • security_result.category_details = "APPLICATION_SETTINGS"
  • target.resource.name matches "Password Management"

Match and Correlation

Match key
$email (principal.user.email_addresses)
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($ws.metadata.id)
principal_iparray_distinct($ws.principal.ip)
principal_countryarray_distinct($ws.principal.ip_geo_artifact.location.country_or_region)
principal_statearray_distinct($ws.principal.ip_geo_artifact.location.state)
principal_user_emailsarray_distinct($ws.principal.user.email_addresses)
principal_user_idarray_distinct($ws.principal.user.userid)
target_applicationarray_distinct($ws.target.application)
password_policiesarray_distinct($ws.target.resource.name)

MITRE ATT&CK T1110.003 RW Windows Password Spray

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

Detect repeated authentication failure with multiple users indicative of a password spray attack.

MITRE ATT&CK Coverage

TacticTechniques
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 USER_LOGIN (4624, 4625, 4648)

  • security_result.action = "BLOCK"

Match and Correlation

Match key
$hostname (principal.hostname)
Within
30m

Outcome

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

FieldExpression
risk_score65
event_countcount_distinct($login.metadata.id)
user_login_threshold10
target_user_distinct_countcount_distinct($user)
target_user_countcount($user)
tlparray_distinct("amber")
principal_iparray_distinct($login.principal.ip)
target_hostnamearray_distinct($login.target.hostname)
src_hostnamearray_distinct($login.src.hostname)
target_iparray_distinct($login.target.ip)
principal_user_useridarray_distinct($login.principal.user.userid)
target_user_useridarray_distinct($login.target.user.userid)
principal_resource_namearray_distinct($login.principal.resource.name)
target_resource_namearray_distinct($login.target.resource.name)
target_urlarray_distinct($login.target.url)

OneLogin Application Password Revealed

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

Detects when a user revealed another user's application password.

MITRE ATT&CK Coverage

TacticTechniques
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 USER_RESOURCE_ACCESS

  • principal.user.userid cross_field_compare "password.target.user.userid"
  • metadata.product_event_type = "240"

Match and Correlation

Match key
$userid (principal.user.userid)
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(75)
principal_iparray_distinct($password.principal.ip)
principal_ip_countryarray_distinct($password.principal.ip_geo_artifact.location.country_or_region)
principal_ip_statearray_distinct($password.principal.ip_geo_artifact.location.state)
principal_user_useridarray_distinct($password.principal.user.userid)
principal_user_user_display_namearray_distinct($password.principal.user.user_display_name)
target_user_useridarray_distinct($password.target.user.userid)
target_user_user_display_namearray_distinct($password.target.user.user_display_name)
target_applicationarray_distinct($password.target.application)

Suspicious Certreq Command to Download

#
Severity
high
Type
Detection
Time window
5m
Match by
hostname
Author
Christian Burkard (Nextron Systems)
Source
github.com/chronicle/detection-rules

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

TacticTechniques
Command & Control

References

Telemetry Coverage

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 PROCESS_LAUNCH (1, 4688)

  • 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

Match key
$hostname (principal.hostname)
Within
5m

Outcome

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

FieldExpression
risk_scoremax(if($process.principal.user.userid = "user" and $process.principal.hostname = "hostname", 0, 15))
principal_process_pidarray_distinct($process.principal.process.pid)
principal_process_command_linearray_distinct($process.principal.process.command_line)
principal_process_file_sha256array_distinct($process.principal.process.file.sha256)
principal_process_file_full_patharray_distinct($process.principal.process.file.full_path)
principal_process_product_specfic_process_idarray_distinct($process.principal.process.product_specific_process_id)
principal_process_parent_process_product_specfic_process_idarray_distinct($process.principal.process.parent_process.product_specific_process_id)
target_process_pidarray_distinct($process.target.process.pid)
target_process_command_linearray_distinct($process.target.process.command_line)
target_process_file_sha256array_distinct($process.target.process.file.sha256)
target_process_file_full_patharray_distinct($process.target.process.file.full_path)
target_process_product_specfic_process_idarray_distinct($process.target.process.product_specific_process_id)
principal_user_useridarray_distinct($process.principal.user.userid)
log_typearray_distinct(strings.concat($process.metadata.log_type,"/",$process.metadata.product_event_type))

WHOIS Expired Domain Accessed

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

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 NETWORK_HTTP

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

$whois entity context (DOMAIN_NAME)

  • 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

Match key
$hostname (target.hostname)
Within
1h

Outcome

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

FieldExpression
risk_score20
event_countcount_distinct($access.metadata.id)
principal_hostnamearray_distinct($access.principal.hostname)
principal_process_pidarray_distinct($access.principal.process.pid)
principal_process_command_linearray_distinct($access.principal.process.command_line)
principal_process_file_sha256array_distinct($access.principal.process.file.sha256)
principal_process_file_full_patharray_distinct($access.principal.process.file.full_path)
principal_process_product_specific_process_idarray_distinct($access.principal.process.product_specific_process_id)
principal_process_parent_process_product_specific_process_idarray_distinct($access.principal.process.parent_process.product_specific_process_id)
target_process_pidarray_distinct($access.target.process.pid)
target_process_command_linearray_distinct($access.target.process.command_line)
target_process_file_sha256array_distinct($access.target.process.file.sha256)
target_process_file_full_patharray_distinct($access.target.process.file.full_path)
target_process_product_specific_process_idarray_distinct($access.target.process.product_specific_process_id)
target_process_parent_process_product_specific_process_idarray_distinct($access.target.process.parent_process.product_specific_process_id)
principal_user_useridarray_distinct($access.principal.user.userid)
target_user_useridarray_distinct($access.target.user.userid)
target_urlarray_distinct($access.target.url)

Back to all YARA-L rules