Procedure consigliate per query in Ricerca avanzataAdvanced hunting query best practices

Importante

Benvenuti in Microsoft 365 Defender, il nuovo nome per Microsoft Threat Protection.Welcome to Microsoft 365 Defender, the new name for Microsoft Threat Protection. Altre informazioni su questo e altri aggiornamenti sono disponibili qui.Read more about this and other updates here. A breve aggiorneremo i nomi nei prodotti e nei documentiWe'll be updating names in products and in the docs in the near future

Si applica a:Applies to:

  • Microsoft Threat ProtectionMicrosoft Threat Protection

Applicare questi suggerimenti per ottenere risultati più velocemente ed evitare timeout durante l'esecuzione di query complesse.Apply these recommendations to get results faster and avoid timeouts while running complex queries. Per altre informazioni su come migliorare le prestazioni della query, vedere procedure consigliate per le query di Esplora dati.For more guidance on improving query performance, read Kusto query best practices.

Informazioni sulle quote delle risorse della CPUUnderstand CPU resource quotas

A seconda delle dimensioni, ogni tenant ha accesso a una quantità di risorse della CPU allocata per l'esecuzione di query di ricerca avanzate.Depending on its size, each tenant has access to a set amount of CPU resources allocated for running advanced hunting queries. Per informazioni dettagliate sui vari limiti di servizio, vedere informazioni sulle quote avanzate di caccia e sui parametri di utilizzo.For detailed information about various service limits, read about advanced hunting quotas and usage parameters.

I clienti che eseguono più query regolarmente devono tenere conto del consumo e applicare le indicazioni di ottimizzazione riportate in questo articolo per ridurre al minimo le interruzioni derivanti dal superamento delle quote o dei parametri di utilizzo.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.

Suggerimenti per l'ottimizzazione generaleGeneral optimization tips

  • Dimensione nuove query: se si ritiene che una query restituirà un set di risultati di grandi dimensioni, valutarla prima utilizzando l' operatore Count.Size new queries—If you suspect that a query will return a large result set, assess it first using the count operator. Utilizzare limit o il relativo sinonimo take per evitare set di risultati di grandi dimensioni.Use limit or its synonym take to avoid large result sets.

  • Applicare i filtri all'inizio: applicare filtri temporali e altri filtri per ridurre il set di dati, soprattutto prima di utilizzare le funzioni di trasformazione e analisi, ad esempio 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(). Nell'esempio riportato di seguito, la funzione di analisi extractjson () viene utilizzata dopo che gli operatori del filtro hanno ridotto il numero di record.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)
    
  • Contiene i battimenti: per evitare che le sottostringhe vengano cercate inutilmente nelle parole, utilizzare l' has operatore anziché contains .Has beats contains—To avoid searching substrings within words unnecessarily, use the has operator instead of contains. Informazioni sugli operatori di stringaLearn about string operators

  • Cerca in colonne specifiche: cercare in una colonna specifica invece di eseguire ricerche full-text su tutte le colonne.Look in specific columns—Look in a specific column rather than running full text searches across all columns. Non utilizzare * per controllare tutte le colonne.Don't use * to check all columns.

  • Distinzione tra maiuscolee minuscole per velocità: le ricerche con distinzione tra maiuscole e minuscole sono più specifiche e generalmente più performanti.Case-sensitive for speed—Case-sensitive searches are more specific and generally more performant. Nomi di operatori stringacon distinzione tra maiuscole e minuscole, ad esempio has_cs e contains_cs , in genere terminano con _cs .Names of case-sensitive string operators, such as has_cs and contains_cs, generally end with _cs. È inoltre possibile utilizzare l'operatore Equals con distinzione tra maiuscole e minuscole == anziché =~ .You can also use the case-sensitive equals operator == instead of =~.

  • Parse, non estrarre: quando possibile, utilizzare l' operatore parse o una funzione di analisi come parse_json ().Parse, don't extract—Whenever possible, use the parse operator or a parsing function like parse_json(). Evitare l' matches regex operatore stringa o la funzione Extract (), che utilizzano entrambe le espressioni regolari.Avoid the matches regex string operator or the extract() function, both of which use regular expression. Riservare l'utilizzo dell'espressione regolare per scenari più complessi.Reserve the use of regular expression for more complex scenarios. Altre informazioni sulle funzioni di analisiRead more about parsing functions

  • Filtro tabelle non espressioni: non filtrare su una colonna calcolata se è possibile filtrare in una colonna di tabella.Filter tables not expressions—Don't filter on a calculated column if you can filter on a table column.

  • N. tre caratteri termini: evitare il confronto o il filtraggio utilizzando termini con tre caratteri o meno.No three-character terms—Avoid comparing or filtering using terms with three characters or fewer. Questi termini non sono indicizzati e la loro corrispondenza richiederà più risorse.These terms are not indexed and matching them will require more resources.

  • Progetto in modo selettivo: rendere i risultati più facili da comprendere proiettando solo le colonne necessarie.Project selectively—Make your results easier to understand by projecting only the columns you need. La proiezione di colonne specifiche prima dell'esecuzione di join o operazioni simili consente inoltre di migliorare le prestazioni.Projecting specific columns prior to running join or similar operations also helps improve performance.

