Suspicious access of BEC related documents
Id | cd8d946d-10a4-40a9-bac1-6d0a6c847d65 |
Rulename | Suspicious access of BEC related documents |
Description | This query looks for users with suspicious spikes in the number of files accessed that relate to topics commonly accessed as part of Business Email Compromise (BEC) attacks. The query looks for access to files in storage that relate to topics such as invoices or payments, and then looks for users accessing these files in significantly higher numbers than in the previous 14 days. Incidents raised by this analytic should be investigated to see if the user accessing these files should be accessing them, and if the volume they accessed them at was related to a legitimate business need. This query contains thresholds to reduce the chance of false positives, these can be adjusted to suit individual environments. In addition false positives could be generated by legitimate, scheduled actions that occur less often than every 14 days, additional exclusions can be added for these actions on username or IP address entities. This query uses the imFileEvent schema from ASIM, you will first need to ensure you have ASIM deployed in your environment. Ref https://learn.microsoft.com/azure/sentinel/normalization-about-parsers |
Severity | Medium |
Tactics | Collection |
Techniques | T1530 |
Kind | Scheduled |
Query frequency | 1d |
Query period | 14d |
Trigger threshold | 0 |
Trigger operator | gt |
Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Business Email Compromise - Financial Fraud/Analytic Rules/SuspiciousAccessOfBECRelatedDocuments.yaml |
Version | 1.0.4 |
Arm template | cd8d946d-10a4-40a9-bac1-6d0a6c847d65.json |
let BEC_Keywords = dynamic([ 'invoice','payment','paycheck','transfer','bank statement','bank details','closing','funds','bank account','account details','remittance','purchase','deposit',"PO#","Zahlung","Rechnung","Paiement", "virement bancaire","Bankuberweisung",'hacked','phishing']);
// Adjust this threshold based on your environment
let sensitivity = 2.5;
let Events = materialize(imFileEvent
| where TimeGenerated between(startofday(ago(14d))..endofday(ago(0d)))
| where User !~ "app@sharepoint"
| where EventType =~ "FileAccessed"
| extend OriginalEvent = column_ifexists("EventOriginalType","Unknown")
| where OriginalEvent !~ "FileSyncDownloadedFull"
| where EventProduct in ("SharePoint 365", "Azure File Storage", "OneDrive" , "SharePoint")
| where FilePath has_any(BEC_Keywords)
| extend _AuthDetails = column_ifexists("AuthorizationDetails", "None")
| extend SPuser = case(gettype(_AuthDetails) == "array", tostring(todynamic(_AuthDetails)[0].principals[0].id), "Unknown")
| extend User = case(isnotempty(User), User, SPuser)
| where isnotempty(User));
Events
| summarize dcount(FileName) by User, bin(startofday(TimeGenerated), 1d)
| summarize CountOfDocs = make_list(dcount_FileName, 10000), TimeStamp = make_list(TimeGenerated, 10000) by User
| extend (Anomalies, Score, Baseline) = series_decompose_anomalies(CountOfDocs, sensitivity, -1, 'linefit')
| mv-expand CountOfDocs to typeof(double), TimeStamp to typeof(datetime), Anomalies to typeof(double), Score to typeof(double), Baseline to typeof(long)
| where Anomalies > 0
| project TimeStamp, CountOfDocs, Baseline, Score, Anomalies, User
| join kind=inner(Events | extend TimeStamp = startofday(TimeGenerated)) on TimeStamp, User
| extend IpAddr = column_ifexists("IpAddr", SrcIpAddr)
| extend Name = iif(User contains "@", split(User, "@")[0], split(User, "\\")[1])
| extend UPNSuffix = iif(User contains "@", split(User, "@")[1], "")
| extend NTDomain = iif(User contains "@", split(User, "\\")[0], "")
| project-reorder TimeGenerated, User, EventType, EventResult, EventProduct, FilePath, HttpUserAgent, IpAddr, CountOfDocs, Baseline, Score
relevantTechniques:
- T1530
name: Suspicious access of BEC related documents
requiredDataConnectors: []
entityMappings:
- fieldMappings:
- identifier: FullName
columnName: User
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
entityType: Account
- fieldMappings:
- identifier: FullName
columnName: User
- identifier: Name
columnName: Name
- identifier: NTDomain
columnName: NTDomain
entityType: Account
- fieldMappings:
- identifier: AadUserId
columnName: User
entityType: Account
- fieldMappings:
- identifier: Address
columnName: IpAddr
entityType: IP
- fieldMappings:
- identifier: Name
columnName: FilePath
entityType: File
triggerThreshold: 0
id: cd8d946d-10a4-40a9-bac1-6d0a6c847d65
tactics:
- Collection
version: 1.0.4
customDetails:
Result: EventResult
Product: EventProduct
Type: EventType
UserAgent: HttpUserAgent
alertDetailsOverride:
alertDisplayNameFormat: Suspicious access of {{number_of_files_accessed}} BEC related documents by {{User}}
alertDescriptionFormat: |
This query looks for users (in this case {{User}}) with suspicious spikes in the number of files accessed (in this case {{number_of_files_accessed}} events) that relate to topics commonly accessed as part of Business Email Compromise (BEC) attacks. The query looks for access to files in storage that relate to topics such as invoices or payments, and then looks for users accessing these files in significantly higher numbers than in the previous 14 days. Incidents raised by this analytic should be investigated to see if the user accessing these files should be accessing them, and if the volume they accessed them at was related to a legitimate business need.
This query contains thresholds to reduce the chance of false positives, these can be adjusted to suit individual environments. In addition false positives could be generated by legitimate, scheduled actions that occur less often than every 14 days, additional exclusions can be added for these actions on username or IP address entities. This query uses the imFileEvent schema from ASIM, you will first need to ensure you have ASIM deployed in your environment. Ref https://learn.microsoft.com/azure/sentinel/normalization-about-parsers
queryPeriod: 14d
kind: Scheduled
eventGroupingSettings:
aggregationKind: SingleAlert
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Business Email Compromise - Financial Fraud/Analytic Rules/SuspiciousAccessOfBECRelatedDocuments.yaml
queryFrequency: 1d
severity: Medium
description: |
'This query looks for users with suspicious spikes in the number of files accessed that relate to topics commonly accessed as part of Business Email Compromise (BEC) attacks.
The query looks for access to files in storage that relate to topics such as invoices or payments, and then looks for users accessing these files in significantly higher numbers than in the previous 14 days. Incidents raised by this analytic should be investigated to see if the user accessing these files should be accessing them, and if the volume they accessed them at was related to a legitimate business need.
This query contains thresholds to reduce the chance of false positives, these can be adjusted to suit individual environments. In addition false positives could be generated by legitimate, scheduled actions that occur less often than every 14 days, additional exclusions can be added for these actions on username or IP address entities. This query uses the imFileEvent schema from ASIM, you will first need to ensure you have ASIM deployed in your environment. Ref https://learn.microsoft.com/azure/sentinel/normalization-about-parsers'
query: |
let BEC_Keywords = dynamic([ 'invoice','payment','paycheck','transfer','bank statement','bank details','closing','funds','bank account','account details','remittance','purchase','deposit',"PO#","Zahlung","Rechnung","Paiement", "virement bancaire","Bankuberweisung",'hacked','phishing']);
// Adjust this threshold based on your environment
let sensitivity = 2.5;
let Events = materialize(imFileEvent
| where TimeGenerated between(startofday(ago(14d))..endofday(ago(0d)))
| where User !~ "app@sharepoint"
| where EventType =~ "FileAccessed"
| extend OriginalEvent = column_ifexists("EventOriginalType","Unknown")
| where OriginalEvent !~ "FileSyncDownloadedFull"
| where EventProduct in ("SharePoint 365", "Azure File Storage", "OneDrive" , "SharePoint")
| where FilePath has_any(BEC_Keywords)
| extend _AuthDetails = column_ifexists("AuthorizationDetails", "None")
| extend SPuser = case(gettype(_AuthDetails) == "array", tostring(todynamic(_AuthDetails)[0].principals[0].id), "Unknown")
| extend User = case(isnotempty(User), User, SPuser)
| where isnotempty(User));
Events
| summarize dcount(FileName) by User, bin(startofday(TimeGenerated), 1d)
| summarize CountOfDocs = make_list(dcount_FileName, 10000), TimeStamp = make_list(TimeGenerated, 10000) by User
| extend (Anomalies, Score, Baseline) = series_decompose_anomalies(CountOfDocs, sensitivity, -1, 'linefit')
| mv-expand CountOfDocs to typeof(double), TimeStamp to typeof(datetime), Anomalies to typeof(double), Score to typeof(double), Baseline to typeof(long)
| where Anomalies > 0
| project TimeStamp, CountOfDocs, Baseline, Score, Anomalies, User
| join kind=inner(Events | extend TimeStamp = startofday(TimeGenerated)) on TimeStamp, User
| extend IpAddr = column_ifexists("IpAddr", SrcIpAddr)
| extend Name = iif(User contains "@", split(User, "@")[0], split(User, "\\")[1])
| extend UPNSuffix = iif(User contains "@", split(User, "@")[1], "")
| extend NTDomain = iif(User contains "@", split(User, "\\")[0], "")
| project-reorder TimeGenerated, User, EventType, EventResult, EventProduct, FilePath, HttpUserAgent, IpAddr, CountOfDocs, Baseline, Score
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/cd8d946d-10a4-40a9-bac1-6d0a6c847d65')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/cd8d946d-10a4-40a9-bac1-6d0a6c847d65')]",
"properties": {
"alertDetailsOverride": {
"alertDescriptionFormat": "This query looks for users (in this case {{User}}) with suspicious spikes in the number of files accessed (in this case {{number_of_files_accessed}} events) that relate to topics commonly accessed as part of Business Email Compromise (BEC) attacks. The query looks for access to files in storage that relate to topics such as invoices or payments, and then looks for users accessing these files in significantly higher numbers than in the previous 14 days. Incidents raised by this analytic should be investigated to see if the user accessing these files should be accessing them, and if the volume they accessed them at was related to a legitimate business need. \nThis query contains thresholds to reduce the chance of false positives, these can be adjusted to suit individual environments. In addition false positives could be generated by legitimate, scheduled actions that occur less often than every 14 days, additional exclusions can be added for these actions on username or IP address entities. This query uses the imFileEvent schema from ASIM, you will first need to ensure you have ASIM deployed in your environment. Ref https://learn.microsoft.com/azure/sentinel/normalization-about-parsers\n",
"alertDisplayNameFormat": "Suspicious access of {{number_of_files_accessed}} BEC related documents by {{User}}"
},
"alertRuleTemplateName": "cd8d946d-10a4-40a9-bac1-6d0a6c847d65",
"customDetails": {
"Product": "EventProduct",
"Result": "EventResult",
"Type": "EventType",
"UserAgent": "HttpUserAgent"
},
"description": "'This query looks for users with suspicious spikes in the number of files accessed that relate to topics commonly accessed as part of Business Email Compromise (BEC) attacks.\nThe query looks for access to files in storage that relate to topics such as invoices or payments, and then looks for users accessing these files in significantly higher numbers than in the previous 14 days. Incidents raised by this analytic should be investigated to see if the user accessing these files should be accessing them, and if the volume they accessed them at was related to a legitimate business need. \nThis query contains thresholds to reduce the chance of false positives, these can be adjusted to suit individual environments. In addition false positives could be generated by legitimate, scheduled actions that occur less often than every 14 days, additional exclusions can be added for these actions on username or IP address entities. This query uses the imFileEvent schema from ASIM, you will first need to ensure you have ASIM deployed in your environment. Ref https://learn.microsoft.com/azure/sentinel/normalization-about-parsers'\n",
"displayName": "Suspicious access of BEC related documents",
"enabled": true,
"entityMappings": [
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "User",
"identifier": "FullName"
},
{
"columnName": "Name",
"identifier": "Name"
},
{
"columnName": "UPNSuffix",
"identifier": "UPNSuffix"
}
]
},
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "User",
"identifier": "FullName"
},
{
"columnName": "Name",
"identifier": "Name"
},
{
"columnName": "NTDomain",
"identifier": "NTDomain"
}
]
},
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "User",
"identifier": "AadUserId"
}
]
},
{
"entityType": "IP",
"fieldMappings": [
{
"columnName": "IpAddr",
"identifier": "Address"
}
]
},
{
"entityType": "File",
"fieldMappings": [
{
"columnName": "FilePath",
"identifier": "Name"
}
]
}
],
"eventGroupingSettings": {
"aggregationKind": "SingleAlert"
},
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Business Email Compromise - Financial Fraud/Analytic Rules/SuspiciousAccessOfBECRelatedDocuments.yaml",
"query": "let BEC_Keywords = dynamic([ 'invoice','payment','paycheck','transfer','bank statement','bank details','closing','funds','bank account','account details','remittance','purchase','deposit',\"PO#\",\"Zahlung\",\"Rechnung\",\"Paiement\", \"virement bancaire\",\"Bankuberweisung\",'hacked','phishing']);\n// Adjust this threshold based on your environment\nlet sensitivity = 2.5;\nlet Events = materialize(imFileEvent\n| where TimeGenerated between(startofday(ago(14d))..endofday(ago(0d)))\n| where User !~ \"app@sharepoint\"\n| where EventType =~ \"FileAccessed\"\n| extend OriginalEvent = column_ifexists(\"EventOriginalType\",\"Unknown\")\n| where OriginalEvent !~ \"FileSyncDownloadedFull\"\n| where EventProduct in (\"SharePoint 365\", \"Azure File Storage\", \"OneDrive\" , \"SharePoint\")\n| where FilePath has_any(BEC_Keywords)\n| extend _AuthDetails = column_ifexists(\"AuthorizationDetails\", \"None\")\n| extend SPuser = case(gettype(_AuthDetails) == \"array\", tostring(todynamic(_AuthDetails)[0].principals[0].id), \"Unknown\")\n| extend User = case(isnotempty(User), User, SPuser)\n| where isnotempty(User));\nEvents\n| summarize dcount(FileName) by User, bin(startofday(TimeGenerated), 1d)\n| summarize CountOfDocs = make_list(dcount_FileName, 10000), TimeStamp = make_list(TimeGenerated, 10000) by User\n| extend (Anomalies, Score, Baseline) = series_decompose_anomalies(CountOfDocs, sensitivity, -1, 'linefit')\n| mv-expand CountOfDocs to typeof(double), TimeStamp to typeof(datetime), Anomalies to typeof(double), Score to typeof(double), Baseline to typeof(long)\n| where Anomalies > 0\n| project TimeStamp, CountOfDocs, Baseline, Score, Anomalies, User\n| join kind=inner(Events | extend TimeStamp = startofday(TimeGenerated)) on TimeStamp, User\n| extend IpAddr = column_ifexists(\"IpAddr\", SrcIpAddr)\n| extend Name = iif(User contains \"@\", split(User, \"@\")[0], split(User, \"\\\\\")[1])\n| extend UPNSuffix = iif(User contains \"@\", split(User, \"@\")[1], \"\")\n| extend NTDomain = iif(User contains \"@\", split(User, \"\\\\\")[0], \"\")\n| project-reorder TimeGenerated, User, EventType, EventResult, EventProduct, FilePath, HttpUserAgent, IpAddr, CountOfDocs, Baseline, Score\n",
"queryFrequency": "P1D",
"queryPeriod": "P14D",
"severity": "Medium",
"subTechniques": [],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"Collection"
],
"techniques": [
"T1530"
],
"templateVersion": "1.0.4",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}