ThreatIntelligenceIndicator correlation and False Positive removal

SentinelNoob 191 Reputation points
2021-01-22T00:11:01.407+00:00

Hi community,

My ThreatIntelligenceIndicator table was fed from an external feed via Graph Security API.
I use it to query against CommonSecurityLog with a query like so:

let QueryTime=ago(4h)  
CommonSecurityLog  
| where not(ipv4_is_private(DestinationIP)) and TimeGenerated >= QueryTime  
| join (ThreatIntelligenceIndicator  
  | where ExpirationDateTime > now()  
   and Active == true   
   and isnotnull(NetworkIP)  
   | distinct NetworkIP  
  ) on $left.DestinationIP == $right.NetworkIP  
  

It works as expected. However, when I tried to delete an indicator via Graph Security API, it appears as a new row in ThreatIntelligenceIndicator table with "active" value of "False". The old indicator with "active" value of "True" still exists. As a result, above union query will still return matches of the old row.

59180-screen-shot-2021-01-21-at-40502-pm.png

While the api has endpoint to update indicator, it requires keeping track of the generated indicator id on the caller end, which adds a lot more complexity. Can anyone suggest how to make the join query so that only indicators with no "False" active value in any rows are returned?

Azure Monitor
Azure Monitor
An Azure service that is used to collect, analyze, and act on telemetry data from Azure and on-premises environments.
2,802 questions
Microsoft Defender for Cloud
Microsoft Defender for Cloud
An Azure service that provides threat protection for workloads running in Azure, on-premises, and in other clouds. Previously known as Azure Security Center and Azure Defender.
1,194 questions
Microsoft Sentinel
Microsoft Sentinel
A scalable, cloud-native solution for security information event management and security orchestration automated response. Previously known as Azure Sentinel.
976 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. SentinelNoob 191 Reputation points
    2021-01-22T01:29:58.75+00:00

    So I figured out a way to filter out the indicators with "false" active status. If anyone knows a better / more efficient way, please suggest:

    // Get a list of inactive indicators (FPs)
    let InactiveIndicators = materialize(
    ThreatIntelligenceIndicator
    | where 
       isnotnull(NetworkIP)
       and TimeGenerated > todatetime('2021-01-01')
       and Active == false
    | distinct NetworkIP
    );
    // Get a list of active indicator filtering out FPs
    let ActiveIndicators = materialize(
    ThreatIntelligenceIndicator
      | where ExpirationDateTime > now()
       and TimeGenerated > todatetime('2021-01-01')
       and Active == true 
       and isnotnull(NetworkIP)
       | distinct NetworkIP
       | where NetworkIP !in (InactiveIndicators)
    );
    // Return events match IPs on Destination
    CommonSecurityLog
    | where not(ipv4_is_private(DestinationIP)) and TimeGenerated >= ago(24h)
    | join (ActiveIndicators) on $left.DestinationIP == $right.NetworkIP