Detection rules › YARA-L

YARA-L rules: 28

GCP Cloud Audit Logging Removed From All Services

#
Severity
high
Type
Alert
Author
Google Cloud Security
Source
github.com/chronicle/detection-rules

Detect when GCP Cloud Audit logs are removed from all services at project or organization level. Audit logging helps organizations maintain security and minimize risk.

MITRE ATT&CK Coverage

Telemetry Coverage

PlatformRecord / event type
GCPSetIamPolicy

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

// Copyright 2024 Google LLC. Licensed under Apache-2.0.

 rule gcp_cloud_audit_logging_removed_from_all_services {

  meta:
    author = "Google Cloud Security"
    description = "Detect when GCP Cloud Audit logs are removed from all services at project or organization level. Audit logging helps organizations maintain security and minimize risk."
    rule_id = "mr_6ffed437-4666-433f-8ba8-b6043daef4c5"
    rule_name = "GCP Cloud Audit Logging Removed From All Services"
    mitre_attack_tactic = "Defense Evasion"
    mitre_attack_technique = "Impair Defenses: Disable Cloud Logs"
    mitre_attack_url = "https://attack.mitre.org/techniques/T1562/008/"
    mitre_attack_version = "v14.1"
    type = "Alert"
    data_source = "GCP Cloud Audit"
    platform = "GCP"
    severity = "High"
    priority = "High"

  events:
    $gcp.metadata.event_type = "USER_RESOURCE_UPDATE_PERMISSIONS"
    $gcp.metadata.log_type = "GCP_CLOUDAUDIT"
    $gcp.metadata.product_event_type = "SetIamPolicy"
    $gcp.security_result.action = "ALLOW"
    $gcp.security_result.detection_fields["action"] = "REMOVE"
    $gcp.security_result.detection_fields["SERVICE"] = "allServices"
    $gcp.target.resource.attribute.labels["ser_type"] = "type.googleapis.com/google.iam.v1.logging.AuditData"
    $gcp.target.application = "cloudresourcemanager.googleapis.com"

  outcome:
    //Increase risk score if it is organization wide
    $risk_score = max(45 +
      if($gcp.target.resource.name = /organizations/,30,0)
    )
    $mitre_attack_tactic = "Defense Evasion"
    $mitre_attack_technique = "Impair Defenses: Disable Cloud Logs"
    $mitre_attack_technique_id = "T1562.008"
    $event_count = count_distinct($gcp.metadata.id)
    $network_http_user_agent = array_distinct($gcp.network.http.user_agent)
    $principal_ip = array_distinct($gcp.principal.ip)
    $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region)
    $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state)
    $principal_user_id = $gcp.principal.user.userid
    $principal_user_display_name = $gcp.principal.user.user_display_name
    $target_resource_name = $gcp.target.resource.name
    $event_name = $gcp.metadata.product_event_type

  condition:
    $gcp
}

YARA-L Rule Structure

Condition

Fires when at least one $gcp event.

Events

$gcp USER_RESOURCE_UPDATE_PERMISSIONS

  • metadata.log_type = "GCP_CLOUDAUDIT"
  • metadata.product_event_type = "SetIamPolicy"
  • security_result.action = "ALLOW"
  • security_result.detection_fields["action"] = "REMOVE"
  • security_result.detection_fields["SERVICE"] = "allServices"
  • target.resource.attribute.labels["ser_type"] = "type.googleapis.com/google.iam.v1.logging.AuditData"
  • target.application = "cloudresourcemanager.googleapis.com"

Outcome

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

FieldExpression
risk_scoremax(45 + if($gcp.target.resource.name = /organizations/,30,0) )
event_countcount_distinct($gcp.metadata.id)
network_http_user_agentarray_distinct($gcp.network.http.user_agent)
principal_iparray_distinct($gcp.principal.ip)
principal_ip_countryarray_distinct($gcp.principal.ip_geo_artifact.location.country_or_region)
principal_ip_statearray_distinct($gcp.principal.ip_geo_artifact.location.state)
principal_user_id$gcp.principal.user.userid
principal_user_display_name$gcp.principal.user.user_display_name
target_resource_name$gcp.target.resource.name
event_name$gcp.metadata.product_event_type

Hunt for Undocumented API - Estimate Access called in Microsoft Graph API

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

