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

TI Map URL Entity to EmailUrlInfo

Back
Ida0038239-72f4-4f7b-90ff-37f89f7881e0
RulenameTI Map URL Entity to EmailUrlInfo
DescriptionThis query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in EmailUrlInfo.
SeverityMedium
TacticsCommandAndControl
TechniquesT1071
Required data connectorsAzureActiveDirectory
MicrosoftDefenderThreatIntelligence
ThreatIntelligence
ThreatIntelligenceTaxii
KindScheduled
Query frequency1h
Query period14d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence/Analytic Rules/URLEntity_EmailUrlInfo.yaml
Version1.0.2
Arm templatea0038239-72f4-4f7b-90ff-37f89f7881e0.json
Deploy To Azure
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let EmailUrlInfo_ = materialize(EmailUrlInfo
    | where isnotempty(Url)
    | where TimeGenerated >= ago(dt_lookBack)
    | extend Url = tolower(Url)
    | extend EmailUrlInfo_TimeGenerated = TimeGenerated);
let EmailUrls = EmailUrlInfo_ | distinct Url | summarize make_list(Url);
let EmailUrlDomains = EmailUrlInfo_ | distinct UrlDomain | summarize make_list(UrlDomain);
let EmailEvents_ = materialize(EmailEvents
    | where TimeGenerated >= ago(dt_lookBack));
let TI = materialize(ThreatIntelligenceIndicator
    | where TimeGenerated >= ago(ioc_lookBack)
    | where (isnotempty(Url) or isnotempty(DomainName)) 
    | where tolower(Url) in (EmailUrls) or tolower(DomainName) in (EmailUrlDomains)
    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
    | where Active == true and ExpirationDateTime > now());
(union
    (TI | join kind=innerunique (EmailUrlInfo_) on Url),
    (TI | join kind=innerunique (EmailUrlInfo_) on $left.DomainName == $right.UrlDomain))
| where EmailUrlInfo_TimeGenerated < ExpirationDateTime
| summarize EmailUrlInfo_TimeGenerated = arg_max(EmailUrlInfo_TimeGenerated, *) by IndicatorId, Url
| project EmailUrlInfo_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Url, UrlDomain, UrlLocation, NetworkMessageId
| extend timestamp = EmailUrlInfo_TimeGenerated
| join kind=inner (EmailEvents_) on NetworkMessageId
| where DeliveryAction !has "Blocked"
| extend Name = tostring(split(RecipientEmailAddress, '@', 0)[0]), UPNSuffix = tostring(split(RecipientEmailAddress, '@', 1)[0])
id: a0038239-72f4-4f7b-90ff-37f89f7881e0
triggerOperator: gt
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence/Analytic Rules/URLEntity_EmailUrlInfo.yaml
requiredDataConnectors:
- dataTypes:
  - EmailUrlInfo
  connectorId: AzureActiveDirectory
- dataTypes:
  - ThreatIntelligenceIndicator
  connectorId: ThreatIntelligence
- dataTypes:
  - ThreatIntelligenceIndicator
  connectorId: ThreatIntelligenceTaxii
- dataTypes:
  - ThreatIntelligenceIndicator
  connectorId: MicrosoftDefenderThreatIntelligence
description: |
    'This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in EmailUrlInfo.'
severity: Medium
queryPeriod: 14d
kind: Scheduled
tactics:
- CommandAndControl
queryFrequency: 1h
query: |
  let dt_lookBack = 1h;
  let ioc_lookBack = 14d;
  let EmailUrlInfo_ = materialize(EmailUrlInfo
      | where isnotempty(Url)
      | where TimeGenerated >= ago(dt_lookBack)
      | extend Url = tolower(Url)
      | extend EmailUrlInfo_TimeGenerated = TimeGenerated);
  let EmailUrls = EmailUrlInfo_ | distinct Url | summarize make_list(Url);
  let EmailUrlDomains = EmailUrlInfo_ | distinct UrlDomain | summarize make_list(UrlDomain);
  let EmailEvents_ = materialize(EmailEvents
      | where TimeGenerated >= ago(dt_lookBack));
  let TI = materialize(ThreatIntelligenceIndicator
      | where TimeGenerated >= ago(ioc_lookBack)
      | where (isnotempty(Url) or isnotempty(DomainName)) 
      | where tolower(Url) in (EmailUrls) or tolower(DomainName) in (EmailUrlDomains)
      | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
      | where Active == true and ExpirationDateTime > now());
  (union
      (TI | join kind=innerunique (EmailUrlInfo_) on Url),
      (TI | join kind=innerunique (EmailUrlInfo_) on $left.DomainName == $right.UrlDomain))
  | where EmailUrlInfo_TimeGenerated < ExpirationDateTime
  | summarize EmailUrlInfo_TimeGenerated = arg_max(EmailUrlInfo_TimeGenerated, *) by IndicatorId, Url
  | project EmailUrlInfo_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Url, UrlDomain, UrlLocation, NetworkMessageId
  | extend timestamp = EmailUrlInfo_TimeGenerated
  | join kind=inner (EmailEvents_) on NetworkMessageId
  | where DeliveryAction !has "Blocked"
  | extend Name = tostring(split(RecipientEmailAddress, '@', 0)[0]), UPNSuffix = tostring(split(RecipientEmailAddress, '@', 1)[0])  
