Detection rules › YARA-L
YARA-L rules: 32
AWS Password Policy Change
#Detects when an existing password policy is updated or deleted in an AWS account.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Discovery |
Telemetry Coverage
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule aws_password_policy_change {
meta:
author = "Google Cloud Security"
description = "Detects when an existing password policy is updated or deleted in an AWS account."
rule_id = "mr_2e66b918-acfc-46ea-b625-58732558005d"
rule_name = "AWS Password Policy Change"
mitre_attack_tactic = "Discovery"
mitre_attack_technique = "Password Policy Discovery"
mitre_attack_url = "https://attack.mitre.org/techniques/T1201/"
mitre_attack_version = "v13.1"
type = "Alert"
data_source = "AWS CloudTrail"
platform = "AWS"
severity = "Medium"
priority = "Medium"
events:
$cloudtrail.metadata.vendor_name = "AMAZON"
$cloudtrail.metadata.product_name = "AWS CloudTrail"
(
$cloudtrail.metadata.product_event_type = "UpdateAccountPasswordPolicy" or
$cloudtrail.metadata.product_event_type = "DeleteAccountPasswordPolicy"
)
$cloudtrail.security_result.action = "ALLOW"
outcome:
$risk_score = max(50)
$mitre_attack_tactic = "Discovery"
$mitre_attack_technique = "Password Policy Discovery"
$mitre_attack_technique_id = "T1201"
$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
condition:
$cloudtrail
}
YARA-L Rule Structure
Condition
Fires when at least one $cloudtrail event.
Events
$cloudtrail
metadata.product_event_typeis one of:UpdateAccountPasswordPolicyDeleteAccountPasswordPolicy
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(50) |
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 |
DNS Query To Recently Created Domain
#DNS query to a recently created domain
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 22: DNSEvent (DNS query) |
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule dns_query_to_recently_created_domain {
meta:
author = "Google Cloud Security"
description = "DNS query to a recently created domain"
rule_id = "mr_a5cff3f1-8092-48a0-b4a3-f3f856299474"
rule_name = "DNS Query To Recently Created Domain"
type = "alert"
tags = "whois"
data_source = "microsoft sysmon"
severity = "Low"
priority = "Low"
events:
$dns.metadata.event_type = "NETWORK_DNS"
$dns.network.dns.questions.name = $dns_query
$dns.principal.user.userid = $user
// whois data provided by GCTI
$whois.graph.entity.hostname = $dns_query
$whois.graph.metadata.entity_type = "DOMAIN_NAME"
$whois.graph.metadata.vendor_name = "WHOIS"
$whois.graph.entity.domain.creation_time.seconds > 0
// domain was created in the last 30 days
2592000 > timestamp.current_seconds() - $whois.graph.entity.domain.creation_time.seconds
match:
$user over 1h
outcome:
$risk_score = max(35)
$event_count = count_distinct($dns.metadata.id)
$network_dns_questions_name = array_distinct($dns.network.dns.questions.name)
$network_dns_answers_data = array_distinct($dns.network.dns.answers.data)
// added to populate alert graph with additional context
$principal_ip = array_distinct($dns.principal.ip)
$target_ip = array_distinct($dns.target.ip)
$principal_process_pid = array_distinct($dns.principal.process.pid)
$principal_process_file_full_path = array_distinct($dns.principal.process.file.full_path)
$principal_process_product_specific_process_id = array_distinct($dns.principal.process.product_specific_process_id)
$principal_process_command_line = array_distinct($dns.principal.process.command_line)
$principal_process_file_sha256 = array_distinct($dns.principal.process.file.sha256)
$principal_process_parent_process_product_specific_process_id = array_distinct($dns.principal.process.parent_process.product_specific_process_id)
// Commented out principal.user.userid because it is already represented in graph as match variable. If match changes, can uncomment to add to results
//$principal_user_userid = array_distinct($dns.principal.user.userid)
condition:
$dns and $whois
}
YARA-L Rule Structure
Condition
Fires when at least one $dns event in the 1h window and $whois matches entity context.
Events
$dns
$whois
graph.metadata.entity_type = "DOMAIN_NAME"graph.metadata.vendor_name = "WHOIS"graph.entity.domain.creation_time.seconds > "0"timestamp.current_seconds() time_arithmetic "graph.entity.domain.creation_time.seconds" or "2592000"
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($dns.metadata.id) |
network_dns_questions_name | array_distinct($dns.network.dns.questions.name) |
network_dns_answers_data | array_distinct($dns.network.dns.answers.data) |
principal_ip | array_distinct($dns.principal.ip) |
target_ip | array_distinct($dns.target.ip) |
principal_process_pid | array_distinct($dns.principal.process.pid) |
principal_process_file_full_path | array_distinct($dns.principal.process.file.full_path) |
principal_process_product_specific_process_id | array_distinct($dns.principal.process.product_specific_process_id) |
principal_process_command_line | array_distinct($dns.principal.process.command_line) |
principal_process_file_sha256 | array_distinct($dns.principal.process.file.sha256) |
principal_process_parent_process_product_specific_process_id | array_distinct($dns.principal.process.parent_process.product_specific_process_id) |
GitHub Enterprise Deleted
#Detects when a GitHub enterprise is deleted.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Impact |
References
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| GitHub | Audit log action business.delete: Enterprise deleted |
Rule Body
// Copyright 2024 Google LLC. Licensed under Apache-2.0.
rule github_enterprise_deleted {
meta:
author = "Google Cloud Security"
description = "Detects when a GitHub enterprise is deleted."
rule_id = "mr_6443a51b-c381-4504-9b45-9d8b5e9531d7"
rule_name = "GitHub Enterprise Deleted"
assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization"
type = "alert"
severity = "High"
priority = "High"
platform = "GitHub"
data_source = "github"
mitre_attack_tactic = "Impact"
mitre_attack_technique = "Data Destruction"
mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1485/"
mitre_attack_version = "v14"
reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise"
events:
$github.metadata.vendor_name = "GITHUB" nocase
$github.metadata.product_name = "GITHUB"
$github.metadata.product_event_type = "business.delete"
$github.principal.user.userid = $user_id
$github.target.user.company_name = $github_enterprise_name
match:
$user_id, $github_enterprise_name over 30m
outcome:
$risk_score = max(85)
$mitre_attack_tactic = "Impact"
$mitre_attack_technique = "Data Destruction"
$mitre_attack_technique_id = "T1485"
$event_count = count_distinct($github.metadata.id)
$principal_ip = array_distinct($github.principal.ip)
$principal_user_userid = array_distinct($github.principal.user.userid)
$principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region)
$principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state)
$principal_ip_city = array_distinct($github.principal.location.city)
$security_result_summary = array_distinct($github.security_result.summary)
condition:
$github
}
YARA-L Rule Structure
Condition
Fires when at least one $github event in the 30m window.
Events
$github
metadata.product_event_type = "business.delete"
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(85) |
event_count | count_distinct($github.metadata.id) |
principal_ip | array_distinct($github.principal.ip) |
principal_user_userid | array_distinct($github.principal.user.userid) |
principal_ip_country | array_distinct($github.principal.ip_geo_artifact.location.country_or_region) |
principal_ip_state | array_distinct($github.principal.ip_geo_artifact.location.state) |
principal_ip_city | array_distinct($github.principal.location.city) |
security_result_summary | array_distinct($github.security_result.summary) |
GitHub Outgoing Repository Transfer Initiated
#Detects when a GitHub repository is transferred.
References
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| GitHub | Audit log action repo.transfer_outgoing: Repository transferred to another network |
Rules Detecting the Same Action
These rules filter on the same operation.
- Github Repository Transfer (Panther)
- Github Repository/Organization Transferred (Sigma)
Rule Body
// Copyright 2024 Google LLC. Licensed under Apache-2.0.
rule github_outgoing_repository_transfer_initiated {
meta:
author = "Google Cloud Security"
description = "Detects when a GitHub repository is transferred."
rule_id = "mr_28486f60-1be2-467c-a3e6-6105491c3226"
rule_name = "GitHub Outgoing Repository Transfer Initiated"
assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization"
type = "alert"
severity = "High"
priority = "High"
platform = "GitHub"
data_source = "github"
reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise"
events:
$github.metadata.vendor_name = "GITHUB" nocase
$github.metadata.product_name = "GITHUB"
$github.metadata.product_event_type = "repo.transfer_outgoing"
$github.principal.user.userid = $user_id
$github.target.resource.name = $github_repo_name
match:
$user_id, $github_repo_name over 30m
outcome:
$risk_score = max(85)
$event_count = count_distinct($github.metadata.id)
$principal_ip = array_distinct($github.principal.ip)
$principal_user_userid = array_distinct($github.principal.user.userid)
$principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region)
$principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state)
$principal_ip_city = array_distinct($github.principal.location.city)
$security_result_summary = array_distinct($github.security_result.summary)
condition:
$github
}
YARA-L Rule Structure
Condition
Fires when at least one $github event in the 30m window.
Events
$github
metadata.product_event_type = "repo.transfer_outgoing"
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(85) |
event_count | count_distinct($github.metadata.id) |
principal_ip | array_distinct($github.principal.ip) |
principal_user_userid | array_distinct($github.principal.user.userid) |
principal_ip_country | array_distinct($github.principal.ip_geo_artifact.location.country_or_region) |
principal_ip_state | array_distinct($github.principal.ip_geo_artifact.location.state) |
principal_ip_city | array_distinct($github.principal.location.city) |
security_result_summary | array_distinct($github.security_result.summary) |
MITRE ATT&CK T1090 Port Proxy Forwarding CISA Report
#Detects port forwarding being enabled using netsh command and registry settings created or modified in support of portproxy v4tov4
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
References
Telemetry Coverage
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule port_proxy_forwarding_T1090_cisa_report {
meta:
author = "Google Cloud Security"
description = "Detects port forwarding being enabled using netsh command and registry settings created or modified in support of portproxy v4tov4"
rule_id = "mr_4c6f2d66-ed6f-4dda-bd2f-7c545898468b"
rule_name = "MITRE ATT&CK T1090 Port Proxy Forwarding CISA Report"
type = "hunt"
platform = "Windows"
data_source = "microsoft sysmon, windows event log"
tactic = "TA0011"
technique = "T1090"
reference = "https://media.defense.gov/2023/May/24/2003229517/-1/-1/0/CSA_Living_off_the_Land.PDF"
severity = "Low"
priority = "Low"
events:
(
$process.metadata.event_type = "PROCESS_LAUNCH" and
// cisa report referenced cmd /c in their report throughout, can filter this in/out for tuning as needed
re.regex($process.target.process.command_line, `(|cmd.*/c).*netsh.*interface.*portproxy.*add.*v4tov4`) nocase
// For greater precision to align with the report, comment out the above line and uncomment the below line to incorporate exact ports referenced
//re.regex($process.target.process.command_line, `(|cmd.*/c).*netsh.*interface.*portproxy.*add.*v4tov4.*port\=(9999|50100).*port\=(8443|1433)`) nocase
)
or
(
// Looks for the actual registry creation or modification that would accompany portproxy command executing
(
$process.metadata.event_type = "REGISTRY_CREATION" or
$process.metadata.event_type = "REGISTRY_MODIFICATION"
) and
$process.target.registry.registry_key = "HKLM\\System\\CurrentControlSet\\Services\\PortProxy\\v4tov4"
)
$process.principal.hostname = $hostname
match:
$hostname over 5m
outcome:
$risk_score = 35
$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)
$principal_user_userid = array_distinct($process.principal.user.userid)
condition:
$process
}
YARA-L Rule Structure
Condition
Fires when at least one $process event in the 5m window.
Events
$process
target.process.command_line matches "(|cmd.*/c).*netsh.*interface.*portproxy.*add.*v4tov4"target.registry.registry_key = "HKLM\System\CurrentControlSet\Services\PortProxy\v4tov4"
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($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) |
principal_user_userid | array_distinct($process.principal.user.userid) |
MITRE ATT&CK T1570 Suspicious Command PSExec
#Command-line execution of the PsExec tool on Windows
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Lateral Movement |
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 2023 Google LLC. Licensed under Apache-2.0.
rule mitre_attack_T1570_suspicious_command_psexec {
meta:
author = "Google Cloud Security"
description = "Command-line execution of the PsExec tool on Windows"
rule_id = "mr_b1c34e7b-79c2-4d44-a105-d8166f6fd2c5"
rule_name = "MITRE ATT&CK T1570 Suspicious Command PSExec"
tactic = "TA0008"
technique = "T1570"
type = "alert"
platform = "Windows"
data_source = "sentinelone"
severity = "Info"
priority = "Info"
events:
$process.metadata.event_type = "PROCESS_LAUNCH"
$process.principal.hostname = $hostname
re.regex($process.principal.process.command_line, `psexec`) nocase
match:
$hostname over 5m
outcome:
$risk_score = 15
$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)
$principal_user_userid = array_distinct($process.principal.user.userid)
condition:
$process
}
YARA-L Rule Structure
Condition
Fires when at least one $process event in the 5m window.
Events
$process
principal.process.command_line matches "psexec"
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 | 15 |
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) |
principal_user_userid | array_distinct($process.principal.user.userid) |