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

TI map IP entity to Web Session Events ASIM Web Session schema

Back
Ide2559891-383c-4caf-ae67-55a008b9f89e
RulenameTI map IP entity to Web Session Events (ASIM Web Session schema)
DescriptionThis rule identifies Web Sessions for which the source IP address is a known IoC. This rule uses the Advanced Security Information Model (ASIM) and supports any web session source that complies with ASIM.
SeverityMedium
TacticsCommandAndControl
TechniquesT1071
Required data connectorsMicrosoftDefenderThreatIntelligence
SquidProxy
ThreatIntelligence
ThreatIntelligenceTaxii
Zscaler
KindScheduled
Query frequency1h
Query period14d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence/Analytic Rules/IPEntity_imWebSession.yaml
Version1.2.5
Arm templatee2559891-383c-4caf-ae67-55a008b9f89e.json
Deploy To Azure
let HAS_ANY_MAX = 10000;
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let IP_TI = ThreatIntelligenceIndicator
  | where TimeGenerated >= ago(ioc_lookBack)
  // As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty.
  // Taking the first non-empty value based on potential IOC match availability
  | extend TI_ipEntity = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, "NO_IP")
  // Picking up only IOC's that contain the entities we want
  | where TI_ipEntity != "NO_IP"
  // Exclude local addresses, using the ipv4_is_private operator
  | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."
  | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
  | where Active == true and ExpirationDateTime > now();
let IP_TI_list = toscalar(IP_TI
  | summarize NIoCs = dcount(TI_ipEntity), IoCs = make_set(TI_ipEntity)
  | project IoCs = iff(NIoCs > HAS_ANY_MAX, dynamic([]), IoCs));
IP_TI
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind = innerunique (
    _Im_WebSession (starttime = ago(dt_lookBack), srcipaddr_has_any_prefix = IP_TI_list)
    | where isnotempty(SrcIpAddr)
    // renaming time column so it is clear the log this came from
    | extend imNWS_TimeGenerated = TimeGenerated
  )
  on $left.TI_ipEntity == $right.SrcIpAddr
| where imNWS_TimeGenerated < ExpirationDateTime
| summarize imNWS_TimeGenerated = arg_max(imNWS_TimeGenerated, *) by IndicatorId, DstIpAddr
| project imNWS_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore,
  TI_ipEntity, Dvc, SrcIpAddr, DstIpAddr, Url, Type
name: TI map IP entity to Web Session Events (ASIM Web Session schema)
alertDetailsOverride:
  alertDisplayNameFormat: The IP {{SrcIpAddr}} of the web request matches an IP IoC
  alertDescriptionFormat: The source address {{SrcIpAddr}} of the web request for the URL {{Url}} matches a known indicator of compromise of {{ThreatType}}. Consult the threat intelligence feed for more information about the indicator.
severity: Medium
queryFrequency: 1h
triggerOperator: gt
customDetails:
  EventTime: imNWS_TimeGenerated
  IoCConfidenceScore: ConfidenceScore
  ThreatType: ThreatType
  IoCExpirationTime: ExpirationDateTime
  IoCDescription: Description
  ActivityGroupNames: ActivityGroupNames
  IndicatorId: IndicatorId
relevantTechniques:
- T1071
version: 1.2.5
description: |
    This rule identifies Web Sessions for which the source IP address is a known IoC. This rule uses the [Advanced Security Information Model (ASIM)](https://aka.ms/AboutASIM) and supports any web session source that complies with ASIM.
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence/Analytic Rules/IPEntity_imWebSession.yaml
requiredDataConnectors:
- connectorId: SquidProxy
  dataTypes:
  - SquidProxy_CL
- connectorId: Zscaler
  dataTypes:
  - CommonSecurityLog
- connectorId: ThreatIntelligence
  dataTypes:
  - ThreatIntelligenceIndicator
- connectorId: ThreatIntelligenceTaxii
  dataTypes:
  - ThreatIntelligenceIndicator
- connectorId: MicrosoftDefenderThreatIntelligence
  dataTypes:
  - ThreatIntelligenceIndicator
entityMappings:
- fieldMappings:
  - identifier: Address
    columnName: DstIpAddr
  entityType: IP
tactics:
- CommandAndControl
queryPeriod: 14d
query: |
  let HAS_ANY_MAX = 10000;
  let dt_lookBack = 1h;
  let ioc_lookBack = 14d;
  let IP_TI = ThreatIntelligenceIndicator
    | where TimeGenerated >= ago(ioc_lookBack)
    // As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty.
    // Taking the first non-empty value based on potential IOC match availability
    | extend TI_ipEntity = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, "NO_IP")
    // Picking up only IOC's that contain the entities we want
    | where TI_ipEntity != "NO_IP"
    // Exclude local addresses, using the ipv4_is_private operator
    | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."
    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
    | where Active == true and ExpirationDateTime > now();
  let IP_TI_list = toscalar(IP_TI
    | summarize NIoCs = dcount(TI_ipEntity), IoCs = make_set(TI_ipEntity)
    | project IoCs = iff(NIoCs > HAS_ANY_MAX, dynamic([]), IoCs));
  IP_TI
  // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
  | join kind = innerunique (
      _Im_WebSession (starttime = ago(dt_lookBack), srcipaddr_has_any_prefix = IP_TI_list)
      | where isnotempty(SrcIpAddr)
      // renaming time column so it is clear the log this came from
      | extend imNWS_TimeGenerated = TimeGenerated
    )
    on $left.TI_ipEntity == $right.SrcIpAddr
  | where imNWS_TimeGenerated < ExpirationDateTime
  | summarize imNWS_TimeGenerated = arg_max(imNWS_TimeGenerated, *) by IndicatorId, DstIpAddr
  | project imNWS_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore,
    TI_ipEntity, Dvc, SrcIpAddr, DstIpAddr, Url, Type  
