Detection rules › YARA-L
YARA-L rules: 1i
Default RDP Port Changed to Non Standard Port
#Detects changes to the default RDP port. Remote desktop is a common feature in operating systems. It allows a user to log into a remote system using an interactive session with a graphical user interface. Microsoft refers to its implementation of the Remote Desktop Protocol (RDP) as Remote Desktop Services (RDS).
Known False Positives
- Unknown
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence |
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 default_rdp_port_changed_to_non_standard_port {
meta:
author = "frack113"
description = "Detects changes to the default RDP port. Remote desktop is a common feature in operating systems. It allows a user to log into a remote system using an interactive session with a graphical user interface. Microsoft refers to its implementation of the Remote Desktop Protocol (RDP) as Remote Desktop Services (RDS)."
reference = "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/registry/registry_set/registry_set_change_rdp_port.yml"
license = "https://github.com/SigmaHQ/Detection-Rule-License/blob/main/LICENSE.Detection.Rules.md"
rule_name = "Default RDP Port Changed to Non Standard Port"
rule_id = "mr_13e82052-08dc-4475-b0df-d22fc689e4c8"
sigma_uuid = "509e84b9-a71a-40e0-834f-05470369bd1e"
sigma_status = "test"
tactic = "TA0003"
technique = "T1547.010"
type = "Detection"
data_source = "Sysmon"
platform = "Windows"
severity = "High"
priority = "High"
false_positives = "Unknown"
events:
$reg.metadata.event_type = "REGISTRY_MODIFICATION"
re.regex($reg.target.registry.registry_key, `\\control\\terminal server\\winstations\\rdp-tcp\\portnumber$`) nocase
NOT $reg.target.registry.registry_value_data = "DWORD (0x00000d3d)" //3389
$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 "\\control\\terminal server\\winstations\\rdp-tcp\\portnumber$"target.registry.registry_value_data = "DWORD (0x00000d3d)"
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)) |
Disable Internal Tools or Feature in Registry
#Detects registry modifications that change features of internal Windows tools (malware like Agent Tesla uses this technique)
Known False Positives
- Legitimate admin script
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 disable_internal_tools_or_feature_in_registry {
meta:
author = "frack113, Nasreddine Bencherchali (Nextron Systems), CrimpSec"
description = "Detects registry modifications that change features of internal Windows tools (malware like Agent Tesla uses this technique)"
reference = "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/registry/registry_set/registry_set_disable_function_user.yml"
license = "https://github.com/SigmaHQ/Detection-Rule-License/blob/main/LICENSE.Detection.Rules.md"
rule_name = "Disable Internal Tools or Feature in Registry"
rule_id = "mr_5840c962-0e51-47e6-9941-d143ebaae00d"
sigma_uuid = "e2482f8d-3443-4237-b906-cc145d87a076"
sigma_status = "test"
tactic = "TA0005"
technique = "T1112"
type = "Detection"
data_source = "Windows Registry"
platform = "Windows"
severity = "Medium"
priority = "Medium"
false_positives = "Legitimate admin script"
events:
$reg.metadata.event_type = "REGISTRY_MODIFICATION"
(
(
(
re.regex($reg.target.registry.registry_key, `SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\DisableCMD$`) nocase or
re.regex($reg.target.registry.registry_key, `SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\NoControlPanel$`) nocase or
re.regex($reg.target.registry.registry_key, `SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\NoRun$`) nocase or
re.regex($reg.target.registry.registry_key, `SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\StartMenuLogOff$`) nocase or
re.regex($reg.target.registry.registry_key, `SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\DisableChangePassword$`) nocase or
re.regex($reg.target.registry.registry_key, `SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\DisableLockWorkstation$`) nocase or
re.regex($reg.target.registry.registry_key, `SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\DisableRegistryTools$`) nocase or
re.regex($reg.target.registry.registry_key, `SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\DisableTaskmgr$`) nocase or
re.regex($reg.target.registry.registry_key, `SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\NoDispBackgroundPage$`) nocase or
re.regex($reg.target.registry.registry_key, `SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\NoDispCPL$`) nocase or
re.regex($reg.target.registry.registry_key, `SOFTWARE\\Policies\\Microsoft\\Windows\\Explorer\\DisableNotificationCenter$`) nocase or
re.regex($reg.target.registry.registry_key, `SOFTWARE\\Policies\\Microsoft\\Windows\\System\\DisableCMD$`) nocase
) and
$reg.target.registry.registry_value_data = "DWORD (0x00000001)" nocase
)
or
(
(
re.regex($reg.target.registry.registry_key, `SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\ConsentPromptBehaviorAdmin$`) nocase or
re.regex($reg.target.registry.registry_key, `Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\InactivityTimeoutSecs$`) nocase or
re.regex($reg.target.registry.registry_key, `SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\shutdownwithoutlogon$`) nocase or
re.regex($reg.target.registry.registry_key, `SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\PushNotifications\\ToastEnabled$`) nocase or
re.regex($reg.target.registry.registry_key, `SYSTEM\\CurrentControlSet\\Control\\Storage\\Write Protection$`) nocase or
re.regex($reg.target.registry.registry_key, `SYSTEM\\CurrentControlSet\\Control\\StorageDevicePolicies\\WriteProtect$`) nocase
) and
$reg.target.registry.registry_value_data = "DWORD (0x00000000)" 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 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\DisableCMD$"target.registry.registry_key matches "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\NoControlPanel$"target.registry.registry_key matches "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\NoRun$"target.registry.registry_key matches "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\StartMenuLogOff$"target.registry.registry_key matches "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\DisableChangePassword$"target.registry.registry_key matches "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\DisableLockWorkstation$"target.registry.registry_key matches "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\DisableRegistryTools$"target.registry.registry_key matches "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\DisableTaskmgr$"target.registry.registry_key matches "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\NoDispBackgroundPage$"target.registry.registry_key matches "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\NoDispCPL$"target.registry.registry_key matches "SOFTWARE\\Policies\\Microsoft\\Windows\\Explorer\\DisableNotificationCenter$"target.registry.registry_key matches "SOFTWARE\\Policies\\Microsoft\\Windows\\System\\DisableCMD$"target.registry.registry_value_data = "DWORD (0x00000001)"target.registry.registry_key matches "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\ConsentPromptBehaviorAdmin$"target.registry.registry_key matches "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\InactivityTimeoutSecs$"target.registry.registry_key matches "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\shutdownwithoutlogon$"target.registry.registry_key matches "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\PushNotifications\\ToastEnabled$"target.registry.registry_key matches "SYSTEM\\CurrentControlSet\\Control\\Storage\\Write Protection$"target.registry.registry_key matches "SYSTEM\\CurrentControlSet\\Control\\StorageDevicePolicies\\WriteProtect$"target.registry.registry_value_data = "DWORD (0x00000000)"
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)) |
GCP Multiple Secrets Deleted
#Detect when multiple secrets or secret versions are deleted from GCP Secret Manager.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Impact |
Telemetry Coverage
Rule Body
// Copyright 2024 Google LLC. Licensed under Apache-2.0.
rule gcp_multiple_secrets_deleted {
meta:
author = "Google Cloud Security"
description = "Detect when multiple secrets or secret versions are deleted from GCP Secret Manager."
rule_id = "mr_c91c9fe8-6569-4764-a8d8-9b88dd3b7f77"
rule_name = "GCP Multiple Secrets Deleted"
mitre_attack_tactic = "Impact"
mitre_attack_technique = "Data Destruction"
mitre_attack_url = "https://attack.mitre.org/techniques/T1485/"
mitre_attack_version = "v14.1"
type = "Alert"
data_source = "GCP Cloud Audit"
platform = "GCP"
severity = "High"
priority = "High"
events:
$gcp.metadata.log_type = "GCP_CLOUDAUDIT"
(
$gcp.metadata.product_event_type = "google.cloud.secretmanager.v1.SecretManagerService.DestroySecretVersion" or
$gcp.metadata.product_event_type = "google.cloud.secretmanager.v1.SecretManagerService.DeleteSecret"
)
$gcp.target.application = "secretmanager.googleapis.com"
$gcp.security_result.action = "ALLOW"
$gcp.target.user.userid = $user_id
match:
$user_id over 1h
outcome:
$risk_score = max(75)
$mitre_attack_tactic = "Impact"
$mitre_attack_technique = "Data Destruction"
$mitre_attack_technique_id = "T1485"
$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)
condition:
#gcp >= 10
}
YARA-L Rule Structure
Condition
Fires when $gcp occurs at least 10 times in the 1h window.
Events
$gcp
metadata.log_type = "GCP_CLOUDAUDIT"metadata.product_event_typeis one of:google.cloud.secretmanager.v1.SecretManagerService.DestroySecretVersiongoogle.cloud.secretmanager.v1.SecretManagerService.DeleteSecret
target.application = "secretmanager.googleapis.com"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) |
GitHub Organization Removed From Enterprise
#Detects when a GitHub organization is removed from an enterprise.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Impact |
References
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| GitHub | Audit log action business.remove_organization: Organization removed from enterprise |
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_organization_removed_from_enterprise {
meta:
author = "Google Cloud Security"
description = "Detects when a GitHub organization is removed from an enterprise."
rule_id = "mr_705af31b-6257-436d-830d-ad9c9e2f052c"
rule_name = "GitHub Organization Removed From Enterprise"
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 = "Medium"
priority = "Medium"
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.remove_organization"
$github.principal.user.userid = $user_id
$github.target.user.company_name = $github_enterprise_name
$github.target.administrative_domain = $github_org_name
match:
$user_id, $github_enterprise_name, $github_org_name over 30m
outcome:
$risk_score = max(65)
$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.remove_organization"
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(65) |
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) |
Lsass Memory Dump via Comsvcs DLL
#Detects adversaries leveraging the MiniDump export function from comsvcs.dll via rundll32 to perform a memory dump from lsass
Known False Positives
- Unknown
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
References
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 10: ProcessAccess |
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule lsass_memory_dump_comsvcs_dll {
meta:
author = "Roberto Rodriguez (Cyb3rWard0g), OTR (Open Threat Research)"
description = "Detects adversaries leveraging the MiniDump export function from comsvcs.dll via rundll32 to perform a memory dump from lsass"
reference = "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/process_access/proc_access_win_lsass_dump_comsvcs_dll.yml"
license = "https://github.com/SigmaHQ/Detection-Rule-License/blob/main/LICENSE.Detection.Rules.md"
rule_name = "Lsass Memory Dump via Comsvcs DLL"
sigma_uuid = "a49fa4d5-11db-418c-8473-1e014a8dd462"
sigma_status = "test"
rule_id = "mr_4efe14fb-53fb-49ba-b137-f5d70cb6adb9"
tactic = "TA0006"
technique = "T1003.001"
type = "Detection"
data_source = "Sysmon"
platform = "Windows"
severity = "High"
priority = "High"
false_positives = "Unknown"
events:
$process.metadata.event_type = "PROCESS_OPEN"
re.regex($process.target.process.file.full_path, `\\lsass\.exe$`) nocase
re.regex($process.principal.process.file.full_path, `\\rundll32\.exe$`) nocase
strings.contains(strings.to_lower($process.additional.fields["CallTrace"]), "comsvcs.dll")
$process.principal.hostname = $hostname
match:
$hostname over 5m
outcome:
//example usage of specifying test hostname to adjust risk score
$risk_score = max(if($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)
$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 "\\lsass\.exe$"principal.process.file.full_path matches "\\rundll32\.exe$"additional.fields["CallTrace"] contains "comsvcs.dll"
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.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) |
log_type | array_distinct(strings.concat($process.metadata.log_type,"/",$process.metadata.product_event_type)) |
Office 365 group modification add member success has exceeded a defined threshold
#Detects when a group GUID in Office 365 has more users added to it by the same user than a defined thresold.
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft 365 | Add member to group. |
Rules Detecting the Same Action
These rules filter on the same operation.
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule o365_group_modification_add_member_success_threshold {
meta:
author = "Google Cloud Security"
description = "Detects when a group GUID in Office 365 has more users added to it by the same user than a defined thresold."
rule_id = "mr_47e13870-800b-4886-b8b8-8e6b68b203b9"
rule_name = "Office 365 group modification add member success has exceeded a defined threshold"
type = "alert"
platform = "azure"
data_source = "o365"
severity = "Low"
priority = "Low"
events:
$group.metadata.event_type = "GROUP_MODIFICATION"
$group.metadata.product_event_type = "Add member to group."
$group.metadata.product_name = "Office 365"
$group.metadata.vendor_name = "Microsoft"
$group.security_result.action = "ALLOW"
$group.principal.user.userid = $user
$group.target.group.product_object_id = $guid
match:
$guid, $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($group.target.group.product_object_id)
$user_added = array_distinct($group.target.user.userid)
$user_count = count_distinct($group.target.user.userid)
condition:
//Modify the user_count value to suit your needs
$group and $user_count > 4
}
YARA-L Rule Structure
Condition
Fires when at least one $group event in the 5m window and $user_count > 4.
Events
$group
metadata.product_event_type = "Add member to 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) |
principal_user_userid | array_distinct($group.principal.user.userid) |
group_name | array_distinct($group.target.group.group_display_name) |
group_guid | array_distinct($group.target.group.product_object_id) |
user_added | array_distinct($group.target.user.userid) |
user_count | count_distinct($group.target.user.userid) |