Detection rules › YARA-L

YARA-L rules: 1d

Enumeration of inboxes accessible by a user in the Microsoft Graph API

#
Severity
medium
Type
Alert
Time window
5m
Match by
ip, session
Author
Google Cloud Security
Source
github.com/chronicle/detection-rules

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 NETWORK_HTTP

  • 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

Match key
$ip (principal.ip[0]), $session (network.session_id)
Within
5m

Outcome

Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.

FieldExpression
risk_score65
event_countcount_distinct($api.metadata.id)
requesting_user_guidarray_distinct($api.principal.user.userid)
requesting_iparray_distinct($ip)
user_agentarray_distinct($api.network.http.user_agent)
locationarray_distinct($api.principal.location.name)
target_application_id_guidarray_distinct($api.target.resource.product_object_id)
session_idarray_distinct($api.network.session_id)
total_scanned_userscount($scanned_user)
successfully_scanned_usersarray_distinct(if($api.network.http.response_code = 200, $scanned_user,""))
successful_accesssum(if($api.network.http.response_code = 200, 1,0))
forbidden_accesssum(if($api.network.http.response_code = 403, 1,0))
inbox_not_foundsum(if($api.network.http.response_code = 404, 1,0))
inbox_othersum(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

#
Severity
high
Type
Detection
Time window
5m
Match by
hostname
Author
E.M. Anhaus, Tony Lambert, oscd.community, Nasreddine Bencherchali (Nextron Systems)
Source
github.com/chronicle/detection-rules

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

TacticTechniques
Credential Access

References

Telemetry Coverage

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 PROCESS_LAUNCH (1, 4688)

  • 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

Match key
$hostname (principal.hostname)
Within
5m

Outcome

Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.

FieldExpression
risk_scoremax(if($process.principal.user.userid = "user" and $process.principal.hostname = "hostname", 0, 15))
principal_process_pidarray_distinct($process.principal.process.pid)
principal_process_command_linearray_distinct($process.principal.process.command_line)
principal_process_file_sha256array_distinct($process.principal.process.file.sha256)
principal_process_file_full_patharray_distinct($process.principal.process.file.full_path)
principal_process_product_specfic_process_idarray_distinct($process.principal.process.product_specific_process_id)
principal_process_parent_process_product_specfic_process_idarray_distinct($process.principal.process.parent_process.product_specific_process_id)
target_process_pidarray_distinct($process.target.process.pid)
target_process_command_linearray_distinct($process.target.process.command_line)
target_process_file_sha256array_distinct($process.target.process.file.sha256)
target_process_file_full_patharray_distinct($process.target.process.file.full_path)
target_process_product_specfic_process_idarray_distinct($process.target.process.product_specific_process_id)
principal_user_useridarray_distinct($process.principal.user.userid)
log_typearray_distinct(strings.concat($process.metadata.log_type,"/",$process.metadata.product_event_type))

MITRE ATT&CK T1110.001 Windows Repeated Authentication Failures Before Successful One

#
Severity
medium
Type
alert
Time window
15m
Match by
hostname, user
Author
Google Cloud Security
Source
github.com/chronicle/detection-rules

Detect Multiple Failed Login Attempts followed by Successful Login

MITRE ATT&CK Coverage

TacticTechniques
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 USER_LOGIN (4625)

  • security_result.action = "BLOCK"
  • metadata.product_event_type = "4625"

$success USER_LOGIN (4624)

  • security_result.action = "ALLOW"
  • metadata.product_event_type = "4624"

Match and Correlation

Order
$fail before $success
Match key
$hostname (principal.hostname), $user (target.user.userid)
Within
15m

Outcome

Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.

FieldExpression
risk_scoremax(if($hostname = /activedir/, 75, 50))
failed_login_threshold5
impacted_systemsarray_distinct($hostname)
impacted_usersarray_distinct($user)
principal_iparray_distinct($success.principal.ip)
target_hostnamearray_distinct($success.target.hostname)
src_hostnamearray_distinct($success.src.hostname)
target_iparray_distinct($success.target.ip)
principal_user_useridarray_distinct($success.principal.user.userid)
principal_resource_namearray_distinct($success.principal.resource.name)
target_resource_namearray_distinct($success.target.resource.name)
target_urlarray_distinct($success.target.url)

Potential Tampering With RDP Related Registry Keys Via Reg.EXE

#

sap critial role assigned to new user

#
Severity
critical
Time window
1h
Match by
target_user
Author
Google Cloud Security
Source
github.com/chronicle/detection-rules

Detects the assignment of high-privilege roles by correlating Change Documents (PFCG) with Security Audit logs (AUD) for IP attribution.

MITRE ATT&CK Coverage

TacticTechniques
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

Match key
$target_user
Within
1h

Outcome

Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.

FieldExpression
user_that_created_accountarray_distinct($audit.principal.user.userid)
user_that_assigned_rolearray_distinct($change.principal.user.userid)
source_iparray_distinct($audit.principal.ip)
assigned_rolearray_distinct($role)
system_idarray_distinct($audit.target.application)
risk_score95

VT Relationships File Downloaded From IP

#
Severity
high
Type
alert
Time window
5m
Match by
userid
Author
Google Cloud Security
Source
github.com/chronicle/detection-rules

Alert on downloading a known file hash from a known IP with VT Relationships.

Telemetry Coverage

ProviderRecord / event type
SysmonEvent 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 NETWORK_HTTP

No field filters (binds the event for correlation only).

$file FILE_CREATION (11)

No field filters (binds the event for correlation only).

$vt entity context (FILE)

  • 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

Order
$network before $file
Match key
$userid (principal.user.userid)
Within
5m

Outcome

Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.

FieldExpression
risk_score85
principal_hostnamearray_distinct($network.principal.hostname)
target_hostnamearray_distinct($network.target.hostname)
principal_process_pidarray_distinct($file.principal.process.pid)
principal_process_command_linearray_distinct($file.principal.process.command_line)
principal_process_file_sha256array_distinct($file.principal.process.file.sha256)
principal_process_file_full_patharray_distinct($file.principal.process.file.full_path)
principal_process_product_specific_process_idarray_distinct($file.principal.process.product_specific_process_id)
principal_process_parent_process_product_specific_process_idarray_distinct($file.principal.process.parent_process.product_specific_process_id)
target_process_pidarray_distinct($file.target.process.pid)
target_process_command_linearray_distinct($file.target.process.command_line)
target_process_file_sha256array_distinct($file.target.process.file.sha256)
target_process_file_full_patharray_distinct($file.target.process.file.full_path)
target_process_product_specific_process_idarray_distinct($file.target.process.product_specific_process_id)
target_process_parent_process_product_specific_process_idarray_distinct($file.target.process.parent_process.product_specific_process_id)
target_user_useridarray_distinct($file.target.user.userid)
target_urlarray_distinct($network.target.url)

Back to all YARA-L rules