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

Multiple users email forwarded to same destination

Back
Ida1551ae4-f61c-4bca-9c57-4d0d681db2e9
RulenameMultiple users email forwarded to same destination
DescriptionIdentifies when multiple (more than one) users mailboxes are configured to forward to the same destination.

This could be an attacker-controlled destination mailbox configured to collect mail from multiple compromised user accounts.
SeverityMedium
TacticsCollection
Exfiltration
TechniquesT1114
T1020
Required data connectorsOffice365
KindScheduled
Query frequency1d
Query period7d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft 365/Hunting Queries/MultipleUsersEmailForwardedToSameDestination.yaml
Version2.0.0
Arm templatea1551ae4-f61c-4bca-9c57-4d0d681db2e9.json
Deploy To Azure
let queryfrequency = 1d;
let queryperiod = 7d;
OfficeActivity
| where TimeGenerated > ago(queryperiod)
| where OfficeWorkload =~ "Exchange"
//| where Operation in ("Set-Mailbox", "New-InboxRule", "Set-InboxRule")
| where Parameters has_any ("ForwardTo", "RedirectTo", "ForwardingSmtpAddress")
| mv-apply DynamicParameters = todynamic(Parameters) on (summarize ParsedParameters = make_bag(pack(tostring(DynamicParameters.Name), DynamicParameters.Value)))
| evaluate bag_unpack(ParsedParameters, columnsConflict='replace_source')
| extend DestinationMailAddress = tolower(case(
    isnotempty(column_ifexists("ForwardTo", "")), column_ifexists("ForwardTo", ""),
    isnotempty(column_ifexists("RedirectTo", "")), column_ifexists("RedirectTo", ""),
    isnotempty(column_ifexists("ForwardingSmtpAddress", "")), trim_start(@"smtp:", column_ifexists("ForwardingSmtpAddress", "")),
    ""))
| where isnotempty(DestinationMailAddress)
| mv-expand split(DestinationMailAddress, ";")
| extend ClientIPValues = extract_all(@'\[?(::ffff:)?(?P<IPAddress>(\d+\.\d+\.\d+\.\d+)|[^\]]+)\]?([-:](?P<Port>\d+))?', dynamic(["IPAddress", "Port"]), ClientIP)[0]
| extend ClientIP = tostring(ClientIPValues[0]), Port = tostring(ClientIPValues[1])
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), DistinctUserCount = dcount(UserId), UserId = make_set(UserId, 250), Ports = make_set(Port, 250), EventCount = count() by tostring(DestinationMailAddress), ClientIP
| where DistinctUserCount > 1 and EndTime > ago(queryfrequency)
| mv-expand UserId to typeof(string)
| extend timestamp = StartTime, AccountCustomEntity = UserId, IPCustomEntity = ClientIP
requiredDataConnectors:
- connectorId: Office365
  dataTypes:
  - OfficeActivity
triggerOperator: gt
queryFrequency: 1d
name: Multiple users email forwarded to same destination
status: Available
queryPeriod: 7d
id: a1551ae4-f61c-4bca-9c57-4d0d681db2e9
description: |
  'Identifies when multiple (more than one) users mailboxes are configured to forward to the same destination. 
  This could be an attacker-controlled destination mailbox configured to collect mail from multiple compromised user accounts.'  
severity: Medium
query: |
  let queryfrequency = 1d;
  let queryperiod = 7d;
  OfficeActivity
  | where TimeGenerated > ago(queryperiod)
  | where OfficeWorkload =~ "Exchange"
  //| where Operation in ("Set-Mailbox", "New-InboxRule", "Set-InboxRule")
  | where Parameters has_any ("ForwardTo", "RedirectTo", "ForwardingSmtpAddress")
  | mv-apply DynamicParameters = todynamic(Parameters) on (summarize ParsedParameters = make_bag(pack(tostring(DynamicParameters.Name), DynamicParameters.Value)))
  | evaluate bag_unpack(ParsedParameters, columnsConflict='replace_source')
  | extend DestinationMailAddress = tolower(case(
      isnotempty(column_ifexists("ForwardTo", "")), column_ifexists("ForwardTo", ""),
      isnotempty(column_ifexists("RedirectTo", "")), column_ifexists("RedirectTo", ""),
      isnotempty(column_ifexists("ForwardingSmtpAddress", "")), trim_start(@"smtp:", column_ifexists("ForwardingSmtpAddress", "")),
      ""))
  | where isnotempty(DestinationMailAddress)
  | mv-expand split(DestinationMailAddress, ";")
  | extend ClientIPValues = extract_all(@'\[?(::ffff:)?(?P<IPAddress>(\d+\.\d+\.\d+\.\d+)|[^\]]+)\]?([-:](?P<Port>\d+))?', dynamic(["IPAddress", "Port"]), ClientIP)[0]
  | extend ClientIP = tostring(ClientIPValues[0]), Port = tostring(ClientIPValues[1])
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), DistinctUserCount = dcount(UserId), UserId = make_set(UserId, 250), Ports = make_set(Port, 250), EventCount = count() by tostring(DestinationMailAddress), ClientIP
  | where DistinctUserCount > 1 and EndTime > ago(queryfrequency)
  | mv-expand UserId to typeof(string)
  | extend timestamp = StartTime, AccountCustomEntity = UserId, IPCustomEntity = ClientIP  
