Zaawansowane najlepsze rozwiązania dotyczące zapytań dotyczących wyszukiwania zagrożeń
Dotyczy:
- Microsoft Defender XDR
Zastosuj te zalecenia, aby szybciej uzyskać wyniki i uniknąć przekroczenia limitu czasu podczas uruchamiania złożonych zapytań. Aby uzyskać więcej wskazówek dotyczących poprawy wydajności zapytań, przeczytaj Najlepsze rozwiązania dotyczące zapytań Kusto.
Omówienie limitów przydziału zasobów procesora CPU
W zależności od rozmiaru każda dzierżawa ma dostęp do określonej ilości zasobów procesora CPU przydzielonych do uruchamiania zaawansowanych zapytań wyszukiwania zagrożeń. Aby uzyskać szczegółowe informacje o różnych parametrach użycia, przeczytaj o zaawansowanych limitach przydziałów zagrożeń i parametrach użycia.
Po uruchomieniu zapytania można zobaczyć czas wykonywania i jego użycie zasobów (niski, średni, wysoki). Wysoka wartość wskazuje, że zapytanie zajęło więcej zasobów do uruchomienia i można je ulepszyć w celu wydajniejszego zwracania wyników.
Klienci, którzy regularnie uruchamiają wiele zapytań, powinni śledzić użycie i stosować wskazówki dotyczące optymalizacji w tym artykule, aby zminimalizować zakłócenia wynikające z przekroczenia limitów przydziału lub parametrów użycia.
Obejrzyj optymalizowanie zapytań KQL , aby zobaczyć niektóre z najpopularniejszych sposobów ulepszania zapytań.
Ogólne porady dotyczące optymalizacji
Rozmiar nowych zapytań — jeśli podejrzewasz, że zapytanie zwróci duży zestaw wyników, najpierw oceń je przy użyciu operatora count. Użyj limitu lub jego synonimu
take
, aby uniknąć dużych zestawów wyników.Zastosuj filtry wcześnie — zastosuj filtry czasu i inne filtry, aby zmniejszyć zestaw danych, zwłaszcza przed użyciem funkcji przekształcania i analizowania, takich jak podciąg(), replace(), trim(), toupper()lub parse_json(). W poniższym przykładzie funkcja analizowania extractjson() jest używana po zmniejszeniu liczby rekordów przez operatory filtrowania.
DeviceEvents | where Timestamp > ago(1d) | where ActionType == "UsbDriveMount" | where DeviceName == "user-desktop.domain.com" | extend DriveLetter = extractjson("$.DriveLetter", AdditionalFields)
Zawiera bity — aby uniknąć niepotrzebnego wyszukiwania podciągów w słowach, użyj
has
operatora zamiastcontains
. Dowiedz się więcej o operatorach ciągówWyszukiwanie w określonych kolumnach — wyszukiwanie w określonej kolumnie zamiast wykonywania wyszukiwania pełnotekstowego we wszystkich kolumnach. Nie używaj do
*
sprawdzania wszystkich kolumn.Wielkość liter dla szybkości — wyszukiwania uwzględniające wielkość liter są bardziej szczegółowe i ogólnie bardziej wydajne. Nazwy operatorów ciągów uwzględniających wielkość liter, takich jak
has_cs
icontains_cs
, zwykle kończą się ciągiem_cs
. Można również użyć operatora==
równości uwzględniania wielkości liter zamiast=~
.Analizuj, nie wyodrębniaj — jeśli to możliwe, użyj operatora analizy lub funkcji analizy, takiej jak parse_json().
matches regex
Unikaj operatora ciągu lub funkcji extract(), które używają wyrażenia regularnego. Zarezerwuj użycie wyrażenia regularnego w bardziej złożonych scenariuszach. Przeczytaj więcej na temat analizowania funkcjiNie filtruj tabel — nie filtruj kolumny obliczeniowej, jeśli możesz filtrować kolumnę tabeli.
Brak terminów trzyznakowych — unikaj porównywania lub filtrowania przy użyciu terminów z trzema znakami lub mniejszą liczbą znaków. Te terminy nie są indeksowane, a ich dopasowanie będzie wymagało większej ilości zasobów.
Selektywne projektowanie — ułatwić zrozumienie wyników przez projekcję tylko potrzebnych kolumn. Projekcja określonych kolumn przed uruchomieniem sprzężenia lub podobnych operacji również pomaga zwiększyć wydajność.
Optymalizowanie join
operatora
Operator sprzężenia scala wiersze z dwóch tabel, dopasowując wartości w określonych kolumnach. Zastosuj te wskazówki, aby zoptymalizować zapytania korzystające z tego operatora.
Mniejsza tabela po lewej stronie —
join
operator dopasowuje rekordy w tabeli po lewej stronie instrukcji join do rekordów po prawej stronie. Mając mniejszą tabelę po lewej stronie, należy dopasować mniej rekordów, co przyspieszy zapytanie.W poniższej tabeli zmniejszamy tabelę
DeviceLogonEvents
po lewej stronie, aby objąć tylko trzy określone urządzenia przed dołączeniemIdentityLogonEvents
jej do niej według identyfikatorów SID konta.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
Użyj smaku sprzężenia wewnętrznego — domyślny smak sprzężenia lub innerunique-join deduplikuje wiersze w lewej tabeli przy użyciu klucza sprzężenia przed zwróceniem wiersza dla każdego dopasowania do prawej tabeli. Jeśli tabela po lewej stronie zawiera wiele wierszy o tej samej wartości dla
join
klucza, te wiersze zostaną deduplikowane, aby pozostawić pojedynczy losowy wiersz dla każdej unikatowej wartości.To domyślne zachowanie może pominąć ważne informacje z lewej tabeli, które mogą dostarczyć przydatnych szczegółowych informacji. Na przykład poniższe zapytanie będzie zawierać tylko jedną wiadomość e-mail zawierającą określony załącznik, nawet jeśli ten sam załącznik został wysłany przy użyciu wielu wiadomości e-mail:
EmailAttachmentInfo | where Timestamp > ago(1h) | where Subject == "Document Attachment" and FileName == "Document.pdf" | join (DeviceFileEvents | where Timestamp > ago(1h)) on SHA256
Aby rozwiązać ten problem, stosujemy smak sprzężenia wewnętrznego , określając
kind=inner
, aby wyświetlić wszystkie wiersze w lewej tabeli z pasującymi wartościami po prawej stronie:EmailAttachmentInfo | where Timestamp > ago(1h) | where Subject == "Document Attachment" and FileName == "Document.pdf" | join kind=inner (DeviceFileEvents | where Timestamp > ago(1h)) on SHA256
Dołączanie rekordów z przedziału czasu — podczas badania zdarzeń zabezpieczeń analitycy poszukają powiązanych zdarzeń występujących w tym samym okresie. Zastosowanie tego samego podejścia w przypadku korzystania
join
z tej samej metody zapewnia również korzyści z wydajności dzięki zmniejszeniu liczby rekordów do sprawdzenia.Poniższe zapytanie sprawdza zdarzenia logowania w ciągu 30 minut od otrzymania złośliwego pliku:
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)
Stosowanie filtrów czasu po obu stronach — nawet jeśli nie badasz określonego przedziału czasu, zastosowanie filtrów czasu w tabelach po lewej i prawej stronie może zmniejszyć liczbę rekordów w celu sprawdzenia i zwiększenia
join
wydajności. Poniższe zapytanie dotyczyTimestamp > ago(1h)
obu tabel, dzięki czemu łączy tylko rekordy z ostatniej godziny:EmailAttachmentInfo | where Timestamp > ago(1h) | where Subject == "Document Attachment" and FileName == "Document.pdf" | join kind=inner (DeviceFileEvents | where Timestamp > ago(1h)) on SHA256
Użyj wskazówek dotyczących wydajności — użyj wskazówek z operatorem,
join
aby poinstruować zaplecze o rozłożeniu obciążenia podczas wykonywania operacji intensywnie korzystających z zasobów. Dowiedz się więcej o wskazówkach dotyczących dołączaniaNa przykład wskazówki dotyczące mieszania pomagają zwiększyć wydajność zapytań podczas łączenia tabel przy użyciu klucza o wysokiej kardynalności — klucza z wieloma unikatowymi wartościami, na przykład
AccountObjectId
w poniższym zapytaniu:IdentityInfo | where JobTitle == "CONSULTANT" | join hint.shufflekey = AccountObjectId (IdentityDirectoryEvents | where Application == "Active Directory" | where ActionType == "Private data retrieval") on AccountObjectId
Wskazówka dotycząca emisji pomaga, gdy tabela po lewej stronie jest mała (do 100 000 rekordów), a prawa tabela jest bardzo duża. Na przykład poniższe zapytanie próbuje dołączyć kilka wiadomości e-mail, które mają określone tematy ze wszystkimi wiadomościami zawierającymi linki w
EmailUrlInfo
tabeli:EmailEvents | where Subject in ("Warning: Update your credentials now", "Action required: Update your credentials now") | join hint.strategy = broadcast EmailUrlInfo on NetworkMessageId
Optymalizowanie summarize
operatora
Operator podsumowania agreguje zawartość tabeli. Zastosuj te wskazówki, aby zoptymalizować zapytania korzystające z tego operatora.
Znajdź odrębne wartości — ogólnie rzecz biorąc, użyj polecenia
summarize
, aby znaleźć różne wartości, które mogą być powtarzalne. Użycie go do agregowania kolumn, które nie mają powtarzających się wartości, może być niepotrzebne.Chociaż pojedyncza wiadomość e-mail może być częścią wielu zdarzeń, poniższy przykład nie jest efektywnym użyciem
summarize
, ponieważ identyfikator wiadomości sieciowej dla pojedynczej wiadomości e-mail zawsze zawiera unikatowy adres nadawcy.EmailEvents | where Timestamp > ago(1h) | summarize by NetworkMessageId, SenderFromAddress
Operator
summarize
można łatwo zastąpić elementemproject
, uzyskując potencjalnie te same wyniki, zużywając mniej zasobów:EmailEvents | where Timestamp > ago(1h) | project NetworkMessageId, SenderFromAddress
Poniższy przykład jest bardziej wydajnym zastosowaniem,
summarize
ponieważ może istnieć wiele różnych wystąpień adresu nadawcy wysyłającego wiadomość e-mail na ten sam adres adresata. Takie kombinacje są mniej odrębne i mogą mieć duplikaty.EmailEvents | where Timestamp > ago(1h) | summarize by SenderFromAddress, RecipientEmailAddress
Mieszanie zapytania — podczas gdy
summarize
najlepiej używać w kolumnach z powtarzającymi się wartościami, te same kolumny mogą mieć również wysoką kardynalność lub dużą liczbę unikatowych wartości.join
Podobnie jak operator, możesz również zastosować wskazówkę mieszania,summarize
aby rozłożyć obciążenie przetwarzania i potencjalnie zwiększyć wydajność podczas pracy na kolumnach o wysokiej kardynalności.Poniższe zapytanie używa
summarize
do zliczania odrębnego adresu e-mail adresata, który może być uruchamiany w setkach tysięcy w dużych organizacjach. Aby zwiększyć wydajność, obejmujehint.shufflekey
ona:EmailEvents | where Timestamp > ago(1h) | summarize hint.shufflekey = RecipientEmailAddress count() by Subject, RecipientEmailAddress
Scenariusze zapytań
Identyfikowanie unikatowych procesów przy użyciu identyfikatorów procesów
Identyfikatory procesów (PID) są poddawane recyklingowi w systemie Windows i ponownie używane w nowych procesach. Same w sobie nie mogą służyć jako unikatowe identyfikatory dla określonych procesów.
Aby uzyskać unikatowy identyfikator procesu na określonej maszynie, użyj identyfikatora procesu wraz z czasem tworzenia procesu. Podczas dołączania lub podsumowywania danych dotyczących procesów dołącz kolumny identyfikatora maszyny ( DeviceId
lub DeviceName
), identyfikator procesu (ProcessId
lub InitiatingProcessId
), a czas tworzenia procesu (ProcessCreationTime
lub InitiatingProcessCreationTime
)
Poniższe przykładowe zapytanie znajduje procesy, które uzyskują dostęp do ponad 10 adresów IP za pośrednictwem portu 445 (SMB), prawdopodobnie skanując udziały plików.
Przykładowe zapytanie:
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
Zapytanie jest podsumowywane zarówno InitiatingProcessId
przez, jak i InitiatingProcessCreationTime
w taki sposób, że analizuje jeden proces bez mieszania wielu procesów z tym samym identyfikatorem procesu.
Wiersze poleceń zapytania
Istnieje wiele sposobów konstruowania wiersza polecenia w celu wykonania zadania. Na przykład osoba atakująca może odwoływać się do pliku obrazu bez ścieżki, bez rozszerzenia pliku, przy użyciu zmiennych środowiskowych lub z cudzysłowami. Osoba atakująca może również zmienić kolejność parametrów lub dodać wiele cudzysłowów i spacji.
Aby utworzyć bardziej trwałe zapytania wokół wierszy poleceń, zastosuj następujące rozwiązania:
- Zidentyfikuj znane procesy (takie jak net.exe lub psexec.exe), dopasowując je do pól nazw plików, zamiast filtrować w samym wierszu polecenia.
- Analizowanie sekcji wiersza polecenia przy użyciu funkcji parse_command_line()
- Podczas wykonywania zapytań o argumenty wiersza polecenia nie szukaj dokładnego dopasowania dla wielu niepowiązanych argumentów w określonej kolejności. Zamiast tego użyj wyrażeń regularnych lub użyj wielu oddzielnych operatorów zawiera.
- Używanie dopasowań bez uwzględniania wielkości liter. Na przykład użyj wartości
=~
,in~
icontains
zamiast==
,in
icontains_cs
. - Aby wyeliminować techniki zaciemniania wiersza polecenia, rozważ usunięcie cudzysłowów, zastąpienie przecinków spacjami i zastąpienie wielu kolejnych spacji pojedynczym spacji. Istnieją bardziej złożone techniki zaciemniania, które wymagają innych metod, ale te poprawki mogą pomóc w rozwiązaniu typowych z nich.
W poniższych przykładach przedstawiono różne sposoby konstruowania zapytania, które szuka pliku net.exe zatrzymania usługi zapory "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"
Pozyskiwanie danych ze źródeł zewnętrznych
Aby uwzględnić długie listy lub duże tabele w zapytaniu, użyj operatora externaldata do pozyskiwania danych z określonego identyfikatora URI. Dane z plików można pobierać w formatach TXT, CSV, JSON lub innych. W poniższym przykładzie pokazano, jak można użyć obszernej listy skrótów sha-256 złośliwego oprogramowania dostarczonych przez malwareBazaar (abuse.ch) do sprawdzania załączników w wiadomościach e-mail:
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
Analizowanie ciągów
Istnieją różne funkcje, których można użyć do wydajnego obsługi ciągów, które wymagają analizowania lub konwersji.
Ciąg | Funkcja | Przykład użycia |
---|---|---|
Wiersze polecenia | parse_command_line() | Wyodrębnij polecenie i wszystkie argumenty. |
Ścieżki | parse_path() | Wyodrębnij sekcje ścieżki pliku lub folderu. |
Numery wersji | parse_version() | Zdekonstruuj numer wersji z maksymalnie czterema sekcjami i maksymalnie ośmioma znakami na sekcję. Użyj przeanalizowanych danych, aby porównać wiek wersji. |
Adresy IPv4 | parse_ipv4() | Konwertuj adres IPv4 na długą liczbę całkowitą. Aby porównać adresy IPv4 bez ich konwertowania, użyj ipv4_compare(). |
Adresy IPv6 | parse_ipv6() | Przekonwertuj adres IPv4 lub IPv6 na kanoniczną notację IPv6. Aby porównać adresy IPv6, użyj ipv6_compare(). |
Aby dowiedzieć się więcej o wszystkich obsługiwanych funkcjach analizowania, przeczytaj o funkcjach ciągu Kusto.
Uwaga
Niektóre tabele w tym artykule mogą nie być dostępne w Ochrona punktu końcowego w usłudze Microsoft Defender. Włącz Microsoft Defender XDR, aby wyszukiwać zagrożenia przy użyciu większej liczby źródeł danych. Zaawansowane przepływy pracy wyszukiwania zagrożeń można przenieść z Ochrona punktu końcowego w usłudze Microsoft Defender do Microsoft Defender XDR, wykonując kroki opisane w temacie Migrowanie zaawansowanych zapytań wyszukiwania zagrożeń z Ochrona punktu końcowego w usłudze Microsoft Defender.
Tematy pokrewne
- Dokumentacja języka zapytań Kusto
- Przydziały i parametry użycia
- Obsługa zaawansowanych błędów wyszukiwania zagrożeń
- Omówienie zaawansowanego wyszukiwania zagrożeń
- Nauka języka zapytań
Porada
Chcesz dowiedzieć się więcej? Zaangażuj się w społeczność rozwiązań zabezpieczających firmy Microsoft w naszej społeczności technicznej Społeczność techniczna usługi Microsoft Defender XDR.