Query Details

Zscaler ZIA - APT Control Evasion: Agent Tampering and Visibility Degradation

37 CSL ZIA Control Evasion Visibility Degradation

Query

let baselineWindow            = 7d;
let recentWindow              = 4h;
let minBaselineRequestsPerDay = 10;
let ZIA_BaselineHosts =
    CommonSecurityLog
    | where TimeGenerated between (ago(baselineWindow) .. ago(recentWindow))
    | where DeviceVendor == "Zscaler"
    | where isnotempty(SourceIP) and isnotempty(SourceUserName)
    | summarize
        BaselineRequestsPerDay = round(toreal(count()) / (baselineWindow / 1d), 1),
        BaselineUsers          = make_set(SourceUserName, 5)
      by SourceIP
    | where BaselineRequestsPerDay >= minBaselineRequestsPerDay;
let ZIA_RecentActive =
    CommonSecurityLog
    | where TimeGenerated > ago(recentWindow)
    | where DeviceVendor == "Zscaler"
    | where isnotempty(SourceIP)
    | distinct SourceIP;
let SilentHosts =
    ZIA_BaselineHosts
    | join kind=leftanti ZIA_RecentActive on SourceIP;
let AgentTampering =
    DeviceEvents
    | where TimeGenerated > ago(recentWindow)
    | where ActionType in (
        "ServiceUninstalled", "ServiceStopped", "DriverUnloaded",
        "TamperingAttempt", "AntivirusScanFailed")
      or (ActionType == "ProcessCreated"
          and InitiatingProcessCommandLine has_any (
              "ZscalerApp", "ZSATunnel", "ZSAUpdater", "ZscalerService",
              "sc stop", "sc delete", "net stop", "taskkill"))
    | summarize
        TamperEvents    = count(),
        TamperActions   = make_set(ActionType, 10),
        TamperCmds      = make_set(InitiatingProcessCommandLine, 5),
        TamperFirstSeen = min(TimeGenerated)
      by DeviceName;
let SvcTampering =
    SecurityEvent
    | where TimeGenerated > ago(recentWindow)
    | where EventID in (7034, 7035, 7036, 7040, 7045)
    | where ServiceName has_any (
        "ZscalerService", "ZSATunnel", "ZSAUpdater",
        "MsSense", "SenseSvc", "WdFilter", "AADConnect")
    | summarize
        SvcEvents      = count(),
        SvcNames       = make_set(ServiceName, 10),
        SvcStateChange = make_set(Message, 5),
        SvcFirstSeen   = min(TimeGenerated)
      by Computer;
SilentHosts
| join kind=leftouter AgentTampering on $left.SourceIP == $right.DeviceName
| join kind=leftouter SvcTampering   on $left.SourceIP == $right.Computer
| extend
    TamperEvents = coalesce(TamperEvents, 0),
    SvcEvents    = coalesce(SvcEvents, 0)
| extend EvasionScore =
    toint(BaselineRequestsPerDay * 2)
  + iff(TamperEvents > 0, 50, 0)
  + iff(SvcEvents    > 0, 40, 0)
| project
    SourceIP, BaselineUsers, BaselineRequestsPerDay,
    TamperEvents, TamperActions, TamperCmds,
    SvcEvents, SvcNames, SvcStateChange,
    EvasionScore,
    TamperFirstSeen, SvcFirstSeen
| order by EvasionScore desc, BaselineRequestsPerDay desc

Explanation

This query is designed to detect potential security threats by identifying hosts that have suddenly stopped sending data to Zscaler, a security service, and checking for signs of tampering with security agents on those hosts. Here's a simple breakdown:

  1. Purpose: The query aims to find cases where an attacker or insider might be trying to hide their activities by disrupting security monitoring tools like Zscaler or endpoint detection and response (EDR) systems.

  2. Detection Criteria:

    • Visibility Loss: It looks for hosts that were previously active (sending at least 10 requests per day) but have gone silent in the last 4 hours, without any known global outage.
    • Agent Tampering: It checks for events indicating tampering with security agents, such as stopping or uninstalling services related to Zscaler or Microsoft Defender.
  3. Scoring and Alerts:

    • Hosts that have gone silent are flagged for investigation.
    • If there are also tampering events, it raises a critical alert.
    • Each host is given an "Evasion Score" based on their activity and tampering events, helping prioritize investigations.
  4. Outcome: The query generates a ranked list of suspicious hosts, which can be used to manually investigate and potentially isolate compromised endpoints.

  5. Technical Details:

    • It uses data from Zscaler logs, Microsoft Defender events, and Windows Security events.
    • The query runs every hour, analyzing data from the past 7 days.
    • Alerts are generated for hosts with suspicious activity, and incidents are created for further investigation.

Overall, this query helps security teams identify and respond to potential threats where attackers might be trying to evade detection by disabling or interfering with security tools.

Details

David Alonso profile picture

David Alonso

Released: March 2, 2026

Tables

CommonSecurityLogDeviceEventsSecurityEvent

Keywords

ZscalerZIAAgentTamperingVisibilityDegradationSOCMicrosoftDefenderEndpointDeviceEventsSecurityEventWindowsServiceControlManagerMITREATT&CKDefenseEvasionImpairDefensesIndicatorRemovalZeroTrustArchitectureCommonSecurityEventsCommonSecurityLogMicrosoftDefenderAdvancedThreatProtectionSecurityEventsSourceIPSourceUserNameDeviceVendorActionTypeInitiatingProcessCommandLineServiceNameMessageComputerEvasionScoreBaselineRequestsPerDayTamperEventsSvcEvents

Operators

letbetweenagoisnotemptysummarizeroundtorealcountmake_setbydistinctjoinkindoninorhas_anymincoalescetointiffprojectextendorder bydesc

Severity

High

Tactics

DefenseEvasion

MITRE Techniques

Frequency: PT1H

Period: P7D

Actions

GitHub