Back
Id3ebd25b1-6f54-49f9-b5a5-0246357ce4ca
RulenameGSA - TI IP Entity
DescriptionThis query identifies IP indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in GSA NetworkAccessTraffic.
SeverityMedium
TacticsCommandAndControl
TechniquesT1071
Required data connectorsAzureActiveDirectory
KindScheduled
Query frequency1h
Query period14d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global%20Secure%20Access/Analytic%20Rules/GSA%20-%20TI%20IP%20Entity.yaml
Arm template3ebd25b1-6f54-49f9-b5a5-0246357ce4ca.json
Deploy To Azure
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let NetworkAccessTraffic_ =
    NetworkAccessTraffic
    | where TimeGenerated >= ago(dt_lookBack)
    | where TrafficType == "internet"
    | project-rename GSANetworkAccessTraffic_TimeGenerated = TimeGenerated;
let IPList = NetworkAccessTraffic_ | summarize by DestinationIp;
ThreatIntelIndicators
| project-rename TI_ipEntity = ObservableValue
| extend IndicatorType = replace(@'\[|\]|"""', "", tostring(split(ObservableKey, ":", 0)))
| where IndicatorType in ("ipv4-addr", "network-traffic")
| extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel)
| where TimeGenerated >= ago(ioc_lookBack)
| where TI_ipEntity in (IPList)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id, TI_ipEntity
| where IsActive and (ValidUntil > now() or isempty(ValidUntil))
| extend Description = tostring(parse_json(Data).description)
| where Description !contains_cs "State: inactive;" and Description !contains_cs "State: falsepos;"
| join kind=innerunique (NetworkAccessTraffic_) on $left.TI_ipEntity == $right.DestinationIp
| extend GSAThreatType = ThreatType
| summarize GSANetworkAccessTraffic_TimeGenerated = arg_max(GSANetworkAccessTraffic_TimeGenerated, *) by Id, DestinationIp
| project-reorder *,
    Tags,
    Confidence,
    TrafficLightProtocolLevel,
    Type,
    TI_ipEntity,
    UserPrincipalName,
    UserId,
    DeviceId,
    InitiatingProcessName,
    GSAThreatType,
    DestinationFqdn,
    DestinationUrl,
    DestinationPort,
    SourceIp,
    SourcePort,
    HttpUserAgent
status: Available
triggerOperator: gt
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global%20Secure%20Access/Analytic%20Rules/GSA%20-%20TI%20IP%20Entity.yaml
kind: Scheduled
entityMappings:
- fieldMappings:
  - columnName: UserPrincipalName
    identifier: Name
  entityType: Account
- fieldMappings:
  - columnName: InitiatingProcessName
    identifier: CommandLine
  entityType: Process
- fieldMappings:
  - columnName: SourceIp
    identifier: Address
  entityType: IP
- fieldMappings:
  - columnName: DeviceId
    identifier: AzureID
  entityType: Host
severity: Medium
name: GSA - TI IP Entity
description: |
  This query identifies IP indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in GSA NetworkAccessTraffic.
queryPeriod: 14d
triggerThreshold: 0
requiredDataConnectors:
- connectorId: AzureActiveDirectory
  dataTypes:
  - NetworkAccessTrafficLogs
