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 DeviceNetworkEvents

Back
Id4f0356b2-d344-4c19-9375-31b9575d80cb
RulenameTI Map URL Entity to DeviceNetworkEvents
DescriptionThis query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in DeviceNetworkEvents.
SeverityMedium
TacticsCommandAndControl
TechniquesT1071
Required data connectorsMicrosoftDefenderThreatIntelligence
MicrosoftThreatProtection
ThreatIntelligence
ThreatIntelligenceTaxii
KindScheduled
Query frequency1h
Query period14d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence (NEW)/Analytic Rules/URLEntity_DeviceNetworkEvents_Updated.yaml
Version1.0.2
Arm template4f0356b2-d344-4c19-9375-31b9575d80cb.json
Deploy To Azure
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let DeviceNetworkEvents_ = DeviceNetworkEvents
  | where isnotempty(RemoteUrl)
  | where TimeGenerated >= ago(dt_lookBack)
  | where ActionType !has "ConnectionFailed"
  | extend RemoteUrl = tolower(RemoteUrl)
  | project-rename DeviceNetworkEvents_TimeGenerated = TimeGenerated;
let DeviceNetworkEventUrls = DeviceNetworkEvents_
  | distinct Url = RemoteUrl
  | summarize make_list(Url);
ThreatIntelIndicators
   //extract key part of kv pair
| extend IndicatorType = replace(@"\[|\]|\""", "", tostring(split(ObservableKey, ":", 0)))
| where IndicatorType == "url"
| extend Url = ObservableValue
| extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel)
| where isnotempty(Url)
| where TimeGenerated >= ago(ioc_lookBack)
| extend Url = tolower(Url)
//| where Url in (DeviceNetworkEventUrls)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id
| where IsActive == true and ValidUntil > now()
| extend Description = tostring(parse_json(Data).description)
| where Description !contains_cs "State: inactive;" and Description !contains_cs "State: falsepos;"
   | project-reorder *, Tags, TrafficLightProtocolLevel, Url, Type
| join kind=innerunique (DeviceNetworkEvents_) on $left.Url == $right.RemoteUrl
| where DeviceNetworkEvents_TimeGenerated < ValidUntil
| summarize DeviceNetworkEvents_TimeGenerated = arg_max(DeviceNetworkEvents_TimeGenerated, *) by Id, Url
| extend Description = tostring(parse_json(Data).description)
| extend ActivityGroupNames = extract(@"ActivityGroup:(\S+)", 1, tostring(parse_json(Data).labels))
| project DeviceNetworkEvents_TimeGenerated, Id, Url, Confidence, Description, Type, Tags, TrafficLightProtocolLevel, ActionType, DeviceId, DeviceName, InitiatingProcessAccountUpn, InitiatingProcessCommandLine, RemoteIP, RemotePort
| extend Name = tostring(split(InitiatingProcessAccountUpn, '@', 0)[0]), UPNSuffix = tostring(split(InitiatingProcessAccountUpn, '@', 1)[0])
| extend timestamp = DeviceNetworkEvents_TimeGenerated, UserPrincipalName = InitiatingProcessAccountUpn
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence (NEW)/Analytic Rules/URLEntity_DeviceNetworkEvents_Updated.yaml
query: |
  let dt_lookBack = 1h;
  let ioc_lookBack = 14d;
  let DeviceNetworkEvents_ = DeviceNetworkEvents
    | where isnotempty(RemoteUrl)
    | where TimeGenerated >= ago(dt_lookBack)
    | where ActionType !has "ConnectionFailed"
    | extend RemoteUrl = tolower(RemoteUrl)
    | project-rename DeviceNetworkEvents_TimeGenerated = TimeGenerated;
  let DeviceNetworkEventUrls = DeviceNetworkEvents_
    | distinct Url = RemoteUrl
    | summarize make_list(Url);
  ThreatIntelIndicators
     //extract key part of kv pair
  | extend IndicatorType = replace(@"\[|\]|\""", "", tostring(split(ObservableKey, ":", 0)))
  | where IndicatorType == "url"
  | extend Url = ObservableValue
  | extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel)
  | where isnotempty(Url)
  | where TimeGenerated >= ago(ioc_lookBack)
  | extend Url = tolower(Url)
  //| where Url in (DeviceNetworkEventUrls)
  | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id
  | where IsActive == true and ValidUntil > now()
  | extend Description = tostring(parse_json(Data).description)
  | where Description !contains_cs "State: inactive;" and Description !contains_cs "State: falsepos;"
     | project-reorder *, Tags, TrafficLightProtocolLevel, Url, Type
  | join kind=innerunique (DeviceNetworkEvents_) on $left.Url == $right.RemoteUrl
  | where DeviceNetworkEvents_TimeGenerated < ValidUntil
  | summarize DeviceNetworkEvents_TimeGenerated = arg_max(DeviceNetworkEvents_TimeGenerated, *) by Id, Url
  | extend Description = tostring(parse_json(Data).description)
  | extend ActivityGroupNames = extract(@"ActivityGroup:(\S+)", 1, tostring(parse_json(Data).labels))
  | project DeviceNetworkEvents_TimeGenerated, Id, Url, Confidence, Description, Type, Tags, TrafficLightProtocolLevel, ActionType, DeviceId, DeviceName, InitiatingProcessAccountUpn, InitiatingProcessCommandLine, RemoteIP, RemotePort
  | extend Name = tostring(split(InitiatingProcessAccountUpn, '@', 0)[0]), UPNSuffix = tostring(split(InitiatingProcessAccountUpn, '@', 1)[0])
  | extend timestamp = DeviceNetworkEvents_TimeGenerated, UserPrincipalName = InitiatingProcessAccountUpn  
