Detection rules › Splunk

Zoom High Video Latency

Status
experimental
Severity
low
Group by
_raw, email
Author
Marissa Bower, Raven Tait
Source
github.com/splunk/security_content

Detects particularly high latency from Zoom logs. Latency observed from threat actors performing Remote Employment Fraud (REF) is typically well above what’s normal for the majority of employees.

MITRE ATT&CK coverage

TacticTechniques
Initial AccessT1078 Valid Accounts
PersistenceT1078 Valid Accounts
Privilege EscalationT1078 Valid Accounts
StealthT1078 Valid Accounts

Rule body splunk

name: Zoom High Video Latency
id: 6ad6b548-adfa-452c-aa77-9ff94877e832
version: 4
creation_date: '2025-06-12'
modification_date: '2026-05-13'
author: Marissa Bower, Raven Tait
status: experimental
type: Anomaly
description: Detects particularly high latency from Zoom logs. Latency observed from threat actors performing Remote Employment Fraud (REF) is typically well above what’s normal for the majority of employees.
data_source: []
search: '`zoom_index` | spath "payload.object.participant.qos{}.type" | search "payload.object.participant.qos{}.type"=video_input | rename payload.object.participant.qos{}.details.avg_latency as avg_latency "payload.object.participant.qos{}.details.latency" as latency payload.object.participant.email as email | rex field=avg_latency "(?<average_latency>\d+) ms" | rex field=latency "(?<overall_latency>\d+) ms" | search email="*" | table email overall_latency latency avg_latency average_latency _raw | stats latest(overall_latency) as overall_latency by email _raw | where overall_latency>300 | `zoom_high_video_latency_filter`'
how_to_implement: The analytic leverages Zoom logs to be ingested using Splunk Connect for Zoom (https://splunkbase.splunk.com/app/4961)
known_false_positives: While latency could simply indicate a slow network connection, when combined with other indicators, it can help build a more complete picture. Tune the threshold as needed for your environment baseline.
drilldown_searches:
    - name: View the detection results for - "$email$"
      search: '%original_detection_search% | search  payload.object.participant.email = "$email$"'
      earliest_offset: $info_min_time$
      latest_offset: $info_max_time$
    - name: View risk events for the last 7 days for - "$email$"
      search: '| from datamodel Risk.All_Risk | search normalized_risk_object IN ("$email$") | stats count min(_time) as firstTime max(_time) as lastTime values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories) as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic) as "ATT&CK Tactics" by normalized_risk_object | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`'
      earliest_offset: 7d
      latest_offset: "0"
intermediate_findings:
    entities:
        - field: email
          type: user
          score: 20
          message: Suspicious latency from $email$ in Zoom activity.
analytic_story:
    - Remote Employment Fraud
asset_type: Identity
mitre_attack_id:
    - T1078
product:
    - Splunk Enterprise
    - Splunk Enterprise Security
    - Splunk Cloud
category: application
security_domain: identity

Stages and Predicates

Stage 1: search

`zoom_index`

Stage 2: spath

| spath "payload.object.participant.qos{}.type"

Stage 3: search

| search "payload.object.participant.qos{}.type"=video_input

Stage 4: rename

| rename payload.object.participant.qos{}.details.avg_latency as avg_latency "payload.object.participant.qos{}.details.latency" as latency payload.object.participant.email as email

Stage 5: rex

| rex field=avg_latency "(?<average_latency>\d+) ms"

Stage 6: rex

| rex field=latency "(?<overall_latency>\d+) ms"

Stage 7: search

| search email="*"

Stage 8: table

| table email overall_latency latency avg_latency average_latency _raw

Stage 9: stats

| stats latest(overall_latency) as overall_latency by email _raw

Stage 10: where

| where overall_latency>300

Stage 11: search

| `zoom_high_video_latency_filter`

Indicators

Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.