queryFrequency: 1h
relevantTechniques:
- T1071
id: 3ebd25b1-6f54-49f9-b5a5-0246357ce4ca
query: |
  let dt_lookBack = 1h;
  let ioc_lookBack = 14d;
  let NetworkAccessTraffic_ =
      NetworkAccessTraffic
      | where TimeGenerated >= ago(dt_lookBack)
      | where TrafficType == "internet"
      | project-rename GSANetworkAccessTraffic_TimeGenerated = TimeGenerated;
  let IPList = NetworkAccessTraffic_ | summarize by DestinationIp;
  ThreatIntelIndicators
  | project-rename TI_ipEntity = ObservableValue
  | extend IndicatorType = replace(@'\[|\]|"""', "", tostring(split(ObservableKey, ":", 0)))
  | where IndicatorType in ("ipv4-addr", "network-traffic")
  | extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel)
  | where TimeGenerated >= ago(ioc_lookBack)
  | where TI_ipEntity in (IPList)
  | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id, TI_ipEntity
  | where IsActive and (ValidUntil > now() or isempty(ValidUntil))
  | extend Description = tostring(parse_json(Data).description)
  | where Description !contains_cs "State: inactive;" and Description !contains_cs "State: falsepos;"
  | join kind=innerunique (NetworkAccessTraffic_) on $left.TI_ipEntity == $right.DestinationIp
  | extend GSAThreatType = ThreatType
  | summarize GSANetworkAccessTraffic_TimeGenerated = arg_max(GSANetworkAccessTraffic_TimeGenerated, *) by Id, DestinationIp
  | project-reorder *,
      Tags,
      Confidence,
      TrafficLightProtocolLevel,
      Type,
      TI_ipEntity,
      UserPrincipalName,
      UserId,
      DeviceId,
      InitiatingProcessName,
      GSAThreatType,
      DestinationFqdn,
      DestinationUrl,
      DestinationPort,
      SourceIp,
      SourcePort,
      HttpUserAgent
tactics:
- CommandAndControl
{
  "$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/3ebd25b1-6f54-49f9-b5a5-0246357ce4ca')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/3ebd25b1-6f54-49f9-b5a5-0246357ce4ca')]",
      "properties": {
        "alertRuleTemplateName": "3ebd25b1-6f54-49f9-b5a5-0246357ce4ca",
        "customDetails": null,
        "description": "This query identifies IP indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in GSA NetworkAccessTraffic.\n",
        "displayName": "GSA - TI IP Entity",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "UserPrincipalName",
                "identifier": "Name"
              }
            ]
          },
          {
            "entityType": "Process",
            "fieldMappings": [
              {
                "columnName": "InitiatingProcessName",
                "identifier": "CommandLine"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "SourceIp",
                "identifier": "Address"
              }
            ]
          },
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "DeviceId",
                "identifier": "AzureID"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global%20Secure%20Access/Analytic%20Rules/GSA%20-%20TI%20IP%20Entity.yaml",
        "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet NetworkAccessTraffic_ =\n    NetworkAccessTraffic\n    | where TimeGenerated >= ago(dt_lookBack)\n    | where TrafficType == \"internet\"\n    | project-rename GSANetworkAccessTraffic_TimeGenerated = TimeGenerated;\nlet IPList = NetworkAccessTraffic_ | summarize by DestinationIp;\nThreatIntelIndicators\n| project-rename TI_ipEntity = ObservableValue\n| extend IndicatorType = replace(@'\\[|\\]|\"\"\"', \"\", tostring(split(ObservableKey, \":\", 0)))\n| where IndicatorType in (\"ipv4-addr\", \"network-traffic\")\n| extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel)\n| where TimeGenerated >= ago(ioc_lookBack)\n| where TI_ipEntity in (IPList)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id, TI_ipEntity\n| where IsActive and (ValidUntil > now() or isempty(ValidUntil))\n| extend Description = tostring(parse_json(Data).description)\n| where Description !contains_cs \"State: inactive;\" and Description !contains_cs \"State: falsepos;\"\n| join kind=innerunique (NetworkAccessTraffic_) on $left.TI_ipEntity == $right.DestinationIp\n| extend GSAThreatType = ThreatType\n| summarize GSANetworkAccessTraffic_TimeGenerated = arg_max(GSANetworkAccessTraffic_TimeGenerated, *) by Id, DestinationIp\n| project-reorder *,\n    Tags,\n    Confidence,\n    TrafficLightProtocolLevel,\n    Type,\n    TI_ipEntity,\n    UserPrincipalName,\n    UserId,\n    DeviceId,\n    InitiatingProcessName,\n    GSAThreatType,\n    DestinationFqdn,\n    DestinationUrl,\n    DestinationPort,\n    SourceIp,\n    SourcePort,\n    HttpUserAgent\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P14D",
        "severity": "Medium",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CommandAndControl"
        ],
        "techniques": [
          "T1071"
        ],
        "templateVersion": "1.0.0",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}