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 Duo Security

Back
Id4988c238-a118-442c-80bd-6c689a1b2e97
RulenameTI Map IP Entity to Duo Security
DescriptionThis query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in DuoSecurity.
SeverityMedium
TacticsCommandAndControl
TechniquesT1071
Required data connectorsCiscoDuoSecurity
MicrosoftDefenderThreatIntelligence
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/IPEntity_DuoSecurity.yaml
Version1.0.6
Arm template4988c238-a118-442c-80bd-6c689a1b2e97.json
Deploy To Azure
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
ThreatIntelIndicators
//extract key part of kv pair
     | extend IndicatorType = replace(@"\[|\]|\""", "", tostring(split(ObservableKey, ":", 0)))
     | where isnotempty(IndicatorType) and IndicatorType == "ipv4-addr"
     | extend NetworkSourceIP = toupper(ObservableValue)
     | extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel)
// Picking up only IOC's that contain the entities we want
| where isnotempty(NetworkSourceIP)
| 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 = iff(isnotempty(NetworkSourceIP), NetworkSourceIP, NetworkSourceIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id
| where IsActive == true and ValidUntil > now()
 | join (
     DuoSecurityAuthentication_CL
     | where TimeGenerated >= ago(dt_lookBack)
     | where isnotempty(access_device_ip_s)
     // renaming time column so it is clear the log this came from
     | extend Duo_TimeGenerated = isotimestamp_t
 )
 on $left.TI_ipEntity == $right.access_device_ip_s
 | where TimeGenerated >= ago(ioc_lookBack)
 | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id
 | where IsActive == true and ValidUntil > now()
 | extend Description = tostring(parse_json(Data).description)
 | extend ActivityGroupNames = extract(@"ActivityGroup:(\S+)", 1, tostring(parse_json(Data).labels))
 | project LatestIndicatorTime, Description, ActivityGroupNames, Id, ValidUntil, Confidence, Duo_TimeGenerated,
 TI_ipEntity, user_name_s, factor_s, result_s, application_name_s, event_type_s, txid_g, user_key_s, access_device_ip_s, access_device_location_city_s, access_device_location_state_s, access_device_location_country_s//, ThreatType, Url
 | extend timestamp = Duo_TimeGenerated, Name = tostring(split(user_name_s, '@', 0)[0]), UPNSuffix = tostring(split(user_name_s, '@', 1)[0])
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence (NEW)/Analytic Rules/IPEntity_DuoSecurity.yaml
query: |
  let dt_lookBack = 1h;
  let ioc_lookBack = 14d;
  ThreatIntelIndicators
  //extract key part of kv pair
       | extend IndicatorType = replace(@"\[|\]|\""", "", tostring(split(ObservableKey, ":", 0)))
       | where isnotempty(IndicatorType) and IndicatorType == "ipv4-addr"
       | extend NetworkSourceIP = toupper(ObservableValue)
       | extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel)
  // Picking up only IOC's that contain the entities we want
  | where isnotempty(NetworkSourceIP)
  | 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 = iff(isnotempty(NetworkSourceIP), NetworkSourceIP, NetworkSourceIP)
  | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
  | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id
  | where IsActive == true and ValidUntil > now()
   | join (
       DuoSecurityAuthentication_CL
       | where TimeGenerated >= ago(dt_lookBack)
       | where isnotempty(access_device_ip_s)
       // renaming time column so it is clear the log this came from
       | extend Duo_TimeGenerated = isotimestamp_t
   )
   on $left.TI_ipEntity == $right.access_device_ip_s
   | where TimeGenerated >= ago(ioc_lookBack)
   | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id
   | where IsActive == true and ValidUntil > now()
   | extend Description = tostring(parse_json(Data).description)
   | extend ActivityGroupNames = extract(@"ActivityGroup:(\S+)", 1, tostring(parse_json(Data).labels))
   | project LatestIndicatorTime, Description, ActivityGroupNames, Id, ValidUntil, Confidence, Duo_TimeGenerated,
   TI_ipEntity, user_name_s, factor_s, result_s, application_name_s, event_type_s, txid_g, user_key_s, access_device_ip_s, access_device_location_city_s, access_device_location_state_s, access_device_location_country_s//, ThreatType, Url
   | extend timestamp = Duo_TimeGenerated, Name = tostring(split(user_name_s, '@', 0)[0]), UPNSuffix = tostring(split(user_name_s, '@', 1)[0])  
description: |
    'This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in DuoSecurity.'
severity: Medium
requiredDataConnectors:
- dataTypes:
  - ThreatIntelligenceIndicator
  connectorId: ThreatIntelligence
- dataTypes:
  - ThreatIntelligenceIndicator
  connectorId: ThreatIntelligenceTaxii
- dataTypes:
  - CiscoDuo
  connectorId: CiscoDuoSecurity
- dataTypes:
  - ThreatIntelligenceIndicator
  connectorId: MicrosoftDefenderThreatIntelligence
name: TI Map IP Entity to Duo Security
triggerThreshold: 0
tactics:
- CommandAndControl
version: 1.0.6
relevantTechniques:
- T1071
triggerOperator: gt
entityMappings:
- entityType: Account
  fieldMappings:
  - columnName: user_name_s
    identifier: FullName
  - columnName: Name
    identifier: Name
  - columnName: UPNSuffix
    identifier: UPNSuffix
- entityType: IP
  fieldMappings:
  - columnName: access_device_ip_s
    identifier: Address
id: 4988c238-a118-442c-80bd-6c689a1b2e97
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/4988c238-a118-442c-80bd-6c689a1b2e97')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/4988c238-a118-442c-80bd-6c689a1b2e97')]",
      "properties": {
        "alertRuleTemplateName": "4988c238-a118-442c-80bd-6c689a1b2e97",
        "customDetails": null,
        "description": "'This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in DuoSecurity.'\n",
        "displayName": "TI Map IP Entity to Duo Security",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "user_name_s",
                "identifier": "FullName"
              },
              {
                "columnName": "Name",
                "identifier": "Name"
              },
              {
                "columnName": "UPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "access_device_ip_s",
                "identifier": "Address"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence (NEW)/Analytic Rules/IPEntity_DuoSecurity.yaml",
        "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nThreatIntelIndicators\n//extract key part of kv pair\n     | extend IndicatorType = replace(@\"\\[|\\]|\\\"\"\", \"\", tostring(split(ObservableKey, \":\", 0)))\n     | where isnotempty(IndicatorType) and IndicatorType == \"ipv4-addr\"\n     | extend NetworkSourceIP = toupper(ObservableValue)\n     | extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel)\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(NetworkSourceIP)\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 = iff(isnotempty(NetworkSourceIP), NetworkSourceIP, NetworkSourceIP)\n| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id\n| where IsActive == true and ValidUntil > now()\n | join (\n     DuoSecurityAuthentication_CL\n     | where TimeGenerated >= ago(dt_lookBack)\n     | where isnotempty(access_device_ip_s)\n     // renaming time column so it is clear the log this came from\n     | extend Duo_TimeGenerated = isotimestamp_t\n )\n on $left.TI_ipEntity == $right.access_device_ip_s\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id\n | where IsActive == true and ValidUntil > now()\n | extend Description = tostring(parse_json(Data).description)\n | extend ActivityGroupNames = extract(@\"ActivityGroup:(\\S+)\", 1, tostring(parse_json(Data).labels))\n | project LatestIndicatorTime, Description, ActivityGroupNames, Id, ValidUntil, Confidence, Duo_TimeGenerated,\n TI_ipEntity, user_name_s, factor_s, result_s, application_name_s, event_type_s, txid_g, user_key_s, access_device_ip_s, access_device_location_city_s, access_device_location_state_s, access_device_location_country_s//, ThreatType, Url\n | extend timestamp = Duo_TimeGenerated, Name = tostring(split(user_name_s, '@', 0)[0]), UPNSuffix = tostring(split(user_name_s, '@', 1)[0])\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P14D",
        "severity": "Medium",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CommandAndControl"
        ],
        "techniques": [
          "T1071"
        ],
        "templateVersion": "1.0.6",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}