Malicious BEC Inbox Rule
Id | 8ac77493-3cae-4840-8634-15fb23f8fb68 |
Rulename | Malicious BEC Inbox Rule |
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. |
Severity | Medium |
Tactics | Persistence DefenseEvasion |
Techniques | T1098 T1078 |
Required data connectors | Office365 |
Kind | Scheduled |
Query frequency | 1d |
Query period | 1d |
Trigger threshold | 0 |
Trigger operator | gt |
Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Business Email Compromise - Financial Fraud/Analytic Rules/BEC_MailboxRule.yaml |
Version | 1.0.2 |
Arm template | 8ac77493-3cae-4840-8634-15fb23f8fb68.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']);
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]
version: 1.0.2
tags:
- BEC
queryFrequency: 1d
triggerOperator: gt
severity: Medium
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Business Email Compromise - Financial Fraud/Analytic Rules/BEC_MailboxRule.yaml
kind: Scheduled
triggerThreshold: 0
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]
entityMappings:
- fieldMappings:
- columnName: UserId
identifier: FullName
- columnName: UserName
identifier: Name
- columnName: DomainName
identifier: UPNSuffix
entityType: Account
- fieldMappings:
- columnName: ClientIPAddress
identifier: Address
entityType: IP
name: Malicious BEC Inbox Rule
queryPeriod: 1d
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.
requiredDataConnectors:
- dataTypes:
- OfficeActivity
connectorId: Office365
id: 8ac77493-3cae-4840-8634-15fb23f8fb68
relevantTechniques:
- T1098
- T1078
tactics:
- Persistence
- DefenseEvasion
{
"$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 Email Compromise - Financial Fraud/Analytic Rules/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"
}
]
}