Prácticas recomendadas para la consulta de búsqueda avanzadaAdvanced hunting query best practices

Importante

El Centro de seguridad de Microsoft 365 mejorado está ahora disponible.The improved Microsoft 365 security center is now available. Esta nueva experiencia incluye Defender para punto de conexión, Defender para Office 365, Microsoft 365 Defender y más en el Centro de seguridad de Microsoft 365.This new experience brings Defender for Endpoint, Defender for Office 365, Microsoft 365 Defender, and more into the Microsoft 365 security center. Ver las novedades.Learn what's new.

Se aplica a:Applies to:

  • Microsoft 365 DefenderMicrosoft 365 Defender

Aplique estas recomendaciones para obtener resultados más rápido y evitar tiempos de espera mientras ejecuta consultas complejas.Apply these recommendations to get results faster and avoid timeouts while running complex queries. Para obtener más información sobre cómo mejorar el rendimiento de las consultas, vea procedimientos recomendados de consulta de Kusto.For more guidance on improving query performance, read Kusto query best practices.

Comprender las cuotas de recursos de CPUUnderstand CPU resource quotas

Según su tamaño, cada inquilino tiene acceso a una cantidad establecida de recursos de CPU asignados para ejecutar consultas de búsqueda avanzada.Depending on its size, each tenant has access to a set amount of CPU resources allocated for running advanced hunting queries. Para obtener información detallada acerca de los distintos límites de servicio, lea acerca de las cuotas de búsqueda avanzadas y los parámetros de uso.For detailed information about various service limits, read about advanced hunting quotas and usage parameters.

Los clientes que ejecutan varias consultas con regularidad deben realizar un seguimiento del consumo y aplicar las instrucciones de optimización de este artículo para minimizar las interrupciones resultantes de la superación de cuotas o parámetros de uso.Customers who run multiple queries regularly should track consumption and apply the optimization guidance in this article to minimize disruption resulting from exceeding quotas or usage parameters.

Sugerencias de optimización generalGeneral optimization tips

  • Nuevas consultas de tamaño: si sospecha que una consulta devolverá un conjunto de resultados grande, evalúe primero con el operador count.Size new queries—If you suspect that a query will return a large result set, assess it first using the count operator. Use limit o su sinónimo take para evitar conjuntos de resultados grandes.Use limit or its synonym take to avoid large result sets.

  • Aplicar filtros de forma anticipada : aplique filtros de tiempo y otros filtros para reducir el conjunto de datos, especialmente antes de usar funciones de transformación y análisis, como substring(), replace(), trim(), toupper()o parse_json().Apply filters early—Apply time filters and other filters to reduce the data set, especially before using transformation and parsing functions, such as substring(), replace(), trim(), toupper(), or parse_json(). En el ejemplo siguiente, se usa la función de análisis extractjson() después de que los operadores de filtrado han reducido el número de registros.In the example below, the parsing function extractjson() is used after filtering operators have reduced the number of records.

    DeviceEvents
    | where Timestamp > ago(1d)
    | where ActionType == "UsbDriveMount" 
    | where DeviceName == "user-desktop.domain.com"
    | extend DriveLetter = extractjson("$.DriveLetter", AdditionalFields)
    
  • Tiene latidos contiene: para evitar buscar subcadenas en palabras innecesariamente, use el has operador en lugar de contains .Has beats contains—To avoid searching substrings within words unnecessarily, use the has operator instead of contains. Información sobre operadores de cadenasLearn about string operators

  • Buscar en columnas específicas: busque en una columna específica en lugar de ejecutar búsquedas de texto completo en todas las columnas.Look in specific columns—Look in a specific column rather than running full text searches across all columns. No lo use para * comprobar todas las columnas.Don't use * to check all columns.

  • Distingue entre mayúsculas y minúsculas para la velocidad: las búsquedas entre mayúsculas y minúsculas son más específicas y, por lo general, más rendimiento.Case-sensitive for speed—Case-sensitive searches are more specific and generally more performant. Nombres de operadores de cadena que distinguen mayúsculas de minúsculas, has_cs como y , generalmente terminan con contains_cs _cs .Names of case-sensitive string operators, such as has_cs and contains_cs, generally end with _cs. También puede usar el operador igual a mayúsculas y minúsculas == en lugar de =~ .You can also use the case-sensitive equals operator == instead of =~.

  • Analizar, no extraer— Siempre que sea posible, use el operador de análisis o una función de análisis como parse_json().Parse, don't extract—Whenever possible, use the parse operator or a parsing function like parse_json(). Evite el matches regex operador de cadena o la función extract(),que usan expresión regular.Avoid the matches regex string operator or the extract() function, both of which use regular expression. Reserve el uso de la expresión regular para escenarios más complejos.Reserve the use of regular expression for more complex scenarios. Más información sobre las funciones de análisisRead more about parsing functions

  • Tablas de filtro no expresiones: no filtre en una columna calculada si puede filtrar en una columna de tabla.Filter tables not expressions—Don't filter on a calculated column if you can filter on a table column.

  • Sin términos de tres caracteres: evite comparar o filtrar con términos con tres caracteres o menos.No three-character terms—Avoid comparing or filtering using terms with three characters or fewer. Estos términos no están indizados y la coincidencia de ellos requerirá más recursos.These terms are not indexed and matching them will require more resources.

  • Project selectivamente: haga que los resultados sean más fáciles de comprender proyectando solo las columnas que necesita.Project selectively—Make your results easier to understand by projecting only the columns you need. La proyección de columnas específicas antes de ejecutar la combinación o operaciones similares también ayuda a mejorar el rendimiento.Projecting specific columns prior to running join or similar operations also helps improve performance.