version: 1.0.2
triggerThreshold: 0
name: TI Map URL Entity to EmailUrlInfo
entityMappings:
- entityType: Account
  fieldMappings:
  - columnName: RecipientEmailAddress
    identifier: FullName
  - columnName: Name
    identifier: Name
  - columnName: UPNSuffix
    identifier: UPNSuffix
- entityType: URL
  fieldMappings:
  - columnName: Url
    identifier: Url
relevantTechniques:
- T1071
{
  "$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/a0038239-72f4-4f7b-90ff-37f89f7881e0')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/a0038239-72f4-4f7b-90ff-37f89f7881e0')]",
      "properties": {
        "alertRuleTemplateName": "a0038239-72f4-4f7b-90ff-37f89f7881e0",
        "customDetails": null,
        "description": "'This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in EmailUrlInfo.'\n",
        "displayName": "TI Map URL Entity to EmailUrlInfo",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "RecipientEmailAddress",
                "identifier": "FullName"
              },
              {
                "columnName": "Name",
                "identifier": "Name"
              },
              {
                "columnName": "UPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "URL",
            "fieldMappings": [
              {
                "columnName": "Url",
                "identifier": "Url"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence/Analytic Rules/URLEntity_EmailUrlInfo.yaml",
        "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet EmailUrlInfo_ = materialize(EmailUrlInfo\n    | where isnotempty(Url)\n    | where TimeGenerated >= ago(dt_lookBack)\n    | extend Url = tolower(Url)\n    | extend EmailUrlInfo_TimeGenerated = TimeGenerated);\nlet EmailUrls = EmailUrlInfo_ | distinct Url | summarize make_list(Url);\nlet EmailUrlDomains = EmailUrlInfo_ | distinct UrlDomain | summarize make_list(UrlDomain);\nlet EmailEvents_ = materialize(EmailEvents\n    | where TimeGenerated >= ago(dt_lookBack));\nlet TI = materialize(ThreatIntelligenceIndicator\n    | where TimeGenerated >= ago(ioc_lookBack)\n    | where (isnotempty(Url) or isnotempty(DomainName)) \n    | where tolower(Url) in (EmailUrls) or tolower(DomainName) in (EmailUrlDomains)\n    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n    | where Active == true and ExpirationDateTime > now());\n(union\n    (TI | join kind=innerunique (EmailUrlInfo_) on Url),\n    (TI | join kind=innerunique (EmailUrlInfo_) on $left.DomainName == $right.UrlDomain))\n| where EmailUrlInfo_TimeGenerated < ExpirationDateTime\n| summarize EmailUrlInfo_TimeGenerated = arg_max(EmailUrlInfo_TimeGenerated, *) by IndicatorId, Url\n| project EmailUrlInfo_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Url, UrlDomain, UrlLocation, NetworkMessageId\n| extend timestamp = EmailUrlInfo_TimeGenerated\n| join kind=inner (EmailEvents_) on NetworkMessageId\n| where DeliveryAction !has \"Blocked\"\n| extend Name = tostring(split(RecipientEmailAddress, '@', 0)[0]), UPNSuffix = tostring(split(RecipientEmailAddress, '@', 1)[0])\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P14D",
        "severity": "Medium",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CommandAndControl"
        ],
        "techniques": [
          "T1071"
        ],
        "templateVersion": "1.0.2",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}