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 Web Session Events ASIM Web Session schema

Back
Id3b4a8c72-5a2e-4f1e-b61a-9d8b2a6d7a21
RulenameTI map URL entity to Web Session Events (ASIM Web Session schema)
DescriptionThis rule identifies Web Sessions where the full requested URL matches a known

malicious URL from Threat Intelligence sources. The rule uses the Advanced Security

Information Model (ASIM) and supports any web session source compliant with ASIM.
SeverityMedium
TacticsCommandAndControl
InitialAccess
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 (NEW)/Analytic Rules/URLEntity_imWebSession.yaml
Version1.0.0
Arm template3b4a8c72-5a2e-4f1e-b61a-9d8b2a6d7a21.json
Deploy To Azure
let HAS_ANY_MAX = 10000;
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
// Extract URL-based Threat Intelligence indicators
let URL_TI =
  ThreatIntelIndicators
  | extend IndicatorType = replace(@"\[|\]|\""", "", tostring(split(ObservableKey, ":", 0)))
  | where IndicatorType == "url"
  | extend MaliciousUrl = tolower(ObservableValue)
  | extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel)
  | extend IndicatorId = tostring(split(Id, "--")[2])
  | where TimeGenerated >= ago(ioc_lookBack)
  | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id, MaliciousUrl
  | where IsActive and (ValidUntil > now() or isempty(ValidUntil));
// Build a dynamic list of malicious URLs
let URL_TI_list =
  toscalar(
      URL_TI
      | summarize NIoCs = dcount(MaliciousUrl),
                  Urls = make_set(MaliciousUrl)
      | project Urls = iff(NIoCs > HAS_ANY_MAX, dynamic([]), Urls)
    );
// Match against ASIM Web Session events
URL_TI
| join kind=innerunique (
    _Im_WebSession(starttime=ago(dt_lookBack), url_has_any = URL_TI_list)
    | extend RequestedUrl = tolower(Url)
    | where isnotempty(RequestedUrl)
    | extend Event_TimeGenerated = TimeGenerated
  ) on $left.MaliciousUrl == $right.RequestedUrl
| where Event_TimeGenerated < ValidUntil
| summarize Event_TimeGenerated = arg_max(Event_TimeGenerated, *) by IndicatorId, RequestedUrl
| extend ParsedData = parse_json(Data)
| extend Description = tostring(ParsedData.description)
| extend ActivityGroupNames = extract(@"ActivityGroup:(\S+)", 1, tostring(ParsedData.labels))
| extend ThreatType = tostring(ParsedData.indicator_types[0])
| project
    Event_TimeGenerated,
    SrcIpAddr,
    RequestedUrl,
    IndicatorId,
    ThreatType,
    Confidence,
    ValidUntil,
    Description,
    ActivityGroupNames
requiredDataConnectors:
- dataTypes:
  - SquidProxy_CL
  connectorId: SquidProxy
- dataTypes:
  - CommonSecurityLog
  connectorId: Zscaler
- dataTypes:
  - ThreatIntelIndicators
  connectorId: ThreatIntelligence
- dataTypes:
  - ThreatIntelIndicators
  connectorId: ThreatIntelligenceTaxii
- dataTypes:
  - ThreatIntelIndicators
  connectorId: MicrosoftDefenderThreatIntelligence
queryPeriod: 14d
triggerThreshold: 0
queryFrequency: 1h
version: 1.0.0
severity: Medium
description: |
  This rule identifies Web Sessions where the full requested URL matches a known
  malicious URL from Threat Intelligence sources. The rule uses the Advanced Security
  Information Model (ASIM) and supports any web session source compliant with ASIM.  
customDetails:
  ActivityGroupNames: ActivityGroupNames
  IoCDescription: Description
  EventTime: Event_TimeGenerated
  ThreatType: ThreatType
  IoCConfidenceScore: Confidence
  IndicatorId: IndicatorId
  IoCExpirationTime: ValidUntil
name: TI map URL entity to Web Session Events (ASIM Web Session schema)
entityMappings:
- fieldMappings:
  - identifier: Address
    columnName: SrcIpAddr
  entityType: IP
- fieldMappings:
  - identifier: Url
    columnName: RequestedUrl
  entityType: URL
triggerOperator: gt
id: 3b4a8c72-5a2e-4f1e-b61a-9d8b2a6d7a21
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence (NEW)/Analytic Rules/URLEntity_imWebSession.yaml
tactics:
- CommandAndControl
- InitialAccess
relevantTechniques:
- T1071
kind: Scheduled
alertDetailsOverride:
  alertDisplayNameFormat: A web request from {{SrcIpAddr}} to malicious URL matched an IoC
  alertDescriptionFormat: A client with address {{SrcIpAddr}} requested the URL {{RequestedUrl}}, which is a known malicious URL associated with {{ThreatType}}. Review threat intelligence blade for further context.
query: |
  let HAS_ANY_MAX = 10000;
  let dt_lookBack = 1h;
  let ioc_lookBack = 14d;
  // Extract URL-based Threat Intelligence indicators
  let URL_TI =
    ThreatIntelIndicators
    | extend IndicatorType = replace(@"\[|\]|\""", "", tostring(split(ObservableKey, ":", 0)))
    | where IndicatorType == "url"
    | extend MaliciousUrl = tolower(ObservableValue)
    | extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel)
    | extend IndicatorId = tostring(split(Id, "--")[2])
    | where TimeGenerated >= ago(ioc_lookBack)
    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id, MaliciousUrl
    | where IsActive and (ValidUntil > now() or isempty(ValidUntil));
  // Build a dynamic list of malicious URLs
  let URL_TI_list =
    toscalar(
        URL_TI
        | summarize NIoCs = dcount(MaliciousUrl),
                    Urls = make_set(MaliciousUrl)
        | project Urls = iff(NIoCs > HAS_ANY_MAX, dynamic([]), Urls)
      );
  // Match against ASIM Web Session events
  URL_TI
  | join kind=innerunique (
      _Im_WebSession(starttime=ago(dt_lookBack), url_has_any = URL_TI_list)
      | extend RequestedUrl = tolower(Url)
      | where isnotempty(RequestedUrl)
      | extend Event_TimeGenerated = TimeGenerated
    ) on $left.MaliciousUrl == $right.RequestedUrl
  | where Event_TimeGenerated < ValidUntil
  | summarize Event_TimeGenerated = arg_max(Event_TimeGenerated, *) by IndicatorId, RequestedUrl
  | extend ParsedData = parse_json(Data)
  | extend Description = tostring(ParsedData.description)
  | extend ActivityGroupNames = extract(@"ActivityGroup:(\S+)", 1, tostring(ParsedData.labels))
  | extend ThreatType = tostring(ParsedData.indicator_types[0])
  | project
      Event_TimeGenerated,
      SrcIpAddr,
      RequestedUrl,
      IndicatorId,
      ThreatType,
      Confidence,
      ValidUntil,
      Description,
      ActivityGroupNames