Optimizar el join operadorOptimize the join operator

El operador join combina filas de dos tablas mediante valores coincidentes en columnas especificadas.The join operator merges rows from two tables by matching values in specified columns. Aplique estas sugerencias para optimizar las consultas que usan este operador.Apply these tips to optimize queries that use this operator.

  • Tabla más pequeña a la izquierda: el operador coincide con los registros de la tabla del lado izquierdo de la instrucción join join con los registros de la derecha.Smaller table to your left—The join operator matches records in the table on the left side of your join statement to records on the right. Al tener la tabla más pequeña a la izquierda, se necesitarán hacer coincidir menos registros, lo que acelerará la consulta.By having the smaller table on the left, fewer records will need to be matched, thus speeding up the query.

    En la tabla siguiente, reducimos la tabla izquierda para cubrir solo tres dispositivos específicos antes de unirla con los SID de DeviceLogonEvents IdentityLogonEvents cuenta.In the table below, we reduce the left table DeviceLogonEvents to cover only three specific devices before joining it with IdentityLogonEvents by account SIDs.

    DeviceLogonEvents 
    | where DeviceName in ("device-1.domain.com", "device-2.domain.com", "device-3.domain.com")
    | where ActionType == "LogonFailed"
    | join
        (IdentityLogonEvents
        | where ActionType == "LogonFailed"
        | where Protocol == "Kerberos")
    on AccountSid
    
  • Use el sabor de unión interna : el tipo de combinación predeterminado o la combinación innerunique deduplica las filas de la tabla izquierda por la clave de combinación antes de devolver una fila para cada coincidencia a la tabla derecha.Use the inner-join flavor—The default join flavor or the innerunique-join deduplicates rows in the left table by the join key before returning a row for each match to the right table. Si la tabla izquierda tiene varias filas con el mismo valor para la clave, esas filas se deduplicarán para dejar una sola fila aleatoria join para cada valor único.If the left table has multiple rows with the same value for the join key, those rows will be deduplicated to leave a single random row for each unique value.

    Este comportamiento predeterminado puede dejar fuera información importante de la tabla izquierda que puede proporcionar información útil.This default behavior can leave out important information from the left table that can provide useful insight. Por ejemplo, la consulta siguiente solo mostrará un correo electrónico que contenga datos adjuntos determinados, incluso si ese mismo dato adjunto se envió con varios mensajes de correo electrónico:For example, the query below will only show one email containing a particular attachment, even if that same attachment was sent using multiple emails messages:

    EmailAttachmentInfo
    | where Timestamp > ago(1h)
    | where Subject == "Document Attachment" and FileName == "Document.pdf"
    | join (DeviceFileEvents | where Timestamp > ago(1h)) on SHA256 
    

    Para solucionar esta limitación, aplicamos el tipo de combinación interna especificando para mostrar todas las filas de la tabla izquierda con valores coincidentes kind=inner a la derecha:To address this limitation, we apply the inner-join flavor by specifying kind=inner to show all rows in the left table with matching values in the right:

    EmailAttachmentInfo
    | where Timestamp > ago(1h)
    | where Subject == "Document Attachment" and FileName == "Document.pdf"
    | join kind=inner (DeviceFileEvents | where Timestamp > ago(1h)) on SHA256 
    
  • Unir registros desde una ventana de tiempo: al investigar eventos de seguridad, los analistas buscan eventos relacionados que se producen alrededor del mismo período de tiempo.Join records from a time window—When investigating security events, analysts look for related events that occur around the same time period. Aplicar el mismo enfoque al usar también join beneficia el rendimiento al reducir el número de registros que se deben comprobar.Applying the same approach when using join also benefits performance by reducing the number of records to check.

    La consulta siguiente comprueba si hay eventos de inicio de sesión en un plazo de 30 minutos después de recibir un archivo malintencionado:The query below checks for logon events within 30 minutes of receiving a malicious file:

    EmailEvents
    | where Timestamp > ago(7d)
    | where ThreatTypes has "Malware"
    | project EmailReceivedTime = Timestamp, Subject, SenderFromAddress, AccountName = tostring(split(RecipientEmailAddress, "@")[0])
    | join (
    DeviceLogonEvents 
    | where Timestamp > ago(7d)
    | project LogonTime = Timestamp, AccountName, DeviceName
    ) on AccountName 
    | where (LogonTime - EmailReceivedTime) between (0min .. 30min)
    
  • Aplicar filtros de tiempo en ambos lados: incluso si no está investigando una ventana de tiempo específica, la aplicación de filtros de tiempo en las tablas izquierda y derecha puede reducir el número de registros para comprobar y mejorar el join rendimiento.Apply time filters on both sides—Even if you're not investigating a specific time window, applying time filters on both the left and right tables can reduce the number of records to check and improve join performance. La consulta siguiente se aplica a ambas tablas de modo que solo Timestamp > ago(1h) une registros de la última hora:The query below applies Timestamp > ago(1h) to both tables so that it joins only records from the past hour:

    EmailAttachmentInfo
    | where Timestamp > ago(1h)
    | where Subject == "Document Attachment" and FileName == "Document.pdf"
    | join kind=inner (DeviceFileEvents | where Timestamp > ago(1h)) on SHA256 
    
  • Usar sugerencias para el rendimiento: use sugerencias con el operador para indicar al back-end que distribuya la carga al join ejecutar operaciones que consumen muchos recursos.Use hints for performance—Use hints with the join operator to instruct the backend to distribute load when running resource-intensive operations. Más información sobre las sugerencias de uniónLearn more about join hints

    Por ejemplo, la sugerencia aleatoria ayuda a mejorar el rendimiento de las consultas al unir tablas con una clave con una cardinalidad alta(una clave con muchos valores únicos), como la siguiente AccountObjectId consulta:For example, the shuffle hint helps improve query performance when joining tables using a key with high cardinality—a key with many unique values—such as the AccountObjectId in the query below:

    IdentityInfo
    | where JobTitle == "CONSULTANT"
    | join hint.shufflekey = AccountObjectId 
    (IdentityDirectoryEvents
        | where Application == "Active Directory"
        | where ActionType == "Private data retrieval")
    on AccountObjectId 
    

    La sugerencia de difusión ayuda cuando la tabla izquierda es pequeña (hasta 100 000 registros) y la tabla derecha es extremadamente grande.The broadcast hint helps when the left table is small (up to 100,000 records) and the right table is extremely large. Por ejemplo, la consulta siguiente está intentando unir algunos correos electrónicos que tienen asuntos específicos con todos los mensajes que contienen vínculos en la EmailUrlInfo tabla:For example, the query below is trying to join a few emails that have specific subjects with all messages containing links in the EmailUrlInfo table:

    EmailEvents 
    | where Subject in ("Warning: Update your credentials now", "Action required: Update your credentials now")
    | join hint.strategy = broadcast EmailUrlInfo on NetworkMessageId 
    

