Detection rules › YARA-L
YARA-L rules: 13
| Rule | Severity |
|---|---|
| Enumeration observed in the Microsoft Graph API using GraphRunner GraphRecon command | medium |
| Google Workspace New Trusted Domain Added | high |
Enumeration observed in the Microsoft Graph API using GraphRunner GraphRecon command
#Identify the use of the GraphRunner recon command Invoke-GraphRecon with the permission enum flag set, providing allowed actions and conditional access data for the current user.
References
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule ms_graph_graphrunner_graphrecon_enumeration {
meta:
author = "Google Cloud Security"
description = "Identify the use of the GraphRunner recon command Invoke-GraphRecon with the permission enum flag set, providing allowed actions and conditional access data for the current user."
rule_id = "mr_2bb3fd42-5569-4bab-9788-855425971b7f"
rule_name = "Enumeration observed in the Microsoft Graph API using GraphRunner GraphRecon command"
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_est.metadata.event_type = "NETWORK_HTTP"
$api_est.metadata.product_event_type = "Microsoft Graph Activity"
$api_est.target.url = "https://graph.microsoft.com/beta/roleManagement/directory/estimateAccess" nocase
//Can be tuned for specific User Agent strings being used - by default GraphRunner does not forge the UA for this action
//$api_est.network.http.user_agent = /PowerShell/ nocase
$api_est.network.http.method = "POST"
$api_est.network.http.response_code = 200
$api_est.principal.ip = $ip
$api_est.network.session_id = $session
$api_me.metadata.event_type = "NETWORK_HTTP"
$api_me.metadata.product_event_type = "Microsoft Graph Activity"
$api_me.target.url = "https://graph.microsoft.com/v1.0/me" nocase
//Can be tuned for specific User Agent strings being used - by default GraphRunner does not forge the UA for this action
//$api_me.network.http.user_agent = /PowerShell/ nocase
$api_me.network.http.method = "GET"
$api_me.network.http.response_code = 200
$api_me.principal.ip = $ip
$api_me.network.session_id = $session
$api_auth.metadata.event_type = "NETWORK_HTTP"
$api_auth.metadata.product_event_type = "Microsoft Graph Activity"
$api_auth.target.url = "https://graph.microsoft.com/beta/policies/authorizationPolicy" nocase
//Can be tuned for specific User Agent strings being used - by default GraphRunner does not forge the UA for this action
//$api_auth.network.http.user_agent = /PowerShell/ nocase
$api_auth.network.http.method = "GET"
$api_auth.network.http.response_code = 200
$api_auth.principal.ip = $ip
$api_auth.network.session_id = $session
match:
$ip, $session over 5m
outcome:
$risk_score = 65
$event_count = count_distinct($api_est.metadata.id) + count_distinct($api_auth.metadata.id) + count_distinct($api_me.metadata.id)
$requesting_user_guid = array_distinct($api_est.principal.user.userid)
$requesting_ip = array_distinct($api_est.principal.ip)
$user_agent = array_distinct($api_est.network.http.user_agent)
$location = array_distinct($api_est.principal.location.name)
$target_application_id_guid = array_distinct($api_est.target.resource.product_object_id)
$session_id = array_distinct($api_est.network.session_id)
condition:
$api_est and $api_auth and $api_me
}
YARA-L Rule Structure
Condition
Fires when at least one $api_est event in the 5m window and at least one $api_auth event in the 5m window and at least one $api_me event in the 5m window.
Events
$api_auth
metadata.product_event_type = "Microsoft Graph Activity"target.url = "https://graph.microsoft.com/beta/policies/authorizationPolicy"network.http.method = "GET"network.http.response_code = "200"
$api_est
metadata.product_event_type = "Microsoft Graph Activity"target.url = "https://graph.microsoft.com/beta/roleManagement/directory/estimateAccess"network.http.method = "POST"network.http.response_code = "200"
$api_me
metadata.product_event_type = "Microsoft Graph Activity"target.url = "https://graph.microsoft.com/v1.0/me"network.http.method = "GET"network.http.response_code = "200"
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_est.metadata.id) + count_distinct($api_auth.metadata.id) + count_distinct($api_me.metadata.id) |
requesting_user_guid | array_distinct($api_est.principal.user.userid) |
requesting_ip | array_distinct($api_est.principal.ip) |
user_agent | array_distinct($api_est.network.http.user_agent) |
location | array_distinct($api_est.principal.location.name) |
target_application_id_guid | array_distinct($api_est.target.resource.product_object_id) |
session_id | array_distinct($api_est.network.session_id) |
Google Workspace New Trusted Domain Added
#Identifies when a domain is added to the list of trusted domains in Google Workspace. An adversary may attempt to manipulate sharing settings for trusted domains to gain unauthorized access to sensitive files and folders within an organization.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Defense Impairment |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Google Workspace | ADD_TRUSTED_DOMAINS: Domains added to Trusted Domains |
Rules Detecting the Same Action
These rules filter on the same operation.
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule google_workspace_new_trusted_domain_added {
meta:
author = "Google Cloud Security"
description = "Identifies when a domain is added to the list of trusted domains in Google Workspace. An adversary may attempt to manipulate sharing settings for trusted domains to gain unauthorized access to sensitive files and folders within an organization."
rule_id = "mr_319d97c3-6f63-4a6c-9fab-e70cc3f03aaf"
rule_name = "Google Workspace New Trusted Domain Added"
mitre_attack_tactic = "Defense Evasion"
mitre_attack_technique = "Impair Defenses: Disable or Modify Cloud Firewall"
mitre_attack_url = "https://attack.mitre.org/techniques/T1562/007/"
mitre_attack_version = "v13.1"
type = "Alert"
data_source = "Workspace Activity"
severity = "High"
priority = "High"
events:
$ws.metadata.vendor_name = "Google Workspace"
$ws.metadata.product_name = "admin"
$ws.metadata.product_event_type = "ADD_TRUSTED_DOMAINS"
outcome:
$risk_score = max(75)
$mitre_attack_tactic = "Defense Evasion"
$mitre_attack_technique = "Impair Defenses: Disable or Modify Cloud Firewall"
$mitre_attack_technique_id = "T1562.007"
$event_count = count_distinct($ws.metadata.id)
$principal_ip = array_distinct($ws.principal.ip)
$principal_country = array_distinct($ws.principal.ip_geo_artifact.location.country_or_region)
$principal_state = array_distinct($ws.principal.ip_geo_artifact.location.state)
$principal_user_emails = array_distinct($ws.principal.user.email_addresses)
$principal_user_id = array_distinct($ws.principal.user.userid)
$target_domain = $ws.target.domain.name
condition:
$ws
}
YARA-L Rule Structure
Condition
Fires when at least one $ws event.
Events
$ws
metadata.product_event_type = "ADD_TRUSTED_DOMAINS"
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($ws.metadata.id) |
principal_ip | array_distinct($ws.principal.ip) |
principal_country | array_distinct($ws.principal.ip_geo_artifact.location.country_or_region) |
principal_state | array_distinct($ws.principal.ip_geo_artifact.location.state) |
principal_user_emails | array_distinct($ws.principal.user.email_addresses) |
principal_user_id | array_distinct($ws.principal.user.userid) |
target_domain | $ws.target.domain.name |