Ottimizzare l' join operatoreOptimize the join operator

L' operatore join unisce le righe di due tabelle eseguendo la corrispondenza dei valori nelle colonne specificate.The join operator merges rows from two tables by matching values in specified columns. Applicare questi suggerimenti per ottimizzare le query che utilizzano questo operatore.Apply these tips to optimize queries that use this operator.

  • Tabella più piccola a sinistra: l' join operatore corrisponde ai record nella tabella a sinistra dell'istruzione join nei record a destra.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. Se si utilizza la tabella più piccola a sinistra, sarà necessario un numero minore di record, velocizzando così la query.By having the smaller table on the left, fewer records will need to be matched, thus speeding up the query.

    Nella tabella seguente è possibile ridurre la tabella a sinistra DeviceLogonEvents per coprire solo tre dispositivi specifici prima di aggiungerli ai IdentityLogonEvents SID account.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
    
  • Utilizzare il saporedi join interno: il sapore di join predefinito o il innerunique-join deduplica le righe nella tabella sinistra per il join Key prima di restituire una riga per ogni corrispondenza alla tabella di destra.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. Se nella tabella a sinistra sono presenti più righe con lo stesso valore per la join chiave, tali righe verranno deduplicate in modo da lasciare una singola riga casuale per ogni valore univoco.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.

    Questo comportamento predefinito può lasciare invariate le informazioni importanti dalla tabella di sinistra che può fornire utili Insight.This default behavior can leave out important information from the left table that can provide useful insight. Ad esempio, la query seguente mostrerà solo un messaggio di posta elettronica contenente un allegato specifico, anche se lo stesso allegato è stato inviato utilizzando più messaggi di posta elettronica: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 
    

    Per risolvere questa limitazione, è possibile applicare il sapore del join interno specificando la kind=inner visualizzazione di tutte le righe nella tabella a sinistra con i valori corrispondenti nel lato destro: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 
    
  • Join Records from a time window: quando si esaminano gli eventi di sicurezza, gli analisti cercano gli eventi correlati che si verificano nello stesso periodo di tempo.Join records from a time window—When investigating security events, analysts look for related events that occur around the same time period. Applicare lo stesso approccio quando join si utilizzano anche le prestazioni dei vantaggi riducendo il numero di record da controllare.Applying the same approach when using join also benefits performance by reducing the number of records to check.

    La query seguente consente di controllare gli eventi di accesso entro 30 minuti dalla ricezione di un file dannoso:The query below checks for logon events within 30 minutes of receiving a malicious file:

    EmailEvents
    | where Timestamp > ago(7d)
    | where MalwareFilterVerdict == "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)
    
  • Applicare i filtri temporali su entrambi i lati, anche se non si sta indagando su una finestra temporale specifica, l'applicazione dei filtri temporali nelle tabelle Left e Right può ridurre il numero di record da controllare e migliorare le join prestazioni.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 query seguente si applica Timestamp > ago(1h) a entrambe le tabelle in modo che si unisca solo ai record dell'ultima ora: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 
    
  • Utilizzo dei suggerimenti per le prestazioni: utilizzare i suggerimenti con l' join operatore per indicare al backend di distribuire il carico quando eseguono operazioni con utilizzo intensivo delle risorse.Use hints for performance—Use hints with the join operator to instruct the backend to distribute load when running resource-intensive operations. Ulteriori informazioni sugli hint di joinLearn more about join hints

    Ad esempio, il Suggerimento shuffle consente di migliorare le prestazioni delle query quando si collegano tabelle utilizzando una chiave con una cardinalità elevata, ovvero una chiave con molti valori univoci, come AccountObjectId nella query seguente: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 
    

    Il Suggerimento per la trasmissione aiuta quando la tabella a sinistra è di dimensioni ridotte (fino a 100.000 record) e la tabella a destra è estremamente grande.The broadcast hint helps when the left table is small (up to 100,000 records) and the right table is extremely large. Ad esempio, la query seguente sta tentando di aggiungere alcuni messaggi di posta elettronica che presentano argomenti specifici con tutti i collegamenti contenuti nella EmailUrlInfo tabella: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 
    

