Czy kiedykolwiek zdarzyło Ci się przeszukiwać dziennik zdarzeń w poszukiwaniu kluczowych informacji? A może chciałeś znaleźć konkretny wpis związany z bezpieczeństwem lub działaniem aplikacji? Zdecydowanie nie jest to łatwe zadanie. Dlatego dziś pokażę Ci jak proces ten, można nieco przyśpieszyć, a nawet zautomatyzować. Zobaczysz, jak wykorzystać PowerShella do filtrowania dzienników zdarzeń oraz jakie metody filtrowania możemy wyróżnić.
Dlaczego PowerShell?
Zanim jednak przejdziemy do przykładów praktycznych, chciałbym przedstawić Ci kilka powodów, dla których moim zdaniem warto skorzystać z PowerShella przy pracy z dziennikiem zdarzeń.
Precyzja: Odpowiednio skonstruowane polecenie pozwoli z chirurgiczną dokładnością określić, jakie zdarzenia i z jakiego czasu chcesz wydobyć z dzienników. To oznacza, że nie musisz przeglądać setek wpisów ręcznie i spędzać godzin na znalezieniu odpowiedniego logu.
Automatyzacja: Filtrowanie i analiza logów za pomocą poleceń PowerShell pozwala zaoszczędzić czas i uniknąć monotonnych czynności. Za pomocą nieskomplikowanych poleceń możesz automatycznie filtrować konkretne informacje.
Skalowalność: Skrypty PowerShell można łatwo dostosować do różnych scenariuszy i środowisk. Bez względu na to, czy zarządzasz pojedynczym komputerem, czy całą siecią, PowerShell pomoże Ci kontrolować zdarzenia w całym środowisku.
Metody filtorwania
Wiesz już, dlaczego warto skorzystać z mocy PowerShella do pracy z dziennikiem zdarzeń. Teraz czas na konkrety. Poniżej prezentuję 4 metody filtrowania logów, które w zależności od konkretnego scenariusza mogą Ci się przydać. Wszystkie zaprezentowane metody wykonują dokładnie to samo działanie, czyli pobierają wpisy z dziennika Windows PowerShell z ostatnich 24 godzin.
Cmdlet Where-Object
Pierwszą i zarazem najprostszą w użyciu metodą jest wykorzystanie gotowego cmdletu Where-Object, który generalnie sprawdza się dość dobrze jeżeli chodzi o różnego typu filtrowanie i wybieranie konkretnych danych.
#Zapisanie do zmiennej przedziału czasowego (ostatnie 24h)
$last_24h = (Get-Date) - (New-TimeSpan -Day 1)
#Pobranie odpowiedniego dziennika zdarzeń i wyfiltrowanie wpisów, które są wcześniejsze niż 24h
Get-WinEvent -LogName 'Windows PowerShell' | Where-Object { $_.TimeCreated -ge $last_24h }
ProviderName: PowerShell
TimeCreated Id LevelDisplayName Message
----------- -- ---------------- -------
23.03.2024 10:08:11 400 Informacje Engine state is changed from None to Available. ...
23.03.2024 10:08:11 600 Informacje Provider "Variable" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "Function" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "FileSystem" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "Environment" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "Alias" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "Registry" is Started. ...
22.03.2024 21:08:35 400 Informacje Engine state is changed from None to Available. ...
22.03.2024 21:08:35 600 Informacje Provider "Variable" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "Function" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "FileSystem" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "Environment" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "Alias" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "Registry" is Started. ...
Jak widzisz w wyniku otrzymałem wylistowane zdarzenia z ostatnich 24 h z dziennika Windows PowerShell. Metoda ta jest bardzo intuicyjna i nie wymaga w zasadzie żadnej specjalistycznej wiedzy. Na całość składają się 2 polecenia. W pierwszej kolejności za pomocą Get-WinEvent listuję cały dziennik Windows PowerShell, a następnie za pomoca Where-Object wybieram tylko te zdarzenia, których czas utworzenia wpisuje się w moje założenie, czyli ostatnie 24 h.
Kolejne trzy metody są nieco bardziej złożone i polegają na użyciu specjalnych filtrów. Generalnie mówi się, że metody filtrowania są bardziej wydajne niż użycie cmdletu Where-Object, gdyż w przypadku filtrów już w czasie pobierania obiektów następuje przesiewanie danych. Z kolei Where-Object pobiera wszystkie obiekty, a dopiero później stosuje filtrowanie. Oczywiście przewaga filtrów będzie wyraźnie widoczna dopiero przy przetwarzaniu sporej liczby obiektów. Niemniej jednak warto czasem pokusić się o filtr, szczególnie jeżeli znajduje się on w skrypcie.
FilterHashTable
Pierwszy filtr to zastosowanie tablicy skrótów. W tym wypadku, zamiast korzystać z cmdletu Where-Object posłużymy się parametrem –FilterHashtable w celu wybrania zdarzeń z dzienika zdarzeń (istnieje możliwość wybrania więcej niż jednego dziennika). Tablica skrótów może zawierać jedną lub większą liczbę par klucz/wartość.
#Zapisanie do zmiennej przedziału czasowego (ostatnie 24h)
$last_24h = (Get-Date) - (New-TimeSpan -Day 1)
#Pobranie wpisów z dziennika zdarzeń Windows PowerShell zaczynając od daty 24h temu
Get-WinEvent -FilterHashtable @{LogName='Windows PowerShell'; StartTime=$last_24h}
ProviderName: PowerShell
TimeCreated Id LevelDisplayName Message
----------- -- ---------------- -------
23.03.2024 10:08:11 400 Informacje Engine state is changed from None to Available. ...
23.03.2024 10:08:11 600 Informacje Provider "Variable" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "Function" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "FileSystem" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "Environment" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "Alias" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "Registry" is Started. ...
22.03.2024 21:08:35 400 Informacje Engine state is changed from None to Available. ...
22.03.2024 21:08:35 600 Informacje Provider "Variable" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "Function" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "FileSystem" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "Environment" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "Alias" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "Registry" is Started. ...
Może się zdarzyć, że cmdlet nie będzie w stanie zinterpretować poprawnie pary klucz/wartość. W tym wypadku uzna klucz jako nazwę danych w zdarzeniach.
Poprawne wartości dla par key/value są następujące:
- LogName=<String[]>
- ProviderName=<String[]>
- Path=<String[]>
- Keywords=<Long[]>
- ID=<Int32[]>
- Level=<Int32[]>
- StartTime=<DateTime>
- EndTime=<DateTime>
- UserID=<SID>
- Data=<String[]>
- <named-data>=<String[]>
- SuppressHashFilter=<Hashtable>
FilterXPath
Z racji tego, że wpisy dziennika zdarzeń są przechowywane jako pliki XML, można użyć filtra Xpath do wykonania zapytań XML w celu filtrowania wpisów dziennika. Wyrażenie XML Path Language (Xpath) wykorzystuje notację ścieżki, podobnie jak te używane w adresach URL, do adresowania części dokumentu XML.
# Użycie parametru -FilterXPath
$XPath = '*[System[TimeCreated[timediff(@SystemTime) <= 86400000]]]'
Get-WinEvent -LogName 'Windows PowerShell' -FilterXPath $XPath
ProviderName: PowerShell
TimeCreated Id LevelDisplayName Message
----------- -- ---------------- -------
23.03.2024 10:08:11 400 Informacje Engine state is changed from None to Available. ...
23.03.2024 10:08:11 600 Informacje Provider "Variable" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "Function" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "FileSystem" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "Environment" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "Alias" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "Registry" is Started. ...
22.03.2024 21:08:35 400 Informacje Engine state is changed from None to Available. ...
22.03.2024 21:08:35 600 Informacje Provider "Variable" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "Function" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "FileSystem" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "Environment" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "Alias" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "Registry" is Started. ...
Zauważ, że w omawianym przykładzie parametr FilterXPath posłuzył jedynie do filtrowania czasu zdarzenia.
FilterXML
Ostatnim parametrem filtrowania, jaki omówiony zostanie na łamach tego artykułu, jest parametr -FilterXML. Jak sama nazwa wskazuje, parametr ten pobiera XML, który jest następnie używany do filtrowania zdarzeń. FilterXML jest nieco bardziej skomplikowany niż FilterXPath i pozwala na bardziej złożone reguły.
# Użycie parametru -FilterXML
$xmlQuery ="<QueryList>
<Query Id='0' Path='Windows PowerShell'>
<Select Path='Windows PowerShell'>*[System[TimeCreated[timediff(@SystemTime) <= 86400000]]]</Select>
</Query>
</QueryList>"
Get-WinEvent -FilterXML $xmlQuery
ProviderName: PowerShell
TimeCreated Id LevelDisplayName Message
----------- -- ---------------- -------
23.03.2024 10:08:11 400 Informacje Engine state is changed from None to Available. ...
23.03.2024 10:08:11 600 Informacje Provider "Variable" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "Function" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "FileSystem" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "Environment" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "Alias" is Started. ...
23.03.2024 10:08:11 600 Informacje Provider "Registry" is Started. ...
22.03.2024 21:08:35 400 Informacje Engine state is changed from None to Available. ...
22.03.2024 21:08:35 600 Informacje Provider "Variable" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "Function" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "FileSystem" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "Environment" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "Alias" is Started. ...
22.03.2024 21:08:35 600 Informacje Provider "Registry" is Started. ...
W tym wypadku, zamiast tworzyć jednowierszowe polecenie, w pierwszej kolejności należy utworzyć samo zapytanie XML i przypisać do zmiennej $Query. Dzięki czemu zyskujemy większą czytelność i prostotę użycia. W kolejnym kroku zmienna trafia jako wartość parametru -FilterXML cmdletu Get-WinEvent.
Praca domowa
Teraz czas na Ciebie! Wypróbuj różne filtry, zmieniaj parametry i eksperymentuj. Spróbuj filtrować inne dzienniki, takie jak Security, Application czy Setup. Poszperaj trochę w Internecie i postaraj się wyodrębnić zdarzenia związane z logowaniem użytkownika o określonej nazwie.
Podsumowanie
W dzisiejszym świecie, w którym ilość danych generowanych przez systemy informatyczne rośnie lawinowo, umiejętne filtrowanie i analiza logów staje się kluczowym elementem utrzymania bezpieczeństwa oraz efektywnego zarządzania infrastrukturą IT. W artykule przedstawiłem 4 metody filtrowania, które w zależności od konkretnego scenariusza mogą się przydać.