Optimizar el summarize operadorOptimize the summarize operator

El operador de resumen agrega el contenido de una tabla.The summarize operator aggregates the contents of a table. Aplique estas sugerencias para optimizar las consultas que usan este operador.Apply these tips to optimize queries that use this operator.

  • Buscar valores distintos: en general, se usan summarize para buscar valores distintos que pueden ser repetitivos.Find distinct values—In general, use summarize to find distinct values that can be repetitive. Puede ser innecesario usarlo para agregar columnas que no tienen valores repetitivos.It can be unnecessary to use it to aggregate columns that don't have repetitive values.

    Aunque un solo correo electrónico puede formar parte de varios eventos, el ejemplo siguiente no es un uso eficaz de porque un identificador de mensaje de red para un correo electrónico individual siempre viene con una dirección summarize de remitente única.While a single email can be part of multiple events, the example below is not an efficient use of summarize because a network message ID for an individual email always comes with a unique sender address.

    EmailEvents  
    | where Timestamp > ago(1h)
    | summarize by NetworkMessageId, SenderFromAddress   
    

    El operador se puede reemplazar fácilmente con , lo que produce potencialmente los mismos resultados summarize project mientras consume menos recursos:The summarize operator can be easily replaced with project, yielding potentially the same results while consuming fewer resources:

    EmailEvents  
    | where Timestamp > ago(1h)
    | project NetworkMessageId, SenderFromAddress   
    

    El ejemplo siguiente es un uso más eficaz de porque puede haber varias instancias distintas de una dirección de remitente que envíe correo electrónico summarize a la misma dirección de destinatario.The following example is a more efficient use of summarize because there can be multiple distinct instances of a sender address sending email to the same recipient address. Estas combinaciones son menos distintas y es probable que tengan duplicados.Such combinations are less distinct and are likely to have duplicates.

    EmailEvents  
    | where Timestamp > ago(1h)
    | summarize by SenderFromAddress, RecipientEmailAddress   
    
  • Barajar la consulta: aunque se usa mejor en columnas con valores repetitivos, las mismas columnas también pueden tener una gran cardinalidad o un gran número summarize de valores únicos. Shuffle the query—While summarize is best used in columns with repetitive values, the same columns can also have high cardinality or large numbers of unique values. Al igual que el operador, también puede aplicar la sugerencia aleatoria con para distribuir la carga de procesamiento y mejorar potencialmente el rendimiento al operar en columnas join con una summarize cardinalidad alta.Like the join operator, you can also apply the shuffle hint with summarize to distribute processing load and potentially improve performance when operating on columns with high cardinality.

    La consulta siguiente se usa para contar una dirección de correo electrónico de destinatario distinta, que puede ejecutarse summarize en los cientos de miles de organizaciones grandes.The query below uses summarize to count distinct recipient email address, which can run in the hundreds of thousands in large organizations. Para mejorar el rendimiento, incorpora hint.shufflekey :To improve performance, it incorporates hint.shufflekey:

    EmailEvents  
    | where Timestamp > ago(1h)
    | summarize hint.shufflekey = RecipientEmailAddress count() by Subject, RecipientEmailAddress
    