version: 2.0.0
kind: Scheduled
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft 365/Hunting Queries/MultipleUsersEmailForwardedToSameDestination.yaml
entityMappings:
- entityType: Account
  fieldMappings:
  - identifier: FullName
    columnName: AccountCustomEntity
- entityType: IP
  fieldMappings:
  - identifier: Address
    columnName: IPCustomEntity
relevantTechniques:
- T1114
- T1020
tactics:
- Collection
- Exfiltration
triggerThreshold: 0
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspace": {
      "type": "String"
    }
  },
  "resources": [
    {
      "id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/a1551ae4-f61c-4bca-9c57-4d0d681db2e9')]",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/a1551ae4-f61c-4bca-9c57-4d0d681db2e9')]",
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules",
      "kind": "Scheduled",
      "apiVersion": "2022-11-01-preview",
      "properties": {
        "displayName": "Multiple users email forwarded to same destination",
        "description": "'Identifies when multiple (more than one) users mailboxes are configured to forward to the same destination. \nThis could be an attacker-controlled destination mailbox configured to collect mail from multiple compromised user accounts.'\n",
        "severity": "Medium",
        "enabled": true,
        "query": "let queryfrequency = 1d;\nlet queryperiod = 7d;\nOfficeActivity\n| where TimeGenerated > ago(queryperiod)\n| where OfficeWorkload =~ \"Exchange\"\n//| where Operation in (\"Set-Mailbox\", \"New-InboxRule\", \"Set-InboxRule\")\n| where Parameters has_any (\"ForwardTo\", \"RedirectTo\", \"ForwardingSmtpAddress\")\n| mv-apply DynamicParameters = todynamic(Parameters) on (summarize ParsedParameters = make_bag(pack(tostring(DynamicParameters.Name), DynamicParameters.Value)))\n| evaluate bag_unpack(ParsedParameters, columnsConflict='replace_source')\n| extend DestinationMailAddress = tolower(case(\n    isnotempty(column_ifexists(\"ForwardTo\", \"\")), column_ifexists(\"ForwardTo\", \"\"),\n    isnotempty(column_ifexists(\"RedirectTo\", \"\")), column_ifexists(\"RedirectTo\", \"\"),\n    isnotempty(column_ifexists(\"ForwardingSmtpAddress\", \"\")), trim_start(@\"smtp:\", column_ifexists(\"ForwardingSmtpAddress\", \"\")),\n    \"\"))\n| where isnotempty(DestinationMailAddress)\n| mv-expand split(DestinationMailAddress, \";\")\n| extend ClientIPValues = extract_all(@'\\[?(::ffff:)?(?P<IPAddress>(\\d+\\.\\d+\\.\\d+\\.\\d+)|[^\\]]+)\\]?([-:](?P<Port>\\d+))?', dynamic([\"IPAddress\", \"Port\"]), ClientIP)[0]\n| extend ClientIP = tostring(ClientIPValues[0]), Port = tostring(ClientIPValues[1])\n| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), DistinctUserCount = dcount(UserId), UserId = make_set(UserId, 250), Ports = make_set(Port, 250), EventCount = count() by tostring(DestinationMailAddress), ClientIP\n| where DistinctUserCount > 1 and EndTime > ago(queryfrequency)\n| mv-expand UserId to typeof(string)\n| extend timestamp = StartTime, AccountCustomEntity = UserId, IPCustomEntity = ClientIP\n",
        "queryFrequency": "P1D",
        "queryPeriod": "P7D",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0,
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "Collection",
          "Exfiltration"
        ],
        "techniques": [
          "T1114",
          "T1020"
        ],
        "alertRuleTemplateName": "a1551ae4-f61c-4bca-9c57-4d0d681db2e9",
        "customDetails": null,
        "entityMappings": [
          {
            "fieldMappings": [
              {
                "identifier": "FullName",
                "columnName": "AccountCustomEntity"
              }
            ],
            "entityType": "Account"
          },
          {
            "fieldMappings": [
              {
                "identifier": "Address",
                "columnName": "IPCustomEntity"
              }
            ],
            "entityType": "IP"
          }
        ],
        "templateVersion": "2.0.0",
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft 365/Hunting Queries/MultipleUsersEmailForwardedToSameDestination.yaml",
        "status": "Available"
      }
    }
  ]
}