Estimate Access is an undocumented API in MS Graph and is used in the following GraphRunner functions Get-UpdatableGroups, Get-DynamicGroups and Invoke-GraphRecon. Although not inherently malicious, it does submit an action and then determines if the user can perform it

References

Rule Body

// Copyright 2025 Google LLC. Licensed under Apache-2.0.

rule ms_graph_estimate_access {

  meta:
    author = "Google Cloud Security"
    description = "Estimate Access is an undocumented API in MS Graph and is used in the following GraphRunner functions Get-UpdatableGroups, Get-DynamicGroups and Invoke-GraphRecon. Although not inherently malicious, it does submit an action and then determines if the user can perform it"
    rule_id = "mr_381921b8-e935-4720-9ff6-2d966aa00a32"
    rule_name = "Hunt for Undocumented API - Estimate Access called in Microsoft Graph API"
    assumption = "This can be chatty due to other commands calling this single API. Additional tuning of admin consoles and user agent strings may be needed."
    reference = "https://github.com/dafthack/GraphRunner/blob/main/GraphRunner.ps1"
    type = "Hunt"
    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"
    $api.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.network.http.method = "POST"
    $api.network.http.response_code = 200
    //Used to filter admin consoles and/or internal Microsoft addresses as needed, the following IP CIDR blocks are part of Azure for instance
    //$api.principal.ip != "10.10.10.10"
    NOT (
        net.ip_in_range_cidr($api.principal.ip, "20.228.0.0/18") or
        net.ip_in_range_cidr($api.principal.ip, "20.228.64.0/18") or
        net.ip_in_range_cidr($api.principal.ip, "20.228.128.0/17")
    )
    /*Used to filter Microsoft IPv6 network ranges, can tune this further as needed;
      additional ranges may need to be added, but this provides an example on how this can be done. */
    NOT net.ip_in_range_cidr($api.principal.ip, "2a01:0111:f100:0000:0000:0000:0000:0000/40")
    $api.principal.ip = $ip
    $api.network.session_id = $session

  match:
    $ip, $session over 5m

  outcome:
    $risk_score = 35
    $event_count = count_distinct($api.metadata.id)
    $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)

  condition:
    //Can be modified to add a threshold for how many estimate access events is considered accesptable
    $api // and $event_count > 10
}

YARA-L Rule Structure

Condition

Fires when at least one $api event in the 5m window.

Events

$api NETWORK_HTTP

  • 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"
  • principal.ip cidr_match "20.228.0.0/18"
  • principal.ip cidr_match "20.228.64.0/18"
  • principal.ip cidr_match "20.228.128.0/17"
  • principal.ip cidr_match "2a01:0111:f100:0000:0000:0000:0000:0000/40"

Match and Correlation

Match key
$ip (principal.ip), $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_score35
event_countcount_distinct($api.metadata.id)
requesting_user_guidarray_distinct($api.principal.user.userid)
requesting_iparray_distinct($api.principal.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)

MITRE ATT&CK T1021.002 Windows Admin Share With User Enrichment

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

Net use commands for SMB/Windows admin shares focused on UDM enriched user fields

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

// Copyright 2023 Google LLC. Licensed under Apache-2.0.

