Tworzenie analizatora ASIM

Ukończone

Użytkownicy zaawansowanego modelu informacji o zabezpieczeniach (ASIM) używają analizatorów ujednolicających zamiast nazw tabel w swoich zapytaniach, aby wyświetlać dane w znormalizowanym formacie i uwzględniać wszystkie dane istotne dla schematu w zapytaniu. Ujednolicanie analizatorów, z kolei, użyj analizatorów specyficznych dla źródła, aby obsłużyć konkretne szczegóły każdego źródła.

Usługa Microsoft Sentinel udostępnia wbudowane analizatory specyficzne dla źródła dla wielu źródeł danych. Możesz zmodyfikować lub opracować te analizatory specyficzne dla źródła w następujących sytuacjach:

Gdy urządzenie udostępnia zdarzenia pasujące do schematu ASIM, ale analizator specyficzny dla źródła dla urządzenia i odpowiedni schemat nie jest dostępny w usłudze Microsoft Sentinel.

Gdy analizatory specyficzne dla źródła ASIM są dostępne dla urządzenia, ale urządzenie wysyła zdarzenia w metodzie lub formacie innym niż oczekiwano przez analizatory ASIM. Na przykład:

Urządzenie źródłowe może być skonfigurowane do wysyłania zdarzeń w sposób niestandardowy.

Urządzenie może mieć inną wersję niż ta obsługiwana przez analizator ASIM.

Zdarzenia mogą być zbierane, modyfikowane i przekazywane przez system pośredniczący.

Niestandardowy proces programowania analizatora

Poniższy przepływ pracy zawiera opis kroków wysokiego poziomu podczas tworzenia niestandardowego analizatora ASIM specyficznego dla źródła:

  1. Zbierz przykładowe dzienniki.

  2. Zidentyfikuj schematy lub schematy, które reprezentują zdarzenia wysyłane ze źródła.

  3. Zamapuj pola zdarzeń źródłowych na zidentyfikowany schemat lub schematy.

  4. Utwórz co najmniej jeden analizator ASIM dla źródła. Należy opracować analizator filtrowania i analizator bez parametrów dla każdego schematu odpowiedniego dla źródła.

  5. Przetestuj analizator.

  6. Wdróż analizatory w obszarach roboczych usługi Microsoft Sentinel.

  7. Zaktualizuj odpowiedni analizator ujednolicający ASIM, aby odwoływać się do nowego analizatora niestandardowego.

  8. Możesz również współtworzyć analizatory do podstawowej dystrybucji ASIM. Współautorzy mogą być również udostępniane we wszystkich obszarach roboczych jako analizatory wbudowane.

Zbieranie przykładowych dzienników

Aby utworzyć skuteczne analizatory ASIM, potrzebny jest reprezentatywny zestaw dzienników, który w większości przypadków będzie wymagał skonfigurowania systemu źródłowego i połączenia go z usługą Microsoft Sentinel. Jeśli nie masz dostępnego urządzenia źródłowego, usługi w chmurze z płatnością zgodnie z rzeczywistym użyciem umożliwiają wdrażanie wielu urządzeń na potrzeby programowania i testowania.

Ponadto znalezienie dokumentacji dostawcy i przykładów dla dzienników może pomóc przyspieszyć opracowywanie i zmniejszyć błędy dzięki zapewnieniu szerokiego pokrycia formatu dziennika.

Reprezentatywny zestaw dzienników powinien obejmować:

  • Zdarzenia z różnymi wynikami zdarzenia.
  • Zdarzenia z różnymi akcjami odpowiedzi.
  • Różne formaty nazw użytkowników, nazw hostów i identyfikatorów oraz innych pól, które wymagają normalizacji wartości.

Mapowanie

Przed utworzeniem analizatora zamapuj informacje dostępne w zdarzeniu źródłowym lub zdarzenia na zidentyfikowany schemat:

  • Mapuj wszystkie pola obowiązkowe i najlepiej zalecane pola.
  • Spróbuj zamapować wszystkie informacje dostępne ze źródła na znormalizowane pola. Jeśli nie jest dostępny w ramach wybranego schematu, rozważ mapowanie pól dostępnych w innych schematach.
  • Mapuj wartości pól w źródle na znormalizowane wartości dozwolone przez kartę ASIM. Oryginalna wartość jest przechowywana w osobnym polu, takim jak EventOriginalResultDetails.