Escenarios de consultaQuery scenarios

Identificar procesos únicos con identificadores de procesoIdentify unique processes with process IDs

Los Id. de proceso (PID) se reciclan en Windows y se reutilizan para los nuevos procesos.Process IDs (PIDs) are recycled in Windows and reused for new processes. Por sí solos, no pueden servir como identificadores únicos para procesos específicos.On their own, they can't serve as unique identifiers for specific processes.

Para obtener un identificador único para un proceso en un equipo específico, utilice el Id. de proceso conjuntamente con la hora de creación del proceso.To get a unique identifier for a process on a specific machine, use the process ID together with the process creation time. Cuando se une a los datos en torno a los procesos, debe incluir columnas para el identificador de la máquina (tanto DeviceId como DeviceName), el identificador de proceso (ProcessId o InitiatingProcessId) y la hora de creación del proceso (ProcessCreationTime o InitiatingProcessCreationTime).When you join or summarize data around processes, include columns for the machine identifier (either DeviceId or DeviceName), the process ID (ProcessId or InitiatingProcessId), and the process creation time (ProcessCreationTime or InitiatingProcessCreationTime)

En la siguiente consulta de ejemplo se buscan procesos que obtienen acceso a más de 10 direcciones IP por el puerto 445 (SMB), lo que podría buscar recursos compartidos de archivos.The following example query finds processes that access more than 10 IP addresses over port 445 (SMB), possibly scanning for file shares.

