|
| 1 | +--- |
| 2 | +title: Work with STIX objects and indicators to enhance threat intelligence and threat hunting in Microsoft Sentinel (Preview) |
| 3 | +titleSuffix: Microsoft Sentinel |
| 4 | +description: This article provides examples of how to incorporate STIX objects into queries to enhance threat hunting. |
| 5 | +author: guywi-ms |
| 6 | +ms.topic: how-to |
| 7 | +ms.date: 03/31/2025 |
| 8 | +ms.author: guywild |
| 9 | +ms.reviewer: alsheheb |
| 10 | +appliesto: |
| 11 | + - Microsoft Sentinel in the Azure portal |
| 12 | + - Microsoft Sentinel in the Microsoft Defender portal |
| 13 | +ms.collection: usx-security |
| 14 | +#Customer intent: As a security analyst, I want to understand how to incorporate STIX objects into queries to enhance threat hunting. |
| 15 | +--- |
| 16 | + |
| 17 | +# Work with STIX objects and indicators to enhance threat intelligence and threat hunting in Microsoft Sentinel (Preview) |
| 18 | + |
| 19 | +On April 3, 2025, we publicly previewed two new tables to support STIX (Structured Threat Information eXpression) indicator and object schemas: `ThreatIntelIndicator` and `ThreatIntelObjects`. This article provides examples of how to incorporate STIX objects into queries to enhance threat hunting, and how to migrate to the new threat indicator schema. |
| 20 | + |
| 21 | +For more information about threat intelligence in Microsoft Sentinel, see [Threat intelligence in Microsoft Sentinel](understand-threat-intelligence.md). |
| 22 | + |
| 23 | +>[!IMPORTANT] |
| 24 | +> Microsoft Sentinel will ingest all threat intelligence into the new `ThreatIntelIndicator` and `ThreatIntelObjects` tables, while continuing to ingest the same data into the legacy `ThreatIntelligenceIndicator` table until July 31, 2025. |
| 25 | +> |
| 26 | +> **Be sure to update your custom queries, analytics and detection rules, workbooks, and automation to use the new tables by July 31, 2025.** After this date, Microsoft Sentinel will stop ingesting data to the legacy `ThreatIntelligenceIndicator` table. We're updating all out-of-the-box threat intelligence solutions in Content hub to leverage the new tables. For more information about the new table schemas, see [ThreatIntelIndicator](/azure/azure-monitor/reference/tables/threatintelligenceindicator) and [ThreatIntelObjects](/azure/azure-monitor/reference/tables/threatintelobjects). |
| 27 | +
|
| 28 | +## Identify threat actors associated with specific threat indicators |
| 29 | + |
| 30 | +This query is an example of how to correlate threat indicators, such as IP addresses, with threat actors: |
| 31 | + |
| 32 | +```Kusto |
| 33 | + let IndicatorsWithThatIP = (ThreatIntelIndicators |
| 34 | +| extend tlId = tostring(Data.id) |
| 35 | +| summarize arg_max(TimeGenerated,*) by Id |
| 36 | +| where IsDeleted == false); |
| 37 | +let ThreatActors = (ThreatIntelObjects |
| 38 | +| where StixType == 'threat-actor' |
| 39 | +| extend tlId = tostring(Data.id) |
| 40 | +| extend ThreatActorName = Data.name |
| 41 | +| extend ThreatActorSource = base64_decode_tostring(tostring(split(Id, '---')[0])) |
| 42 | +| summarize arg_max(TimeGenerated,*) by Id |
| 43 | +| where IsDeleted == false); |
| 44 | +let AllRelationships = (ThreatIntelObjects |
| 45 | +| where StixType == 'relationship' |
| 46 | +| extend tlSourceRef = tostring(Data.source_ref) |
| 47 | +| extend tlTargetRef = tostring(Data.target_ref) |
| 48 | +| extend tlId = tostring(Data.id) |
| 49 | +| summarize arg_max(TimeGenerated,*) by Id |
| 50 | +| where IsDeleted == false); |
| 51 | +let IndicatorAsSource = (IndicatorsWithThatIP |
| 52 | +| join AllRelationships on $left.tlId == $right.tlSourceRef |
| 53 | +| join ThreatActors on $left.tlTargetRef == $right.tlId); |
| 54 | +let IndicatorAsTarget = (IndicatorsWithThatIP |
| 55 | +| join AllRelationships on $left.tlId == $right.tlTargetRef |
| 56 | +| join ThreatActors on $left.tlSourceRef == $right.tlId); |
| 57 | +IndicatorAsSource |
| 58 | +| union IndicatorAsTarget |
| 59 | +| project ObservableValue, ThreatActorName |
| 60 | +``` |
| 61 | + |
| 62 | + |
| 63 | +## List threat intelligence data related to a specific threat actor |
| 64 | + |
| 65 | +This query provides insights into the tactics, techniques, and procedures (TTPs) of the threat actor (replace `Sangria Tempest` with the name of the threat actor you want to investigate): |
| 66 | + |
| 67 | +```Kusto |
| 68 | +let THREAT_ACTOR_NAME = 'Sangria Tempest'; |
| 69 | +let ThreatIntelObjectsPlus = (ThreatIntelObjects |
| 70 | +| union (ThreatIntelIndicators |
| 71 | +| extend StixType = 'indicator') |
| 72 | +| extend tlId = tostring(Data.id) |
| 73 | +| extend PlusStixTypes = StixType |
| 74 | +| extend importantfield = case(StixType == "indicator", Data.pattern, |
| 75 | + StixType == "attack-pattern", Data.name, |
| 76 | + "Unkown") |
| 77 | +| extend feedSource = base64_decode_tostring(tostring(split(Id, '---')[0])) |
| 78 | +| summarize arg_max(TimeGenerated,*) by Id |
| 79 | +| where IsDeleted == false); |
| 80 | +let ThreatActorsWithThatName = (ThreatIntelObjects |
| 81 | +| where StixType == 'threat-actor' |
| 82 | +| where Data.name == THREAT_ACTOR_NAME |
| 83 | +| extend tlId = tostring(Data.id) |
| 84 | +| extend ActorName = tostring(Data.name) |
| 85 | +| summarize arg_max(TimeGenerated,*) by Id |
| 86 | +| where IsDeleted == false); |
| 87 | +let AllRelationships = (ThreatIntelObjects |
| 88 | +| where StixType == 'relationship' |
| 89 | +| extend tlSourceRef = tostring(Data.source_ref) |
| 90 | +| extend tlTargetRef = tostring(Data.target_ref) |
| 91 | +| extend tlId = tostring(Data.id) |
| 92 | +| summarize arg_max(TimeGenerated,*) by Id |
| 93 | +| where IsDeleted == false); |
| 94 | +let SourceRelationships = (ThreatActorsWithThatName |
| 95 | +| join AllRelationships on $left.tlId == $right.tlSourceRef |
| 96 | +| join ThreatIntelObjectsPlus on $left.tlTargetRef == $right.tlId); |
| 97 | +let TargetRelationships = (ThreatActorsWithThatName |
| 98 | +| join AllRelationships on $left.tlId == $right.tlTargetRef |
| 99 | +| join ThreatIntelObjectsPlus on $left.tlSourceRef == $right.tlId); |
| 100 | +SourceRelationships |
| 101 | +| union TargetRelationships |
| 102 | +| project ActorName, PlusStixTypes, ObservableValue, importantfield, Tags, feedSource |
| 103 | + ``` |
| 104 | + |
| 105 | +## Migrate existing queries to the new ThreatIntelObjects schema |
| 106 | + |
| 107 | +This example shows how to migrate existing queries from the legacy `ThreatIntelligenceIndicator` table to the new `ThreatIntelObjects` schema. The query uses the `extend` operator to recreate legacy columns based on the `ObservableKey` and `ObservableValue` columns in the new table. |
| 108 | + |
| 109 | +```Kusto |
| 110 | +ThreatIntelIndicators |
| 111 | +| extend NetworkIP = iff(ObservableKey == 'ipv4-addr:value', ObservableValue, ''), |
| 112 | + NetworkSourceIP = iff(ObservableKey == 'network-traffic:src_ref.value', ObservableValue, ''), |
| 113 | + NetworkDestinationIP = iff(ObservableKey == 'network-traffic:dst_ref.value', ObservableValue, ''), |
| 114 | + DomainName = iff(ObservableKey == 'domain-name:value', ObservableValue, ''), |
| 115 | + EmailAddress = iff(ObservableKey == 'email-addr:value', ObservableValue, ''), |
| 116 | + FileHashType = case(ObservableKey has 'MD5', 'MD5', |
| 117 | + ObservableKey has 'SHA-1', 'SHA-1', |
| 118 | + ObservableKey has 'SHA-256', 'SHA-256', |
| 119 | + ''), |
| 120 | + FileHashValue = iff(ObservableKey has 'file:hashes', ObservableValue, ''), |
| 121 | + Url = iff(ObservableKey == 'url:value', ObservableValue, ''), |
| 122 | + x509Certificate = iff(ObservableKey has 'x509-certificate:hashes.', ObservableValue, ''), |
| 123 | + x509Issuer = iff(ObservableKey has 'x509-certificate:issuer', ObservableValue, ''), |
| 124 | + x509CertificateNumber = iff(ObservableKey == 'x509-certificate:serial_number', ObservableValue, ''), |
| 125 | + Description = tostring(Data.description), |
| 126 | + CreatedByRef = Data.created_by_ref, |
| 127 | + Extensions = Data.extensions, |
| 128 | + ExternalReferences = Data.references, |
| 129 | + GranularMarkings = Data.granular_markings, |
| 130 | + IndicatorId = tostring(Data.id), |
| 131 | + ThreatType = tostring(Data.indicator_types[0]), |
| 132 | + KillChainPhases = Data.kill_chain_phases, |
| 133 | + Labels = Data.labels, |
| 134 | + Lang = Data.lang, |
| 135 | + Name = Data.name, |
| 136 | + ObjectMarkingRefs = Data.object_marking_refs, |
| 137 | + PatternType = Data.pattern_type, |
| 138 | + PatternVersion = Data.pattern_version, |
| 139 | + Revoked = Data.revoked, |
| 140 | + SpecVersion = Data.spec_version |
| 141 | +| project-reorder TimeGenerated, WorkspaceId, AzureTenantId, ThreatType, ObservableKey, ObservableValue, Confidence, Name, Description, LastUpdateMethod, SourceSystem, Created, Modified, ValidFrom, ValidUntil, IsDeleted, Tags, AdditionalFields, CreatedByRef, Extensions, ExternalReferences, GranularMarkings, IndicatorId, KillChainPhases, Labels, Lang, ObjectMarkingRefs, Pattern, PatternType, PatternVersion, Revoked, SpecVersion, NetworkIP, NetworkDestinationIP, NetworkSourceIP, DomainName, EmailAddress, FileHashType, FileHashValue, Url, x509Certificate, x509Issuer, x509CertificateNumber, Data |
| 142 | +``` |
| 143 | + |
| 144 | +## Related content |
| 145 | + |
| 146 | +For more information, see the following articles: |
| 147 | + |
| 148 | +- [Threat intelligence in Microsoft Sentinel](understand-threat-intelligence.md). |
| 149 | +- Connect Microsoft Sentinel to [STIX/TAXII threat intelligence feeds](./connect-threat-intelligence-taxii.md). |
| 150 | +- See which [TIPs, TAXII feeds, and enrichments](threat-intelligence-integration.md) can be readily integrated with Microsoft Sentinel. |
| 151 | + |
| 152 | +[!INCLUDE [kusto-reference-general-no-alert](includes/kusto-reference-general-no-alert.md)] |
0 commit comments