Opracowywanie analizatorów

Opracuj zarówno filtrowanie, jak i analizator bez parametrów dla każdego odpowiedniego schematu.

Analizator niestandardowy to zapytanie KQL opracowane na stronie Dzienniki usługi Microsoft Sentinel. Zapytanie analizatora ma trzy części:

Filtrowanie > analizowania > pól przygotowywania

Filtrowanie odpowiednich rekordów

W wielu przypadkach tabela w usłudze Microsoft Sentinel zawiera wiele typów zdarzeń. Na przykład:

  • Tabela Syslog zawiera dane z wielu źródeł.
  • Tabele niestandardowe mogą zawierać informacje z jednego źródła, które udostępnia więcej niż jeden typ zdarzenia i mogą pasować do różnych schematów.

W związku z tym analizator powinien najpierw filtrować tylko rekordy istotne dla schematu docelowego.

Filtrowanie w języku KQL odbywa się przy użyciu operatora where . Na przykład zdarzenie Sysmon 1 zgłasza tworzenie procesu i dlatego jest znormalizowane do schematu ProcessEvent . Zdarzenie Sysmon 1 jest częścią tabeli Zdarzenia , więc należy użyć następującego filtru:

Event | where Source == "Microsoft-Windows-Sysmon" and EventID == 1

Ważne

Analizator nie powinien filtrować według czasu. Zapytanie korzystające z analizatora zastosuje zakres czasu.

Filtrowanie według typu źródłowego przy użyciu listy kontrolnej

W niektórych przypadkach samo zdarzenie nie zawiera informacji, które umożliwiają filtrowanie określonych typów źródłowych.

Na przykład zdarzenia DNS systemu Infoblox są wysyłane jako komunikaty dziennika systemowego i trudno je odróżnić od komunikatów dziennika systemowego wysyłanych z innych źródeł. W takich przypadkach analizator opiera się na liście źródeł, które definiują odpowiednie zdarzenia. Ta lista jest przechowywana na liście obserwowanych ASimSourceType.

Aby użyć listy kontrolnej ASimSourceType w analizatorach:

  • Dołącz następujący wiersz na początku analizatora:
let Sources_by_SourceType=(sourcetype:string){_GetWatchlist('ASimSourceType') | where SearchKey == tostring(sourcetype) | extend Source=column_ifexists('Source','') | where isnotempty(Source)| distinct Source };
  • Dodaj filtr, który używa listy obserwowanych w sekcji filtrowania analizatora. Na przykład analizator DNS infoblox zawiera następujące elementy w sekcji filtrowania:
| where Computer in (Sources_by_SourceType('InfobloxNIOS'))

Aby użyć tego przykładu w analizatorze:

  • Zastąp wartość Computer nazwą pola zawierającego informacje o źródle. Możesz zachować to jako komputer dla dowolnych analizatorów opartych na dzienniku systemowym.

  • Zastąp token InfobloxNIOS wybraną wartością analizatora. Poinformuj użytkowników analizatora, że muszą zaktualizować listę obserwatorów ASimSourceType przy użyciu wybranej wartości oraz listę źródeł, które wysyłają zdarzenia tego typu.

Filtrowanie na podstawie parametrów analizatora

Podczas opracowywania analizatorów filtrowania upewnij się, że analizator akceptuje parametry filtrowania dla odpowiedniego schematu, zgodnie z opisem w artykule referencyjnym dla tego schematu. Użycie istniejącego analizatora jako punktu początkowego gwarantuje, że analizator zawiera prawidłowy podpis funkcji. W większości przypadków rzeczywisty kod filtrowania jest również podobny do analizatorów filtrowania dla tego samego schematu.

Podczas filtrowania upewnij się, że:

  • Filtruj przed analizowaniem przy użyciu pól fizycznych. Jeśli przefiltrowane wyniki nie są wystarczająco dokładne, powtórz test po przeanalizowaniu, aby dostosować wyniki. Aby uzyskać więcej informacji, zobacz optymalizacja filtrowania.
  • Nie filtruj, jeśli parametr nie jest zdefiniowany i nadal ma wartość domyślną.

