Trabajar con objetos e indicadores STIX para mejorar la inteligencia sobre amenazas y la búsqueda de amenazas en Microsoft Sentinel (versión preliminar)

El 3 de abril de 2025, presentamos en versión preliminar pública dos tablas nuevas para dar soporte a los esquemas de indicadores y objetos de STIX (Structured Threat Information eXpression): ThreatIntelIndicators y ThreatIntelObjects. En este artículo se proporcionan ejemplos de cómo incorporar objetos STIX en consultas para mejorar la búsqueda de amenazas y cómo migrar al nuevo ThreatIntelIndicators esquema de tabla.

Para obtener más información sobre la inteligencia sobre amenazas en Microsoft Sentinel, consulte Inteligencia sobre amenazas en Microsoft Sentinel.

Importante

Microsoft Sentinel ingerirá toda la inteligencia sobre amenazas en las nuevas tablas ThreatIntelIndicators y ThreatIntelObjects, mientras continúa ingiriendo los mismos datos en la tabla heredada ThreatIntelligenceIndicator hasta el 31 de julio de 2025. Asegúrese de actualizar las consultas personalizadas, las reglas de análisis y detección, los libros y la automatización para usar las nuevas tablas antes del 31 de julio de 2025. Después del 31 de julio de 2025, Microsoft Sentinel dejará de incorporar datos a la tabla heredadaThreatIntelligenceIndicator. Estamos actualizando todas las soluciones predefinidas de inteligencia de amenazas en Content hub para aprovechar las nuevas tablas. Se han introducido actualizaciones importantes para los procesos de republicación de datos.

  1. Anteriormente, los datos se dividieron y se publicaron en Log Analytics durante un período de 12 días. Ahora, todos los datos se vuelven a publicar cada 7-10 días. Puede identificar estos datos en las ThreatIntelIndicators tablas y ThreatIntelObjects comprobando si LastUpdateMethod es igual a LogARepublisher.
  2. Las nuevas tablas ahora admiten más columnas, incluida la Data columna , que contiene el objeto de datos completo (excepto los atributos que ya existen en otras columnas) que se usan en escenarios de búsqueda avanzada. Si la Data columna u otras columnas agregadas no se alinean con el escenario, obtenga más información sobre el filtrado de columnas y el filtrado de filas antes de la ingesta en Log Analytics.
  3. Para optimizar la ingesta en Log Analytics, se excluyen los pares clave-valor sin datos. Además, algunos campos de la Data columna, como description y pattern, se truncan si superan los 1000 caracteres. Para obtener más información sobre el esquema actualizado y cómo podría afectar al uso, vea ThreatIntelIndicators y ThreatIntelObjects.

Identificación de los actores de amenazas asociados a indicadores de amenazas específicos

Esta consulta es un ejemplo de cómo correlacionar indicadores de amenazas, como direcciones IP, con actores de amenazas:

 let IndicatorsWithThatIP = (ThreatIntelIndicators
| extend tlId = tostring(Data.id)
| summarize arg_max(TimeGenerated,*) by Id
|  where IsDeleted == false);
let ThreatActors = (ThreatIntelObjects
| where StixType == 'threat-actor'
| extend tlId = tostring(Data.id)
| extend ThreatActorName = Data.name
| extend ThreatActorSource = base64_decode_tostring(tostring(split(Id, '---')[0]))
| summarize arg_max(TimeGenerated,*) by Id
|  where IsDeleted == false);
let AllRelationships = (ThreatIntelObjects
| where StixType == 'relationship'
| extend tlSourceRef = tostring(Data.source_ref)
| extend tlTargetRef = tostring(Data.target_ref)
| extend tlId = tostring(Data.id)
| summarize arg_max(TimeGenerated,*) by Id
|  where IsDeleted == false);
let IndicatorAsSource = (IndicatorsWithThatIP
| join AllRelationships on $left.tlId == $right.tlSourceRef
| join ThreatActors on $left.tlTargetRef == $right.tlId);
let IndicatorAsTarget = (IndicatorsWithThatIP
| join AllRelationships on $left.tlId == $right.tlTargetRef
| join ThreatActors on $left.tlSourceRef == $right.tlId);
IndicatorAsSource
| union IndicatorAsTarget
| project ObservableValue, ThreatActorName

Esta consulta proporciona información sobre las tácticas, técnicas y procedimientos (TTP) del actor de amenazas (reemplace por Sangria Tempest el nombre del actor de amenazas que desea investigar):