rule mitre_attack_T1021_002_windows_admin_share_with_user_enrichment {

  meta:
    author = "Google Cloud Security"
    description = "Net use commands for SMB/Windows admin shares focused on UDM enriched user fields"
    rule_id = "mr_57f52ed2-c7e2-4c8d-b308-2a3238986e98"
    rule_name = "MITRE ATT&CK T1021.002 Windows Admin Share With User Enrichment"
    tactic = "TA0008"
    technique = "T1021.002"
    type = "alert"
    tags = "user enrichment"
    platform = "Windows"
    data_source = "microsoft sysmon, microsoft windows events"
    severity = "Low"
    priority = "Low"

  events:
    $process.metadata.event_type = "PROCESS_LAUNCH"
    $process.target.process.command_line = /net.*use.*(C|ADMIN|IPC)\$/ nocase
    $process.principal.user.userid = $userid

    /* Enriched UDM fields from assets & users can often be used without needing to
    join to entity graph for these fields, assuming assets and users are being ingested */
    $process.principal.user.department != "Information Technology" or
    $process.principal.user.title = "Intern"

  match:
    $userid over 5m

  outcome:
    $risk_score = 35
    $event_count = count_distinct($process.metadata.id)
    // added to populate alert graph with additional context
    $principal_hostname = array_distinct($process.principal.hostname)
    $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_specific_process_id = array_distinct($process.principal.process.product_specific_process_id)
    $principal_process_parent_process_product_specific_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_specific_process_id = array_distinct($process.target.process.product_specific_process_id)
    // Commented out principal.ip because it is already represented in graph as match variable. If match changes, can uncomment to add to results
    //$principal_user_userid = array_distinct($process.principal.user.userid)

  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 matches "net.*use.*(C|ADMIN|IPC)\$"
  • principal.user.department != "Information Technology"
  • principal.user.title = "Intern"

Match and Correlation

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_score35
event_countcount_distinct($process.metadata.id)
principal_hostnamearray_distinct($process.principal.hostname)
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_specific_process_idarray_distinct($process.principal.process.product_specific_process_id)
principal_process_parent_process_product_specific_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_specific_process_idarray_distinct($process.target.process.product_specific_process_id)

Potential Webshell Process Execution

#
Severity
medium
Author
Google Cloud Security
Source
github.com/chronicle/detection-rules

Detects on the execution arguments associated with cmd.exe invocations originating from an active ASP.NET webshell.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

// Copyright 2025 Google LLC. Licensed under Apache-2.0.

rule ttp_windows_webserver_process_potential_webshell_execution {
  meta:
    author = "Google Cloud Security"
    rule_name = "Potential Webshell Process Execution"
    description = "Detects on the execution arguments associated with cmd.exe invocations originating from an active ASP.NET webshell."
    severity = "Medium"
    tactic = "TA0003"
    technique = "T1505.003"
    rule_id = "mr_37c87ffe-d6ab-4fc6-a191-ad0da8f9ec98"

  events:
    $e.metadata.event_type = "PROCESS_LAUNCH"
    $e.principal.process.file.full_path = /(^|\\)(w3wp.exe|httpd.exe|tomcat.exe|tomcat\d+\.exe)$/ nocase
    $e.target.process.command_line = /^"[A-Za-z]:\\.{16}\\cmd\.exe" \/c [^"][^:]/ nocase
    $e.target.process.command_line = /^"c:\\windows\\system32\\cmd\.exe" \/c/ nocase
    //Tuning
    not $e.target.process.command_line = /^"C:\\Windows\\system32\\cmd.exe" \/c ping / nocase
    not $e.target.process.command_line = /^"C:\\Windows\\System32\\cmd.exe" \/c ftp.exe / nocase
    not $e.target.process.command_line = /^"C:\\Windows\\system32\\cmd.exe" \/c az account get-access-token/ nocase
    not $e.target.process.command_line = /^"C:\\Windows\\System32\\cmd.exe" \/c GoalBus.exe  \/DBT:sql / nocase
    not $e.target.process.command_line = /"C:\\Windows\\System32\\cmd.exe" \/c Rscript "D:\\\\Opti\\\\R\\\\\\R/ nocase
    not $e.target.process.command_line = /^"C:\\Windows\\system32\\cmd\.exe" \/c timeout \d+ \/nobreak$/ nocase
    not $e.target.process.command_line = /^"C:\\Windows\\System32\\cmd\.exe" \/c copy.*\\Department\\HR\\HR-Wellness\\APPS$/ nocase
    not $e.target.process.command_line = /^"C:\\Windows\\System32\\cmd.exe" \/C\s+del\s.*\\System5\\Web\\NDA\\TempUploadFiles\\/ nocase
    not $e.target.process.command_line = /^"C:\\Windows\\System32\\cmd\.exe".*--footer-html "[A-Z]:\\PublishedApp\\SystemProductRelease\\.*\\ProductReleasePDF\\/ nocase
    not $e.target.process.command_line = /^"C:\\Windows\\System32\\cmd.exe"\s+\/c\s+(rmdir|rename)\s.*"D:\\Domains\\Internal\\Deploy\\(Tools|Released)\\/ nocase
    not $e.target.process.command_line = /^"C:\\windows\\system32\\cmd.exe"\s+\/C type\s+.*\\CHARGEBACK\\(BILLING|RETAIL)\\[^\\]+\\TEMP\\header.txt/ nocase
    not $e.principal.process.command_line = /w3wp.exe\s*-ap\s*"EUSI"\s.*\\apppools\\EUSI\\EUSI\.config"/ nocase

  outcome:
    $principal_hostname = $e.principal.hostname
    $risk_score = 65
    $vendor_name = array($e.metadata.vendor_name)
    $product_name = $e.metadata.product_name
    $victim_uid = $e.principal.asset.asset_id
    $victim_name = $e.principal.asset.hostname
    $victim_netid = array($e.principal.ip)
    $adversary_uid = $e.principal.user.userid
    $adversary_name = $e.principal.user.user_display_name
    $adversary_netid = $e.principal.user.windows_sid
    $tmp1 = max(
        if($e.security_result.action != "BLOCK" and $e.security_result.action != "UNKNOWN_ACTION", 2)
    )
    $tmp2 = max(
        if($e.security_result.action = "BLOCK", 1)
    )
    $result = arrays.index_to_str(strings.split("attempted,failed,succeeded,succeeded"), $tmp1 + $tmp2)
    $result_time = $e.metadata.event_timestamp.seconds
    $event_count = 1

  condition:
    $e
}

YARA-L Rule Structure

Condition

Fires when at least one $e event.

Events

$e PROCESS_LAUNCH (1, 4688)

  • principal.process.file.full_path matches "(^|\\)(w3wp.exe|httpd.exe|tomcat.exe|tomcat\d+\.exe)$"
  • target.process.command_line matches "^"[A-Za-z]:\\.{16}\\cmd\.exe" \/c [^"][^:]"
  • target.process.command_line matches "^"c:\\windows\\system32\\cmd\.exe" \/c"
  • target.process.command_line matches "^"C:\\Windows\\system32\\cmd.exe" \/c ping "
  • target.process.command_line matches "^"C:\\Windows\\System32\\cmd.exe" \/c ftp.exe "
  • target.process.command_line matches "^"C:\\Windows\\system32\\cmd.exe" \/c az account get-access-token"
  • target.process.command_line matches "^"C:\\Windows\\System32\\cmd.exe" \/c GoalBus.exe \/DBT:sql "
  • target.process.command_line matches ""C:\\Windows\\System32\\cmd.exe" \/c Rscript "D:\\\\Opti\\\\R\\\\\\R"
  • target.process.command_line matches "^"C:\\Windows\\system32\\cmd\.exe" \/c timeout \d+ \/nobreak$"
  • target.process.command_line matches "^"C:\\Windows\\System32\\cmd\.exe" \/c copy.*\\Department\\HR\\HR-Wellness\\APPS$"
  • target.process.command_line matches "^"C:\\Windows\\System32\\cmd.exe" \/C\s+del\s.*\\System5\\Web\\NDA\\TempUploadFiles\\"
  • target.process.command_line matches "^"C:\\Windows\\System32\\cmd\.exe".*--footer-html "[A-Z]:\\PublishedApp\\SystemProductRelease\\.*\\ProductReleasePDF\\"
  • target.process.command_line matches "^"C:\\Windows\\System32\\cmd.exe"\s+\/c\s+(rmdir|rename)\s.*"D:\\Domains\\Internal\\Deploy\\(Tools|Released)\\"
  • target.process.command_line matches "^"C:\\windows\\system32\\cmd.exe"\s+\/C type\s+.*\\CHARGEBACK\\(BILLING|RETAIL)\\[^\\]+\\TEMP\\header.txt"
  • principal.process.command_line matches "w3wp.exe\s*-ap\s*"EUSI"\s.*\\apppools\\EUSI\\EUSI\.config""

Outcome

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

FieldExpression
principal_hostname$e.principal.hostname
risk_score65
vendor_namearray($e.metadata.vendor_name)
product_name$e.metadata.product_name
victim_uid$e.principal.asset.asset_id
victim_name$e.principal.asset.hostname
victim_netidarray($e.principal.ip)
adversary_uid$e.principal.user.userid
adversary_name$e.principal.user.user_display_name
adversary_netid$e.principal.user.windows_sid
tmp1max( if($e.security_result.action != "BLOCK" and $e.security_result.action != "UNKNOWN_ACTION", 2) )
tmp2max( if($e.security_result.action = "BLOCK", 1) )
resultarrays.index_to_str(strings.split("attempted,failed,succeeded,succeeded"), $tmp1 + $tmp2)
result_time$e.metadata.event_timestamp.seconds
event_count1

Back to all YARA-L rules