Detection rules › YARA-L
YARA-L rules: 1q
| Rule | Severity |
|---|---|
| Office 365 logging has been enabled | critical |
| Potential Suspicious Activity Using SeCEdit | medium |
| Safebrowsing Process Creation Hashes Seen More Than 7 Days | medium |
Office 365 logging has been enabled
#Detect when the Unified Audit Log is enabled
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Defense Impairment |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft 365 | Exchange audit operation Set-AdminAuditLogConfig: Federated domain added |
Rules Detecting the Same Action
These rules filter on the same operation.
- Office 365 logging is disabled (YARA-L)
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule o365_logging_enabled {
meta:
author = "Google Cloud Security"
description = "Detect when the Unified Audit Log is enabled"
rule_id = "mr_a45012d7-4430-4666-b172-5488a48e9ca6"
rule_name = "Office 365 logging has been enabled"
assumption = "If logging is expected, there is no reason for this to be switched off. If it has been disabled and then this event triggers, it has been enabled which may indicate a gap in logging."
tactic = "TA0005"
technique = "T1562.008"
type = "alert"
platform = "azure"
data_source = "o365"
severity = "Critical"
priority = "Critical"
events:
$log.metadata.event_type = "SETTING_CREATION"
$log.metadata.product_event_type = "Set-AdminAuditLogConfig"
$log.metadata.product_name = "Office 365"
$log.metadata.vendor_name = "Microsoft"
$log.security_result.detection_fields["UnifiedAuditLogIngestionEnabled"] = "True"
$log.principal.user.userid = $user
match:
$user over 5m
outcome:
$risk_score = 85
$event_count = count_distinct($log.metadata.id)
$referral_url = array_distinct($log.network.http.referral_url)
$user_agent = array_distinct($log.network.http.user_agent)
$principal_application = array_distinct($log.principal.application)
$principal_ip = array_distinct($log.principal.ip)
$target_application = array_distinct($log.target.application)
//$principal_user_email_address = array_distinct(principal.user.email_addresses)
//$principal_user_userid = array_distinct($log.principal.user.userid)
$session = array_distinct($log.network.session_id)
$location = array_distinct(strings.coalesce($log.principal.location.state,$log.principal.location.country_or_region))
$target_resource_resource_type = array_distinct($log.target.resource.resource_type)
$target_url = array_distinct($log.target.url)
condition:
$log
}
YARA-L Rule Structure
Condition
Fires when at least one $log event in the 5m window.
Events
$log
metadata.product_event_type = "Set-AdminAuditLogConfig"security_result.detection_fields["UnifiedAuditLogIngestionEnabled"] = "True"
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($log.metadata.id) |
referral_url | array_distinct($log.network.http.referral_url) |
user_agent | array_distinct($log.network.http.user_agent) |
principal_application | array_distinct($log.principal.application) |
principal_ip | array_distinct($log.principal.ip) |
target_application | array_distinct($log.target.application) |
session | array_distinct($log.network.session_id) |
location | array_distinct(strings.coalesce($log.principal.location.state,$log.principal.location.country_or_region)) |
target_resource_resource_type | array_distinct($log.target.resource.resource_type) |
target_url | array_distinct($log.target.url) |
Potential Suspicious Activity Using SeCEdit
#Detects potential suspicious behaviour using secedit.exe. Such as exporting or modifying the security policy
Known False Positives
- Legitimate administrative use
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence |
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 potential_suspicious_activity_using_secedit {
meta:
author = "Janantha Marasinghe"
description = "Detects potential suspicious behaviour using secedit.exe. Such as exporting or modifying the security policy"
reference = "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/process_creation/proc_creation_win_secedit_execution.yml"
license = "https://github.com/SigmaHQ/Detection-Rule-License/blob/main/LICENSE.Detection.Rules.md"
rule_name = "Potential Suspicious Activity Using SeCEdit"
rule_id = "mr_3e4574ef-8aa1-446b-94e6-9458c01631ab"
sigma_uuid = "c2c76b77-32be-4d1f-82c9-7e544bdfe0eb"
sigma_status = "test"
//tactic = "TA0007"
//tactic = "TA0005"
//tactic = "TA0006"
//tactic = "TA0004"
tactic = "TA0003"
//technique = "T1562.002"
technique = "T1547.001"
//technique = "T1505.005"
//technique = "T1556.002"
//technique = "T1562"
//technique = "T1574.007"
//technique = "T1564.002"
//technique = "T1546.008"
//technique = "T1546.007"
//technique = "T1547.014"
//technique = "T1547.010"
//technique = "T1547.002"
//technique = "T1557"
//technique = "T1082"
type = "Detection"
data_source = "Windows Event Logs"
platform = "Windows"
severity = "Medium"
priority = "Medium"
false_positives = "Legitimate administrative use"
events:
$process.metadata.event_type = "PROCESS_LAUNCH"
(
re.regex($process.target.process.file.full_path, `\\secedit\.exe$`) nocase or
$process.src.process.file.full_path = "secedit" nocase
)
(
(
strings.contains(strings.to_lower($process.target.process.command_line), "/export") and
strings.contains(strings.to_lower($process.target.process.command_line), "/cfg")
)
or
(
strings.contains(strings.to_lower($process.target.process.command_line), "/configure") and
strings.contains(strings.to_lower($process.target.process.command_line), "/db")
)
)
$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 "\\secedit\.exe$"src.process.file.full_path = "secedit"target.process.command_line contains "/export"target.process.command_line contains "/cfg"target.process.command_line contains "/configure"target.process.command_line contains "/db"
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)) |
Safebrowsing Process Creation Hashes Seen More Than 7 Days
#Identify process and file creation using safe browsing hashes where the first and last seen are more than 7 days apart
Telemetry Coverage
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule safebrowsing_process_creation_hashes_seen_more_than_7_days {
meta:
author = "Google Cloud Security"
description = "Identify process and file creation using safe browsing hashes where the first and last seen are more than 7 days apart"
rule_id = "mr_9970945d-45cf-44ed-887a-ff876d5a072b"
rule_name = "Safebrowsing Process Creation Hashes Seen More Than 7 Days"
type = "alert"
tags = "safe browsing, first last seen"
data_source = "microsoft sysmon, crowdstrike"
severity = "Medium"
priority = "Medium"
events:
($execution.metadata.event_type = "PROCESS_LAUNCH" or $execution.metadata.event_type = "FILE_CREATION")
$execution.principal.hostname = $hostname
$execution.target.process.file.sha256 = $sha256
// Safe Browsing file hashes provided by GCTI Feed
$safebrowse.graph.entity.file.sha256 = $sha256
$safebrowse.graph.metadata.entity_type = "FILE"
$safebrowse.graph.metadata.product_name = "Google Safe Browsing"
$safebrowse.graph.metadata.source_type = "GLOBAL_CONTEXT"
// derived from events ingested by Google SecOps
$seen.graph.entity.file.sha256 = $sha256
$seen.graph.metadata.entity_type = "FILE"
$seen.graph.metadata.source_type = "DERIVED_CONTEXT"
$seen.graph.entity.file.last_seen_time.seconds > 0
604800 <= $seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds
match:
$sha256 over 1h
outcome:
$risk_score = max( if($seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds > 604800 and
$seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds < 1209600, 25, 0) +
if($seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds >= 1209600 and
$seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds < 1814400, 50, 0) +
if($seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds >= 1814400 and
$seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds < 2592000, 75, 0) +
if($seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds >= 2592000, 100, 0))
$event_count = count_distinct($execution.metadata.id)
// added to populate alert graph with additional context
$principal_hostname = array_distinct($execution.principal.hostname)
$principal_process_pid = array_distinct($execution.principal.process.pid)
$principal_process_command_line = array_distinct($execution.principal.process.command_line)
$principal_process_file_sha256 = array_distinct($execution.principal.process.file.sha256)
$principal_process_file_full_path = array_distinct($execution.principal.process.file.full_path)
$principal_process_product_specific_process_id = array_distinct($execution.principal.process.product_specific_process_id)
$principal_process_parent_process_product_specific_process_id = array_distinct($execution.principal.process.parent_process.product_specific_process_id)
$target_process_pid = array_distinct($execution.target.process.pid)
$target_process_command_line = array_distinct($execution.target.process.command_line)
// Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results
//$target_process_file_sha256 = array_distinct($execution.target.process.file.sha256)
$target_process_file_full_path = array_distinct($execution.target.process.file.full_path)
$target_process_product_specific_process_id = array_distinct($execution.target.process.product_specific_process_id)
$principal_user_userid = array_distinct($execution.principal.user.userid)
$target_file_sha256 = array_distinct($execution.target.file.sha256)
$target_file_full_path = array_distinct($execution.target.file.full_path)
condition:
$execution and $safebrowse and $seen
}
YARA-L Rule Structure
Condition
Fires when at least one $execution event in the 1h window and $safebrowse matches entity context and $seen matches entity context.
Events
$execution
$safebrowse
graph.metadata.entity_type = "FILE"graph.metadata.product_name = "Google Safe Browsing"graph.metadata.source_type = "GLOBAL_CONTEXT"
$seen
graph.metadata.entity_type = "FILE"graph.metadata.source_type = "DERIVED_CONTEXT"graph.entity.file.last_seen_time.seconds > "0"graph.entity.file.last_seen_time.seconds time_arithmetic "graph.entity.file.first_seen_time.seconds" or "604800"
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($seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds > 604800 and $seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds < 1209600, 25, 0) + if($seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds >= 1209600 and $seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds < 1814400, 50, 0) + if($seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds >= 1814400 and $seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds < 2592000, 75, 0) + if($seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds >= 2592000, 100, 0)) |
event_count | count_distinct($execution.metadata.id) |
principal_hostname | array_distinct($execution.principal.hostname) |
principal_process_pid | array_distinct($execution.principal.process.pid) |
principal_process_command_line | array_distinct($execution.principal.process.command_line) |
principal_process_file_sha256 | array_distinct($execution.principal.process.file.sha256) |
principal_process_file_full_path | array_distinct($execution.principal.process.file.full_path) |
principal_process_product_specific_process_id | array_distinct($execution.principal.process.product_specific_process_id) |
principal_process_parent_process_product_specific_process_id | array_distinct($execution.principal.process.parent_process.product_specific_process_id) |
target_process_pid | array_distinct($execution.target.process.pid) |
target_process_command_line | array_distinct($execution.target.process.command_line) |
target_process_file_full_path | array_distinct($execution.target.process.file.full_path) |
target_process_product_specific_process_id | array_distinct($execution.target.process.product_specific_process_id) |
principal_user_userid | array_distinct($execution.principal.user.userid) |
target_file_sha256 | array_distinct($execution.target.file.sha256) |
target_file_full_path | array_distinct($execution.target.file.full_path) |