kind: Scheduled
triggerThreshold: 0
id: e2559891-383c-4caf-ae67-55a008b9f89e
{
  "$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/e2559891-383c-4caf-ae67-55a008b9f89e')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/e2559891-383c-4caf-ae67-55a008b9f89e')]",
      "properties": {
        "alertDetailsOverride": {
          "alertDescriptionFormat": "The source address {{SrcIpAddr}} of the web request for the URL {{Url}} matches a known indicator of compromise of {{ThreatType}}. Consult the threat intelligence feed for more information about the indicator.",
          "alertDisplayNameFormat": "The IP {{SrcIpAddr}} of the web request matches an IP IoC"
        },
        "alertRuleTemplateName": "e2559891-383c-4caf-ae67-55a008b9f89e",
        "customDetails": {
          "ActivityGroupNames": "ActivityGroupNames",
          "EventTime": "imNWS_TimeGenerated",
          "IndicatorId": "IndicatorId",
          "IoCConfidenceScore": "ConfidenceScore",
          "IoCDescription": "Description",
          "IoCExpirationTime": "ExpirationDateTime",
          "ThreatType": "ThreatType"
        },
        "description": "This rule identifies Web Sessions for which the source IP address is a known IoC. This rule uses the [Advanced Security Information Model (ASIM)](https://aka.ms/AboutASIM) and supports any web session source that complies with ASIM.\n",
        "displayName": "TI map IP entity to Web Session Events (ASIM Web Session schema)",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "DstIpAddr",
                "identifier": "Address"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence/Analytic Rules/IPEntity_imWebSession.yaml",
        "query": "let HAS_ANY_MAX = 10000;\nlet dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet IP_TI = ThreatIntelligenceIndicator\n  | where TimeGenerated >= ago(ioc_lookBack)\n  // As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty.\n  // Taking the first non-empty value based on potential IOC match availability\n  | extend TI_ipEntity = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, \"NO_IP\")\n  // Picking up only IOC's that contain the entities we want\n  | where TI_ipEntity != \"NO_IP\"\n  // Exclude local addresses, using the ipv4_is_private operator\n  | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\"\n  | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n  | where Active == true and ExpirationDateTime > now();\nlet IP_TI_list = toscalar(IP_TI\n  | summarize NIoCs = dcount(TI_ipEntity), IoCs = make_set(TI_ipEntity)\n  | project IoCs = iff(NIoCs > HAS_ANY_MAX, dynamic([]), IoCs));\nIP_TI\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind = innerunique (\n    _Im_WebSession (starttime = ago(dt_lookBack), srcipaddr_has_any_prefix = IP_TI_list)\n    | where isnotempty(SrcIpAddr)\n    // renaming time column so it is clear the log this came from\n    | extend imNWS_TimeGenerated = TimeGenerated\n  )\n  on $left.TI_ipEntity == $right.SrcIpAddr\n| where imNWS_TimeGenerated < ExpirationDateTime\n| summarize imNWS_TimeGenerated = arg_max(imNWS_TimeGenerated, *) by IndicatorId, DstIpAddr\n| project imNWS_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore,\n  TI_ipEntity, Dvc, SrcIpAddr, DstIpAddr, Url, Type\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P14D",
        "severity": "Medium",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CommandAndControl"
        ],
        "techniques": [
          "T1071"
        ],
        "templateVersion": "1.2.5",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}