Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Suspicious access of BEC related documents in AWS S3 buckets

Back
Idf3e2d35f-1202-4215-995c-4654ef07d1d8
RulenameSuspicious access of BEC related documents in AWS S3 buckets
DescriptionThis 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 AWS S3 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.
SeverityMedium
TacticsCollection
TechniquesT1530
Required data connectorsAWS
KindScheduled
Query frequency1d
Query period14d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Business Email Compromise - Financial Fraud/Analytic Rules/SuspiciousAccessOfBECRelatedDocumentsInAWSS3Buckets.yaml
Version1.0.4
Arm templatef3e2d35f-1202-4215-995c-4654ef07d1d8.json
Deploy To Azure
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(AWSCloudTrail
| where TimeGenerated between (ago(14d)..ago(0d))
| where UserIdentityAccountId != "anonymous"
| where EventSource startswith "s3."
| where EventName =~ "GetObject"
| extend FilePath = tostring(parse_json(RequestParameters).key)
| where FilePath has_any(BEC_Keywords)
);
Events
| summarize dcount(FilePath) by UserIdentityPrincipalid, bin(startofday(TimeGenerated), 1d)
| summarize CountOfDocs = make_list(dcount_FilePath, 10000), TimeStamp = make_list(TimeGenerated, 10000) by UserIdentityPrincipalid
| 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, UserIdentityPrincipalid
| join kind=inner(Events | extend TimeStamp = startofday(TimeGenerated)) on TimeStamp, UserIdentityPrincipalid
| extend Name = iif(UserIdentityUserName contains "@", split(UserIdentityUserName, "@")[0], UserIdentityUserName)
| extend UPNSuffix = iif(UserIdentityUserName contains "@", split(UserIdentityUserName, "@")[1], "")
| project-reorder TimeGenerated, UserIdentityType, UserIdentityPrincipalid, UserIdentityUserName, FilePath, EventName, UserAgent, SourceIpAddress, CountOfDocs, Baseline, Score
relevantTechniques:
- T1530
name: Suspicious access of BEC related documents in AWS S3 buckets
requiredDataConnectors:
- dataTypes:
  - AWSCloudTrail
  connectorId: AWS
entityMappings:
- fieldMappings:
  - identifier: FullName
    columnName: UserIdentityUserName
  - identifier: Name
    columnName: Name
  - identifier: UPNSuffix
    columnName: UPNSuffix
  entityType: Account
- fieldMappings:
  - identifier: Address
    columnName: SourceIpAddress
  entityType: IP
- fieldMappings:
  - identifier: Name
    columnName: FilePath
  entityType: File
triggerThreshold: 0
id: f3e2d35f-1202-4215-995c-4654ef07d1d8
tactics:
- Collection
version: 1.0.4
customDetails:
  UserType: UserIdentityType
  Event: EventName
  UserAgent: UserAgent
alertDetailsOverride:
  alertDisplayNameFormat: Suspicious access of {{CountOfDocs}} BEC related documents in AWS S3 buckets by {{UserIdentityUserName}}
  alertDescriptionFormat: |
    This query looks for users (in this case {{UserIdentityUserName}}) with suspicious spikes in the number of files accessed (in this case {{CountOfDocs}})that relate to topics commonly accessed as part of Business Email Compromise (BEC) attacks. The query looks for access to files in AWS S3 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.    
queryPeriod: 14d
kind: Scheduled
eventGroupingSettings:
  aggregationKind: SingleAlert
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Business Email Compromise - Financial Fraud/Analytic Rules/SuspiciousAccessOfBECRelatedDocumentsInAWSS3Buckets.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 AWS S3 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.'  
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(AWSCloudTrail
  | where TimeGenerated between (ago(14d)..ago(0d))
  | where UserIdentityAccountId != "anonymous"
  | where EventSource startswith "s3."
  | where EventName =~ "GetObject"
  | extend FilePath = tostring(parse_json(RequestParameters).key)
  | where FilePath has_any(BEC_Keywords)
  );
  Events
  | summarize dcount(FilePath) by UserIdentityPrincipalid, bin(startofday(TimeGenerated), 1d)
  | summarize CountOfDocs = make_list(dcount_FilePath, 10000), TimeStamp = make_list(TimeGenerated, 10000) by UserIdentityPrincipalid
  | 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, UserIdentityPrincipalid
  | join kind=inner(Events | extend TimeStamp = startofday(TimeGenerated)) on TimeStamp, UserIdentityPrincipalid
  | extend Name = iif(UserIdentityUserName contains "@", split(UserIdentityUserName, "@")[0], UserIdentityUserName)
  | extend UPNSuffix = iif(UserIdentityUserName contains "@", split(UserIdentityUserName, "@")[1], "")
  | project-reorder TimeGenerated, UserIdentityType, UserIdentityPrincipalid, UserIdentityUserName, FilePath, EventName, UserAgent, SourceIpAddress, 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/f3e2d35f-1202-4215-995c-4654ef07d1d8')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/f3e2d35f-1202-4215-995c-4654ef07d1d8')]",
      "properties": {
        "alertDetailsOverride": {
          "alertDescriptionFormat": "This query looks for users (in this case {{UserIdentityUserName}}) with suspicious spikes in the number of files accessed (in this case {{CountOfDocs}})that relate to topics commonly accessed as part of Business Email Compromise (BEC) attacks. The query looks for access to files in AWS S3 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.\n",
          "alertDisplayNameFormat": "Suspicious access of {{CountOfDocs}} BEC related documents in AWS S3 buckets by {{UserIdentityUserName}}"
        },
        "alertRuleTemplateName": "f3e2d35f-1202-4215-995c-4654ef07d1d8",
        "customDetails": {
          "Event": "EventName",
          "UserAgent": "UserAgent",
          "UserType": "UserIdentityType"
        },
        "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 AWS S3 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.'\n",
        "displayName": "Suspicious access of BEC related documents in AWS S3 buckets",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "UserIdentityUserName",
                "identifier": "FullName"
              },
              {
                "columnName": "Name",
                "identifier": "Name"
              },
              {
                "columnName": "UPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "SourceIpAddress",
                "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/SuspiciousAccessOfBECRelatedDocumentsInAWSS3Buckets.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(AWSCloudTrail\n| where TimeGenerated between (ago(14d)..ago(0d))\n| where UserIdentityAccountId != \"anonymous\"\n| where EventSource startswith \"s3.\"\n| where EventName =~ \"GetObject\"\n| extend FilePath = tostring(parse_json(RequestParameters).key)\n| where FilePath has_any(BEC_Keywords)\n);\nEvents\n| summarize dcount(FilePath) by UserIdentityPrincipalid, bin(startofday(TimeGenerated), 1d)\n| summarize CountOfDocs = make_list(dcount_FilePath, 10000), TimeStamp = make_list(TimeGenerated, 10000) by UserIdentityPrincipalid\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, UserIdentityPrincipalid\n| join kind=inner(Events | extend TimeStamp = startofday(TimeGenerated)) on TimeStamp, UserIdentityPrincipalid\n| extend Name = iif(UserIdentityUserName contains \"@\", split(UserIdentityUserName, \"@\")[0], UserIdentityUserName)\n| extend UPNSuffix = iif(UserIdentityUserName contains \"@\", split(UserIdentityUserName, \"@\")[1], \"\")\n| project-reorder TimeGenerated, UserIdentityType, UserIdentityPrincipalid, UserIdentityUserName, FilePath, EventName, UserAgent, SourceIpAddress, 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"
    }
  ]
}