Detection rules › Kusto
Dataverse - Executable uploaded to SharePoint document management site
Identifies executable files and scripts uploaded to SharePoint sites used for Dynamics document management, circumventing native file extension restrictions in Dataverse.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Execution | T0863 User Execution |
| Persistence | T0873 Project File Infection |
Event coverage
| Provider | Event |
|---|---|
| M365-SharePointFileOperation | FileUploaded |
Rules detecting the same action
Other rules on this platform that filter on the same API call or operation.
Rule body kusto
id: ba5e608f-7879-4927-8b0d-a9948b4fe6f3
kind: Scheduled
name: Dataverse - Executable uploaded to SharePoint document management site
description: Identifies executable files and scripts uploaded to SharePoint sites
used for Dynamics document management, circumventing native file extension restrictions
in Dataverse.
severity: Low
status: Available
requiredDataConnectors:
- connectorId: Office365
dataTypes:
- OfficeActivity (SharePoint)
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
- Execution
- Persistence
relevantTechniques:
- T0863
- T0873
query: |
let file_extensions = dynamic(['com', 'exe', 'bat', 'cmd', 'vbs', 'vbe', 'js', 'jse', 'wsf', 'wsh', 'msc', 'cpl', 'ps1', 'scr']);
let query_frequency = 1h;
DataverseSharePointSites
| join kind=inner (
OfficeActivity
| where TimeGenerated >= ago(query_frequency)
| where OfficeWorkload == "SharePoint" and Operation == "FileUploaded")
on $left.SharePointUrl == $right.Site_Url
| where SourceFileExtension in (file_extensions)
| extend
CloudAppId = int(32780),
SharePointId = int(20892),
AccountName = tostring(split(UserId, '@')[0]),
UPNSuffix = tostring(split(UserId, '@')[1])
| project
TimeGenerated,
UserId,
ClientIP,
InstanceUrl,
SourceFileName,
SharePointUrl,
CloudAppId,
SharePointId,
AccountName,
UPNSuffix
eventGroupingSettings:
aggregationKind: SingleAlert
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: UPNSuffix
- entityType: IP
fieldMappings:
- identifier: Address
columnName: ClientIP
- entityType: CloudApplication
fieldMappings:
- identifier: AppId
columnName: CloudAppId
- identifier: InstanceName
columnName: InstanceUrl
- entityType: File
fieldMappings:
- identifier: Name
columnName: SourceFileName
- entityType: CloudApplication
fieldMappings:
- identifier: AppId
columnName: SharePointId
- identifier: InstanceName
columnName: SharePointUrl
alertDetailsOverride:
alertDisplayNameFormat: Dataverse - Executable files uploaded in document management
for {{InstanceUrl}}
alertDescriptionFormat: Executable/script {{SourceFileName}} was uploaded by {{UserId}}
in SharePoint site {{SharePointUrl}}
version: 3.2.0
Stages and Predicates
Parameters
let file_extensions = dynamic(['com', 'exe', 'bat', 'cmd', 'vbs', 'vbe', 'js', 'jse', 'wsf', 'wsh', 'msc', 'cpl', 'ps1', 'scr']);
let query_frequency = 1h;
Stage 1: source
DataverseSharePointSites
Stage 2: join
| join kind=inner (
OfficeActivity
| where TimeGenerated >= ago(query_frequency)
| where OfficeWorkload == "SharePoint" and Operation == "FileUploaded")
on $left.SharePointUrl == $right.Site_Url
Stage 3: where
| where SourceFileExtension in (file_extensions)
Stage 4: extend
| extend
CloudAppId = int(32780),
SharePointId = int(20892),
AccountName = tostring(split(UserId, '@')[0]),
UPNSuffix = tostring(split(UserId, '@')[1])
Stage 5: project
| project
TimeGenerated,
UserId,
ClientIP,
InstanceUrl,
SourceFileName,
SharePointUrl,
CloudAppId,
SharePointId,
AccountName,
UPNSuffix
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.
| Field | Kind | Values |
|---|---|---|
OfficeWorkload | eq |
|
Operation | eq |
|
SourceFileExtension | in |
|
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.
| Field | Source |
|---|---|
AccountName | project |
ClientIP | project |
CloudAppId | project |
InstanceUrl | project |
SharePointId | project |
SharePointUrl | project |
SourceFileName | project |
TimeGenerated | project |
UPNSuffix | project |
UserId | project |