Consulta de ejemplo:Example query:

DeviceNetworkEvents
| where RemotePort == 445 and Timestamp > ago(12h) and InitiatingProcessId !in (0, 4)
| summarize RemoteIPCount=dcount(RemoteIP) by DeviceName, InitiatingProcessId
InitiatingProcessCreationTime, InitiatingProcessFileName
| where RemoteIPCount > 10

La consulta resume tanto en InitiatingProcessId como en InitiatingProcessCreationTime para que se vea un único proceso, sin mezclar varios procesos con el mismo Id. de proceso.The query summarizes by both InitiatingProcessId and InitiatingProcessCreationTime so that it looks at a single process, without mixing multiple processes with the same process ID.

Líneas de comandos de consultaQuery command lines

Hay varias formas de crear una línea de comandos para llevar a cabo una tarea.There are numerous ways to construct a command line to accomplish a task. Por ejemplo, un atacante puede hacer referencia a un archivo de imagen sin una ruta de acceso, sin una extensión de archivo, con variables de entorno o con comillas.For example, an attacker could reference an image file without a path, without a file extension, using environment variables, or with quotes. El atacante también podría cambiar el orden de los parámetros o agregar varias comillas y espacios.The attacker could also change the order of parameters or add multiple quotes and spaces.

Para crear consultas más duraderas alrededor de las líneas de comandos, aplique los siguientes procedimientos:To create more durable queries around command lines, apply the following practices:

  • Identifique los procesos conocidos (como net.exe opsexec.exe) haciendo coincidir en los campos de nombre de archivo, en lugar de filtrar en la propia línea de comandos.Identify the known processes (such as net.exe or psexec.exe) by matching on the file name fields, instead of filtering on the command-line itself.
  • Analizar secciones de línea de comandos mediante la función parse_command_line()Parse command-line sections using the parse_command_line() function
  • Al consultar argumentos de la línea de comandos, no busque una coincidencia exacta en varios argumentos no relacionados en un orden determinado.When querying for command-line arguments, don't look for an exact match on multiple unrelated arguments in a certain order. En su lugar, use expresiones regulares o use operadores de contenedores separados múltiples.Instead, use regular expressions or use multiple separate contains operators.
  • Use coincidencias que no distinga mayúsculas de minúsculas.Use case insensitive matches. Por ejemplo, use =~ , , y en lugar de , y in~ contains == in contains_cs .For example, use =~, in~, and contains instead of ==, in, and contains_cs.
  • Para mitigar las técnicas de ofuscación de línea de comandos, considere la posibilidad de quitar comillas, reemplazar comas por espacios y reemplazar varios espacios consecutivos por un solo espacio.To mitigate command-line obfuscation techniques, consider removing quotes, replacing commas with spaces, and replacing multiple consecutive spaces with a single space. Hay técnicas de ofuscación más complejas que requieren otros enfoques, pero estos retoques pueden ayudar a abordar los métodos comunes.There are more complex obfuscation techniques that require other approaches, but these tweaks can help address common ones.

Los ejemplos siguientes muestran varias formas de crear una consulta que busca el archivonet.exedetener el servicio de firewall "MpsSvc":The following examples show various ways to construct a query that looks for the file net.exe to stop the firewall service "MpsSvc":

// Non-durable query - do not use
DeviceProcessEvents
| where ProcessCommandLine == "net stop MpsSvc"
| limit 10

// Better query - filters on file name, does case-insensitive matches
DeviceProcessEvents
| where Timestamp > ago(7d) and FileName in~ ("net.exe", "net1.exe") and ProcessCommandLine contains "stop" and ProcessCommandLine contains "MpsSvc" 

