Detection rules › YARA-L
YARA-L rules: 16
GitHub Secret Scanning Alert
#Detects when a secret is found in a GitHub repository. Adversaries may attempt to harvest leaked/exposed secrets to further infiltrate their target's environment, maintain access, or steal data.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
References
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| GitHub | Audit log action secret_scanning_alert.create: Secret scanning alert created |
Rules Detecting the Same Action
These rules filter on the same operation.
- GitHub Secret Scanning Alert Created (Panther)
Rule Body
// Copyright 2024 Google LLC. Licensed under Apache-2.0.
rule github_secret_scanning_alert {
meta:
author = "Google Cloud Security"
description = "Detects when a secret is found in a GitHub repository. Adversaries may attempt to harvest leaked/exposed secrets to further infiltrate their target's environment, maintain access, or steal data."
rule_id = "mr_7cd99259-68ef-4b09-96a5-3130f44664b5"
rule_name = "GitHub Secret Scanning Alert"
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 = "Credential Access"
mitre_attack_technique = "Unsecured Credentials"
mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1552/"
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 = "secret_scanning_alert.create"
outcome:
$risk_score = max(85)
$mitre_attack_tactic = "Credential Access"
$mitre_attack_technique = "Unsecured Credentials"
$mitre_attack_technique_id = "T1552"
$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.
Events
$github
metadata.product_event_type = "secret_scanning_alert.create"
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) |
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) |
Hunt for successful group creation in the Microsoft Graph API
#Identify a successful group creation. Triggered through the use of GraphRunner's Invoke-SecurityGroupCloner function.
References
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule ms_graph_group_creation_success {
meta:
author = "Google Cloud Security"
description = "Identify a successful group creation. Triggered through the use of GraphRunner's Invoke-SecurityGroupCloner function."
rule_id = "mr_04b3df2c-470f-4b4d-9382-cdbe0539e5ec"
rule_name = "Hunt for successful group creation in the Microsoft Graph API"
assumption = "This detects all web activity associated with the groups endpoint with a response code 201, normal admin actions could trigger as well. Tune using IP address ranges for admins and user agents."
reference = "https://github.com/dafthack/GraphRunner/blob/main/GraphRunner.ps1"
type = "Hunt"
data_source = "MS Graph Activity Logs"
platform = "Azure"
severity = "Low"
priority = "Low"
events:
$api.metadata.event_type = "NETWORK_HTTP"
$api.metadata.product_event_type = "Microsoft Graph Activity"
$api.target.url = "https://graph.microsoft.com/v1.0/groups" nocase
$api.network.http.method = "POST"
$api.network.http.response_code = 201
//Can be tuned for specific User Agent strings being used - by default GraphRunner does not forge the UA for this action
//$api.network.http.user_agent = /PowerShell/ nocase
$api.principal.ip = $ip
$api.network.session_id = $session
match:
$ip, $session over 5m
outcome:
$risk_score = 35
$event_count = count_distinct($api.metadata.id)
$requesting_user_guid = array_distinct($api.principal.user.userid)
$requesting_ip = array_distinct($api.principal.ip)
$user_agent = array_distinct($api.network.http.user_agent)
$location = array_distinct($api.principal.location.name)
$target_application_id_guid = array_distinct($api.target.resource.product_object_id)
$session_id = array_distinct($api.network.session_id)
$target_url = array_distinct($api.target.url)
condition:
$api
}
YARA-L Rule Structure
Condition
Fires when at least one $api event in the 5m window.
Events
$api
metadata.product_event_type = "Microsoft Graph Activity"target.url = "https://graph.microsoft.com/v1.0/groups"network.http.method = "POST"network.http.response_code = "201"
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($api.metadata.id) |
requesting_user_guid | array_distinct($api.principal.user.userid) |
requesting_ip | array_distinct($api.principal.ip) |
user_agent | array_distinct($api.network.http.user_agent) |
location | array_distinct($api.principal.location.name) |
target_application_id_guid | array_distinct($api.target.resource.product_object_id) |
session_id | array_distinct($api.network.session_id) |
target_url | array_distinct($api.target.url) |
IOC IP Target
#Detect network events that indicate communication to a watchlisted IP address
Telemetry Coverage
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule ioc_ip_target {
meta:
author = "Google Cloud Security"
description = "Detect network events that indicate communication to a watchlisted IP address"
rule_id = "mr_cb71b798-5931-47a9-8572-8166db41fc5c"
rule_name = "IOC IP Target"
type = "alert"
tags = "threat indicators"
assumption = "Assumes MISP data has been ingested into entity graph; this rule can be modified to utilize other TI indicators"
data_source = "microsoft windows events"
severity = "Medium"
priority = "Medium"
events:
$network.metadata.event_type = "NETWORK_CONNECTION"
$network.target.ip = $ip
//Target IP is not part of RFC1918 space, can modify as needed
not net.ip_in_range_cidr($network.target.ip, "10.0.0.0/24")
not net.ip_in_range_cidr($network.target.ip, "172.16.0.0/12")
not net.ip_in_range_cidr($network.target.ip, "192.168.0.0/16")
// Correlates with MISP data; can be modified based on your MISP parser or other TI
$ioc.graph.metadata.product_name = "MISP"
$ioc.graph.metadata.entity_type = "IP_ADDRESS"
$ioc.graph.metadata.source_type = "ENTITY_CONTEXT"
$ioc.graph.entity.ip = $ip
match:
$ip over 5m
outcome:
$risk_score = 65
$event_count = count_distinct($network.metadata.id)
// added to populate alert graph with additional context
$principal_ip = array_distinct($network.principal.ip)
// Commented out target.ip because it is already represented in graph as match variable. If match changes, can uncomment to add to results
//$target_ip = array_distinct($network.target.ip)
$principal_process_pid = array_distinct($network.principal.process.pid)
$principal_process_command_line = array_distinct($network.principal.process.command_line)
$principal_process_file_sha256 = array_distinct($network.principal.process.file.sha256)
$principal_process_file_full_path = array_distinct($network.principal.process.file.full_path)
$principal_process_product_specific_process_id = array_distinct($network.principal.process.product_specific_process_id)
$principal_process_parent_process_product_specific_process_id = array_distinct($network.principal.process.parent_process.product_specific_process_id)
$target_process_pid = array_distinct($network.target.process.pid)
$target_process_command_line = array_distinct($network.target.process.command_line)
$target_process_file_sha256 = array_distinct($network.target.process.file.sha256)
$target_process_file_full_path = array_distinct($network.target.process.file.full_path)
$target_process_product_specific_process_id = array_distinct($network.target.process.product_specific_process_id)
$target_process_parent_process_product_specific_process_id = array_distinct($network.target.process.parent_process.product_specific_process_id)
$principal_user_userid = array_distinct($network.principal.user.userid)
$target_user_userid = array_distinct($network.target.user.userid)
condition:
$network and $ioc
}
YARA-L Rule Structure
Condition
Fires when at least one $network event in the 5m window and $ioc matches entity context.
Events
$ioc
graph.metadata.product_name = "MISP"graph.metadata.entity_type = "IP_ADDRESS"graph.metadata.source_type = "ENTITY_CONTEXT"
$network
target.ip cidr_match "10.0.0.0/24"target.ip cidr_match "172.16.0.0/12"target.ip cidr_match "192.168.0.0/16"
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($network.metadata.id) |
principal_ip | array_distinct($network.principal.ip) |
principal_process_pid | array_distinct($network.principal.process.pid) |
principal_process_command_line | array_distinct($network.principal.process.command_line) |
principal_process_file_sha256 | array_distinct($network.principal.process.file.sha256) |
principal_process_file_full_path | array_distinct($network.principal.process.file.full_path) |
principal_process_product_specific_process_id | array_distinct($network.principal.process.product_specific_process_id) |
principal_process_parent_process_product_specific_process_id | array_distinct($network.principal.process.parent_process.product_specific_process_id) |
target_process_pid | array_distinct($network.target.process.pid) |
target_process_command_line | array_distinct($network.target.process.command_line) |
target_process_file_sha256 | array_distinct($network.target.process.file.sha256) |
target_process_file_full_path | array_distinct($network.target.process.file.full_path) |
target_process_product_specific_process_id | array_distinct($network.target.process.product_specific_process_id) |
target_process_parent_process_product_specific_process_id | array_distinct($network.target.process.parent_process.product_specific_process_id) |
principal_user_userid | array_distinct($network.principal.user.userid) |
target_user_userid | array_distinct($network.target.user.userid) |
Recon Credential Theft CISA Report
#Detects suspicious credential access commands as identified in CISA Living off the Land pdf. Alone they may be normal but in concert, they may be worth looking into
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
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 2023 Google LLC. Licensed under Apache-2.0.
rule recon_credential_theft_cisa_report {
meta:
author = "Google Cloud Security"
description = "Detects suspicious credential access commands as identified in CISA Living off the Land pdf. Alone they may be normal but in concert, they may be worth looking into"
rule_id = "mr_90b80326-d559-4e82-b5da-613e5406127a"
rule_name = "Recon Credential Theft CISA Report"
type = "hunt"
platform = "Windows"
data_source = "microsoft sysmon"
tactic = "TA0006"
technique = "T1555"
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"
$process.principal.hostname = $hostname
$process.target.process.command_line = $command_line
// 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).*dir.*C:\\Users\\.*\\.ssh\\known_hosts`) nocase or
re.regex($process.target.process.command_line, `(|cmd.*/c).*dir.*C:\\users\\.*\\appdata\\roaming\\Mozilla\\firefox\\profiles`) nocase or
re.regex($process.target.process.command_line, `(|cmd.*/c).*mimikatz`) nocase or
re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*query.*hklm\\software\\OpenSSH`) nocase or
re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*query.*hklm\\software\\OpenSSH\\Agent`) nocase or
re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*query.*hklm\\software\\realvnc`) nocase or
re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*query.*hklm\\software\\realvnc\\vncserver`) nocase or
re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*query.*hklm\\software\\realvnc\\Allusers`) nocase or
re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*query.*hklm\\software\\realvnc\\Allusers\\vncserver`) nocase or
re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*query.*hkcu\\software\\.*\\putty\\session`) nocase or
re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*save.*hklm\\sam ss.dat`) nocase or
re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*save.*hklm\\system sy.dat`) nocase
)
match:
$hostname over 15m
outcome:
$risk_score = 35
$event_count = count_distinct($process.metadata.id)
$unique_command_line_threshold = max(5)
// 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:
// modify the condition value for command line to throttle how many of these commands can be issued until the rule is triggered
$process and #command_line > 5
}
YARA-L Rule Structure
Condition
Fires when at least one $process event in the 15m window and $command_line occurs more than 5 times in the 15m window.
Events
$process
target.process.command_line matches "(|cmd.*/c).*dir.*C:\\Users\\.*\\.ssh\\known_hosts"target.process.command_line matches "(|cmd.*/c).*dir.*C:\\users\\.*\\appdata\\roaming\\Mozilla\\firefox\\profiles"target.process.command_line matches "(|cmd.*/c).*mimikatz"target.process.command_line matches "(|cmd.*/c).*reg.*query.*hklm\\software\\OpenSSH"target.process.command_line matches "(|cmd.*/c).*reg.*query.*hklm\\software\\OpenSSH\\Agent"target.process.command_line matches "(|cmd.*/c).*reg.*query.*hklm\\software\\realvnc"target.process.command_line matches "(|cmd.*/c).*reg.*query.*hklm\\software\\realvnc\\vncserver"target.process.command_line matches "(|cmd.*/c).*reg.*query.*hklm\\software\\realvnc\\Allusers"target.process.command_line matches "(|cmd.*/c).*reg.*query.*hklm\\software\\realvnc\\Allusers\\vncserver"target.process.command_line matches "(|cmd.*/c).*reg.*query.*hkcu\\software\\.*\\putty\\session"target.process.command_line matches "(|cmd.*/c).*reg.*save.*hklm\\sam ss.dat"target.process.command_line matches "(|cmd.*/c).*reg.*save.*hklm\\system sy.dat"
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) |
unique_command_line_threshold | max(5) |
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) |
Wdigest Enable UseLogonCredential
#Detects potential malicious modification of the property value of UseLogonCredential from HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest to enable clear-text credentials
Known False Positives
- Unknown
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Defense Impairment |
References
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 13: RegistryEvent (Value Set) |
| Security-Auditing | Event ID 4657: A registry value was modified. |
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule wdigest_enable_uselogoncredential {
meta:
author = "Roberto Rodriguez (Cyb3rWard0g), OTR (Open Threat Research)"
description = "Detects potential malicious modification of the property value of UseLogonCredential from HKLM:\\SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\WDigest to enable clear-text credentials"
reference = "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/registry/registry_set/registry_set_wdigest_enable_uselogoncredential.yml"
license = "https://github.com/SigmaHQ/Detection-Rule-License/blob/main/LICENSE.Detection.Rules.md"
rule_name = "Wdigest Enable UseLogonCredential"
rule_id = "mr_b91eeb90-12e0-40f2-878c-a4716fe722bc"
sigma_uuid = "d6a9b252-c666-4de6-8806-5561bbbd3bdc"
sigma_status = "test"
tactic = "TA0005"
technique = "T1112"
type = "Detection"
data_source = "Sysmon Windows Registry"
platform = "Windows"
severity = "High"
priority = "High"
false_positives = "Unknown"
events:
$reg.metadata.event_type = "REGISTRY_MODIFICATION"
re.regex($reg.target.registry.registry_key, `WDigest\\UseLogonCredential$`) nocase
$reg.target.registry.registry_value_data = "DWORD (0x00000001)" nocase
$reg.principal.hostname = $hostname
match:
$hostname over 5m
outcome:
//example usage of specifying test user and hostname to adjust risk score
$risk_score = max(if($reg.principal.user.userid = "user" and $reg.principal.hostname = "hostname", 0, 15))
$principal_hostname = array_distinct($reg.principal.hostname)
$principal_process_pid = array_distinct($reg.principal.process.pid)
$principal_process_file_full_path = array_distinct($reg.principal.process.file.full_path)
$principal_process_product_specific_process_id = array_distinct($reg.principal.process.product_specific_process_id)
$principal_user_userid = array_distinct($reg.principal.user.userid)
$target_registry_key = array_distinct($reg.target.registry.registry_key)
$target_registry_value_data = array_distinct($reg.target.registry.registry_value_data)
$log_type = array_distinct(strings.concat($reg.metadata.log_type,"/",$reg.metadata.product_event_type))
condition:
$reg
}
YARA-L Rule Structure
Condition
Fires when at least one $reg event in the 5m window.
Events
$reg
target.registry.registry_key matches "WDigest\\UseLogonCredential$"target.registry.registry_value_data = "DWORD (0x00000001)"
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($reg.principal.user.userid = "user" and $reg.principal.hostname = "hostname", 0, 15)) |
principal_hostname | array_distinct($reg.principal.hostname) |
principal_process_pid | array_distinct($reg.principal.process.pid) |
principal_process_file_full_path | array_distinct($reg.principal.process.file.full_path) |
principal_process_product_specific_process_id | array_distinct($reg.principal.process.product_specific_process_id) |
principal_user_userid | array_distinct($reg.principal.user.userid) |
target_registry_key | array_distinct($reg.target.registry.registry_key) |
target_registry_value_data | array_distinct($reg.target.registry.registry_value_data) |
log_type | array_distinct(strings.concat($reg.metadata.log_type,"/",$reg.metadata.product_event_type)) |