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, se previsualizaron públicamente dos nuevas tablas para admitir esquemas de objetos y indicadores STIX (eXpression de información de amenazas estructuradas): 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 esquema de indicador de amenazas.

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 tablas y ThreatIntelObjects nuevasThreatIntelIndicators, mientras continúa ingeriendo 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 de esta fecha, Microsoft Sentinel dejará de ingerir datos en la tabla heredadaThreatIntelligenceIndicator. Estamos actualizando todas las soluciones de inteligencia sobre amenazas integradas 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 estas columnas no se alinean con el escenario, obtenga más información sobre el filtrado de columnas y 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

Transformación de datos enviados 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 Lenguaje de consulta 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.

Transformación de columnas enviadas a Log Analytics

Las ThreatIntelIndicator 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

Transformación de filas enviadas a Log Analytics

La ThreatIntelIndicators tabla siempre recibe al menos una fila por cada indicador sin explorar. 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 procesar, lo que permite a los usuarios crear análisis personalizados 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: