TI Map IP Entity to Duo Security
| Id | d23ed927-5be3-4902-a9c1-85f841eb4fa1 |
| Rulename | TI Map IP Entity to Duo Security |
| Description | This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in DuoSecurity. |
| Severity | Medium |
| Tactics | CommandAndControl |
| Techniques | T1071 |
| Required data connectors | CiscoDuoSecurity MicrosoftDefenderThreatIntelligence ThreatIntelligence ThreatIntelligenceTaxii |
| Kind | Scheduled |
| Query frequency | 1h |
| Query period | 14d |
| Trigger threshold | 0 |
| Trigger operator | gt |
| Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence/Analytic Rules/IPEntity_DuoSecurity.yaml |
| Version | 1.0.6 |
| Arm template | d23ed927-5be3-4902-a9c1-85f841eb4fa1.json |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
ThreatIntelligenceIndicator
// Picking up only IOC's that contain the entities we want
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or 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(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > 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 IndicatorId
| where Active == true and ExpirationDateTime > now()
| project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, 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
| extend timestamp = Duo_TimeGenerated, Name = tostring(split(user_name_s, '@', 0)[0]), UPNSuffix = tostring(split(user_name_s, '@', 1)[0])
tactics:
- CommandAndControl
triggerOperator: gt
queryPeriod: 14d
queryFrequency: 1h
requiredDataConnectors:
- dataTypes:
- ThreatIntelligenceIndicator
connectorId: ThreatIntelligence
- dataTypes:
- ThreatIntelligenceIndicator
connectorId: ThreatIntelligenceTaxii
- dataTypes:
- CiscoDuo
connectorId: CiscoDuoSecurity
- dataTypes:
- ThreatIntelligenceIndicator
connectorId: MicrosoftDefenderThreatIntelligence
id: d23ed927-5be3-4902-a9c1-85f841eb4fa1
relevantTechniques:
- T1071
triggerThreshold: 0
kind: Scheduled
entityMappings:
- fieldMappings:
- identifier: FullName
columnName: user_name_s
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
entityType: Account
- fieldMappings:
- identifier: Address
columnName: access_device_ip_s
entityType: IP
query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
ThreatIntelligenceIndicator
// Picking up only IOC's that contain the entities we want
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or 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(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > 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 IndicatorId
| where Active == true and ExpirationDateTime > now()
| project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, 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
| 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/Analytic Rules/IPEntity_DuoSecurity.yaml
name: TI Map IP Entity to Duo Security
version: 1.0.6
severity: Medium
description: |
'This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in DuoSecurity.'