Detection rules › Kusto

Files Copied to USB Drives

Status
available
Severity
high
Time window
1h
Source
github.com/Azure/Azure-Sentinel

This query lists files copied to USB external drives with USB drive information based on FileCreated events associated with most recent USBDriveMount events befor file creations. But be aware that Advanced Hunting is not monitoring all the file types.

MITRE ATT&CK coverage

TacticTechniques
ExfiltrationT1041 Exfiltration Over C2 Channel

Event coverage

Rule body kusto

id: 3ab04acf-e0e7-4f7c-8995-748ab4c848c2
name: Files Copied to USB Drives
description: | 
  This query lists files copied to USB external drives with USB drive information based on FileCreated events associated with most recent USBDriveMount events befor file creations. But be aware that Advanced Hunting is not monitoring all the file types.
severity: High
status: Available
requiredDataConnectors:
  - connectorId: MicrosoftThreatProtection
    dataTypes:
      - DeviceEvents
      - DeviceFileEvents
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Exfiltration
relevantTechniques:
  - T1041
query: |
  let UsbDriveMount = DeviceEvents
  | where ActionType=="UsbDriveMounted"
  | extend ParsedFields=parse_json(AdditionalFields)
  | project DeviceId, DeviceName, DriveLetter=ParsedFields.DriveLetter, MountTime=TimeGenerated,
  ProductName=ParsedFields.ProductName,SerialNumber=ParsedFields.SerialNumber,Manufacturer=ParsedFields.Manufacturer
  | order by DeviceId asc, MountTime desc;
  let FileCreation = DeviceFileEvents
  | where InitiatingProcessAccountName != "system"
  | where ActionType == "FileCreated"
  | where FolderPath !startswith "C:\\"
  | where FolderPath !startswith "\\"
  | project ReportId,DeviceId,InitiatingProcessAccountDomain,
  InitiatingProcessAccountName,InitiatingProcessAccountUpn,
  FileName, FolderPath, SHA256, TimeGenerated, SensitivityLabel, IsAzureInfoProtectionApplied
  | order by DeviceId asc, TimeGenerated desc;
  FileCreation | lookup kind=inner (UsbDriveMount) on DeviceId
  | where FolderPath startswith DriveLetter
  | where TimeGenerated >= MountTime
  | partition hint.strategy=native by ReportId ( top 1 by MountTime )
  | order by DeviceId asc, TimeGenerated desc
  | extend HostName = iff(DeviceName has '.', substring(DeviceName, 0, indexof(DeviceName, '.')), DeviceName)
  | extend DnsDomain = iff(DeviceName has '.', substring(DeviceName, indexof(DeviceName, '.') + 1), "")
  | extend FileHashAlgorithm = 'SHA256'
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: DeviceName
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: DnsDomain
  - entityType: File
    fieldMappings:
      - identifier: Name
        columnName: FileName
      - identifier: Directory
        columnName: FolderPath
  - entityType: FileHash
    fieldMappings:
      - identifier: Algorithm
        columnName: FileHashAlgorithm
      - identifier: Value
        columnName: SHA256
version: 1.0.0
kind: Scheduled

Stages and Predicates

Let binding: UsbDriveMount

let UsbDriveMount = DeviceEvents
| where ActionType=="UsbDriveMounted"
| extend ParsedFields=parse_json(AdditionalFields)
| project DeviceId, DeviceName, DriveLetter=ParsedFields.DriveLetter, MountTime=TimeGenerated,
ProductName=ParsedFields.ProductName,SerialNumber=ParsedFields.SerialNumber,Manufacturer=ParsedFields.Manufacturer
| order by DeviceId asc, MountTime desc;

The stages below define let FileCreation (the rule's main pipeline source).

Stage 1: source

DeviceFileEvents

Stage 2: where

| where InitiatingProcessAccountName != "system"

Stage 3: where

| where ActionType == "FileCreated"

Stage 4: where

| where FolderPath !startswith "C:\\"

Stage 5: where

| where FolderPath !startswith "\\"

Stage 6: project

| project ReportId,DeviceId,InitiatingProcessAccountDomain,
InitiatingProcessAccountName,InitiatingProcessAccountUpn,
FileName, FolderPath, SHA256, TimeGenerated, SensitivityLabel, IsAzureInfoProtectionApplied

Stage 7: sort

| order by DeviceId asc, TimeGenerated desc

The stages below run on FileCreation (the outer pipeline).

Stage 8: kusto:lookup

FileCreation
| lookup kind=inner (UsbDriveMount) on DeviceId

Stage 9: where

| where FolderPath startswith DriveLetter

Stage 10: where

| where TimeGenerated >= MountTime

Stage 11: partition

| partition hint.strategy=native by ReportId ( top 1 by MountTime )

Stage 12: sort

| order by DeviceId asc, TimeGenerated desc

Stage 13: extend (3 consecutive steps)

| extend HostName = iff(DeviceName has '.', substring(DeviceName, 0, indexof(DeviceName, '.')), DeviceName)
| extend DnsDomain = iff(DeviceName has '.', substring(DeviceName, indexof(DeviceName, '.') + 1), "")
| extend FileHashAlgorithm = 'SHA256'
HostName =
ifDeviceName has "."substring(DeviceName, 0, indexof(DeviceName, '.'))
elseDeviceName

Exclusions

Top-level NOT(...) conjuncts: predicates this rule actively suppresses.

FieldKindExcluded values
FolderPathstarts_withC:\\
FolderPathstarts_with\\

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.

FieldKindValues
ActionTypeeq
  • FileCreated transforms: cased corpus 8 (kusto 8)
FolderPathstarts_with
  • DriveLetter
InitiatingProcessAccountNamene
  • system transforms: cased
TimeGeneratedge
  • MountTime transforms: cased

Output fields

Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.

FieldSource
DeviceIdproject
FileNameproject
FolderPathproject
InitiatingProcessAccountDomainproject
InitiatingProcessAccountNameproject
InitiatingProcessAccountUpnproject
IsAzureInfoProtectionAppliedproject
ReportIdproject
SHA256project
SensitivityLabelproject
TimeGeneratedproject
HostNameextend
DnsDomainextend
FileHashAlgorithmextend