Query Details

34 CSL ZPA App Volume Spike

Query

id: b134c2d3-e4f5-4a6b-7c8d-9e0f1a2b3c4d
name: "Zscaler ZPA - App Access Volume Spike - User Accessing Significantly More Apps Than Baseline"
version: 1.0.0
kind: Scheduled
description: |
  Detects ZPA users whose distinct application access count in a 1-hour window exceeds their 14-day daily average by 3x or more. A single user suddenly accessing many more internal apps than usual is a strong indicator of automated reconnaissance, credential compromise where the attacker is enumerating internal resources, or an insider staging access before an exfiltration event. MITRE ATT&CK: T1046 (Network Service Discovery), T1078 (Valid Accounts).
severity: Medium
requiredDataConnectors:
  - connectorId: CommonSecurityEvents
    dataTypes:
      - CommonSecurityLog
queryFrequency: PT1H
queryPeriod: P14D
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Discovery
  - InitialAccess
relevantTechniques:
  - T1046
  - T1078
query: |
    let recentWindow   = 1h;
    let baselineWindow = 14d;
    let baseline = CommonSecurityLog
        | where TimeGenerated between (ago(baselineWindow) .. ago(recentWindow))
        | where DeviceVendor == "Zscaler" and DeviceProduct has "ZPA"
        | where DeviceAction !in ("block", "BLOCK", "Blocked", "Failed")
        | where isnotempty(SourceUserName)
        | summarize DailyApps = dcount(DestinationHostName)
            by SourceUserName, Day = bin(TimeGenerated, 1d)
        | summarize AvgDailyApps = avg(DailyApps)
            by SourceUserName;
    let recent = CommonSecurityLog
        | where TimeGenerated > ago(recentWindow)
        | where DeviceVendor == "Zscaler" and DeviceProduct has "ZPA"
        | where DeviceAction !in ("block", "BLOCK", "Blocked", "Failed")
        | where isnotempty(SourceUserName)
        | summarize
            RecentAppCount = dcount(DestinationHostName),
            RecentApps     = make_set(DestinationHostName, 20),
            RecentConns    = count()
            by SourceUserName;
    recent
    | join kind=inner baseline on SourceUserName
    | where AvgDailyApps > 0
    | extend SpikeRatio = round(toreal(RecentAppCount) / toreal(AvgDailyApps), 1)
    | where SpikeRatio >= 3.0 and RecentAppCount >= 5
    | project SourceUserName, RecentAppCount, AvgDailyApps, SpikeRatio, RecentApps, RecentConns
    | order by SpikeRatio desc
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: SourceUserName
customDetails:
  RecentAppCount: RecentAppCount
  SpikeRatio: SpikeRatio
  AvgDailyApps: AvgDailyApps
alertDetailsOverride:
  alertDisplayNameFormat: "ZPA App Volume Spike - {{SourceUserName}} ({{SpikeRatio}}x baseline)"
  alertDescriptionFormat: "ZPA user {{SourceUserName}} accessed {{RecentAppCount}} distinct apps in 1h vs avg {{AvgDailyApps}}/day ({{SpikeRatio}}x spike)."
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: PT6H
    matchingMethod: Selected
    groupByEntities:
      - Account
    groupByAlertDetails: []
    groupByCustomDetails: []

Explanation

This query is designed to detect unusual behavior in users accessing applications through Zscaler Private Access (ZPA). Here's a simplified breakdown of what it does:

  1. Purpose: The query identifies users who access significantly more applications than their usual pattern, which could indicate suspicious activity such as automated reconnaissance, credential compromise, or insider threats.

  2. How It Works:

    • It examines the number of distinct applications accessed by each user in the past hour.
    • It compares this number to the user's average daily application access over the past 14 days.
    • If a user accesses three times more applications than their average, and at least five different applications in the past hour, they are flagged.
  3. Technical Details:

    • The query uses data from the CommonSecurityLog where the vendor is "Zscaler" and the product includes "ZPA".
    • It excludes actions that are blocked or failed.
    • It calculates the daily average of applications accessed by each user over the last 14 days.
    • It checks the number of applications accessed in the last hour and calculates a "Spike Ratio" (current access count divided by the average).
    • Users with a Spike Ratio of 3.0 or higher are highlighted.
  4. Output:

    • The query outputs details such as the username, the number of applications accessed recently, the average daily access, the spike ratio, and a list of recently accessed applications.
    • It orders the results by the spike ratio in descending order.
  5. Alerts and Incidents:

    • If the conditions are met, an alert is generated with details about the spike.
    • The alert can create an incident, grouping similar alerts by user account for easier management.

In summary, this query helps security teams identify potential security incidents by flagging users who suddenly access a lot more applications than usual, which could be a sign of malicious activity.

Details

David Alonso profile picture

David Alonso

Released: March 2, 2026

Tables

CommonSecurityLog

Keywords

ZscalerZPAAppAccessVolumeSpikeUserApplicationAccessBaselineReconnaissanceCredentialCompromiseAttackerInternalResourcesInsiderExfiltrationEventMITREATTCKNetworkServiceDiscoveryValidAccountsCommonSecurityEventsCommonSecurityLogDeviceVendorDeviceProductDeviceActionSourceUserNameDestinationHostNameRecentAppCountRecentAppsRecentConnsSpikeRatioAccountFullName

Operators

letbetweenago..has!inisnotemptysummarizedcountbinavg>make_setcountjoinkind=inneronextendroundtoreal/>=projectorder bydesc

Actions