Detection rules › YARA-L
YARA-L rules: 0h
GitHub User Unblocked From Accessing Organization Repositories
#Detects when a user is unblocked from accessing repositories within a GitHub organization.
References
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| GitHub | Audit log action org.unblock_user: User unblocked from organization |
Rule Body
// Copyright 2024 Google LLC. Licensed under Apache-2.0.
rule github_user_unblocked_from_accessing_organization_repositories {
meta:
author = "Google Cloud Security"
description = "Detects when a user is unblocked from accessing repositories within a GitHub organization."
rule_id = "mr_3a6905e8-e5e1-40af-b911-52bc4918d2ba"
rule_name = "GitHub User Unblocked 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.unblock_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.unblock_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) |
IOC Domain C2
#Detect DNS events that indicate communication to a C2 domain in MISP
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 ioc_domain_C2 {
meta:
author = "Google Cloud Security"
description = "Detect DNS events that indicate communication to a C2 domain in MISP"
rule_id = "mr_cb22c45e-b29d-487f-9cf5-1310bfed6d6c"
rule_name = "IOC Domain C2"
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 sysmon"
severity = "High"
priority = "High"
events:
$dns.metadata.event_type = "NETWORK_DNS"
$dns.network.dns.questions.name = $dns_query
// 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 = "DOMAIN_NAME"
$ioc.graph.metadata.source_type = "ENTITY_CONTEXT"
//Summary is used to focus on a specific subset of MISP indicators, can modify as needed
$ioc.graph.metadata.threat.summary = "C2 domains"
$ioc.graph.entity.hostname = $dns_query
match:
$dns_query over 5m
outcome:
$risk_score = 85
$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_user_userid = array_distinct($dns.principal.user.userid)
$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)
condition:
$dns and $ioc
}
YARA-L Rule Structure
Condition
Fires when at least one $dns event in the 5m window and $ioc matches entity context.
Events
$dns
$ioc
graph.metadata.product_name = "MISP"graph.metadata.entity_type = "DOMAIN_NAME"graph.metadata.source_type = "ENTITY_CONTEXT"graph.metadata.threat.summary = "C2 domains"
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 | 85 |
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_user_userid | array_distinct($dns.principal.user.userid) |
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) |
O365 OneDrive Anonymous Link Created or Updated
#Anonymous links can be used to export files from OneDrive. While this isn't always a sign of malicious activity, some organizations do not support the creation of anonymous links because of the risk of data leakage. This rule detects the creation or modification of anonymous links in OneDrive.
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft 365 | AnonymousLinkCreated |
| Microsoft 365 | AnonymousLinkUpdated |
Rules Detecting the Same Action
These rules filter on the same operation.
- Microsoft365 External Document Sharing (Panther)
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule o365_onedrive_anonymous_link_created_updated {
meta:
author = "Google Cloud Security"
description = "Anonymous links can be used to export files from OneDrive. While this isn't always a sign of malicious activity, some organizations do not support the creation of anonymous links because of the risk of data leakage. This rule detects the creation or modification of anonymous links in OneDrive."
rule_id = "mr_3e2572c1-cc14-4c2b-b60b-434db1b0f4ae"
rule_name = "O365 OneDrive Anonymous Link Created or Updated"
type = "hunt"
platform = "azure"
data_source = "o365"
severity = "Medium"
priority = "Medium"
events:
(
(
$file.metadata.event_type = "USER_RESOURCE_CREATION" and
$file.metadata.product_event_type = "AnonymousLinkCreated"
)
or
(
$file.metadata.event_type = "STATUS_UPDATE" and
$file.metadata.product_event_type = "AnonymousLinkUpdated"
)
)
$file.metadata.product_name = "Office 365"
$file.metadata.vendor_name = "Microsoft"
$file.principal.user.userid = $user
match:
$user over 5m
outcome:
$risk_score = 35
$event_count = count_distinct($file.metadata.id)
$referral_url = array_distinct($file.network.http.referral_url)
$user_agent = array_distinct($file.network.http.user_agent)
$principal_application = array_distinct($file.principal.application)
//The IP address for creation is a Microsoft IP address while update is the system making the change
$principal_ip = array_distinct($file.principal.ip)
$target_application = array_distinct($file.target.application)
$principal_user_userid = array_distinct($file.principal.user.userid)
$target_file_full_path = array_distinct($file.target.file.full_path)
$target_url = array_distinct($file.target.url)
condition:
$file
}
YARA-L Rule Structure
Condition
Fires when at least one $file event in the 5m window.
Events
$file
metadata.product_event_type = "AnonymousLinkCreated"metadata.product_event_type = "AnonymousLinkUpdated"
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($file.metadata.id) |
referral_url | array_distinct($file.network.http.referral_url) |
user_agent | array_distinct($file.network.http.user_agent) |
principal_application | array_distinct($file.principal.application) |
principal_ip | array_distinct($file.principal.ip) |
target_application | array_distinct($file.target.application) |
principal_user_userid | array_distinct($file.principal.user.userid) |
target_file_full_path | array_distinct($file.target.file.full_path) |
target_url | array_distinct($file.target.url) |
Office 365 group deletion success
#Detects when a group is deleted.
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft 365 | Delete group. |
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule o365_group_deletion_success {
meta:
author = "Google Cloud Security"
description = "Detects when a group is deleted."
rule_id = "mr_24a45257-b6b5-4b1d-b301-526dc6a17adf"
rule_name = "Office 365 group deletion success"
type = "alert"
platform = "azure"
data_source = "o365"
severity = "Low"
priority = "Low"
events:
$group.metadata.event_type = "GROUP_DELETION"
$group.metadata.product_event_type = "Delete group."
$group.metadata.product_name = "Office 365"
$group.metadata.vendor_name = "Microsoft"
$group.security_result.action = "ALLOW"
$group.principal.user.userid = $user
match:
$user over 5m
outcome:
$risk_score = 35
$event_count = count_distinct($group.metadata.id)
$user_agent = array_distinct($group.network.http.user_agent)
$security_summary = array_distinct($group.security_result.summary)
$target_application = array_distinct($group.target.application)
//$principal_user_userid = array_distinct($group.principal.user.userid)
$group_name = array_distinct($group.target.group.group_display_name)
$group_guid = array_distinct(re.replace($group.security_result.detection_fields["target_2"],`Group_`,""))
condition:
$group
}
YARA-L Rule Structure
Condition
Fires when at least one $group event in the 5m window.
Events
$group
metadata.product_event_type = "Delete group."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 | 35 |
event_count | count_distinct($group.metadata.id) |
user_agent | array_distinct($group.network.http.user_agent) |
security_summary | array_distinct($group.security_result.summary) |
target_application | array_distinct($group.target.application) |
group_name | array_distinct($group.target.group.group_display_name) |
group_guid | array_distinct(re.replace($group.security_result.detection_fields["target_2"],`Group_`,"")) |
Okta User Failed Number Challenge During Push Notification
#Detects when an Okta user failed a number challenge during push notification.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
References
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Okta | System Log event type user.authentication.auth_via_mfa: User authenticated via MFA |
Rules Detecting the Same Action
These rules filter on the same operation.
- First Occurrence of Okta User Session Started via Proxy (Elastic)
- MFA Fatigue (OKTA) (Kusto)
- Okta AiTM Phishing Attempt Blocked by FastPass (Panther)
- Okta Authentication Failed During MFA Challenge (Splunk)
- Okta Fast Pass phishing Detection (Kusto)
- Okta FastPass Phishing Detection (Sigma)
- Okta FastPass Phishing Detection (Elastic)
- Okta MFA Bruteforce Attack (YARA-L)
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule okta_user_failed_number_challenge_during_push_notification {
meta:
author = "Google Cloud Security"
description = "Detects when an Okta user failed a number challenge during push notification."
rule_id = "mr_c5542a92-03d7-463a-bab8-ad10a6cd42f0"
rule_name = "Okta User Failed Number Challenge During Push Notification"
reference = "https://support.okta.com/help/s/article/Number-Challenge-for-Okta-Verify"
mitre_attack_tactic = "Credential Access"
mitre_attack_technique = "Multi-Factor Authentication Request Generation"
mitre_attack_url = "https://attack.mitre.org/techniques/T1621/"
mitre_attack_version = "v13.1"
type = "Alert"
data_source = "Okta"
severity = "Medium"
priority = "Medium"
events:
$login.metadata.product_name = "Okta"
$login.metadata.vendor_name = "Okta"
$login.metadata.event_type = "USER_LOGIN"
$login.metadata.product_event_type = "user.authentication.auth_via_mfa"
$login.security_result.detection_fields["pushWithNumberChallengeResponseType"] = "OV_WITH_CHALLENGE_RESPONSE_INVALID"
$login.security_result.action = "BLOCK"
$login.target.user.userid = $userid
match:
$userid over 1h
outcome:
$risk_score = max(35)
$mitre_attack_tactic = "Credential Access"
$mitre_attack_technique = "Multi-Factor Authentication Request Generation"
$target_user_agent = array_distinct($login.network.http.user_agent)
$principal_ip = array_distinct($login.principal.ip)
$principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region)
$principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state)
$principal_ip_city = array_distinct($login.principal.location.city)
$principal_user_email_addresses = array_distinct ($login.principal.user.email_addresses)
$security_result_summary = array_distinct($login.security_result.summary)
$target_user_email_addresses = array_distinct($login.target.user.email_addresses)
$target_user_userid = array_distinct($login.target.user.userid)
condition:
$login
}
YARA-L Rule Structure
Condition
Fires when at least one $login event in the 1h window.
Events
$login
metadata.product_event_type = "user.authentication.auth_via_mfa"security_result.detection_fields["pushWithNumberChallengeResponseType"] = "OV_WITH_CHALLENGE_RESPONSE_INVALID"security_result.action = "BLOCK"
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) |
target_user_agent | array_distinct($login.network.http.user_agent) |
principal_ip | array_distinct($login.principal.ip) |
principal_ip_country | array_distinct($login.principal.ip_geo_artifact.location.country_or_region) |
principal_ip_state | array_distinct($login.principal.ip_geo_artifact.location.state) |
principal_ip_city | array_distinct($login.principal.location.city) |
principal_user_email_addresses | array_distinct ($login.principal.user.email_addresses) |
security_result_summary | array_distinct($login.security_result.summary) |
target_user_email_addresses | array_distinct($login.target.user.email_addresses) |
target_user_userid | array_distinct($login.target.user.userid) |