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.
3,645 questions
Microsoft Security Microsoft Defender Microsoft Defender for Cloud
Microsoft Security Microsoft Sentinel
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
    

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.