Detection rules › Kusto
Netskope - Excessive Downloads Detection (Spike vs Baseline)
Detects users with excessive download activity compared to their 7-day baseline. Triggers when current download volume exceeds 3x the average.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Collection |
Rule body
id: dd0ebd84-ffbe-45df-848b-0615ac446b04
name: Netskope - Excessive Downloads Detection (Spike vs Baseline)
description: |
Detects users with excessive download activity compared to their 7-day baseline. Triggers when current download volume exceeds 3x the average.
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: NetskopeWebTxConnector
dataTypes:
- NetskopeWebTransactions_CL
queryFrequency: 1h
queryPeriod: 7d
triggerOperator: gt
triggerThreshold: 0
tactics:
- Exfiltration
- Collection
relevantTechniques:
- T1530
- T1074
query: |
let lookbackPeriod = 7d;
let currentPeriod = 1h;
let threshold = 3;
let baseline = NetskopeWebTransactions_CL
| where TimeGenerated between (ago(lookbackPeriod) .. ago(currentPeriod))
| where isnotempty(CsUsername)
| where XCsAppActivity =~ 'Download' or ScBytes > 0
| summarize
BaselineAvgBytes = avg(ScBytes),
BaselineTotalBytes = sum(ScBytes),
BaselineCount = count()
by CsUsername
| extend BaselineDailyAvg = BaselineTotalBytes / 7;
let current = NetskopeWebTransactions_CL
| where TimeGenerated > ago(currentPeriod)
| where isnotempty(CsUsername)
| where XCsAppActivity =~ 'Download' or ScBytes > 0
| summarize
CurrentTotalBytes = sum(ScBytes),
CurrentCount = count(),
Apps = make_set(XCsApp),
Files = make_set(XCsAppObjectName)
by CsUsername;
current
| join kind=inner baseline on CsUsername
| where CurrentTotalBytes > (BaselineDailyAvg * threshold)
| extend
SpikeMultiplier = round(CurrentTotalBytes / BaselineDailyAvg, 2),
CurrentTotalMB = round(CurrentTotalBytes / 1048576.0, 2),
BaselineDailyMB = round(BaselineDailyAvg / 1048576.0, 2)
| project
TimeGenerated = now(),
User = CsUsername,
CurrentDownloadMB = CurrentTotalMB,
BaselineDailyAvgMB = BaselineDailyMB,
SpikeMultiplier,
DownloadCount = CurrentCount,
ApplicationsUsed = Apps,
FilesDownloaded = Files
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: User
version: 1.0.0
kind: Scheduled
Stages and Predicates
Parameters
let lookbackPeriod = 7d;
let currentPeriod = 1h;
let threshold = 3;
let current is inlined into the numbered stages below.
Let binding: baseline
let baseline = NetskopeWebTransactions_CL
| where TimeGenerated between (ago(lookbackPeriod) .. ago(currentPeriod))
| where isnotempty(CsUsername)
| where XCsAppActivity =~ 'Download' or ScBytes > 0
| summarize
BaselineAvgBytes = avg(ScBytes),
BaselineTotalBytes = sum(ScBytes),
BaselineCount = count()
by CsUsername
| extend BaselineDailyAvg = BaselineTotalBytes / 7;
Stages 1 to 5 define let current (the rule's main pipeline source); stages 6 to 9 run on it.
Stage 1: source
NetskopeWebTransactions_CL
Stage 2: where
| where TimeGenerated > ago(currentPeriod)
Stage 3: where
| where isnotempty(CsUsername)
Stage 4: where
| where XCsAppActivity =~ 'Download' or ScBytes > 0
Stage 5: summarize
| summarize
CurrentTotalBytes = sum(ScBytes),
CurrentCount = count(),
Apps = make_set(XCsApp),
Files = make_set(XCsAppObjectName)
by CsUsername
Stage 6: join
current
| join kind=inner baseline on CsUsername
Stage 7: where
| where CurrentTotalBytes > (BaselineDailyAvg * threshold)
Stage 8: extend
| extend
SpikeMultiplier = round(CurrentTotalBytes / BaselineDailyAvg, 2),
CurrentTotalMB = round(CurrentTotalBytes / 1048576.0, 2),
BaselineDailyMB = round(BaselineDailyAvg / 1048576.0, 2)
Stage 9: project
| project
TimeGenerated = now(),
User = CsUsername,
CurrentDownloadMB = CurrentTotalMB,
BaselineDailyAvgMB = BaselineDailyMB,
SpikeMultiplier,
DownloadCount = CurrentCount,
ApplicationsUsed = Apps,
FilesDownloaded = Files
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
CsUsername | is_not_null | field:"CsUsername" kind:is_not_null | |
CurrentTotalBytes | cross_field_compare |
| field:"CurrentTotalBytes" kind:cross_field_compare value:"BaselineDailyAvg" |
ScBytes | gt |
| field:"ScBytes" kind:gt value:"0" |
XCsAppActivity | eq |
| field:"XCsAppActivity" kind:eq value:"Download" |
Output fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
ApplicationsUsed | project |
BaselineDailyAvgMB | project |
CurrentDownloadMB | project |
DownloadCount | project |
FilesDownloaded | project |
SpikeMultiplier | project |
TimeGenerated | project |
User | project |