Detection rules › Kusto
Mail redirect via ExO transport rule
Identifies when Exchange Online transport rule configured to forward emails. This could be an adversary mailbox configured to collect mail from multiple user accounts.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Collection | |
| Exfiltration |
Telemetry coverage
Rules detecting the same action
These rules filter on the same operation.
Rule body
id: 500415fb-bba7-4227-a08a-9857fb61b6a7
name: Mail redirect via ExO transport rule
description: |
'Identifies when Exchange Online transport rule configured to forward emails.
This could be an adversary mailbox configured to collect mail from multiple user accounts.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: Office365
dataTypes:
- OfficeActivity (Exchange)
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Collection
- Exfiltration
relevantTechniques:
- T1114
- T1020
query: |
OfficeActivity
| where OfficeWorkload == "Exchange"
| where Operation in~ ("New-TransportRule", "Set-TransportRule")
| mv-apply DynamicParameters = todynamic(Parameters) on (summarize ParsedParameters = make_bag(pack(tostring(DynamicParameters.Name), DynamicParameters.Value)))
| extend RuleName = case(
Operation =~ "Set-TransportRule", OfficeObjectId,
Operation =~ "New-TransportRule", ParsedParameters.Name,
"Unknown")
| mv-expand ExpandedParameters = todynamic(Parameters)
| where ExpandedParameters.Name in~ ("BlindCopyTo", "RedirectMessageTo") and isnotempty(ExpandedParameters.Value)
| extend RedirectTo = ExpandedParameters.Value
| extend ClientIPValues = extract_all(@'\[?(::ffff:)?(?P<IPAddress>(\d+\.\d+\.\d+\.\d+)|[^\]]+)\]?([-:](?P<Port>\d+))?', dynamic(["IPAddress", "Port"]), ClientIP)[0]
| extend From = ParsedParameters.From
| project TimeGenerated, RedirectTo, IPAddress = tostring(ClientIPValues[0]), Port = tostring(ClientIPValues[1]), UserId, From, Operation, RuleName, Parameters
| extend AccountName = tostring(split(UserId, "@")[0]), AccountUPNSuffix = tostring(split(UserId, "@")[1])
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: UserId
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountUPNSuffix
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IPAddress
version: 2.0.4
kind: Scheduled
Stages and Predicates
Stage 1: source
OfficeActivity
Stage 2: where
| where OfficeWorkload == "Exchange"
Stage 3: where
| where Operation in~ ("New-TransportRule", "Set-TransportRule")
Stage 4: kusto:mv-apply
| mv-apply DynamicParameters = todynamic(Parameters) on (summarize ParsedParameters = make_bag(pack(tostring(DynamicParameters.Name), DynamicParameters.Value)))
Stage 5: extend
| extend RuleName = case(
Operation =~ "Set-TransportRule", OfficeObjectId,
Operation =~ "New-TransportRule", ParsedParameters.Name,
"Unknown")
RuleName =if
Operation =~ "Set-TransportRule"OfficeObjectIdelif
Operation =~ "New-TransportRule"ParsedParameters.Nameelse
"Unknown"Stage 6: mv-expand
| mv-expand ExpandedParameters = todynamic(Parameters)
Stage 7: where
| where ExpandedParameters.Name in~ ("BlindCopyTo", "RedirectMessageTo") and isnotempty(ExpandedParameters.Value)
Stage 8: extend (3 consecutive steps)
| extend RedirectTo = ExpandedParameters.Value
| extend ClientIPValues = extract_all(@'\[?(::ffff:)?(?P<IPAddress>(\d+\.\d+\.\d+\.\d+)|[^\]]+)\]?([-:](?P<Port>\d+))?', dynamic(["IPAddress", "Port"]), ClientIP)[0]
| extend From = ParsedParameters.From
Stage 9: project
| project TimeGenerated, RedirectTo, IPAddress = tostring(ClientIPValues[0]), Port = tostring(ClientIPValues[1]), UserId, From, Operation, RuleName, Parameters
Stage 10: extend
| extend AccountName = tostring(split(UserId, "@")[0]), AccountUPNSuffix = tostring(split(UserId, "@")[1])
Stage 11: summarize aggregation inside the mv-apply branch
summarize
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Name | in |
| field:"Name" kind:in |
OfficeWorkload | eq |
| field:"m365::Workload" kind:eq value:"Exchange" |
Operation | in |
| field:"Operation" kind:in |
Value | is_not_null | field:"Value" kind:is_not_null |