Detection rules › YARA-L
YARA-L rules: 3f
AWS Backup Plan Deleted
#Detects when AWS Backup Plan is deleted.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Impact |
Telemetry Coverage
Rule Body
// Copyright 2024 Google LLC. Licensed under Apache-2.0.
rule aws_backup_plan_deleted {
meta:
author = "Google Cloud Security"
description = "Detects when AWS Backup Plan is deleted."
rule_id = "mr_ac4b93af-f166-44fa-951d-83f08ded6fd8"
rule_name = "AWS Backup Plan Deleted"
mitre_attack_tactic = "Impact"
mitre_attack_technique = "Inhibit System Recovery"
mitre_attack_url = "https://attack.mitre.org/techniques/T1490/"
mitre_attack_version = "v15.1"
type = "Alert"
data_source = "AWS CloudTrail"
platform = "AWS"
severity = "Low"
priority = "Low"
events:
$cloudtrail.metadata.vendor_name = "AMAZON"
$cloudtrail.metadata.product_name = "AWS CloudTrail"
$cloudtrail.metadata.event_type = "RESOURCE_DELETION"
($cloudtrail.metadata.product_event_type = "DeleteBackupPlan" or
$cloudtrail.metadata.product_event_type = "DeleteBackupSelection")
$cloudtrail.security_result.action = "ALLOW"
outcome:
$risk_score = max(35)
$mitre_attack_tactic = "Impact"
$mitre_attack_technique = "Inhibit System Recovery"
$mitre_attack_technique_id = "T1490"
$event_count = count_distinct($cloudtrail.metadata.id)
$network_http_user_agent = array_distinct($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 = array_distinct($cloudtrail.principal.user.user_display_name)
$recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"])
$aws_region = array_distinct($cloudtrail.principal.location.name)
condition:
$cloudtrail
}
YARA-L Rule Structure
Condition
Fires when at least one $cloudtrail event.
Events
$cloudtrail
metadata.product_event_type = "DeleteBackupPlan" or "DeleteBackupSelection"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(35) |
event_count | count_distinct($cloudtrail.metadata.id) |
network_http_user_agent | array_distinct($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 | array_distinct($cloudtrail.principal.user.user_display_name) |
recipient_aws_account_id | array_distinct($cloudtrail.additional.fields["recipientAccountId"]) |
aws_region | array_distinct($cloudtrail.principal.location.name) |
AWS IAM Activity By S3 Browser Utility
#Detect AWS IAM activities associated with the S3 Browser utility.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence |
References
Telemetry Coverage
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule aws_iam_activity_by_s3_browser_utility {
meta:
author = "Google Cloud Security"
description = "Detect AWS IAM activities associated with the S3 Browser utility."
rule_id = "mr_003e618f-e099-4c72-a170-03d2e03836f9"
rule_name = "AWS IAM Activity By S3 Browser Utility"
reference = "https://permiso.io/blog/s/unmasking-guivil-new-cloud-threat-actor/"
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 = "AWS CloudTrail"
platform = "AWS"
severity = "High"
priority = "High"
events:
$cloudtrail.metadata.vendor_name = "AMAZON"
$cloudtrail.metadata.product_name = "AWS CloudTrail"
$cloudtrail.target.application = "iam.amazonaws.com"
(
$cloudtrail.metadata.product_event_type = "CreateUser" or
$cloudtrail.metadata.product_event_type = "CreateLoginProfile" or
$cloudtrail.metadata.product_event_type = "CreateAccessKey" or
$cloudtrail.metadata.product_event_type = "PutUserPolicy"
)
$cloudtrail.network.http.user_agent = /S3 Browser/
$cloudtrail.security_result.action = "ALLOW"
$cloudtrail.principal.ip = $ip
match:
$ip over 1h
outcome:
$risk_score = max(75)
$mitre_attack_tactic = "Persistence"
$mitre_attack_technique = "Account Manipulation"
$mitre_attack_technique_id = "T1098"
$event_count = count_distinct($cloudtrail.metadata.id)
$network_http_user_agent = array_distinct($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)
$target_user_display_name = array_distinct($cloudtrail.target.user.user_display_name)
$recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"])
$aws_region = array_distinct($cloudtrail.principal.location.name)
$target_resource_name = array_distinct($cloudtrail.target.resource.name)
$target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id)
condition:
$cloudtrail
}
YARA-L Rule Structure
Condition
Fires when at least one $cloudtrail event in the 1h window.
Events
$cloudtrail
target.application = "iam.amazonaws.com"metadata.product_event_typeis one of:CreateUserCreateLoginProfileCreateAccessKeyPutUserPolicy
network.http.user_agent matches "S3 Browser"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 | max(75) |
event_count | count_distinct($cloudtrail.metadata.id) |
network_http_user_agent | array_distinct($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) |
target_user_display_name | array_distinct($cloudtrail.target.user.user_display_name) |
recipient_aws_account_id | array_distinct($cloudtrail.additional.fields["recipientAccountId"]) |
aws_region | array_distinct($cloudtrail.principal.location.name) |
target_resource_name | array_distinct($cloudtrail.target.resource.name) |
target_resource_product_object_id | array_distinct($cloudtrail.target.resource.product_object_id) |
GCP BigQuery Results Downloaded From Multiple Tables
#Detect a user downloads GCP BigQuery results from multiple tables which might indicate data exfiltration activity.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Exfiltration |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| GCP | jobservice.getqueryresults: Get query results |
Rule Body
// Copyright 2024 Google LLC. Licensed under Apache-2.0.
rule gcp_bigquery_results_downloaded_from_multiple_tables {
meta:
author = "Google Cloud Security"
description = "Detect a user downloads GCP BigQuery results from multiple tables which might indicate data exfiltration activity."
rule_id = "mr_dc6b1f68-734d-4b4b-91c2-1675f2422c11"
rule_name = "GCP BigQuery Results Downloaded From Multiple Tables"
mitre_attack_tactic = "Exfiltration"
mitre_attack_technique = "Exfiltration Over Web Service"
mitre_attack_url = "https://attack.mitre.org/techniques/T1567/"
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_ACCESS"
$gcp.metadata.log_type = "GCP_CLOUDAUDIT"
$gcp.metadata.product_event_type = "jobservice.getqueryresults"
$gcp.metadata.product_name = "BigQuery"
$gcp.security_result.action = "ALLOW"
$gcp.principal.user.userid = $user_id
match:
$user_id over 1h
outcome:
$risk_score = max(75)
$mitre_attack_tactic = "Exfiltration"
$mitre_attack_technique = "Exfiltration Over Web Service"
$mitre_attack_technique_id = "T1567"
$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 = array_distinct($gcp.principal.user.userid)
$principal_user_display_name = array_distinct($gcp.principal.user.user_display_name)
$target_resource_name = array_distinct($gcp.target.resource.name)
$event_name = array_distinct($gcp.metadata.product_event_type)
$bq_table_name = array_distinct($gcp.target.resource.name)
$dc_bq_table_name = count_distinct($gcp.target.resource.name)
condition:
$gcp and $dc_bq_table_name > 3
}
YARA-L Rule Structure
Condition
Fires when at least one $gcp event in the 1h window and $dc_bq_table_name > 3.
Events
$gcp
metadata.log_type = "GCP_CLOUDAUDIT"metadata.product_event_type = "jobservice.getqueryresults"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 | 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 | array_distinct($gcp.principal.user.userid) |
principal_user_display_name | array_distinct($gcp.principal.user.user_display_name) |
target_resource_name | array_distinct($gcp.target.resource.name) |
event_name | array_distinct($gcp.metadata.product_event_type) |
bq_table_name | array_distinct($gcp.target.resource.name) |
dc_bq_table_name | count_distinct($gcp.target.resource.name) |
GitHub Invitation Sent To Non Company Email Domain
#Detects when an invitation to join a GitHub enterprise or organization is sent to a non-company email address. This rule can be customized to alert you when a GitHub invitation is sent to an unexpected domain i.e. not one of your company's domains used for email.
References
Telemetry Coverage
Rules Detecting the Same Action
These rules filter on the same operation.
Rule Body
// Copyright 2024 Google LLC. Licensed under Apache-2.0.
rule github_invitation_sent_to_non_company_email_domain {
meta:
author = "Google Cloud Security"
description = "Detects when an invitation to join a GitHub enterprise or organization is sent to a non-company email address. This rule can be customized to alert you when a GitHub invitation is sent to an unexpected domain i.e. not one of your company's domains used for email."
rule_id = "mr_c191df42-006f-485a-b037-f0cbf737bdd4"
rule_name = "GitHub Invitation Sent To Non Company Email Domain"
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 = "business.invite_admin" or
$github.metadata.product_event_type = "business.invite_billing_manager" or
$github.metadata.product_event_type = "org.invite_member"
)
// Filter events based on the invitee's email address. Customize the regex expression to fit your environment i.e. alert on invites sent to domains that are not managed by your company
$github.extracted.fields["invitee_email"] != /@my-company-domain-name\.com/ nocase
$github.extracted.fields["invitee_email"] = $invitee_email
match:
$invitee_email 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_typeis one of:business.invite_adminbusiness.invite_billing_managerorg.invite_member
extracted.fields["invitee_email"] matches "@my-company-domain-name\.com"
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) |
Suspicious Curl.EXE Download
#Detects a suspicious curl process start on Windows and outputs the requested document to a local file
Known False Positives
- Unknown
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_curl_exe_download {
meta:
author = "Florian Roth (Nextron Systems), Nasreddine Bencherchali (Nextron Systems)"
description = "Detects a suspicious curl process start on Windows and outputs the requested document to a local file"
reference = "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/process_creation/proc_creation_win_curl_susp_download.yml"
license = "https://github.com/SigmaHQ/Detection-Rule-License/blob/main/LICENSE.Detection.Rules.md"
rule_name = "Suspicious Curl.EXE Download"
sigma_uuid = "e218595b-bbe7-4ee5-8a96-f32a24ad3468"
sigma_status = "test"
rule_id = "mr_51da61c3-b1c7-4dd1-ad4c-ab5dfc96e075"
tactic = "TA0011"
technique = "T1105"
type = "Detection"
data_source = "Sysmon"
platform = "Windows"
severity = "High"
priority = "High"
false_positives = "Unknown"
events:
$process.metadata.event_type = "PROCESS_LAUNCH"
(
re.regex($process.target.process.file.full_path, `\\curl\.exe$`) nocase or
$process.target.asset.software.description = "The curl executable" nocase
)
(
strings.contains(strings.to_lower($process.target.process.command_line), "%appdata%") or
strings.contains(strings.to_lower($process.target.process.command_line), "%public%") or
strings.contains(strings.to_lower($process.target.process.command_line), "%temp%") or
strings.contains(strings.to_lower($process.target.process.command_line), "%tmp%") or
strings.contains(strings.to_lower($process.target.process.command_line), "\\appdata\\") or
strings.contains(strings.to_lower($process.target.process.command_line), "\\desktop\\") or
strings.contains(strings.to_lower($process.target.process.command_line), "\\temp\\") or
strings.contains(strings.to_lower($process.target.process.command_line), "\\users\\public\\") or
strings.contains(strings.to_lower($process.target.process.command_line), "c:\\perflogs\\") or
strings.contains(strings.to_lower($process.target.process.command_line), "c:\\programdata\\") or
strings.contains(strings.to_lower($process.target.process.command_line), "c:\\windows\\temp\\") or
re.regex($process.target.process.command_line, `\.(dll|gif|jpeg|jpg|png|temp|tmp|txt|vbe|vbs)$`) NOCASE
)
not (
$process.principal.process.file.full_path = "C:\\Program Files\\Git\\usr\\bin\\sh.exe" and
$process.target.process.file.full_path = "C:\\Program Files\\Git\\mingw64\\bin\\curl.exe" and
strings.contains(strings.to_lower($process.target.process.command_line), "--silent --show-error --output ") and
strings.contains(strings.to_lower($process.target.process.command_line), "gfw-httpget-") and
strings.contains(strings.to_lower($process.target.process.command_line), "appdata")
)
$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 "\\curl\.exe$"target.asset.software.description = "The curl executable"target.process.command_line contains "%appdata%"target.process.command_line contains "%public%"target.process.command_line contains "%temp%"target.process.command_line contains "%tmp%"target.process.command_line contains "\appdata\"target.process.command_line contains "\desktop\"target.process.command_line contains "\temp\"target.process.command_line contains "\users\public\"target.process.command_line contains "c:\perflogs\"target.process.command_line contains "c:\programdata\"target.process.command_line contains "c:\windows\temp\"target.process.command_line matches "\.(dll|gif|jpeg|jpg|png|temp|tmp|txt|vbe|vbs)$"principal.process.file.full_path = "C:\Program Files\Git\usr\bin\sh.exe"target.process.file.full_path = "C:\Program Files\Git\mingw64\bin\curl.exe"target.process.command_line contains "--silent --show-error --output "target.process.command_line contains "gfw-httpget-"target.process.command_line contains "appdata"
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)) |