Detection rules › YARA-L
YARA-L rules: 1e
GitHub User Blocked From Accessing Organization Repositories
#Detects when a user is blocked from accessing repositories within a GitHub organization.
References
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| GitHub | Audit log action org.block_user: User blocked from organization repositories |
Rules Detecting the Same Action
These rules filter on the same operation.
- GitHub - User was blocked (Kusto)
- GitHub User Blocked From Organization (Elastic)
Rule Body
// Copyright 2024 Google LLC. Licensed under Apache-2.0.
rule github_user_blocked_from_accessing_organization_repositories {
meta:
author = "Google Cloud Security"
description = "Detects when a user is blocked from accessing repositories within a GitHub organization."
rule_id = "mr_f422422c-7a15-47da-accd-b499b8d0b33f"
rule_name = "GitHub User Blocked From Accessing Organization Repositories"
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 = "Low"
priority = "Low"
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 = "org.block_user"
$github.principal.user.userid = $actor_user_id
$github.extracted.fields["blocked_user"] = $target_user_id
match:
$actor_user_id, $target_user_id over 30m
outcome:
$risk_score = max(35)
$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 = "org.block_user"
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($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) |
Okta User Password and MFA Factor Reset or Deactivated
#Detects when an Okta user's password is reset and MFA factor(s) are deactivated or reset within a 30 minute time window. This activity may indicate that the user account has been compromised.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Credential Access |
References
Telemetry Coverage
Rules Detecting the Same Action
These rules filter on the same operation.
- Attempt to Reset MFA Factors for an Okta User Account (Elastic)
- MFA Deactivation with no Re-Activation for Okta User Account (Elastic)
- New Device/Location sign-in along with critical operation (Kusto)
- Okta Investigate MFA and Password resets (Panther)
- Okta MFA Reset or Deactivated (Sigma)
- Okta Multi-Factor Authentication Disabled (Splunk)
- Okta Support Reset Credential (Panther)
- Okta User MFA Reset All (Panther)
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule okta_user_password_and_mfa_factor_reset_or_deactivated {
meta:
author = "Drew Pilarski - Tempus AI"
description = "Detects when an Okta user's password is reset and MFA factor(s) are deactivated or reset within a 30 minute time window. This activity may indicate that the user account has been compromised."
rule_id = "mr_a4344fef-2310-4fed-8f3a-8e76237cfc1f"
rule_name = "Okta User Password and MFA Factor Reset or Deactivated"
reference = "https://developer.okta.com/docs/reference/api/event-types/"
mitre_attack_tactic = "Credential Access, Defense Evasion, Persistence"
mitre_attack_technique = "Modify Authentication Process: Multi-Factor Authentication"
mitre_attack_url = "https://attack.mitre.org/techniques/T1556/006/"
type = "Alert"
platform = "Okta"
data_source = "Okta"
severity = "Medium"
priority = "Medium"
events:
$pw.metadata.product_name = "Okta"
$pw.metadata.vendor_name = "Okta"
(
$pw.metadata.product_event_type = "user.mfa.factor.reset_all" OR
$pw.metadata.product_event_type = "user.mfa.factor.deactivate"
)
$user_id = $pw.target.user.product_object_id
$mfa.metadata.product_name = "Okta"
$mfa.metadata.vendor_name = "Okta"
$mfa.metadata.product_event_type = "user.account.reset_password"
$user_id = $mfa.target.user.product_object_id
match:
$user_id over 30m
outcome:
$principal_user_email = array_distinct($pw.principal.user.email_addresses)
$principal_ip = array_distinct($pw.principal.ip)
$risk_score = 65
$mitre_attack_tactic = array_distinct("Credential Access, Defense Evasion, Persistence")
$mitre_attack_technique = array_distinct("Modify Authentication Process: Multi-Factor Authentication")
$mitre_attack_technique_id = array_distinct("T1556.006")
condition:
$pw and $mfa
}
YARA-L Rule Structure
Condition
Fires when at least one $pw event in the 30m window and at least one $mfa event in the 30m window.
Events
$mfa
metadata.product_event_type = "user.account.reset_password"
$pw
metadata.product_event_typeis one of:user.mfa.factor.reset_alluser.mfa.factor.deactivate
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 |
|---|---|
principal_user_email | array_distinct($pw.principal.user.email_addresses) |
principal_ip | array_distinct($pw.principal.ip) |
risk_score | 65 |
Process Memory Dump Via Comsvcs.DLL
#Detects a process memory dump via comsvcs.dll using rundll32, covering multiple different techniques
Known False Positives
- Unlikely
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 2025 Google LLC. Licensed under Apache-2.0.
rule process_memory_dump_via_comsvcs_dll {
meta:
author = "Florian Roth (Nextron Systems), Modexp, Nasreddine Bencherchali (Nextron Systems), Swachchhanda Shrawan Poudel (Nextron Systems)"
description = "Detects a process memory dump via comsvcs.dll using rundll32, covering multiple different techniques"
reference = "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/process_creation/proc_creation_win_rundll32_process_dump_via_comsvcs.yml"
license = "https://github.com/SigmaHQ/Detection-Rule-License/blob/main/LICENSE.Detection.Rules.md"
rule_name = "Process Memory Dump Via Comsvcs.DLL"
sigma_uuid = "646ea171-dded-4578-8a4d-65e9822892e3"
sigma_status = "test"
rule_id = "mr_ad21bd09-c624-48c8-a949-a82a40fbb88c"
tactic = "TA0006"
technique = "T1003.001"
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, `\\rundll32\.exe$`) nocase or
$process.src.process.file.full_path = "RUNDLL32.EXE" nocase or
strings.contains(strings.to_lower($process.target.process.command_line), "rundll32")
)
and
(
(
strings.contains(strings.to_lower($process.target.process.command_line), "comsvcs") and
strings.contains(strings.to_lower($process.target.process.command_line), "full")
)
or
(
strings.contains($process.target.process.command_line, "#-") or
strings.contains($process.target.process.command_line, "#+") or
strings.contains($process.target.process.command_line, "#24") or
strings.contains(strings.to_lower($process.target.process.command_line), "minidump")
)
)
)
or
(
(
strings.contains($process.target.process.command_line, "24") and
strings.contains(strings.to_lower($process.target.process.command_line), "comsvcs") and
strings.contains(strings.to_lower($process.target.process.command_line), "full")
)
and
(
strings.contains($process.target.process.command_line, " #") or
strings.contains($process.target.process.command_line, ",#") or
strings.contains($process.target.process.command_line, ", #")
)
)
)
$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 "\\rundll32\.exe$"src.process.file.full_path = "RUNDLL32.EXE"target.process.command_line contains "rundll32"target.process.command_line contains "comsvcs"target.process.command_line contains "full"target.process.command_line contains "#-"target.process.command_line contains "#+"target.process.command_line contains "#24"target.process.command_line contains "minidump"target.process.command_line contains "24"target.process.command_line contains "comsvcs"target.process.command_line contains "full"target.process.command_line contains " #"target.process.command_line contains ",#"target.process.command_line contains ", #"
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)) |
sap impossible travel
#Identifies two successful logons for the same User ID from two different geographic locations in a timeframe that is physically impossible to travel between, indicating credential sharing or theft.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Persistence | |
| Privilege Escalation | |
| Stealth |
Telemetry Coverage
Rule Body
// Copyright 2026 Google LLC. Licensed under Apache-2.0.
rule sap_impossible_travel {
meta:
author = "Google Cloud Security"
description = "Identifies two successful logons for the same User ID from two different geographic locations in a timeframe that is physically impossible to travel between, indicating credential sharing or theft."
severity = "medium"
tactic = "TA0006"
technique = "T1078"
events:
$e.metadata.log_type = "SAP_SECURITY_AUDIT"
(
$e.metadata.event_type = "USER_LOGIN" or
$e.additional.fields["msg_1"] = /^AU1$|^AU5$/
)
$e.principal.ip_geo_artifact.location.country_or_region != ""
$country = $e.principal.ip_geo_artifact.location.country_or_region
$state = $e.principal.ip_geo_artifact.location.state
$user = $e.principal.user.userid
match:
$user over 1h
outcome:
$countries = array_distinct($country)
$states = array_distinct($state)
$count_of_countries = count_distinct($country)
$count_of_states = count_distinct($state)
$risk_score = if(count_distinct($country) > 1, 30, 0) + if(count_distinct($state) > 2, 30, 0) + 30
$network_carrier_name = array_distinct($e.principal.ip_geo_artifact.network.carrier_name)
$networn_dns_domain = array_distinct($e.principal.ip_geo_artifact.network.dns_domain)
$network_org = array_distinct($e.principal.ip_geo_artifact.network.organization_name)
$sap_instance = array_distinct($e.target.resource.name)
condition:
#country >= 2 or #state >= 2
}
YARA-L Rule Structure
Condition
Fires when $country occurs at least 2 times in the 1h window or $state occurs at least 2 times in the 1h window.
Events
$e
metadata.log_type = "SAP_SECURITY_AUDIT"additional.fields["msg_1"] matches "^AU1$|^AU5$"principal.ip_geo_artifact.location.country_or_region is not null
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 |
|---|---|
countries | array_distinct($country) |
states | array_distinct($state) |
count_of_countries | count_distinct($country) |
count_of_states | count_distinct($state) |
risk_score | if(count_distinct($country) > 1, 30, 0) + if(count_distinct($state) > 2, 30, 0) + 30 |
network_carrier_name | array_distinct($e.principal.ip_geo_artifact.network.carrier_name) |
networn_dns_domain | array_distinct($e.principal.ip_geo_artifact.network.dns_domain) |
network_org | array_distinct($e.principal.ip_geo_artifact.network.organization_name) |
sap_instance | array_distinct($e.target.resource.name) |