Detection rules › YARA-L
YARA-L rules: 1d
Enumeration of inboxes accessible by a user in the Microsoft Graph API
#Identify enumeration of inboxes across the Entra ID tenant. This detection is based on the Invoke-GraphOpenInboxFinder in GraphRunner but the concepts are applicable to other tools that scan for accessible inboxes.
References
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule ms_graph_security_open_inbox_enumeration {
meta:
author = "Google Cloud Security"
description = "Identify enumeration of inboxes across the Entra ID tenant. This detection is based on the Invoke-GraphOpenInboxFinder in GraphRunner but the concepts are applicable to other tools that scan for accessible inboxes."
rule_id = "mr_94dbfeae-2a20-472d-b359-9784b66213e7"
rule_name = "Enumeration of inboxes accessible by a user in the Microsoft Graph API"
assumption = "User agent and IP address of the admin consoles that normally interact with the application listing can be filtered out to reduce detections."
reference = "https://github.com/dafthack/GraphRunner/blob/main/GraphRunner.ps1"
type = "Alert"
data_source = "MS Graph Activity Logs"
platform = "Azure"
severity = "Medium"
priority = "Medium"
events:
$api.metadata.event_type = "NETWORK_HTTP"
$api.metadata.product_event_type = "Microsoft Graph Activity"
re.regex($api.target.url, `^https://graph.microsoft.com/v1.0/users/.*/mailFolders/Inbox/messages$`) nocase
//Can be tuned for specific User Agent strings being used
//$api.network.http.user_agent = /PowerShell/ nocase
$api.network.http.method = "GET"
$api.principal.ip[0] = $ip
$api.network.session_id = $session
re.capture($api.target.url, `^https://graph.microsoft.com/v1.0/users/(.*)/mailFolders/Inbox/messages$`) = $scanned_user
match:
$ip, $session over 5m
outcome:
$risk_score = 65
$event_count = count_distinct($api.metadata.id)
$requesting_user_guid = array_distinct($api.principal.user.userid)
//Using $ip placeholder variable since we specify first value in repeated field only, if repeated field is used, it can cause duplicate counts in sums below
$requesting_ip = array_distinct($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)
$total_scanned_users = count($scanned_user)
$successfully_scanned_users = array_distinct(if($api.network.http.response_code = 200, $scanned_user,""))
//Provide breakdown of inboxes that the user scanning can access, can't find and are unauthorized based on http response code
$successful_access = sum(if($api.network.http.response_code = 200, 1,0))
$forbidden_access = sum(if($api.network.http.response_code = 403, 1,0))
$inbox_not_found = sum(if($api.network.http.response_code = 404, 1,0))
$inbox_other = sum(if($api.network.http.response_code != 404
and $api.network.http.response_code != 403
and $api.network.http.response_code != 200, 1,0))
condition:
//Can remove the total_scanned_users to detect everytime this endpoint is called or use this as a threshold to eliminate stray calls
$api and $total_scanned_users > 10
//Another option is to trigger based on the number of successful inboxes enumerated instead of the total number of inboxes scanned
//$api and $successful_access > 2
}
YARA-L Rule Structure
Condition
Fires when at least one $api event in the 5m window and $total_scanned_users > 10.
Events
$api
metadata.product_event_type = "Microsoft Graph Activity"target.url matches "^https://graph.microsoft.com/v1.0/users/.*/mailFolders/Inbox/messages$"network.http.method = "GET"
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($api.metadata.id) |
requesting_user_guid | array_distinct($api.principal.user.userid) |
requesting_ip | array_distinct($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) |
total_scanned_users | count($scanned_user) |
successfully_scanned_users | array_distinct(if($api.network.http.response_code = 200, $scanned_user,"")) |
successful_access | sum(if($api.network.http.response_code = 200, 1,0)) |
forbidden_access | sum(if($api.network.http.response_code = 403, 1,0)) |
inbox_not_found | sum(if($api.network.http.response_code = 404, 1,0)) |
inbox_other | sum(if($api.network.http.response_code != 404 and $api.network.http.response_code != 403 and $api.network.http.response_code != 200, 1,0)) |
LSASS Dump Keyword In CommandLine
#Detects the presence of the keywords lsass and .dmp in the commandline, which could indicate a potential attempt to dump or create a dump of the lsass process
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 lsass_dump_keyword_command_line {
meta:
author = "E.M. Anhaus, Tony Lambert, oscd.community, Nasreddine Bencherchali (Nextron Systems)"
description = "Detects the presence of the keywords lsass and .dmp in the commandline, which could indicate a potential attempt to dump or create a dump of the lsass process"
reference = "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/process_creation/proc_creation_win_susp_lsass_dmp_cli_keywords.yml"
license = "https://github.com/SigmaHQ/Detection-Rule-License/blob/main/LICENSE.Detection.Rules.md"
rule_name = "LSASS Dump Keyword In CommandLine"
sigma_uuid = "ffa6861c-4461-4f59-8a41-578c39f3f23e"
sigma_status = "test"
rule_id = "mr_b7e51852-e836-4020-9ea4-7d9f9ace350f"
tactic = "TA0006"
technique = "T1003.001"
type = "Detection"
data_source = "Windows Event, Sysmon"
platform = "Windows"
severity = "High"
priority = "High"
false_positives = "Unlikely"
events:
$process.metadata.event_type = "PROCESS_LAUNCH"
(
(
strings.contains(strings.to_lower($process.target.process.command_line), "lsass.dmp") or
strings.contains(strings.to_lower($process.target.process.command_line), "lsass.zip") or
strings.contains(strings.to_lower($process.target.process.command_line), "lsass.rar") or
strings.contains(strings.to_lower($process.target.process.command_line), "andrew.dmp") or
strings.contains(strings.to_lower($process.target.process.command_line), "coredump.dmp") or
strings.contains(strings.to_lower($process.target.process.command_line), "notlsass.zip") or
strings.contains(strings.to_lower($process.target.process.command_line), "lsass_2") or
strings.contains(strings.to_lower($process.target.process.command_line), "lsassdump") or
strings.contains(strings.to_lower($process.target.process.command_line), "lsassdmp")
)
or
(
strings.contains(strings.to_lower($process.target.process.command_line), "lsass") and
strings.contains(strings.to_lower($process.target.process.command_line), ".dmp")
)
or
(
strings.contains(strings.to_lower($process.target.process.command_line), "sqldmpr") and
strings.contains(strings.to_lower($process.target.process.command_line), ".mdmp")
)
or
(
strings.contains(strings.to_lower($process.target.process.command_line), "nanodump") and
strings.contains(strings.to_lower($process.target.process.command_line), ".dmp")
)
)
$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.command_line contains "lsass.dmp"target.process.command_line contains "lsass.zip"target.process.command_line contains "lsass.rar"target.process.command_line contains "andrew.dmp"target.process.command_line contains "coredump.dmp"target.process.command_line contains "notlsass.zip"target.process.command_line contains "lsass_2"target.process.command_line contains "lsassdump"target.process.command_line contains "lsassdmp"target.process.command_line contains "lsass"target.process.command_line contains ".dmp"target.process.command_line contains "sqldmpr"target.process.command_line contains ".mdmp"target.process.command_line contains "nanodump"target.process.command_line contains ".dmp"
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)) |
MITRE ATT&CK T1110.001 Windows Repeated Authentication Failures Before Successful One
#Detect Multiple Failed Login Attempts followed by Successful Login
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Telemetry Coverage
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule win_repeatedAuthFailure_thenSuccess_T1110_001 {
meta:
author = "Google Cloud Security"
description = "Detect Multiple Failed Login Attempts followed by Successful Login"
rule_id = "mr_16893c0e-2563-44ed-84c9-57ab326eb1c2"
rule_name = "MITRE ATT&CK T1110.001 Windows Repeated Authentication Failures Before Successful One"
type = "alert"
data_source = "microsoft windows events"
platform = "Windows"
severity = "Medium"
priority = "Medium"
tactic = "TA0006"
technique = "T1110.001"
events:
$fail.metadata.event_type = "USER_LOGIN"
$fail.metadata.vendor_name = "Microsoft"
$fail.principal.hostname = $hostname
$fail.target.user.userid = $user
$fail.security_result.action = "BLOCK"
$fail.metadata.product_event_type = "4625"
$fail.metadata.event_timestamp.seconds < $success.metadata.event_timestamp.seconds
$success.metadata.event_type = "USER_LOGIN"
$success.metadata.vendor_name = "Microsoft"
$success.target.user.userid = $user
$success.principal.hostname = $hostname
$success.security_result.action = "ALLOW"
$success.metadata.product_event_type = "4624"
match:
$user, $hostname over 15m
outcome:
// increment risk score if the system targeted is active directory server, can modify as you see fit, using this as an example
$risk_score = max(if($hostname = /activedir/, 75, 50))
$failed_login_threshold = 5
$impacted_systems = array_distinct($hostname)
$impacted_users = array_distinct($user)
$alert_type = "Successful Brute Force Attack"
$tlp = "red"
// 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($success.principal.hostname)
$principal_ip = array_distinct($success.principal.ip)
$target_hostname = array_distinct($success.target.hostname)
$src_hostname = array_distinct($success.src.hostname)
$target_ip = array_distinct($success.target.ip)
$principal_user_userid = array_distinct($success.principal.user.userid)
// Commented out target.user.userid because it is already represented in graph as match variable. If match changes, can uncomment to add to results
//$target_user_userid = array_distinct($success.target.user.userid)
$principal_resource_name = array_distinct($success.principal.resource.name)
$target_resource_name = array_distinct($success.target.resource.name)
$target_url = array_distinct($success.target.url)
condition:
#fail > 4 and $success
}
YARA-L Rule Structure
Condition
Fires when $fail occurs more than 4 times in the 15m window and at least one $success event in the 15m window.
Events
$fail
security_result.action = "BLOCK"metadata.product_event_type = "4625"
$success
security_result.action = "ALLOW"metadata.product_event_type = "4624"
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($hostname = /activedir/, 75, 50)) |
failed_login_threshold | 5 |
impacted_systems | array_distinct($hostname) |
impacted_users | array_distinct($user) |
principal_ip | array_distinct($success.principal.ip) |
target_hostname | array_distinct($success.target.hostname) |
src_hostname | array_distinct($success.src.hostname) |
target_ip | array_distinct($success.target.ip) |
principal_user_userid | array_distinct($success.principal.user.userid) |
principal_resource_name | array_distinct($success.principal.resource.name) |
target_resource_name | array_distinct($success.target.resource.name) |
target_url | array_distinct($success.target.url) |
sap critial role assigned to new user
#Detects the assignment of high-privilege roles by correlating Change Documents (PFCG) with Security Audit logs (AUD) for IP attribution.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation |
Rule Body
// Copyright 2026 Google LLC. Licensed under Apache-2.0.
rule sap_critial_role_assigned_to_new_user {
meta:
author = "Google Cloud Security"
name = "SAP - Critical Authorization Assignment"
description = "Detects the assignment of high-privilege roles by correlating Change Documents (PFCG) with Security Audit logs (AUD) for IP attribution."
severity = "Critical"
tactic = "TA0004"
technique = "T1098"
events:
$change.metadata.log_type = "SAP_CHANGE_DOCUMENT"
$change.target.resource.attribute.labels["TABNAME"] = "AGR_USERS"
$change.target.resource.attribute.labels["CHNGIND"] = "I"
$role = $change.target.resource.product_object_id
$audit.metadata.log_type = "SAP_SECURITY_AUDIT"
$audit.additional.fields["msg_1"] = "AU7"
//join
$target_user = re.capture($change.target.resource.attribute.labels["TABKEY"], "^.{33}\\s*(\\S+)\\s*\\d{16}$")
$target_user = $audit.additional.fields["param1_1"]
$role in %sap_sensitive_roles.role
match:
$target_user over 1h
outcome:
$user_that_created_account = array_distinct($audit.principal.user.userid)
$user_that_assigned_role = array_distinct($change.principal.user.userid)
$source_ip = array_distinct($audit.principal.ip)
$assigned_role = array_distinct($role)
$system_id = array_distinct($audit.target.application)
$risk_score = 95
condition:
$change and $audit
}
YARA-L Rule Structure
Condition
Fires when at least one $change event in the 1h window and at least one $audit event in the 1h window.
Events
$audit
metadata.log_type = "SAP_SECURITY_AUDIT"additional.fields["msg_1"] = "AU7"additional.fields["param1_1"] macro "re.capture($change.target.resource.attribute.labels["TABKEY"], "^.{33}\\s*(\\S+)\\s*\\d{16}$")"
$change
metadata.log_type = "SAP_CHANGE_DOCUMENT"target.resource.attribute.labels["TABNAME"] = "AGR_USERS"target.resource.attribute.labels["CHNGIND"] = "I"target.resource.product_object_id in "%sap_sensitive_roles.role"
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 |
|---|---|
user_that_created_account | array_distinct($audit.principal.user.userid) |
user_that_assigned_role | array_distinct($change.principal.user.userid) |
source_ip | array_distinct($audit.principal.ip) |
assigned_role | array_distinct($role) |
system_id | array_distinct($audit.target.application) |
risk_score | 95 |
VT Relationships File Downloaded From IP
#Alert on downloading a known file hash from a known IP with VT Relationships.
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 11: FileCreate |
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule vt_relationships_file_downloaded_from_ip {
meta:
author = "Google Cloud Security"
description = "Alert on downloading a known file hash from a known IP with VT Relationships."
rule_id = "mr_1a62ba21-6f3d-40c7-9278-b1e2d639a10b"
rule_name = "VT Relationships File Downloaded From IP"
type = "alert"
tags = "vt"
data_source = "zscalar, crowdstrike"
severity = "High"
priority = "High"
events:
// NETWORK_HTTP
$network.metadata.event_type = "NETWORK_HTTP"
$network.principal.user.userid = $userid
$network.target.ip = $ip
// FILE_CREATION
$file.metadata.event_type = "FILE_CREATION"
$file.target.user.userid = $userid
$file.target.file.sha256 = $file_hash
// Network HTTP event must occur before the file creation event
$network.metadata.event_timestamp.seconds < $file.metadata.event_timestamp.seconds
//Uses VirusTotal integration via entity graph, this section maps to target file hash
$vt.graph.metadata.entity_type = "FILE"
$vt.graph.metadata.source_type = "GLOBAL_CONTEXT"
$vt.graph.metadata.vendor_name = "VirusTotal"
$vt.graph.metadata.product_name = "VirusTotal Relationships"
$vt.graph.entity.file.sha256 = $file_hash
//Uses VirusTotal integration via entity graph, this section maps the hash to the ip address it is downloaded from
$vt.graph.relations.entity_type = "IP_ADDRESS"
$vt.graph.relations.relationship = "DOWNLOADED_FROM"
$vt.graph.relations.entity.ip = $ip
match:
$userid over 5m
outcome:
$risk_score = 85
// added to populate alert graph with additional context
$principal_hostname = array_distinct($network.principal.hostname)
$target_hostname = array_distinct($network.target.hostname)
$principal_process_pid = array_distinct($file.principal.process.pid)
$principal_process_command_line = array_distinct($file.principal.process.command_line)
$principal_process_file_sha256 = array_distinct($file.principal.process.file.sha256)
$principal_process_file_full_path = array_distinct($file.principal.process.file.full_path)
$principal_process_product_specific_process_id = array_distinct($file.principal.process.product_specific_process_id)
$principal_process_parent_process_product_specific_process_id = array_distinct($file.principal.process.parent_process.product_specific_process_id)
$target_process_pid = array_distinct($file.target.process.pid)
$target_process_command_line = array_distinct($file.target.process.command_line)
$target_process_file_sha256 = array_distinct($file.target.process.file.sha256)
$target_process_file_full_path = array_distinct($file.target.process.file.full_path)
$target_process_product_specific_process_id = array_distinct($file.target.process.product_specific_process_id)
$target_process_parent_process_product_specific_process_id = array_distinct($file.target.process.parent_process.product_specific_process_id)
// Commented out principal.user.userid because it is already represented in graph as match variable. If match changes, can uncomment to add to results
//$principal_user_userid = array_distinct($file.principal.user.userid)
$target_user_userid = array_distinct($file.target.user.userid)
$target_url = array_distinct($network.target.url)
condition:
$network and $file and $vt
}
YARA-L Rule Structure
Condition
Fires when at least one $network event in the 5m window and at least one $file event in the 5m window and $vt matches entity context.
Events
$network
$file
$vt
graph.metadata.entity_type = "FILE"graph.metadata.source_type = "GLOBAL_CONTEXT"graph.metadata.vendor_name = "VirusTotal"graph.metadata.product_name = "VirusTotal Relationships"graph.relations.entity_type = "IP_ADDRESS"graph.relations.relationship = "DOWNLOADED_FROM"
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 |
principal_hostname | array_distinct($network.principal.hostname) |
target_hostname | array_distinct($network.target.hostname) |
principal_process_pid | array_distinct($file.principal.process.pid) |
principal_process_command_line | array_distinct($file.principal.process.command_line) |
principal_process_file_sha256 | array_distinct($file.principal.process.file.sha256) |
principal_process_file_full_path | array_distinct($file.principal.process.file.full_path) |
principal_process_product_specific_process_id | array_distinct($file.principal.process.product_specific_process_id) |
principal_process_parent_process_product_specific_process_id | array_distinct($file.principal.process.parent_process.product_specific_process_id) |
target_process_pid | array_distinct($file.target.process.pid) |
target_process_command_line | array_distinct($file.target.process.command_line) |
target_process_file_sha256 | array_distinct($file.target.process.file.sha256) |
target_process_file_full_path | array_distinct($file.target.process.file.full_path) |
target_process_product_specific_process_id | array_distinct($file.target.process.product_specific_process_id) |
target_process_parent_process_product_specific_process_id | array_distinct($file.target.process.parent_process.product_specific_process_id) |
target_user_userid | array_distinct($file.target.user.userid) |
target_url | array_distinct($network.target.url) |