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
incidentConfiguration:
groupingConfiguration:
lookbackDuration: PT5H
reopenClosedIncident: false
matchingMethod: AllEntities
enabled: true
createIncident: true
name: Whisper Security - SPF Record Unauthorized Include Detection
triggerOperator: gt
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
queryFrequency: 1h
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.
id: 9c275139-b554-58f1-b390-8520b10e54ad
triggerThreshold: 0
queryPeriod: 1d
version: 1.0.0
kind: Scheduled
customDetails:
Domain: DnsDomain
UnauthorizedInclude: UnauthorizedInclude
status: Available
severity: High
requiredDataConnectors:
- connectorId: WhisperSecurityConnector
dataTypes:
- WhisperInfraContext_CL
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Whisper/Analytic%20Rules/SpfRecordUnauthorizedInclude.yaml
relevantTechniques:
- T1566
tactics:
- InitialAccess
entityMappings:
- fieldMappings:
- identifier: DomainName
columnName: DnsDomain
entityType: DNS
{
"$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"
}
]
}