W poniższych przykładach pokazano, jak zaimplementować filtrowanie parametru ciągu, gdzie wartość domyślna to zwykle "*" i parametr listy, gdzie wartość domyślna jest zwykle pustą listą.

srcipaddr=='*' or ClientIP==srcipaddr
array_length(domain_has_any) == 0 or Name has_any (domain_has_any)

Optymalizacja filtrowania

Aby zapewnić wydajność analizatora, zwróć uwagę na następujące zalecenia dotyczące filtrowania:

  • Zawsze filtruj na wbudowanych, a nie analizowanych polach. Chociaż czasami łatwiej jest filtrować przy użyciu analizowanych pól, ma to znaczący wpływ na wydajność.
  • Używaj operatorów zapewniających zoptymalizowaną wydajność. W szczególności ==, has i startswith. Użycie operatorów, takich jak zawiera lub pasuje do wyrażenia regularnego, również znacząco wpływa na wydajność.

Zalecenia dotyczące filtrowania pod kątem wydajności mogą nie zawsze być łatwe do naśladowania. Na przykład użycie funkcji has jest mniej dokładne niż zawiera. W innych przypadkach dopasowanie wbudowanego pola, takiego jak SyslogMessage, jest mniej dokładne niż porównywanie wyodrębnionego pola, takiego jak DvcAction. W takich przypadkach zalecamy, aby nadal wstępnie filtrować przy użyciu operatora optymalizacji wydajności w przypadku wbudowanego pola i powtarzać filtr przy użyciu bardziej dokładnych warunków po przeanalizowaniu.

Przykład można znaleźć w poniższym fragmencie analizatora DNS infoblox. Analizator najpierw sprawdza, czy pole SyslogMessage ma słowo client. Jednak termin może być używany w innym miejscu w komunikacie, więc po przeanalizowaniu pola Log_Type analizator sprawdza ponownie, że słowo client rzeczywiście wartością pola.

Syslog | where ProcessName == "named" and SyslogMessage has "client"
…
      | extend Log_Type = tostring(Parser[1]),
      | where Log_Type == "client"

Analiza

Gdy zapytanie wybierze odpowiednie rekordy, może być konieczne ich przeanalizowanie. Zazwyczaj analizowanie jest wymagane, jeśli wiele pól zdarzeń jest przekazywanych w jednym polu tekstowym.

Poniżej wymieniono operatory KQL, które wykonują analizowanie, uporządkowane według ich optymalizacji wydajności. Pierwszy zapewnia najbardziej zoptymalizowaną wydajność, a ostatni zapewnia najmniej zoptymalizowaną wydajność.

Operator opis
split Przeanalizuj ciąg rozdzielonych wartości.
parse_csv Przeanalizuj ciąg wartości sformatowanych jako wiersz CSV (wartości rozdzielane przecinkami).
analizowanie Przeanalizuj wiele wartości z dowolnego ciągu przy użyciu wzorca, który może być uproszczonym wzorcem o lepszej wydajności lub wyrażeniu regularnym.
extract_all Analizowanie pojedynczych wartości z dowolnego ciągu przy użyciu wyrażenia regularnego. extract_all ma podobną wydajność do analizy, jeśli ten ostatni używa wyrażenia regularnego.
Wyodrębnić Wyodrębnij pojedynczą wartość z dowolnego ciągu przy użyciu wyrażenia regularnego. Użycie funkcji wyodrębniania zapewnia lepszą wydajność niż analizowanie lub extract_all, jeśli potrzebna jest pojedyncza wartość. Jednak użycie wielu aktywacji wyodrębniania w tym samym ciągu źródłowym jest mniej wydajne niż pojedyncze analizowanie lub extract_all i należy unikać.
parse_json Przeanalizuj wartości w ciągu sformatowanym jako JSON. Jeśli z formatu JSON jest potrzebnych tylko kilka wartości, użycie analizy, wyodrębniania lub extract_all zapewnia lepszą wydajność.
parse_xml Przeanalizuj wartości w ciągu sformatowanym jako XML. Jeśli z kodu XML jest potrzebnych tylko kilka wartości, użycie analizy, wyodrębniania lub extract_all zapewnia lepszą wydajność.

Oprócz analizowania ciągu faza analizowania może wymagać więcej przetwarzania oryginalnych wartości, w tym:

  • Formatowanie i konwersja typów. Po wyodrębnieniu pola źródłowego może być konieczne sformatowanie w celu dopasowania do pola schematu docelowego. Na przykład może być konieczne przekonwertowanie ciągu reprezentującego datę i godzinę na pole daty/godziny. Funkcje, takie jak todatetime i tohex, są przydatne w tych przypadkach.

  • Wyszukiwanie wartości. Wartość pola źródłowego, po wyodrębnieniu, może być konieczne zamapowanie na zestaw wartości określonych dla pola schematu docelowego. Na przykład niektóre źródła zgłaszają numeryczne kody odpowiedzi DNS, podczas gdy schemat nakazuje bardziej typowe kody odpowiedzi tekstowych. Funkcjaiff i wielkość liter mogą być przydatne do mapowania kilku wartości.

    Na przykład analizator DNS firmy Microsoft przypisuje pole EventResult na podstawie identyfikatora zdarzenia i kodu odpowiedzi przy użyciu instrukcji iff w następujący sposób:

    extend EventResult = iff(EventId==257 and ResponseCode==0 ,'Success','Failure')
    

    W przypadku kilku wartości użyj elementu datatable i lookup, jak pokazano w tym samym analizatorze DNS:

    let RCodeTable = datatable(ResponseCode:int,ResponseCodeName:string) [ 0, 'NOERROR', 1, 'FORMERR'....];
    ...
     | lookup RCodeTable on ResponseCode
     | extend EventResultDetails = case (
     isnotempty(ResponseCodeName), ResponseCodeName,
     ResponseCode between (3841 .. 4095), 'Reserved for Private Use',
     'Unassigned')
    

Wartości mapowania

W wielu przypadkach oryginalna wartość wyodrębniona musi być znormalizowana. Na przykład w ASIM adres MAC używa dwukropków jako separatora, podczas gdy źródło może wysłać rozdzielany adres MAC łącznika. Podstawowy operator przekształcania wartości jest rozszerzany wraz z szerokim zestawem funkcji KQL ciągów, liczbowych i dat, jak pokazano w powyższej sekcji Analizowanie.

Instrukcje przypadków użycia, iff i lookup, gdy istnieje potrzeba mapowania zestawu wartości na wartości dozwolone przez pole docelowe.

Gdy każda wartość źródłowa jest mapowania na wartość docelową, zdefiniuj mapowanie przy użyciu operatora datatable i wyszukiwania. Na przykład

let NetworkProtocolLookup = datatable(Proto:real, NetworkProtocol:string)[
        6, 'TCP',
        17, 'UDP'
   ];
    let DnsResponseCodeLookup=datatable(DnsResponseCode:int,DnsResponseCodeName:string)[
      0,'NOERROR',
      1,'FORMERR',
      2,'SERVFAIL',
      3,'NXDOMAIN',
      ...
   ];
   ...
   | lookup DnsResponseCodeLookup on DnsResponseCode
   | lookup NetworkProtocolLookup on Proto

Zwróć uwagę, że wyszukiwanie jest przydatne i wydajne również wtedy, gdy mapowanie ma tylko dwie możliwe wartości.

Gdy warunki mapowania są bardziej złożone, należy używać funkcjiiff lub case . Funkcja iff umożliwia mapowanie dwóch wartości:

