GSA Enriched Office 365 - Sharepoint File Transfer Above Threshold
Id | abd6976d-8f71-4851-98c4-4d086201319c |
Rulename | GSA Enriched Office 365 - Sharepoint File Transfer Above Threshold |
Description | Identifies Office365 SharePoint file transfers with a distinct folder count above a certain threshold in a 15-minute time period. Please note that entity mapping for arrays is not supported, so when there is a single value in an array, we will pull that value from the array as a single string to populate the entity to support entity mapping features within Sentinel. Additionally, if the array is multivalued, we will input a string to indicate this with a unique hash so that matching will not occur. |
Severity | Medium |
Tactics | Exfiltration |
Techniques | T1020 |
Required data connectors | AzureActiveDirectory Office365 |
Kind | Scheduled |
Query frequency | 15m |
Query period | 15m |
Trigger threshold | 0 |
Trigger operator | gt |
Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Analytic Rules/Office 365 - sharepoint_file_transfer_folders_above_threshold.yaml |
Version | 2.0.8 |
Arm template | abd6976d-8f71-4851-98c4-4d086201319c.json |
let threshold = 5000;
// EnrichedMicrosoft365AuditLogs Query
let EnrichedEvents = EnrichedMicrosoft365AuditLogs
| where Workload has_any("SharePoint", "OneDrive")
| where Operation has_any("FileDownloaded", "FileSyncDownloadedFull", "FileSyncUploadedFull", "FileUploaded")
| extend UserAgent = tostring(AdditionalProperties["UserAgent"])
| summarize count_distinct_ObjectId = dcount(ObjectId),
fileslist = make_set(ObjectId, 10000),
any_UserAgent = any(UserAgent)
by UserId, ClientIP = ClientIp, bin(TimeGenerated, 15m)
| where count_distinct_ObjectId >= threshold
| extend FileSample = iff(array_length(fileslist) == 1, tostring(fileslist[0]),
strcat("SeeFilesListField_", tostring(hash(tostring(fileslist)))))
| extend AccountName = tostring(split(UserId, "@")[0]),
AccountUPNSuffix = tostring(split(UserId, "@")[1]);
// OfficeActivity Query
let OfficeEvents = OfficeActivity
| where EventSource == "SharePoint"
| where OfficeWorkload has_any("SharePoint", "OneDrive")
| where Operation has_any("FileDownloaded", "FileSyncDownloadedFull", "FileSyncUploadedFull", "FileUploaded")
| summarize count_distinct_ObjectId = dcount(OfficeObjectId),
fileslist = make_set(OfficeObjectId, 10000),
any_UserAgent = any(UserAgent)
by UserId, ClientIP, bin(TimeGenerated, 15m)
| where count_distinct_ObjectId >= threshold
| extend FileSample = iff(array_length(fileslist) == 1, tostring(fileslist[0]),
strcat("SeeFilesListField_", tostring(hash(tostring(fileslist)))))
| extend AccountName = tostring(split(UserId, "@")[0]),
AccountUPNSuffix = tostring(split(UserId, "@")[1]);
// Combine Office and Enriched Logs
let CombinedEvents = OfficeEvents
| union EnrichedEvents
| summarize arg_min(TimeGenerated, *) by UserId, ClientIP, any_UserAgent;
// Final Output
CombinedEvents
| extend TransferCount = count_distinct_ObjectId
| project TimeGenerated, UserId, ClientIP, AccountName, AccountUPNSuffix, FileSample, UserAgent = any_UserAgent, TransferCount, fileslist
| order by TimeGenerated desc
relevantTechniques:
- T1020
incidentConfiguration:
createIncident: true
groupingConfiguration:
lookbackDuration: PT5H
enabled: true
reopenClosedIncident: false
matchingMethod: Selected
groupByEntities:
- Account
name: GSA Enriched Office 365 - Sharepoint File Transfer Above Threshold
requiredDataConnectors:
- dataTypes:
- EnrichedMicrosoft365AuditLogs
connectorId: AzureActiveDirectory
- dataTypes:
- OfficeActivity (SharePoint)
connectorId: Office365
entityMappings:
- fieldMappings:
- identifier: FullName
columnName: UserId
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountUPNSuffix
entityType: Account
- fieldMappings:
- identifier: Address
columnName: ClientIP
entityType: IP
- fieldMappings:
- identifier: Name
columnName: FileSample
entityType: File
triggerThreshold: 0
id: abd6976d-8f71-4851-98c4-4d086201319c
tactics:
- Exfiltration
version: 2.0.8
customDetails:
FilesList: fileslist
TransferCount: TransferCount
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Analytic Rules/Office 365 - sharepoint_file_transfer_folders_above_threshold.yaml
queryPeriod: 15m
kind: Scheduled
queryFrequency: 15m
severity: Medium
status: Available
description: |
'Identifies Office365 SharePoint file transfers with a distinct folder count above a certain threshold in a 15-minute time period. Please note that entity mapping for arrays is not supported, so when there is a single value in an array, we will pull that value from the array as a single string to populate the entity to support entity mapping features within Sentinel. Additionally, if the array is multivalued, we will input a string to indicate this with a unique hash so that matching will not occur.'
query: |
let threshold = 5000;
// EnrichedMicrosoft365AuditLogs Query
let EnrichedEvents = EnrichedMicrosoft365AuditLogs
| where Workload has_any("SharePoint", "OneDrive")
| where Operation has_any("FileDownloaded", "FileSyncDownloadedFull", "FileSyncUploadedFull", "FileUploaded")
| extend UserAgent = tostring(AdditionalProperties["UserAgent"])
| summarize count_distinct_ObjectId = dcount(ObjectId),
fileslist = make_set(ObjectId, 10000),
any_UserAgent = any(UserAgent)
by UserId, ClientIP = ClientIp, bin(TimeGenerated, 15m)
| where count_distinct_ObjectId >= threshold
| extend FileSample = iff(array_length(fileslist) == 1, tostring(fileslist[0]),
strcat("SeeFilesListField_", tostring(hash(tostring(fileslist)))))
| extend AccountName = tostring(split(UserId, "@")[0]),
AccountUPNSuffix = tostring(split(UserId, "@")[1]);
// OfficeActivity Query
let OfficeEvents = OfficeActivity
| where EventSource == "SharePoint"
| where OfficeWorkload has_any("SharePoint", "OneDrive")
| where Operation has_any("FileDownloaded", "FileSyncDownloadedFull", "FileSyncUploadedFull", "FileUploaded")
| summarize count_distinct_ObjectId = dcount(OfficeObjectId),
fileslist = make_set(OfficeObjectId, 10000),
any_UserAgent = any(UserAgent)
by UserId, ClientIP, bin(TimeGenerated, 15m)
| where count_distinct_ObjectId >= threshold
| extend FileSample = iff(array_length(fileslist) == 1, tostring(fileslist[0]),
strcat("SeeFilesListField_", tostring(hash(tostring(fileslist)))))
| extend AccountName = tostring(split(UserId, "@")[0]),
AccountUPNSuffix = tostring(split(UserId, "@")[1]);
// Combine Office and Enriched Logs
let CombinedEvents = OfficeEvents
| union EnrichedEvents
| summarize arg_min(TimeGenerated, *) by UserId, ClientIP, any_UserAgent;
// Final Output
CombinedEvents
| extend TransferCount = count_distinct_ObjectId
| project TimeGenerated, UserId, ClientIP, AccountName, AccountUPNSuffix, FileSample, UserAgent = any_UserAgent, TransferCount, fileslist
| order by TimeGenerated desc
triggerOperator: gt
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workspace": {
"type": "String"
}
},
"resources": [
{
"apiVersion": "2024-01-01-preview",
"id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/abd6976d-8f71-4851-98c4-4d086201319c')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/abd6976d-8f71-4851-98c4-4d086201319c')]",
"properties": {
"alertRuleTemplateName": "abd6976d-8f71-4851-98c4-4d086201319c",
"customDetails": {
"FilesList": "fileslist",
"TransferCount": "TransferCount"
},
"description": "'Identifies Office365 SharePoint file transfers with a distinct folder count above a certain threshold in a 15-minute time period. Please note that entity mapping for arrays is not supported, so when there is a single value in an array, we will pull that value from the array as a single string to populate the entity to support entity mapping features within Sentinel. Additionally, if the array is multivalued, we will input a string to indicate this with a unique hash so that matching will not occur.'\n",
"displayName": "GSA Enriched Office 365 - Sharepoint File Transfer Above Threshold",
"enabled": true,
"entityMappings": [
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "UserId",
"identifier": "FullName"
},
{
"columnName": "AccountName",
"identifier": "Name"
},
{
"columnName": "AccountUPNSuffix",
"identifier": "UPNSuffix"
}
]
},
{
"entityType": "IP",
"fieldMappings": [
{
"columnName": "ClientIP",
"identifier": "Address"
}
]
},
{
"entityType": "File",
"fieldMappings": [
{
"columnName": "FileSample",
"identifier": "Name"
}
]
}
],
"incidentConfiguration": {
"createIncident": true,
"groupingConfiguration": {
"enabled": true,
"groupByEntities": [
"Account"
],
"lookbackDuration": "PT5H",
"matchingMethod": "Selected",
"reopenClosedIncident": false
}
},
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Analytic Rules/Office 365 - sharepoint_file_transfer_folders_above_threshold.yaml",
"query": "let threshold = 5000;\n// EnrichedMicrosoft365AuditLogs Query\nlet EnrichedEvents = EnrichedMicrosoft365AuditLogs\n | where Workload has_any(\"SharePoint\", \"OneDrive\")\n | where Operation has_any(\"FileDownloaded\", \"FileSyncDownloadedFull\", \"FileSyncUploadedFull\", \"FileUploaded\")\n | extend UserAgent = tostring(AdditionalProperties[\"UserAgent\"])\n | summarize count_distinct_ObjectId = dcount(ObjectId),\n fileslist = make_set(ObjectId, 10000),\n any_UserAgent = any(UserAgent)\n by UserId, ClientIP = ClientIp, bin(TimeGenerated, 15m)\n | where count_distinct_ObjectId >= threshold\n | extend FileSample = iff(array_length(fileslist) == 1, tostring(fileslist[0]),\n strcat(\"SeeFilesListField_\", tostring(hash(tostring(fileslist)))))\n | extend AccountName = tostring(split(UserId, \"@\")[0]),\n AccountUPNSuffix = tostring(split(UserId, \"@\")[1]);\n// OfficeActivity Query\nlet OfficeEvents = OfficeActivity\n | where EventSource == \"SharePoint\"\n | where OfficeWorkload has_any(\"SharePoint\", \"OneDrive\")\n | where Operation has_any(\"FileDownloaded\", \"FileSyncDownloadedFull\", \"FileSyncUploadedFull\", \"FileUploaded\")\n | summarize count_distinct_ObjectId = dcount(OfficeObjectId),\n fileslist = make_set(OfficeObjectId, 10000),\n any_UserAgent = any(UserAgent)\n by UserId, ClientIP, bin(TimeGenerated, 15m)\n | where count_distinct_ObjectId >= threshold\n | extend FileSample = iff(array_length(fileslist) == 1, tostring(fileslist[0]),\n strcat(\"SeeFilesListField_\", tostring(hash(tostring(fileslist)))))\n | extend AccountName = tostring(split(UserId, \"@\")[0]),\n AccountUPNSuffix = tostring(split(UserId, \"@\")[1]);\n// Combine Office and Enriched Logs\nlet CombinedEvents = OfficeEvents\n | union EnrichedEvents\n | summarize arg_min(TimeGenerated, *) by UserId, ClientIP, any_UserAgent;\n// Final Output\nCombinedEvents\n | extend TransferCount = count_distinct_ObjectId\n | project TimeGenerated, UserId, ClientIP, AccountName, AccountUPNSuffix, FileSample, UserAgent = any_UserAgent, TransferCount, fileslist\n | order by TimeGenerated desc\n",
"queryFrequency": "PT15M",
"queryPeriod": "PT15M",
"severity": "Medium",
"status": "Available",
"subTechniques": [],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"Exfiltration"
],
"techniques": [
"T1020"
],
"templateVersion": "2.0.8",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}