Detection rules › YARA-L
YARA-L rules: 05
Client Secret Added to Entra ID Application
#Secrets added to applications have legitimate purposes, but can also be a method of persistence.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Azure | any: Entra ID audit event (any operation) |
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule entra_id_secret_added_to_app {
meta:
author = "Google Cloud Security"
description = "Secrets added to applications have legitimate purposes, but can also be a method of persistence."
rule_id = "mr_22d3881f-f84d-42ee-a1bc-5d5eb419b769"
rule_name = "Client Secret Added to Entra ID Application"
tactic = "TA0003"
technique = "T1098.001"
type = "alert"
platform = "azure"
data_source = "azure ad"
severity = "Medium"
priority = "Medium"
events:
$app.metadata.event_type = "SERVICE_MODIFICATION"
$app.metadata.product_event_type = /Update application.*Certificates and secrets management/
$app.metadata.product_name = "Azure AD Directory Audit"
$app.metadata.vendor_name = "Microsoft"
$app.security_result.action = "ALLOW"
$app.principal.user.userid = $user
match:
$user over 5m
outcome:
$risk_score = 65
$event_count = count_distinct($app.metadata.id)
$user_agent = array_distinct($app.network.http.user_agent)
$network_session = array_distinct($app.network.session_id)
$principal_county_region = array_distinct($app.principal.ip_geo_artifact.location.country_or_region)
$principal_ip = array_distinct($app.principal.ip)
$principal_email = array_distinct($app.principal.user.email_addresses)
$target_application = array_distinct($app.target.resource.name)
$target_application_id = array_distinct($app.target.resource.product_object_id)
condition:
$app
}
YARA-L Rule Structure
Condition
Fires when at least one $app event in the 5m window.
Events
$app
metadata.product_event_type matches "Update application.*Certificates and secrets management"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 | 65 |
event_count | count_distinct($app.metadata.id) |
user_agent | array_distinct($app.network.http.user_agent) |
network_session | array_distinct($app.network.session_id) |
principal_county_region | array_distinct($app.principal.ip_geo_artifact.location.country_or_region) |
principal_ip | array_distinct($app.principal.ip) |
principal_email | array_distinct($app.principal.user.email_addresses) |
target_application | array_distinct($app.target.resource.name) |
target_application_id | array_distinct($app.target.resource.product_object_id) |
Multiple failed unique file downloads from OneDrive observed in the Microsoft Graph API
#This detects when a 401 Unauthorized status code is returned when attempting to download multiple unique files from OneDrive and may indicate a permissions issue for the user.
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule ms_graph_failed_file_downloads_uniq_docs {
meta:
author = "Google Cloud Security"
description = "This detects when a 401 Unauthorized status code is returned when attempting to download multiple unique files from OneDrive and may indicate a permissions issue for the user."
rule_id = "mr_63f3d1b6-6d0c-4d35-8faf-2876aeb5c2e7"
rule_name = "Multiple failed unique file downloads from OneDrive observed in the Microsoft Graph API"
type = "alert"
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"
re.regex($api.target.url, `^https://graph\.microsoft\.com/v1\.0/drives/.*/content$`) nocase
//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.network.http.method = "GET"
$api.network.http.response_code = 401
$api.principal.ip = $ip
$api.network.session_id = $session
match:
$ip, $session over 15m
outcome:
$risk_score = 35
$event_count = count_distinct($api.metadata.id)
$doc_count = count_distinct($api.target.url)
$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:
//Threshold on unique docs can be modified here
$api and $doc_count > 2
}
YARA-L Rule Structure
Condition
Fires when at least one $api event in the 15m window and $doc_count > 2.
Events
$api
metadata.product_event_type = "Microsoft Graph Activity"target.url matches "^https://graph\.microsoft\.com/v1\.0/drives/.*/content$"network.http.method = "GET"network.http.response_code = "401"
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) |
doc_count | count_distinct($api.target.url) |
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) |
PrintBrm ZIP Creation of Extraction
#Detects the execution of the LOLBIN PrintBrm.exe, which can be used to create or extract ZIP files. PrintBrm.exe should not be run on a normal workstation
Known False Positives
- Unknown
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
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 printbrm_zip_creation_or_extraction {
meta:
author = "frack113"
description = "Detects the execution of the LOLBIN PrintBrm.exe, which can be used to create or extract ZIP files. PrintBrm.exe should not be run on a normal workstation"
reference = "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/process_creation/proc_creation_win_lolbin_printbrm.yml"
license = "https://github.com/SigmaHQ/Detection-Rule-License/blob/main/LICENSE.Detection.Rules.md"
rule_name = "PrintBrm ZIP Creation of Extraction"
sigma_uuid = "cafeeba3-01da-4ab4-b6c4-a31b1d9730c7"
sigma_status = "test"
rule_id = "mr_3d3036d7-f2f8-4037-ab33-f4cef1e1f4b5"
tactic = "TA0011"
technique = "T1105"
type = "Detection"
data_source = "Windows Event Logs"
platform = "Windows"
severity = "High"
priority = "High"
false_positives = "Unknown"
events:
$process.metadata.event_type = "PROCESS_LAUNCH"
re.regex($process.target.process.file.full_path, `\\PrintBrm\.exe$`) nocase
(
strings.contains(strings.to_lower($process.target.process.command_line), " -f") and
strings.contains(strings.to_lower($process.target.process.command_line), ".zip")
)
$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 "\\PrintBrm\.exe$"target.process.command_line contains " -f"target.process.command_line contains ".zip"
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)) |
PUA - Nimgrab Execution
#Detects the usage of nimgrab, a tool bundled with the Nim programming framework and used for downloading files.
Known False Positives
- Legitimate use of Nim on a developer systems
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
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 pua_nimgrab_execution {
meta:
author = "frack113"
description = "Detects the usage of nimgrab, a tool bundled with the Nim programming framework and used for downloading files."
reference = "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/process_creation/proc_creation_win_pua_nimgrab.yml"
license = "https://github.com/SigmaHQ/Detection-Rule-License/blob/main/LICENSE.Detection.Rules.md"
rule_name = "PUA - Nimgrab Execution"
sigma_uuid = "74a12f18-505c-4114-8d0b-8448dd5485c6"
sigma_status = "test"
rule_id = "mr_70b5f0f8-6bd3-42ab-be2f-928084b09942"
tactic = "TA0011"
technique = "T1105"
type = "Detection"
data_source = "Sysmon"
platform = "Windows"
severity = "High"
priority = "High"
false_positives = "Legitimate use of Nim on a developer systems"
events:
$process.metadata.event_type = "PROCESS_LAUNCH"
(
re.regex($process.target.process.file.full_path, `\\nimgrab\.exe$`) nocase or
(
strings.contains(strings.to_upper($process.target.process.file.md5), "2DD44C3C29D667F5C0EF5F9D7C7FFB8B") or
strings.contains(strings.to_upper($process.target.process.file.sha256), "F266609E91985F0FE3E31C5E8FAEEEC4FFA5E0322D8B6F15FE69F4C5165B9559") or
strings.contains(strings.to_upper($process.target.process.file.pe_file.imphash), "C07FDDD21D123EA9B3A08EEF44AAAC45")
)
)
$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 "\\nimgrab\.exe$"target.process.file.md5 contains "2DD44C3C29D667F5C0EF5F9D7C7FFB8B"target.process.file.sha256 contains "F266609E91985F0FE3E31C5E8FAEEEC4FFA5E0322D8B6F15FE69F4C5165B9559"target.process.file.pe_file.imphash contains "C07FDDD21D123EA9B3A08EEF44AAAC45"
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 function module testing detected
#Detects direct execution and testing of SAP Function Modules via SE37 test frame. This identifies correlation between a transaction start (AU7) and a function module call (BU4) in close succession
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution |
Rule Body
// Copyright 2026 Google LLC. Licensed under Apache-2.0.
rule sap_function_module_testing_detected {
meta:
author = "Google Cloud Security"
description = "Detects direct execution and testing of SAP Function Modules via SE37 test frame. This identifies correlation between a transaction start (AU7) and a function module call (BU4) in close succession"
severity = "Medium"
tactic = "TA0002"
technique = "T1129"
events:
$e.security_result.detection_fields["slgtc_1"] = /^SE37$|^SE80$|^SEU_INT$/
$e.principal.process.file.names = "RS_TESTFRAME_CALL"
$user = $e.principal.user.userid
match:
$user over 1h
outcome:
$resource_accessed = array_distinct($e.additional.fields["param1_1"])
$event_name = array_distinct($e.security_result.summary)
$description = array_distinct($e.metadata.description)
$msg = array_distinct($e.additional.fields["msg_1"])
$src_ip = array_distinct($e.principal.ip)
condition:
$e
}
YARA-L Rule Structure
Condition
Fires when at least one $e event in the 1h window.
Events
$e
security_result.detection_fields["slgtc_1"] matches "^SE37$|^SE80$|^SEU_INT$"principal.process.file.names = "RS_TESTFRAME_CALL"
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 |
|---|---|
resource_accessed | array_distinct($e.additional.fields["param1_1"]) |
event_name | array_distinct($e.security_result.summary) |
description | array_distinct($e.metadata.description) |
msg | array_distinct($e.additional.fields["msg_1"]) |
src_ip | array_distinct($e.principal.ip) |