let THREAT_ACTOR_NAME = 'Sangria Tempest';
let ThreatIntelObjectsPlus = (ThreatIntelObjects
| union (ThreatIntelIndicators
| extend StixType = 'indicator')
| extend tlId = tostring(Data.id)
| extend PlusStixTypes = StixType
| extend importantfield = case(StixType == "indicator", Data.pattern,
                            StixType == "attack-pattern", Data.name,
                            "Unkown")
| extend feedSource = base64_decode_tostring(tostring(split(Id, '---')[0]))
| summarize arg_max(TimeGenerated,*) by Id
|  where IsDeleted == false);
let ThreatActorsWithThatName = (ThreatIntelObjects
| where StixType == 'threat-actor'
| where Data.name == THREAT_ACTOR_NAME
| extend tlId = tostring(Data.id)
| extend ActorName = tostring(Data.name)
| summarize arg_max(TimeGenerated,*) by Id
|  where IsDeleted == false);
let AllRelationships = (ThreatIntelObjects
| where StixType == 'relationship'
| extend tlSourceRef = tostring(Data.source_ref)
| extend tlTargetRef = tostring(Data.target_ref)
| extend tlId = tostring(Data.id)
| summarize arg_max(TimeGenerated,*) by Id
|  where IsDeleted == false);
let SourceRelationships = (ThreatActorsWithThatName
| join AllRelationships on $left.tlId == $right.tlSourceRef
| join ThreatIntelObjectsPlus on $left.tlTargetRef == $right.tlId);
let TargetRelationships = (ThreatActorsWithThatName
| join AllRelationships on $left.tlId == $right.tlTargetRef
| join ThreatIntelObjectsPlus on $left.tlSourceRef == $right.tlId);
SourceRelationships
| union TargetRelationships
| project ActorName, PlusStixTypes, ObservableValue, importantfield, Tags, feedSource

Migración de consultas existentes al nuevo esquema ThreatIntelIndicators

En este ejemplo se muestra cómo migrar las consultas existentes de la tabla heredada ThreatIntelligenceIndicator al nuevo ThreatIntelIndicators esquema. La consulta usa el extend operador para volver a crear columnas heredadas basadas en las ObservableKey columnas y ObservableValue de la nueva tabla.

ThreatIntelIndicators
| extend NetworkIP = iff(ObservableKey == 'ipv4-addr:value', ObservableValue, ''),
        NetworkSourceIP = iff(ObservableKey == 'network-traffic:src_ref.value', ObservableValue, ''),
        NetworkDestinationIP = iff(ObservableKey == 'network-traffic:dst_ref.value', ObservableValue, ''),
        DomainName = iff(ObservableKey == 'domain-name:value', ObservableValue, ''),
        EmailAddress = iff(ObservableKey == 'email-addr:value', ObservableValue, ''),
        FileHashType = case(ObservableKey has 'MD5', 'MD5',
                                ObservableKey has 'SHA-1', 'SHA-1',
                                ObservableKey has 'SHA-256', 'SHA-256',
                                ''),
        FileHashValue = iff(ObservableKey has 'file:hashes', ObservableValue, ''),
        Url = iff(ObservableKey == 'url:value', ObservableValue, ''),
        x509Certificate = iff(ObservableKey has 'x509-certificate:hashes.', ObservableValue, ''),
        x509Issuer = iff(ObservableKey has 'x509-certificate:issuer', ObservableValue, ''),
        x509CertificateNumber = iff(ObservableKey == 'x509-certificate:serial_number', ObservableValue, ''),        
        Description = tostring(Data.description),
        CreatedByRef = Data.created_by_ref,
        Extensions = Data.extensions,
        ExternalReferences = Data.references,
        GranularMarkings = Data.granular_markings,
        IndicatorId = tostring(Data.id),
        ThreatType = tostring(Data.indicator_types[0]),
        KillChainPhases = Data.kill_chain_phases,
        Labels = Data.labels,
        Lang = Data.lang,
        Name = Data.name,
        ObjectMarkingRefs = Data.object_marking_refs,
        PatternType = Data.pattern_type,
        PatternVersion = Data.pattern_version,
        Revoked = Data.revoked,
        SpecVersion = Data.spec_version
| 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

Filtrar datos antes de enviarlos a Log Analytics

Las transformaciones de Azure Monitor permiten filtrar o modificar los datos entrantes antes de almacenarlos en un área de trabajo de Log Analytics. Se implementan como una instrucción del Lenguaje de consultas Kusto (KQL) en una regla de recopilación de datos (DCR). Obtenga más información sobre cómo crear transformaciones de área de trabajo y el costo de las transformaciones.

Excluir columnas antes de enviar datos a Log Analytics

Las ThreatIntelIndicators tablas y ThreatIntelObjects incluyen una Data columna que contiene el objeto STIX original completo. Si esta columna no es relevante para su caso de uso, puede filtrarla antes de la ingesta mediante la siguiente instrucción KQL:

source
| project-away Data

Excluir filas antes de enviar datos a Log Analytics

La ThreatIntelIndicators tabla siempre recibe al menos una fila por cada indicador no caducado. En algunos casos, el patrón STIX no se puede analizar en pares clave-valor. Cuando esto sucede, el indicador se sigue enviando a Log Analytics, pero solo se incluye el patrón sin procesar y sin analizar, lo que permite a los usuarios crear analíticas personalizadas si es necesario. Si estas filas no son útiles para su escenario, puede filtrarlas antes de la ingesta mediante la siguiente instrucción KQL:

source
| where (ObservableKey != "" and isnotempty(ObservableKey)) 
    or (ObservableValue != "" and isnotempty(ObservableValue))

Para más información, consulte los siguientes artículos:

Para obtener más información sobre KQL, consulte introducción a Lenguaje de consulta Kusto (KQL).

Otros recursos: