Geavanceerde best practices voor opsporingsquery's
Van toepassing op:
- Microsoft Defender XDR
Pas deze aanbevelingen toe om sneller resultaten te krijgen en time-outs te voorkomen tijdens het uitvoeren van complexe query's. Lees Best practices voor Kusto-query's voor meer hulp bij het verbeteren van queryprestaties.
Inzicht in CPU-resourcequota
Afhankelijk van de grootte heeft elke tenant toegang tot een bepaalde hoeveelheid CPU-resources die zijn toegewezen voor het uitvoeren van geavanceerde opsporingsquery's. Lees geavanceerde opsporingsquota en gebruiksparameters voor gedetailleerde informatie over verschillende gebruiksparameters.
Nadat u de query hebt uitgevoerd, ziet u de uitvoeringstijd en het resourcegebruik (Laag, Gemiddeld, Hoog). Hoog geeft aan dat de query meer resources nodig heeft om uit te voeren en kan worden verbeterd om de resultaten efficiënter te retourneren.
Klanten die regelmatig meerdere query's uitvoeren, moeten het verbruik bijhouden en de optimalisatierichtlijnen in dit artikel toepassen om onderbrekingen als gevolg van het overschrijden van quota of gebruiksparameters te minimaliseren.
Bekijk KQL-query's optimaliseren om enkele van de meest voorkomende manieren te zien om uw query's te verbeteren.
Algemene optimalisatietips
Grootte van nieuwe query's: als u vermoedt dat een query een grote resultatenset retourneert, beoordeelt u deze eerst met behulp van de operator count. Gebruik limiet of het synoniem
take
om grote resultatensets te voorkomen.Filters vroeg toepassen: pas tijdfilters en andere filters toe om de gegevensset te verminderen, met name voordat u transformatie- en parseringsfuncties gebruikt, zoals substring(), replace(), trim(), toupper() of parse_json(). In het onderstaande voorbeeld wordt de parseringsfunctie extractjson() gebruikt nadat filteroperatoren het aantal records hebben verminderd.
DeviceEvents | where Timestamp > ago(1d) | where ActionType == "UsbDriveMount" | where DeviceName == "user-desktop.domain.com" | extend DriveLetter = extractjson("$.DriveLetter", AdditionalFields)
Bevat beats: als u wilt voorkomen dat subtekenreeksen in woorden onnodig worden gezocht, gebruikt u de
has
operator in plaats vancontains
. Meer informatie over tekenreeksoperatorenZoeken in specifieke kolommen: zoek in een specifieke kolom in plaats van zoekopdrachten in volledige tekst uit te voeren in alle kolommen. Gebruik niet
*
om alle kolommen te controleren.Hoofdlettergevoelig voor snelheid: hoofdlettergevoelige zoekopdrachten zijn specifieker en presteren doorgaans beter. Namen van hoofdlettergevoelige tekenreeksoperatoren, zoals
has_cs
encontains_cs
, eindigen meestal op_cs
. U kunt ook de operator==
hoofdlettergevoelige equals gebruiken in plaats van=~
.Parseren, niet extraheren. Gebruik indien mogelijk de parseringsoperator of een parseringsfunctie zoals parse_json(). Vermijd de
matches regex
tekenreeksoperator of de functie extract(), die beide een reguliere expressie gebruiken. Reserveer het gebruik van de reguliere expressie voor complexere scenario's. Meer informatie over parseerfunctiesFiltertabellen, geen expressies: filter niet op een berekende kolom als u kunt filteren op een tabelkolom.
Geen termen van drie tekens: vermijd het vergelijken of filteren van termen met drie tekens of minder. Deze termen worden niet geïndexeerd en er zijn meer resources voor nodig.
Selectief projecteren: maak uw resultaten gemakkelijker te begrijpen door alleen de kolommen te projecteren die u nodig hebt. Het projecteren van specifieke kolommen voorafgaand aan het uitvoeren van join - of vergelijkbare bewerkingen helpt ook bij het verbeteren van de prestaties.
join
De operator optimaliseren
De join-operator voegt rijen uit twee tabellen samen door waarden in opgegeven kolommen te vergelijken. Pas deze tips toe om query's te optimaliseren die gebruikmaken van deze operator.
Kleinere tabel aan de linkerkant: de
join
operator koppelt records in de tabel aan de linkerkant van de join-instructie aan records aan de rechterkant. Door de kleinere tabel aan de linkerkant te hebben, hoeven er minder records te worden vergeleken, waardoor de query wordt versneld.In de onderstaande tabel beperken we de linkertabel
DeviceLogonEvents
tot slechts drie specifieke apparaten voordat ze worden samengevoegd metIdentityLogonEvents
per account-SID's.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
Gebruik de inner-join-smaak: de standaard join-smaak of de innerunique-join ontdubbelt rijen in de linkertabel met de joinsleutel voordat een rij wordt geretourneerd voor elke overeenkomst naar de rechtertabel. Als de linkertabel meerdere rijen bevat met dezelfde waarde voor de
join
sleutel, worden deze rijen ontdubbeld zodat er één willekeurige rij overblijft voor elke unieke waarde.Dit standaardgedrag kan belangrijke informatie uit de linkertabel weglaten die nuttig inzicht kan bieden. In de onderstaande query wordt bijvoorbeeld slechts één e-mailbericht met een bepaalde bijlage weergegeven, zelfs als dezelfde bijlage is verzonden met meerdere e-mailberichten:
EmailAttachmentInfo | where Timestamp > ago(1h) | where Subject == "Document Attachment" and FileName == "Document.pdf" | join (DeviceFileEvents | where Timestamp > ago(1h)) on SHA256
Om deze beperking aan te pakken, passen we de inner-join-smaak toe door op te geven dat alle rijen in de linkertabel worden weergegeven met overeenkomende
kind=inner
waarden aan de rechterkant:EmailAttachmentInfo | where Timestamp > ago(1h) | where Subject == "Document Attachment" and FileName == "Document.pdf" | join kind=inner (DeviceFileEvents | where Timestamp > ago(1h)) on SHA256
Records toevoegen vanuit een tijdvenster: bij het onderzoeken van beveiligingsevenementen zoeken analisten naar gerelateerde gebeurtenissen die zich rond dezelfde periode voordoen. Het toepassen van dezelfde benadering bij het gebruik
join
van ook voordelen voor de prestaties door het aantal te controleren records te verminderen.Met de onderstaande query wordt gecontroleerd op aanmeldingsevenementen binnen 30 minuten na ontvangst van een schadelijk bestand:
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)
Tijdfilters aan beide zijden toepassen: zelfs als u een bepaald tijdvenster niet onderzoekt, kan het toepassen van tijdfilters op zowel de linker- als rechtertabel het aantal records verminderen om de prestaties te controleren en te verbeteren
join
. De onderstaande query is van toepassing opTimestamp > ago(1h)
beide tabellen, zodat alleen records van het afgelopen uur worden samengevoegd:EmailAttachmentInfo | where Timestamp > ago(1h) | where Subject == "Document Attachment" and FileName == "Document.pdf" | join kind=inner (DeviceFileEvents | where Timestamp > ago(1h)) on SHA256
Hints gebruiken voor prestaties: gebruik hints met de
join
operator om de back-end te instrueren om de belasting te verdelen bij het uitvoeren van resource-intensieve bewerkingen. Meer informatie over hints voor deelnameDe hint voor willekeurige volgorde helpt bijvoorbeeld bij het verbeteren van queryprestaties bij het samenvoegen van tabellen met behulp van een sleutel met een hoge kardinaliteit, een sleutel met veel unieke waarden, zoals de
AccountObjectId
in de onderstaande query:IdentityInfo | where JobTitle == "CONSULTANT" | join hint.shufflekey = AccountObjectId (IdentityDirectoryEvents | where Application == "Active Directory" | where ActionType == "Private data retrieval") on AccountObjectId
De broadcasthint helpt wanneer de linkertabel klein is (maximaal 100.000 records) en de rechtertabel extreem groot is. De onderstaande query probeert bijvoorbeeld een paar e-mailberichten met specifieke onderwerpen samen te voegen met alle berichten die koppelingen in de
EmailUrlInfo
tabel bevatten:EmailEvents | where Subject in ("Warning: Update your credentials now", "Action required: Update your credentials now") | join hint.strategy = broadcast EmailUrlInfo on NetworkMessageId
summarize
De operator optimaliseren
De samenvattingsoperator voegt de inhoud van een tabel samen. Pas deze tips toe om query's te optimaliseren die gebruikmaken van deze operator.
Unieke waarden zoeken: gebruik in het algemeen
summarize
om unieke waarden te vinden die herhaaldelijk kunnen worden gebruikt. Het kan onnodig zijn om deze te gebruiken om kolommen te aggregeren die geen terugkerende waarden hebben.Hoewel één e-mailbericht deel kan uitmaken van meerdere gebeurtenissen, is het onderstaande voorbeeld geen efficiënt gebruik van
summarize
omdat een netwerkbericht-id voor een afzonderlijke e-mail altijd een uniek afzenderadres heeft.EmailEvents | where Timestamp > ago(1h) | summarize by NetworkMessageId, SenderFromAddress
De
summarize
operator kan eenvoudig worden vervangenproject
door , wat mogelijk dezelfde resultaten oplevert en minder resources verbruikt:EmailEvents | where Timestamp > ago(1h) | project NetworkMessageId, SenderFromAddress
Het volgende voorbeeld is een efficiënter gebruik van
summarize
, omdat er meerdere afzonderlijke exemplaren van een afzenderadres kunnen zijn dat e-mail naar hetzelfde adres van de geadresseerde verzendt. Dergelijke combinaties zijn minder verschillend en hebben waarschijnlijk dubbele waarden.EmailEvents | where Timestamp > ago(1h) | summarize by SenderFromAddress, RecipientEmailAddress
De query wijzigen: hoewel
summarize
het het beste wordt gebruikt in kolommen met terugkerende waarden, kunnen dezelfde kolommen ook een hoge kardinaliteit of grote aantallen unieke waarden hebben. Net als dejoin
operator kunt u de shuffle-hint ook toepassen omsummarize
de verwerkingsbelasting te verdelen en mogelijk de prestaties te verbeteren wanneer u werkt op kolommen met een hoge kardinaliteit.In de onderstaande query wordt gebruikgemaakt
summarize
van het tellen van het afzonderlijke e-mailadres van de geadresseerde, dat kan worden uitgevoerd in de honderdduizenden in grote organisaties. Om de prestaties te verbeteren, bevathint.shufflekey
het :EmailEvents | where Timestamp > ago(1h) | summarize hint.shufflekey = RecipientEmailAddress count() by Subject, RecipientEmailAddress
Queryscenario's
Unieke processen identificeren met proces-id's
Proces-id's (PID's) worden gerecycled in Windows en hergebruikt voor nieuwe processen. Op zichzelf kunnen ze niet fungeren als unieke id's voor specifieke processen.
Als u een unieke id voor een proces op een specifieke computer wilt ophalen, gebruikt u de proces-id samen met de aanmaaktijd van het proces. Wanneer u gegevens rond processen samenvoegt of samenvat, neemt u kolommen op voor de machine-id (of DeviceId
DeviceName
), de proces-id (ProcessId
of InitiatingProcessId
), en de aanmaaktijd van het proces (ProcessCreationTime
of InitiatingProcessCreationTime
)
Met de volgende voorbeeldquery worden processen gevonden die toegang hebben tot meer dan 10 IP-adressen via poort 445 (SMB), mogelijk scannen op bestandsshares.
Voorbeeldquery:
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
De query is een samenvatting van beide InitiatingProcessId
en InitiatingProcessCreationTime
zodat er naar één proces wordt gekeken, zonder meerdere processen met dezelfde proces-id te mengen.
Opdrachtregels opvragen
Er zijn verschillende manieren om een opdrachtregel te maken om een taak uit te voeren. Een aanvaller kan bijvoorbeeld verwijzen naar een afbeeldingsbestand zonder pad, zonder bestandsextensie, met behulp van omgevingsvariabelen of met aanhalingstekens. De aanvaller kan ook de volgorde van parameters wijzigen of meerdere aanhalingstekens en spaties toevoegen.
Als u duurzamere query's wilt maken rond opdrachtregels, past u de volgende procedures toe:
- Identificeer de bekende processen (zoals net.exe of psexec.exe) door te vergelijken op de bestandsnaamvelden, in plaats van te filteren op de opdrachtregel zelf.
- Opdrachtregelsecties parseren met de functie parse_command_line()
- Wanneer u een query uitvoert op opdrachtregelargumenten, moet u niet zoeken naar een exacte overeenkomst voor meerdere niet-gerelateerde argumenten in een bepaalde volgorde. Gebruik in plaats daarvan reguliere expressies of gebruik meerdere afzonderlijke contains-operators.
- Gebruik hoofdlettergevoelige overeenkomsten. Gebruik
=~
bijvoorbeeld ,in~
encontains
in plaats van==
,in
encontains_cs
. - Als u technieken voor het verhullen van opdrachtregels wilt beperken, kunt u aanhalingstekens verwijderen, komma's vervangen door spaties en meerdere opeenvolgende spaties vervangen door één spatie. Er zijn complexere verduisteringstechnieken waarvoor andere benaderingen nodig zijn, maar deze aanpassingen kunnen helpen bij het aanpakken van veelvoorkomende methoden.
In de volgende voorbeelden ziet u verschillende manieren om een query te maken die zoekt naar het bestand net.exe om de firewallservice 'MpsSvc' te stoppen:
// 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"
Gegevens uit externe bronnen opnemen
Als u lange lijsten of grote tabellen in uw query wilt opnemen, gebruikt u de operator externaldata om gegevens op te nemen uit een opgegeven URI. U kunt gegevens ophalen uit bestanden in TXT-, CSV-, JSON - of andere indelingen. In het onderstaande voorbeeld ziet u hoe u de uitgebreide lijst met sha-256-hashes van MalwareBazaar (abuse.ch) kunt gebruiken om bijlagen in e-mailberichten te controleren:
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
Tekenreeksen parseren
Er zijn verschillende functies die u kunt gebruiken om tekenreeksen die moeten worden geparseerd of geconverteerd efficiënt te verwerken.
Tekenreeks | Functie | Gebruiksvoorbeeld |
---|---|---|
Opdrachtregels | parse_command_line() | Pak de opdracht en alle argumenten uit. |
Paden | parse_path() | Pak de secties van een bestands- of mappad uit. |
Versienummers | parse_version() | Deconstrueer een versienummer met maximaal vier secties en maximaal acht tekens per sectie. Gebruik de geparseerde gegevens om de leeftijd van de versie te vergelijken. |
IPv4-adressen | parse_ipv4() | Converteer een IPv4-adres naar een lang geheel getal. Als u IPv4-adressen wilt vergelijken zonder ze te converteren, gebruikt u ipv4_compare(). |
IPv6-adressen | parse_ipv6() | Converteer een IPv4- of IPv6-adres naar de canonieke IPv6-notatie. Als u IPv6-adressen wilt vergelijken, gebruikt u ipv6_compare(). |
Lees meer over Kusto-tekenreeksfuncties voor meer informatie over alle ondersteunde parseringsfuncties.
Opmerking
Sommige tabellen in dit artikel zijn mogelijk niet beschikbaar in Microsoft Defender voor Eindpunt. Schakel Microsoft Defender XDR in om bedreigingen op te sporen met behulp van meer gegevensbronnen. U kunt uw geavanceerde opsporingswerkstromen van Microsoft Defender voor Eindpunt naar Microsoft Defender XDR verplaatsen door de stappen in Geavanceerde opsporingsquery's migreren van Microsoft Defender voor Eindpunt te volgen.
Verwante onderwerpen
- Documentatie voor Kusto-querytaal
- Quota en gebruiksparameters
- Geavanceerde opsporingsfouten verwerken
- Overzicht van geavanceerd opsporen
- De querytaal leren
Tip
Wil je meer weten? Engage met de Microsoft Security-community in onze Tech Community: Microsoft Defender XDR Tech Community.