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
TacticsImpact
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.1
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])
queryPeriod: 14d
entityMappings:
- fieldMappings:
  - columnName: RecipientEmailAddress
    identifier: FullName
  - columnName: Name
    identifier: Name
  - columnName: UPNSuffix
    identifier: UPNSuffix
  entityType: Account
- fieldMappings:
  - columnName: Url
    identifier: Url
  entityType: URL
id: a0038239-72f4-4f7b-90ff-37f89f7881e0
name: TI Map URL Entity to EmailUrlInfo
description: |
    'This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in EmailUrlInfo.'
tactics:
- Impact
triggerOperator: gt
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])  
queryFrequency: 1h
triggerThreshold: 0
kind: Scheduled
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
version: 1.0.1
severity: Medium
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspace": {
      "type": "String"
    }
  },
  "resources": [
    {
      "apiVersion": "2023-02-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",
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "Impact"
        ],
        "templateVersion": "1.0.1",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}