| extend EventResult = 
      iff(EventId==257 and ResponseCode==0,'Success','Failure’)

Funkcja case obsługuje więcej niż dwie wartości docelowe. W poniższym przykładzie pokazano, jak połączyć wyszukiwanie i wielkość liter. Powyższy przykład odnośnika zwraca pustą wartość w polu DnsResponseCodeName, jeśli nie znaleziono wartości odnośnika. Poniższy przykład przypadku rozszerza go przy użyciu wyniku operacji wyszukiwania , jeśli jest dostępna, i określa dodatkowe warunki w przeciwnym razie.

| extend DnsResponseCodeName = 
      case (
        DnsResponseCodeName != "", DnsResponseCodeName,
        DnsResponseCode between (3841 .. 4095), 'Reserved for Private Use',
        'Unassigned'
      )

Przygotowywanie pól w zestawie wyników

Analizator musi przygotować pola w zestawie wyników, aby upewnić się, że są używane znormalizowane pola.

Następujące operatory KQL służą do przygotowywania pól w zestawie wyników:

Operator opis Kiedy należy używać w analizatorze
zmiana nazwy projektu Zmienia nazwy pól. Jeśli pole istnieje w rzeczywistym zdarzeniu i należy zmienić jego nazwę tylko, użyj nazwy projektu. Zmienione pole nadal zachowuje się jak wbudowane pole, a operacje na polu mają znacznie lepszą wydajność.
odchodzi od projektu Usuwa pola. Użyj opcji project-away dla określonych pól, które chcesz usunąć z zestawu wyników. Zalecamy, aby nie usuwać oryginalnych pól, które nie są znormalizowane z zestawu wyników, chyba że powodują one zamieszanie lub są bardzo duże i mogą mieć wpływ na wydajność.
projekt Wybiera pola, które istniały wcześniej lub zostały utworzone w ramach instrukcji, i usuwa wszystkie inne pola. Nie zaleca się używania w analizatorze, ponieważ analizator nie powinien usuwać żadnych innych pól, które nie są znormalizowane. Jeśli musisz usunąć określone pola, takie jak wartości tymczasowe używane podczas analizowania, użyj opcji project-away, aby usunąć je z wyników.
Rozszerzanie Dodaj aliasy. Oprócz roli w generowaniu pól obliczeniowych operator rozszerzenia jest również używany do tworzenia aliasów.

Obsługa wariantów analizy

W wielu przypadkach zdarzenia w strumieniu zdarzeń obejmują warianty wymagające różnych logiki analizowania. Aby przeanalizować różne warianty w jednym analizatorze, użyj instrukcji warunkowych, takich jak iff i case, lub użyj struktury unii.

Aby użyć unii do obsługi wielu wariantów, utwórz oddzielną funkcję dla każdego wariantu i użyj instrukcji union, aby połączyć wyniki:

let AzureFirewallNetworkRuleLogs = AzureDiagnostics
    | where Category == "AzureFirewallNetworkRule"
    | where isnotempty(msg_s);
let parseLogs = AzureFirewallNetworkRuleLogs
    | where msg_s has_any("TCP", "UDP")
    | parse-where
        msg_s with           networkProtocol:string 
        " request from "     srcIpAddr:string
        ":"                  srcPortNumber:int
    …
    | project-away msg_s;
let parseLogsWithUrls = AzureFirewallNetworkRuleLogs
    | where msg_s has_all ("Url:","ThreatIntel:")
    | parse-where
        msg_s with           networkProtocol:string 
        " request from "     srcIpAddr:string
        " to "               dstIpAddr:string
    …
union parseLogs,  parseLogsWithUrls…

Aby uniknąć zduplikowanych zdarzeń i nadmiernego przetwarzania, upewnij się, że każda funkcja rozpoczyna się od filtrowania, używając pól natywnych, tylko zdarzeń, które mają być analizowane. Ponadto w razie potrzeby użyj opcji project-away w każdej gałęzi przed unią.

Wdrażanie analizatorów

Ręczne wdrażanie analizatorów przez skopiowanie ich na stronę dziennika usługi Azure Monitor i zapisanie zapytania jako funkcji. Ta metoda jest przydatna do testowania. Aby uzyskać więcej informacji, zobacz Tworzenie funkcji.

Aby wdrożyć dużą liczbę analizatorów, zalecamy użycie szablonów analizatora arm w następujący sposób:

  1. Utwórz plik YAML na podstawie odpowiedniego szablonu dla każdego schematu i dołącz do niego zapytanie. Zacznij od szablonu YAML odpowiedniego dla typu schematu i analizatora, filtrowania lub bez parametrów.

  2. Użyj konwertera szablonów ASIM Yaml do usługi ARM, aby przekonwertować plik YAML na szablon usługi ARM.

  3. W przypadku wdrażania aktualizacji usuń starsze wersje funkcji przy użyciu portalu lub narzędzia programu PowerShell do usuwania funkcji.

  4. Wdróż szablon przy użyciu witryny Azure Portal lub programu PowerShell.

Można również połączyć wiele szablonów w jeden proces wdrażania przy użyciu połączonych szablonów.