Analytic rule catalog
Whisper Security - SPF Record Unauthorized Include Detection
Back
| Id | 9c275139-b554-58f1-b390-8520b10e54ad |
| Rulename | Whisper Security - SPF Record Unauthorized Include Detection |
| Description | Detects new SPF include directives on monitored domains that were not seen in the previous scan window. Unauthorized SPF modifications may allow adversaries to send phishing emails that pass SPF checks. |
| Severity | High |
| Tactics | InitialAccess |
| Techniques | T1566 |
| Required data connectors | WhisperSecurityConnector |
| Kind | Scheduled |
| Query frequency | 1h |
| Query period | 1d |
| Trigger threshold | 0 |
| Trigger operator | gt |
| Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Whisper/Analytic%20Rules/SpfRecordUnauthorizedInclude.yaml |
| Version | 1.0.0 |
| Arm template | 9c275139-b554-58f1-b390-8520b10e54ad.json |
// MITRE ATT&CK: T1566.001 - Phishing: Spearphishing Attachment
// Tactic: Initial Access
// Detects unauthorized SPF include directives not seen in previous scans
// Configure authorized_spf_includes with your organization's known SPF providers
let authorized_spf_includes = dynamic(["_spf.google.com", "spf.protection.outlook.com", "amazonses.com", "sendgrid.net", "mailgun.org"]);
let previousIncludes = WhisperInfraContext_CL
| where TimeGenerated between (ago(1d) .. ago(1h))
| where isnotempty(spfIncludes)
| mv-expand SpfInclude = split(spfIncludes, ",")
| extend SpfInclude = tostring(SpfInclude)
| summarize PreviousIncludes = make_set(SpfInclude) by indicator;
let currentIncludes = WhisperInfraContext_CL
| where TimeGenerated > ago(1h)
| where isnotempty(spfIncludes)
| mv-expand SpfInclude = split(spfIncludes, ",")
| extend SpfInclude = tostring(SpfInclude)
| project indicator, SpfInclude, TimeGenerated;
currentIncludes
| join kind=leftanti (previousIncludes | mv-expand PrevInclude = PreviousIncludes | extend SpfInclude = tostring(PrevInclude) | project indicator, SpfInclude) on indicator, SpfInclude
| where SpfInclude !in (authorized_spf_includes)
| project TimeGenerated, DnsDomain = indicator, UnauthorizedInclude = SpfInclude
entityMappings:
- entityType: DNS
fieldMappings:
- identifier: DomainName
columnName: DnsDomain
name: Whisper Security - SPF Record Unauthorized Include Detection
kind: Scheduled
triggerOperator: gt
status: Available
queryPeriod: 1d
requiredDataConnectors:
- connectorId: WhisperSecurityConnector
dataTypes:
- WhisperInfraContext_CL
tactics:
- InitialAccess
query: |
// MITRE ATT&CK: T1566.001 - Phishing: Spearphishing Attachment
// Tactic: Initial Access
// Detects unauthorized SPF include directives not seen in previous scans
// Configure authorized_spf_includes with your organization's known SPF providers
let authorized_spf_includes = dynamic(["_spf.google.com", "spf.protection.outlook.com", "amazonses.com", "sendgrid.net", "mailgun.org"]);
let previousIncludes = WhisperInfraContext_CL
| where TimeGenerated between (ago(1d) .. ago(1h))
| where isnotempty(spfIncludes)
| mv-expand SpfInclude = split(spfIncludes, ",")
| extend SpfInclude = tostring(SpfInclude)
| summarize PreviousIncludes = make_set(SpfInclude) by indicator;
let currentIncludes = WhisperInfraContext_CL
| where TimeGenerated > ago(1h)
| where isnotempty(spfIncludes)
| mv-expand SpfInclude = split(spfIncludes, ",")
| extend SpfInclude = tostring(SpfInclude)
| project indicator, SpfInclude, TimeGenerated;
currentIncludes
| join kind=leftanti (previousIncludes | mv-expand PrevInclude = PreviousIncludes | extend SpfInclude = tostring(PrevInclude) | project indicator, SpfInclude) on indicator, SpfInclude
| where SpfInclude !in (authorized_spf_includes)
| project TimeGenerated, DnsDomain = indicator, UnauthorizedInclude = SpfInclude
description: |
Detects new SPF include directives on monitored domains that were not seen in the previous scan window. Unauthorized SPF modifications may allow adversaries to send phishing emails that pass SPF checks.
severity: High
incidentConfiguration:
groupingConfiguration:
lookbackDuration: PT5H
enabled: true
reopenClosedIncident: false
matchingMethod: AllEntities
createIncident: true
id: 9c275139-b554-58f1-b390-8520b10e54ad
customDetails:
UnauthorizedInclude: UnauthorizedInclude
Domain: DnsDomain
triggerThreshold: 0
queryFrequency: 1h
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Whisper/Analytic%20Rules/SpfRecordUnauthorizedInclude.yaml
version: 1.0.0
relevantTechniques:
- T1566
{
"$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/9c275139-b554-58f1-b390-8520b10e54ad')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/9c275139-b554-58f1-b390-8520b10e54ad')]",
"properties": {
"alertRuleTemplateName": "9c275139-b554-58f1-b390-8520b10e54ad",
"customDetails": {
"Domain": "DnsDomain",
"UnauthorizedInclude": "UnauthorizedInclude"
},
"description": "Detects new SPF include directives on monitored domains that were not seen in the previous scan window. Unauthorized SPF modifications may allow adversaries to send phishing emails that pass SPF checks.\n",
"displayName": "Whisper Security - SPF Record Unauthorized Include Detection",
"enabled": true,
"entityMappings": [
{
"entityType": "DNS",
"fieldMappings": [
{
"columnName": "DnsDomain",
"identifier": "DomainName"
}
]
}
],
"incidentConfiguration": {
"createIncident": true,
"groupingConfiguration": {
"enabled": true,
"lookbackDuration": "PT5H",
"matchingMethod": "AllEntities",
"reopenClosedIncident": false
}
},
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Whisper/Analytic%20Rules/SpfRecordUnauthorizedInclude.yaml",
"query": "// MITRE ATT&CK: T1566.001 - Phishing: Spearphishing Attachment\n// Tactic: Initial Access\n// Detects unauthorized SPF include directives not seen in previous scans\n// Configure authorized_spf_includes with your organization's known SPF providers\nlet authorized_spf_includes = dynamic([\"_spf.google.com\", \"spf.protection.outlook.com\", \"amazonses.com\", \"sendgrid.net\", \"mailgun.org\"]);\nlet previousIncludes = WhisperInfraContext_CL\n | where TimeGenerated between (ago(1d) .. ago(1h))\n | where isnotempty(spfIncludes)\n | mv-expand SpfInclude = split(spfIncludes, \",\")\n | extend SpfInclude = tostring(SpfInclude)\n | summarize PreviousIncludes = make_set(SpfInclude) by indicator;\nlet currentIncludes = WhisperInfraContext_CL\n | where TimeGenerated > ago(1h)\n | where isnotempty(spfIncludes)\n | mv-expand SpfInclude = split(spfIncludes, \",\")\n | extend SpfInclude = tostring(SpfInclude)\n | project indicator, SpfInclude, TimeGenerated;\ncurrentIncludes\n | join kind=leftanti (previousIncludes | mv-expand PrevInclude = PreviousIncludes | extend SpfInclude = tostring(PrevInclude) | project indicator, SpfInclude) on indicator, SpfInclude\n | where SpfInclude !in (authorized_spf_includes)\n | project TimeGenerated, DnsDomain = indicator, UnauthorizedInclude = SpfInclude\n",
"queryFrequency": "PT1H",
"queryPeriod": "P1D",
"severity": "High",
"status": "Available",
"subTechniques": [],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"InitialAccess"
],
"techniques": [
"T1566"
],
"templateVersion": "1.0.0",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}