Private/Core/Test-BulkFileDownload.ps1
|
# PSGuerrilla - Jim Tyler, Microsoft MVP - CC BY 4.0 # https://github.com/jimrtyler/PSGuerrilla | https://creativecommons.org/licenses/by/4.0/ # AI/LLM use: see AI-USAGE.md for required attribution function Test-BulkFileDownload { [CmdletBinding()] param( [hashtable[]]$DriveEvents = @(), [int]$Threshold = 50, [int]$WindowMinutes = 10 ) $results = [System.Collections.Generic.List[PSCustomObject]]::new() # Filter to download events $downloadEvents = @($DriveEvents | Where-Object { $_.EventName -in @('download', 'DOWNLOAD', 'view', 'VIEW', 'copy', 'COPY') }) if ($downloadEvents.Count -lt $Threshold) { return @($results) } # Sort by timestamp $sorted = @($downloadEvents | Sort-Object { [datetime]::Parse($_.Timestamp) }) # Sliding window detection $windowMs = $WindowMinutes * 60 * 1000 for ($i = 0; $i -lt $sorted.Count; $i++) { $windowStart = [datetime]::Parse($sorted[$i].Timestamp) $windowEnd = $windowStart.AddMinutes($WindowMinutes) $windowEvents = @($sorted | Where-Object { $ts = [datetime]::Parse($_.Timestamp) $ts -ge $windowStart -and $ts -le $windowEnd }) if ($windowEvents.Count -ge $Threshold) { $uniqueFiles = @($windowEvents | ForEach-Object { $_.Params['doc_title'] ?? $_.Params['DOCUMENT_TITLE'] ?? 'unknown' } | Sort-Object -Unique) $results.Add([PSCustomObject]@{ WindowStart = $windowStart.ToString('o') WindowEnd = $windowEnd.ToString('o') EventCount = $windowEvents.Count UniqueFiles = $uniqueFiles.Count SampleFiles = @($uniqueFiles | Select-Object -First 5) User = $sorted[$i].User IpAddress = $sorted[$i].IpAddress }) # Skip ahead past this window to avoid duplicate detections $skipTo = $sorted.Count - 1 for ($j = $i + 1; $j -lt $sorted.Count; $j++) { if ([datetime]::Parse($sorted[$j].Timestamp) -gt $windowEnd) { $skipTo = $j break } } $i = $skipTo } } return @($results) } |