Detection rules › Kusto

Dataverse - Malware found in SharePoint document management site

Status
available
Severity
medium
Time window
14d
Group by
MalwareUserId, SharePointUrl, Site_Url, SourceFileName
Source
github.com/Azure/Azure-Sentinel

This query identifies malware uploaded via Dynamics 365 document management or directly in SharePoint impacting Dataverse associated SharePoint sites.

MITRE ATT&CK coverage

TacticTechniques
ExecutionT1204 User Execution

Rule body kusto

id: 2e3878bb-d519-43aa-9992-ea069df099e4
kind: Scheduled
name: Dataverse - Malware found in SharePoint document management site
description: This query identifies malware uploaded via Dynamics 365 document management
  or directly in SharePoint impacting Dataverse associated SharePoint sites.
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: Dataverse
    dataTypes:
      - DataverseActivity
  - connectorId: Office365
    dataTypes:
      - OfficeActivity (SharePoint)
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Execution
relevantTechniques:
  - T1204
query: |
  let query_frequency = 15m;
    let malware_events = OfficeActivity
        | where OfficeWorkload == "SharePoint" and Operation == "FileMalwareDetected"
        | summarize by MalwareUserId = UserId, SourceFileName, Site_Url
        | join kind=inner (DataverseSharePointSites) on $left.Site_Url == $right.SharePointUrl;
    let file_upload_events = OfficeActivity
        | where OfficeWorkload == "SharePoint" and Operation == "FileUploaded"
        | project TimeGenerated, UserId, Site_Url, SourceFileName, ApplicationId, ClientIP;
    let d365_upload_events = DataverseActivity
        | where TimeGenerated >= ago(query_frequency)
        | where Message == "UploadDocument"
        | summarize by UserId, D365ClientIp = ClientIp;
    malware_events
    | join kind=inner (file_upload_events) on SourceFileName, Site_Url
    | lookup (d365_upload_events) on UserId
    | extend ClientIp = iif(ApplicationId == "00000007-0000-0000-c000-000000000000", D365ClientIp, ClientIP)
    | extend
        CloudAppId = int(32780),
        SharePointId = int(20892),
        AccountName = tostring(split(UserId, '@')[0]),
        UPNSuffix = tostring(split(UserId, '@')[1])
    | project
        TimeGenerated,
        UserId,
        ClientIp,
        InstanceUrl,
        SharePointUrl,
        SourceFileName,
        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: File
    fieldMappings:
      - identifier: Name
        columnName: SourceFileName
  - entityType: CloudApplication
    fieldMappings:
      - identifier: AppId
        columnName: CloudAppId
      - identifier: InstanceName
        columnName: InstanceUrl
  - entityType: CloudApplication
    fieldMappings:
      - identifier: AppId
        columnName: SharePointId
      - identifier: InstanceName
        columnName: SharePointUrl
alertDetailsOverride:
  alertDisplayNameFormat: 'Dataverse - Malware was found in SharePoint document management
    site for {{InstanceUrl}} '
  alertDescriptionFormat: A malicious file {{SourceFileName}} was found in SharePoint
    site {{SharePointUrl}}. The file was uploaded by {{UserId}}
version: 3.2.0

Stages and Predicates

Parameters

let query_frequency = 15m;

Let binding: file_upload_events

let file_upload_events = OfficeActivity
      | where OfficeWorkload == "SharePoint" and Operation == "FileUploaded"
      | project TimeGenerated, UserId, Site_Url, SourceFileName, ApplicationId, ClientIP;

Let binding: d365_upload_events

let d365_upload_events = DataverseActivity
      | where TimeGenerated >= ago(query_frequency)
      | where Message == "UploadDocument"
      | summarize by UserId, D365ClientIp = ClientIp;

Derived from query_frequency.

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

Stage 1: source

OfficeActivity

Stage 2: where

| where OfficeWorkload == "SharePoint" and Operation == "FileMalwareDetected"

Stage 3: summarize

| summarize by MalwareUserId = UserId, SourceFileName, Site_Url

Stage 4: join

| join kind=inner (DataverseSharePointSites) on $left.Site_Url == $right.SharePointUrl

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

Stage 5: join

malware_events
| join kind=inner (file_upload_events) on SourceFileName, Site_Url

Stage 6: kusto:lookup

| lookup (d365_upload_events) on UserId

Stage 7: extend

| extend ClientIp = iif(ApplicationId == "00000007-0000-0000-c000-000000000000", D365ClientIp, ClientIP)

Stage 8: extend

| extend
      CloudAppId = int(32780),
      SharePointId = int(20892),
      AccountName = tostring(split(UserId, '@')[0]),
      UPNSuffix = tostring(split(UserId, '@')[1])

Stage 9: project

| project
      TimeGenerated,
      UserId,
      ClientIp,
      InstanceUrl,
      SharePointUrl,
      SourceFileName,
      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.

FieldKindValues
OfficeWorkloadeq
  • SharePoint transforms: cased corpus 3 (kusto 3)
Operationeq
  • FileMalwareDetected transforms: cased corpus 2 (splunk 1, kusto 1)
  • FileUploaded transforms: cased corpus 4 (kusto 4)

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
AccountNameproject
ClientIpproject
CloudAppIdproject
InstanceUrlproject
SharePointIdproject
SharePointUrlproject
SourceFileNameproject
TimeGeneratedproject
UPNSuffixproject
UserIdproject