Ottimizzare l' summarize operatoreOptimize the summarize operator

L' operatore di riepilogo aggrega il contenuto di una tabella.The summarize operator aggregates the contents of a table. Applicare questi suggerimenti per ottimizzare le query che utilizzano questo operatore.Apply these tips to optimize queries that use this operator.

  • Individuare valori distinti, in generale, summarize per individuare valori distinti che possono essere ripetitivi.Find distinct values—In general, use summarize to find distinct values that can be repetitive. Non è possibile utilizzarlo per aggregare colonne prive di valori ripetitivi.It can be unnecessary to use it to aggregate columns that don't have repetitive values.

    Anche se un singolo messaggio di posta elettronica può essere incluso in più eventi, l'esempio seguente non è un utilizzo efficace summarize perché un ID di messaggi di rete per un singolo indirizzo di posta elettronica viene sempre fornito con un mittente univoco.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   
    

    L' summarize operatore può essere facilmente sostituito con project , producendo potenzialmente gli stessi risultati, consumando meno risorse: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   
    

    Nell'esempio seguente viene utilizzato un utilizzo più efficiente summarize perché possono essere presenti più istanze distinte di un indirizzo mittente che invia messaggi di posta elettronica allo stesso indirizzo del 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. Tali combinazioni sono meno distinte e probabilmente sono duplicate.Such combinations are less distinct and are likely to have duplicates.

    EmailEvents  
    | where Timestamp > ago(1h)
    | summarize by SenderFromAddress, RecipientEmailAddress   
    
  • Shuffle la query, mentre summarize è meglio utilizzata nelle colonne con valori ripetitivi, le stesse colonne possono anche avere una cardinalità elevata o un numero elevato di valori univoci.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. Analogamente all' join operatore, è anche possibile applicare l' hint shuffle summarize a per distribuire il carico di elaborazione e potenzialmente migliorare le prestazioni quando si opera su colonne con alta cardinalità.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 query che segue utilizza summarize per contare l'indirizzo di posta elettronica del destinatario distinto, che può essere eseguito in centinaia di migliaia di organizzazioni di grandi dimensioni.The query below uses summarize to count distinct recipient email address, which can run in the hundreds of thousands in large organizations. Per migliorare le prestazioni, include hint.shufflekey :To improve performance, it incorporates hint.shufflekey:

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

Scenari di queryQuery scenarios

Identificare i processi univoci con gli ID processoIdentify unique processes with process IDs

Gli ID processo (PID) sono riciclati in Windows e riutilizzati per i nuovi processi.Process IDs (PIDs) are recycled in Windows and reused for new processes. Di per sé, non possono servire come identificatori univoci per processi specifici.On their own, they can't serve as unique identifiers for specific processes.

Per ottenere un identificatore univoco per un computer specifico, usare l'ID processo insieme all'ora di creazione del processo.To get a unique identifier for a process on a specific machine, use the process ID together with the process creation time. Quando si uniscono o si riepilogano i dati relativi a processi, includere le colonne per l'identificatore del computer (DeviceId o DeviceName), l'ID processo (ProcessId o InitiatingProcessId) e l'ora di creazione del processo (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)

La seguente query di esempio trova i processi che accedono a più di 10 indirizzi IP dalla porta 445 (SMB), possibilmente analizzando le condivisioni file.The following example query finds processes that access more than 10 IP addresses over port 445 (SMB), possibly scanning for file shares.

Query di esempio: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 query riepiloga sia InitiatingProcessId che InitiatingProcessCreationTime in modo da visualizzare un singolo processo, senza combinare più processi con lo stesso ID processo.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.

Righe di comando di queryQuery command lines

Esistono diversi modi per creare una riga di comando per eseguire un'attività.There are numerous ways to construct a command line to accomplish a task. Ad esempio, un utente malintenzionato può fare riferimento a un file di immagine senza un percorso, senza un'estensione di file, utilizzando variabili di ambiente o con virgolette.For example, an attacker could reference an image file without a path, without a file extension, using environment variables, or with quotes. L'utente malintenzionato può anche modificare l'ordine dei parametri o aggiungere più virgolette e spazi.The attacker could also change the order of parameters or add multiple quotes and spaces.