// Best query also ignores quotes
DeviceProcessEvents
| where Timestamp > ago(7d) and FileName in~ ("net.exe", "net1.exe")
| extend CanonicalCommandLine=replace("\"", "", ProcessCommandLine)
| where CanonicalCommandLine contains "stop" and CanonicalCommandLine contains "MpsSvc" 

Ingerir datos de orígenes externosIngest data from external sources

Para incorporar listas largas o tablas grandes a la consulta, use el operador externaldata para ingerir datos de un URI especificado.To incorporate long lists or large tables into your query, use the externaldata operator to ingest data from a specified URI. Puede obtener datos de archivos en TXT, CSV, JSON u otros formatos.You can get data from files in TXT, CSV, JSON, or other formats. En el ejemplo siguiente se muestra cómo usar la extensa lista de hashes sha-256 de malware proporcionados por MalwareBazaar (abuse.ch) para comprobar los datos adjuntos de los correos electrónicos:The example below shows how you can utilize the extensive list of malware SHA-256 hashes provided by MalwareBazaar (abuse.ch) to check attachments on emails:

let abuse_sha256 = (externaldata(sha256_hash: string )
[@"https://bazaar.abuse.ch/export/txt/sha256/recent/"]
with (format="txt"))
| where sha256_hash !startswith "#"
| project sha256_hash;
abuse_sha256
| join (EmailAttachmentInfo 
| where Timestamp > ago(1d) 
) on $left.sha256_hash == $right.SHA256
| project Timestamp,SenderFromAddress,RecipientEmailAddress,FileName,FileType,
SHA256,ThreatTypes,DetectionMethods

Analizar cadenasParse strings

Hay varias funciones que puede usar para controlar eficazmente las cadenas que necesitan análisis o conversión.There are various functions you can use to efficiently handle strings that need parsing or conversion.

CadenaString FunciónFunction Ejemplo de usoUsage example
Líneas de comandosCommand-lines parse_command_line()parse_command_line() Extraiga el comando y todos los argumentos.Extract the command and all arguments.
PathsPaths parse_path()parse_path() Extraiga las secciones de una ruta de acceso de archivo o carpeta.Extract the sections of a file or folder path.
Números de versiónVersion numbers parse_version()parse_version() Deconstruir un número de versión con hasta cuatro secciones y hasta ocho caracteres por sección.Deconstruct a version number with up to four sections and up to eight characters per section. Use los datos analizados para comparar la antigüedad de la versión.Use the parsed data to compare version age.
Direcciones IPv4IPv4 addresses parse_ipv4()parse_ipv4() Convertir una dirección IPv4 en un entero largo.Convert an IPv4 address to a long integer. Para comparar direcciones IPv4 sin convertirlas, use ipv4_compare().To compare IPv4 addresses without converting them, use ipv4_compare().
Direcciones IPv6IPv6 addresses parse_ipv6()parse_ipv6() Convierta una dirección IPv4 o IPv6 en la notación IPv6 canónica.Convert an IPv4 or IPv6 address to the canonical IPv6 notation. Para comparar direcciones IPv6, use ipv6_compare().To compare IPv6 addresses, use ipv6_compare().

Para obtener información sobre todas las funciones de análisis admitidas, lea acerca de las funciones de cadena kusto.To learn about all supported parsing functions, read about Kusto string functions.

Nota

Es posible que algunas tablas de este artículo no estén disponibles en Microsoft Defender para endpoint.Some tables in this article might not be available in Microsoft Defender for Endpoint. Activa Microsoft 365 Defender para buscar amenazas con más orígenes de datos.Turn on Microsoft 365 Defender to hunt for threats using more data sources. Puede mover los flujos de trabajo avanzados de búsqueda de Microsoft Defender para endpoint a Microsoft 365 Defender siguiendo los pasos descritos en Migrar consultas avanzadas de búsqueda desde Microsoft Defender para endpoint.You can move your advanced hunting workflows from Microsoft Defender for Endpoint to Microsoft 365 Defender by following the steps in Migrate advanced hunting queries from Microsoft Defender for Endpoint.