Back
Id8ac77493-3cae-4840-8634-15fb23f8fb68
RulenameMalicious BEC Inbox Rule
DescriptionOften times after the initial compromise in a BEC attack the attackers create inbox rules to delete emails that contain certain keywords related to their BEC attack.

This is done so as to limit ability to warn compromised users that they’ve been compromised.
SeverityMedium
TacticsPersistence
DefenseEvasion
TechniquesT1098
T1078
Required data connectorsOffice365
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Business%20Email%20Compromise%20-%20Financial%20Fraud/Analytic%20Rules/BEC_MailboxRule.yaml
Version1.0.2
Arm template8ac77493-3cae-4840-8634-15fb23f8fb68.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']);
OfficeActivity
| where Operation =~ "New-InboxRule"
| where Parameters has "Deleted Items" or Parameters has "Junk Email"  or Parameters has "DeleteMessage"
| extend Events=todynamic(Parameters)
| parse Events  with * "SubjectContainsWords" SubjectContainsWords '}'*
| parse Events  with * "BodyContainsWords" BodyContainsWords '}'*
| parse Events  with * "SubjectOrBodyContainsWords" SubjectOrBodyContainsWords '}'*
| where SubjectContainsWords has_any (BEC_Keywords)
 or BodyContainsWords has_any (BEC_Keywords)
 or SubjectOrBodyContainsWords has_any (BEC_Keywords)
| extend ClientIPAddress = case( ClientIP has ".", tostring(split(ClientIP,":")[0]), ClientIP has "[", tostring(trim_start(@'[[]',tostring(split(ClientIP,"]")[0]))), ClientIP )
| extend Keyword = iff(isnotempty(SubjectContainsWords), SubjectContainsWords, (iff(isnotempty(BodyContainsWords),BodyContainsWords,SubjectOrBodyContainsWords )))
| extend RuleDetail = case(OfficeObjectId contains '/' , tostring(split(OfficeObjectId, '/')[-1]) , tostring(split(OfficeObjectId, '\\')[-1]))
| summarize count(), StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated) by  Operation, UserId, ClientIPAddress, ResultStatus, Keyword, OriginatingServer, OfficeObjectId, RuleDetail
| extend UserName = split(UserId, '@')[0], DomainName = split(UserId, '@')[1]
tactics:
- Persistence
- DefenseEvasion
tags:
- BEC
requiredDataConnectors:
- dataTypes:
  - OfficeActivity
  connectorId: Office365
queryPeriod: 1d
kind: Scheduled
severity: Medium
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Business%20Email%20Compromise%20-%20Financial%20Fraud/Analytic%20Rules/BEC_MailboxRule.yaml
queryFrequency: 1d
triggerThreshold: 0
description: |
  'Often times after the initial compromise in a BEC attack the attackers create inbox rules to delete emails that contain certain keywords related to their BEC attack.
   This is done so as to limit ability to warn compromised users that they've been compromised. 
id: 8ac77493-3cae-4840-8634-15fb23f8fb68
triggerOperator: gt
relevantTechniques:
- T1098
- T1078
version: 1.0.2
name: Malicious BEC Inbox Rule
entityMappings:
- entityType: Account
  fieldMappings:
  - columnName: UserId
    identifier: FullName
  - columnName: UserName
    identifier: Name
  - columnName: DomainName
    identifier: UPNSuffix
- entityType: IP
  fieldMappings:
  - columnName: ClientIPAddress
    identifier: Address
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']);
  OfficeActivity
  | where Operation =~ "New-InboxRule"
  | where Parameters has "Deleted Items" or Parameters has "Junk Email"  or Parameters has "DeleteMessage"
  | extend Events=todynamic(Parameters)
  | parse Events  with * "SubjectContainsWords" SubjectContainsWords '}'*
  | parse Events  with * "BodyContainsWords" BodyContainsWords '}'*
  | parse Events  with * "SubjectOrBodyContainsWords" SubjectOrBodyContainsWords '}'*
  | where SubjectContainsWords has_any (BEC_Keywords)
   or BodyContainsWords has_any (BEC_Keywords)
   or SubjectOrBodyContainsWords has_any (BEC_Keywords)
  | extend ClientIPAddress = case( ClientIP has ".", tostring(split(ClientIP,":")[0]), ClientIP has "[", tostring(trim_start(@'[[]',tostring(split(ClientIP,"]")[0]))), ClientIP )
  | extend Keyword = iff(isnotempty(SubjectContainsWords), SubjectContainsWords, (iff(isnotempty(BodyContainsWords),BodyContainsWords,SubjectOrBodyContainsWords )))
  | extend RuleDetail = case(OfficeObjectId contains '/' , tostring(split(OfficeObjectId, '/')[-1]) , tostring(split(OfficeObjectId, '\\')[-1]))
  | summarize count(), StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated) by  Operation, UserId, ClientIPAddress, ResultStatus, Keyword, OriginatingServer, OfficeObjectId, RuleDetail
  | extend UserName = split(UserId, '@')[0], DomainName = split(UserId, '@')[1]
{
  "$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/8ac77493-3cae-4840-8634-15fb23f8fb68')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/8ac77493-3cae-4840-8634-15fb23f8fb68')]",
      "properties": {
        "alertRuleTemplateName": "8ac77493-3cae-4840-8634-15fb23f8fb68",
        "customDetails": null,
        "description": "'Often times after the initial compromise in a BEC attack the attackers create inbox rules to delete emails that contain certain keywords related to their BEC attack.\n This is done so as to limit ability to warn compromised users that they've been compromised. \n",
        "displayName": "Malicious BEC Inbox Rule",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "UserId",
                "identifier": "FullName"
              },
              {
                "columnName": "UserName",
                "identifier": "Name"
              },
              {
                "columnName": "DomainName",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "ClientIPAddress",
                "identifier": "Address"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Business%20Email%20Compromise%20-%20Financial%20Fraud/Analytic%20Rules/BEC_MailboxRule.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']);\nOfficeActivity\n| where Operation =~ \"New-InboxRule\"\n| where Parameters has \"Deleted Items\" or Parameters has \"Junk Email\"  or Parameters has \"DeleteMessage\"\n| extend Events=todynamic(Parameters)\n| parse Events  with * \"SubjectContainsWords\" SubjectContainsWords '}'*\n| parse Events  with * \"BodyContainsWords\" BodyContainsWords '}'*\n| parse Events  with * \"SubjectOrBodyContainsWords\" SubjectOrBodyContainsWords '}'*\n| where SubjectContainsWords has_any (BEC_Keywords)\n or BodyContainsWords has_any (BEC_Keywords)\n or SubjectOrBodyContainsWords has_any (BEC_Keywords)\n| extend ClientIPAddress = case( ClientIP has \".\", tostring(split(ClientIP,\":\")[0]), ClientIP has \"[\", tostring(trim_start(@'[[]',tostring(split(ClientIP,\"]\")[0]))), ClientIP )\n| extend Keyword = iff(isnotempty(SubjectContainsWords), SubjectContainsWords, (iff(isnotempty(BodyContainsWords),BodyContainsWords,SubjectOrBodyContainsWords )))\n| extend RuleDetail = case(OfficeObjectId contains '/' , tostring(split(OfficeObjectId, '/')[-1]) , tostring(split(OfficeObjectId, '\\\\')[-1]))\n| summarize count(), StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated) by  Operation, UserId, ClientIPAddress, ResultStatus, Keyword, OriginatingServer, OfficeObjectId, RuleDetail\n| extend UserName = split(UserId, '@')[0], DomainName = split(UserId, '@')[1]\n",
        "queryFrequency": "P1D",
        "queryPeriod": "P1D",
        "severity": "Medium",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "DefenseEvasion",
          "Persistence"
        ],
        "tags": [
          "BEC"
        ],
        "techniques": [
          "T1078",
          "T1098"
        ],
        "templateVersion": "1.0.2",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}