Per creare query più durevoli sulle righe di comando, applicare le procedure seguenti:To create more durable queries around command lines, apply the following practices:

  • Identificare i processi noti, ad esempio net.exe o psexec.exe, in base ai campi del nome di file anziché filtrare nella riga di comando stessa.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.
  • Analizzare le sezioni della riga di comando utilizzando la funzione parse_command_line ()Parse command-line sections using the parse_command_line() function
  • Quando si eseguono query per gli argomenti della riga di comando, non cercare una corrispondenza esatta su più argomenti non correlati in un determinato ordine.When querying for command-line arguments, don't look for an exact match on multiple unrelated arguments in a certain order. Usare invece espressioni regolari o utilizzare più operatori distinti.Instead, use regular expressions or use multiple separate contains operators.
  • Usare corrispondenza maiuscole/minuscole.Use case insensitive matches. Ad esempio, utilizzare =~ , in~ e contains invece di == , in e contains_cs .For example, use =~, in~, and contains instead of ==, in, and contains_cs.
  • Per attenuare le tecniche di offuscamento della riga di comando, valutare la possibilità di rimuovere le virgolette, sostituire le virgole con spazi e sostituire più spazi consecutivi con un singolo spazio.To mitigate command-line obfuscation techniques, consider removing quotes, replacing commas with spaces, and replacing multiple consecutive spaces with a single space. Sono disponibili tecniche di offuscamento più complesse che richiedono altri approcci, ma queste modifiche possono essere utili per l'indirizzamento di quelle comuni.There are more complex obfuscation techniques that require other approaches, but these tweaks can help address common ones.

Negli esempi seguenti vengono illustrati diversi modi per creare una query che cerca il file net.exe per arrestare il servizio 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" 

Ingestione dei dati da origini esterneIngest data from external sources

Per incorporare elenchi lunghi o tabelle di grandi dimensioni nella query, utilizzare l' operatore externaldata per ingerire dati da un URI specificato.To incorporate long lists or large tables into your query, use the externaldata operator to ingest data from a specified URI. È possibile ottenere dati da file in formato TXT, CSV, JSON o in altri formati.You can get data from files in TXT, CSV, JSON, or other formats. Nell'esempio seguente viene illustrato come utilizzare l'elenco completo degli hash SHA-256 di malware forniti da MalwareBazaar (abuse.ch) per controllare gli allegati nei messaggi di posta elettronica: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,MalwareFilterVerdict,MalwareDetectionMethod

Stringhe di analisiParse strings

Esistono diverse funzioni che è possibile utilizzare per gestire in modo efficiente le stringhe che richiedono l'analisi o la conversione.There are various functions you can use to efficiently handle strings that need parsing or conversion.

StringaString FunzioneFunction Esempio di utilizzoUsage example
Riga di comandoCommand-lines parse_command_line ()parse_command_line() Estrarre il comando e tutti gli argomenti.Extract the command and all arguments.
PercorsiPaths parse_path ()parse_path() Estrarre le sezioni di un percorso di file o cartella.Extract the sections of a file or folder path.
Numeri di versioneVersion numbers parse_version ()parse_version() Deconstruct un numero di versione con un massimo di quattro sezioni e fino a otto caratteri per sezione.Deconstruct a version number with up to four sections and up to eight characters per section. Utilizzare i dati analizzati per confrontare la versione di Age.Use the parsed data to compare version age.
Indirizzi IPv4IPv4 addresses parse_ipv4 ()parse_ipv4() Convertire un indirizzo IPv4 in un numero intero lungo.Convert an IPv4 address to a long integer. Per confrontare gli indirizzi IPv4 senza convertirli, utilizzare ipv4_compare ().To compare IPv4 addresses without converting them, use ipv4_compare().
Indirizzi IPv6IPv6 addresses parse_ipv6 ()parse_ipv6() Convertire un indirizzo IPv4 o IPv6 nella notazione IPv6 canonica.Convert an IPv4 or IPv6 address to the canonical IPv6 notation. Per confrontare gli indirizzi IPv6, utilizzare ipv6_compare ().To compare IPv6 addresses, use ipv6_compare().

Per informazioni su tutte le funzioni di analisi supportate, vedere informazioni sulle funzioni di stringa di Kusto.To learn about all supported parsing functions, read about Kusto string functions.