description: |
    'This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in DeviceNetworkEvents.'
severity: Medium
requiredDataConnectors:
- dataTypes:
  - DeviceNetworkEvents
  connectorId: MicrosoftThreatProtection
- dataTypes:
  - ThreatIntelligenceIndicator
  connectorId: ThreatIntelligence
- dataTypes:
  - ThreatIntelligenceIndicator
  connectorId: ThreatIntelligenceTaxii
- dataTypes:
  - ThreatIntelligenceIndicator
  connectorId: MicrosoftDefenderThreatIntelligence
name: TI Map URL Entity to DeviceNetworkEvents
triggerThreshold: 0
tactics:
- CommandAndControl
version: 1.0.2
relevantTechniques:
- T1071
triggerOperator: gt
entityMappings:
- entityType: Account
  fieldMappings:
  - columnName: Name
    identifier: Name
  - columnName: UPNSuffix
    identifier: UPNSuffix
- entityType: Host
  fieldMappings:
  - columnName: DeviceName
    identifier: FullName
- entityType: URL
  fieldMappings:
  - columnName: Url
    identifier: Url
- entityType: Process
  fieldMappings:
  - columnName: InitiatingProcessCommandLine
    identifier: CommandLine
id: 4f0356b2-d344-4c19-9375-31b9575d80cb
kind: Scheduled
queryFrequency: 1h
queryPeriod: 14d
{
  "$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/4f0356b2-d344-4c19-9375-31b9575d80cb')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/4f0356b2-d344-4c19-9375-31b9575d80cb')]",
      "properties": {
        "alertRuleTemplateName": "4f0356b2-d344-4c19-9375-31b9575d80cb",
        "customDetails": null,
        "description": "'This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in DeviceNetworkEvents.'\n",
        "displayName": "TI Map URL Entity to DeviceNetworkEvents",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "Name",
                "identifier": "Name"
              },
              {
                "columnName": "UPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "DeviceName",
                "identifier": "FullName"
              }
            ]
          },
          {
            "entityType": "URL",
            "fieldMappings": [
              {
                "columnName": "Url",
                "identifier": "Url"
              }
            ]
          },
          {
            "entityType": "Process",
            "fieldMappings": [
              {
                "columnName": "InitiatingProcessCommandLine",
                "identifier": "CommandLine"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence (NEW)/Analytic Rules/URLEntity_DeviceNetworkEvents_Updated.yaml",
        "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet DeviceNetworkEvents_ = DeviceNetworkEvents\n  | where isnotempty(RemoteUrl)\n  | where TimeGenerated >= ago(dt_lookBack)\n  | where ActionType !has \"ConnectionFailed\"\n  | extend RemoteUrl = tolower(RemoteUrl)\n  | project-rename DeviceNetworkEvents_TimeGenerated = TimeGenerated;\nlet DeviceNetworkEventUrls = DeviceNetworkEvents_\n  | distinct Url = RemoteUrl\n  | summarize make_list(Url);\nThreatIntelIndicators\n   //extract key part of kv pair\n| extend IndicatorType = replace(@\"\\[|\\]|\\\"\"\", \"\", tostring(split(ObservableKey, \":\", 0)))\n| where IndicatorType == \"url\"\n| extend Url = ObservableValue\n| extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel)\n| where isnotempty(Url)\n| where TimeGenerated >= ago(ioc_lookBack)\n| extend Url = tolower(Url)\n//| where Url in (DeviceNetworkEventUrls)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id\n| where IsActive == true and ValidUntil > now()\n| extend Description = tostring(parse_json(Data).description)\n| where Description !contains_cs \"State: inactive;\" and Description !contains_cs \"State: falsepos;\"\n   | project-reorder *, Tags, TrafficLightProtocolLevel, Url, Type\n| join kind=innerunique (DeviceNetworkEvents_) on $left.Url == $right.RemoteUrl\n| where DeviceNetworkEvents_TimeGenerated < ValidUntil\n| summarize DeviceNetworkEvents_TimeGenerated = arg_max(DeviceNetworkEvents_TimeGenerated, *) by Id, Url\n| extend Description = tostring(parse_json(Data).description)\n| extend ActivityGroupNames = extract(@\"ActivityGroup:(\\S+)\", 1, tostring(parse_json(Data).labels))\n| project DeviceNetworkEvents_TimeGenerated, Id, Url, Confidence, Description, Type, Tags, TrafficLightProtocolLevel, ActionType, DeviceId, DeviceName, InitiatingProcessAccountUpn, InitiatingProcessCommandLine, RemoteIP, RemotePort\n| extend Name = tostring(split(InitiatingProcessAccountUpn, '@', 0)[0]), UPNSuffix = tostring(split(InitiatingProcessAccountUpn, '@', 1)[0])\n| extend timestamp = DeviceNetworkEvents_TimeGenerated, UserPrincipalName = InitiatingProcessAccountUpn\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"
    }
  ]
}