Examiner les journaux d'événements en pratique avec Get-WinEvent — La rapidité du filtrage détermine le temps d'investigation

· · PowerShell, Windows, Journaux d'événements, Investigation d'incidents, Amélioration opérationnelle, Systèmes d'information, Audit, Dépannage

« On dirait que le serveur a redémarré tout seul vendredi dernier au milieu de la nuit. » « Sur un poste en particulier, l’application métier plante plusieurs fois par mois. » — le point de départ de ce type d’investigation, c’est presque toujours le journal des événements Windows. Mais si vous faites défiler des centaines de milliers d’entrées dans l’interface graphique de l’Observateur d’événements, votre matinée entière y passe.

Avec Get-WinEvent en PowerShell, ce travail se termine en quelques dizaines de secondes. Mais il y a une condition : effectuer le filtrage au bon endroit. Si vous écrivez Get-WinEvent | Where-Object { ... }, tous les événements sont d’abord chargés puis écartés, ce qui peut même être plus lent que l’interface graphique.

Cet article présente la bonne façon d’utiliser le filtrage de Get-WinEvent, des recettes pour les investigations fréquentes sur le terrain (redémarrages inattendus, ouvertures de session, arrêts anormaux d’applications, arrêts de services), ainsi que la collecte depuis plusieurs machines.

Environnement de référence

Élément Contenu
Système d’exploitation ciblé Windows 10/11, Windows Server. Get-WinEvent lit l’infrastructure de journal d’événements introduite à partir de Windows Vista, et peut traiter à la fois les journaux classiques et les journaux ETW1
Version de PowerShell Utilisable aussi bien avec Windows PowerShell 5.1 qu’avec PowerShell 7 (Get-WinEvent est une applet de commande réservée à Windows ; elle n’est pas disponible avec PowerShell 7 sur Linux/macOS). Le code de cet article est écrit pour fonctionner à la fois avec 5.1 et avec 71
Droits De nombreux journaux comme System ou Application peuvent être lus par un utilisateur ordinaire, mais la lecture du journal Security nécessite des droits d’administrateur ou l’attribution de droits équivalents. Certains journaux ne peuvent pas être obtenus si vous ne l’exécutez pas en tant qu’administrateur (la procédure d’attribution des droits figure au chapitre 4(2))12
Récupération à distance Au chapitre 5, la méthode 1 (-ComputerName) ne dépend pas du traitement à distance PowerShell (WinRM). En revanche, il faut avoir autorisé l’accès distant au service de journal d’événements dans le pare-feu de la machine cible. La méthode 2 (Invoke-Command) suppose WinRM1

1. Pour commencer, la conclusion

  • Utilisez Get-WinEvent, pas Get-EventLog. Le second est réservé à Windows PowerShell et ne traite que les journaux classiques ; il n’est pas utilisable avec PowerShell 7.1
  • Effectuez le filtrage avec -FilterHashtable. Comme le filtrage a lieu côté journal d’événements, c’est d’un ou plusieurs ordres de grandeur plus rapide qu’un filtrage en aval avec Where-Object.3
  • Les clés de -FilterHashtable sont fixées d’avance : LogName, ProviderName, ID, Level, StartTime, EndTime, Keywords, Path, UserID, entre autres.3
  • Pour des conditions complexes ou un filtrage sur les données d’événement, utilisez XPath (-FilterXPath). Vous pouvez copier une expression XPath depuis les « Affichages personnalisés » de l’Observateur d’événements.1
  • Level est une valeur numérique : 1 = Critique, 2 = Erreur, 3 = Avertissement, 4 = Information, 5 = Détaillé.4
  • La lecture du journal de sécurité nécessite des droits particuliers. Exécuter en tant qu’administrateur est le plus simple, mais pour la personne chargée de l’investigation, accorder uniquement la lecture via le groupe « Event Log Readers » ou une ACL de canal respecte mieux le principe du moindre privilège.12
  • Regardez les données d’événement plutôt que la chaîne de message. En récupérant des données structurées avec ToXml(), votre script ne dépend plus de la langue du système d’exploitation.1
  • Vous pouvez aussi analyser des fichiers .evtx. En spécifiant -Path, vous pouvez examiner localement un journal collecté sur place.1
  • Pour une centralisation permanente, utilisez le Transfert d’événements Windows (WEF). Pour une investigation ponctuelle, une exécution parallèle avec Invoke-Command suffit.5

2. Les deux types de journaux et le choix de l’applet de commande

Les journaux d’événements Windows se répartissent globalement en deux familles.

Type Exemple Applet de commande utilisable
Journal classique System / Application / Security Get-EventLog (5.1 uniquement), Get-WinEvent
Journaux des applications et des services Microsoft-Windows-TaskScheduler/Operational, entre autres Get-WinEvent uniquement

C’est précisément dans cette seconde catégorie que se trouvent les informations utiles à l’investigation. L’historique d’exécution du planificateur de tâches, les journaux de blocs de script PowerShell, l’historique d’application de WindowsUpdate — la plupart des journaux décisifs pour identifier une cause se trouvent de ce côté. C’est pourquoi la bonne approche consiste à s’appuyer uniformément sur Get-WinEvent pour tout nouveau script.1

Commencez par vérifier quels journaux existent.

# Liste des journaux (par nombre d'entrées décroissant). Un journal avec RecordCount à 0 n'est pas alimenté
Get-WinEvent -ListLog * -ErrorAction SilentlyContinue |
    Where-Object RecordCount -gt 0 |
    Sort-Object RecordCount -Descending |
    Select-Object LogName, RecordCount, MaximumSizeInBytes, IsEnabled -First 20

# Rechercher les journaux d'un produit particulier
Get-WinEvent -ListLog *TaskScheduler* | Format-Table LogName, IsEnabled, RecordCount
Get-WinEvent -ListProvider *PowerShell* | Select-Object Name

3. Le filtrage : tout dépend de « où » il est fait

Comparons trois façons d’écrire qui produisent le même résultat.

# [Le pire] Charger tout puis écarter côté PowerShell
Get-WinEvent -LogName System | Where-Object { $_.Id -eq 41 }

# [Recommandé] Filtrer côté journal d'événements (FilterHashtable)
Get-WinEvent -FilterHashtable @{ LogName = 'System'; ID = 41 }

# [Condition complexe] Filtrer avec XPath
Get-WinEvent -LogName System -FilterXPath "*[System[EventID=41]]"

La première convertit d’abord en objets des centaines de milliers d’événements avant de les écarter, si bien que la majeure partie du temps d’attente est gaspillée. Les deuxième et troisième filtrent côté API du journal d’événements, de sorte que seul ce qui est nécessaire est renvoyé.3

Les clés utilisables avec -FilterHashtable sont fixées d’avance.3

Clé Ce qu’elle spécifie Exemple
LogName Nom du journal 'System', 'Microsoft-Windows-TaskScheduler/Operational'
ProviderName Source de l’événement 'Application Error', 'Service Control Manager'
ID ID d’événement (tableau possible) 41, @(1000, 1001)
Level Gravité (numérique) 2 (Erreur), @(1,2)
StartTime / EndTime Période (Get-Date).AddDays(-7)
Keywords Mots-clés (succès/échec d’audit, etc.) 9007199254740992 (audit réussi)
Path Fichier .evtx 'D:\collect\srv01_System.evtx'
UserID SID de l’utilisateur 'S-1-5-21-...'

Les valeurs numériques de Level sont les suivantes.4

Valeur (Level) Affichage en environnement japonais Affichage en environnement anglais
1 重大 Critical
2 エラー Error
3 警告 Warning
4 情報 Information
5 詳細 Verbose

Les deux colonnes de droite montrent les chaînes qui apparaissent dans la colonne « Niveau » de l’Observateur d’événements et dans la propriété LevelDisplayName des résultats de Get-WinEvent. LevelDisplayName change selon la langue d’affichage du système d’exploitation. Utilisez ce tableau de correspondance quand vous comparez visuellement une sortie, mais pour filtrer dans un script, spécifiez toujours la valeur numérique de Level (juger sur le nom affiché produit un script qui ne fonctionnera pas dans un environnement anglais).

Sous une forme pratique, cela donne ceci.

# Agréger les événements Erreur/Critique des 7 derniers jours, par source (premier geste pour cerner la situation)
$filter = @{
    LogName   = 'System', 'Application'
    Level     = 1, 2
    StartTime = (Get-Date).AddDays(-7)
}
try {
    Get-WinEvent -FilterHashtable $filter -ErrorAction Stop |
        Group-Object ProviderName, Id |
        Sort-Object Count -Descending |
        Select-Object Count, Name -First 15
}
catch {
    # Ne laisser passer silencieusement que le cas « aucun événement correspondant ». Indépendant de la locale
    # Se baser sur FullyQualifiedErrorId (la chaîne de message ne correspond pas en environnement japonais)
    if ($_.FullyQualifiedErrorId -notlike 'NoMatchingEventsFound*') { throw }
}

Comment lire le résultat. La sortie de Group-Object comporte deux colonnes : Count et Name. Comme le regroupement se fait sur plusieurs propriétés (ProviderName, Id), Name affiche source, ID d'événement séparés par une virgule (par exemple : Service Control Manager, 7034). Le tri se fait par nombre décroissant, donc le premier réflexe consiste à vérifier si une source inconnue apparaît en haut de liste et si un pic de nombre correspond à la période où l’incident s’est produit. Une fois une piste identifiée ici, approfondissez les événements individuels avec les recettes du chapitre suivant.

Lorsqu’aucun événement ne correspond, Get-WinEvent renvoie une erreur. Ne mettez pas trop facilement -ErrorAction SilentlyContinue ici. « Aucune correspondance », « pas de droits pour lire ce journal » et « la cible est inaccessible » finissent tous par produire le même « résultat vide ». C’est la pire façon dont cela puisse mal se passer dans une situation d’investigation.

La bonne approche est de capter l’erreur avec -ErrorAction Stop comme ci-dessus, et de ne l’ignorer que lorsque FullyQualifiedErrorId vaut NoMatchingEventsFound. Juger sur la chaîne de message ne fonctionne pas, car elle ne correspond pas en environnement japonais (pour l’approche de la gestion des erreurs, voir « Gestion des erreurs et conception des tentatives dans PowerShell »).

4. Recettes d’investigation fréquentes sur le terrain

(1) Redémarrages et arrêts inattendus

# 41 : redémarré sans arrêt normal (Kernel-Power)
# 6008 : arrêt inattendu (EventLog)
# 1074 : demande d'arrêt par un processus/utilisateur (qui ou quoi a provoqué l'arrêt)
# 6005/6006 : démarrage/arrêt du service de journal d'événements (= repère de démarrage/arrêt)
Get-WinEvent -FilterHashtable @{
    LogName   = 'System'
    ID        = 41, 1074, 6005, 6006, 6008
    StartTime = (Get-Date).AddDays(-30)
} | Select-Object TimeCreated, Id, ProviderName,
      @{ n = 'Message'; e = { ($_.Message -split "`r?`n")[0] } } |
    Sort-Object TimeCreated -Descending | Format-Table -AutoSize

Comment lire le résultat. La sortie comporte quatre colonnes — TimeCreated, Id, ProviderName, Message (seulement la première ligne, car c’est long) — triées de la plus récente à la plus ancienne. Ce qu’il faut regarder n’est pas tant le contenu ligne par ligne que quels ID apparaissent dans quel ordre pour chaque redémarrage. Pour un redémarrage planifié, on voit apparaître le triplet 1074 (quelqu’un l’a demandé) → 6006 (arrêt du service de journal d’événements = arrêt normal) → 6005 (démarrage = démarrage terminé).

1074 est un événement important : il révèle qui a demandé le redémarrage. Si WindowsUpdate ou le nom d’un processus particulier y apparaît, la cause est quasiment établie. Si seuls 41 et 6008 apparaissent sans 1074, suspectez un arrêt anormal dû à une coupure d’alimentation ou à un blocage.

(2) Suivi des ouvertures et fermetures de session (journal de sécurité)

# 4624 : connexion réussie / 4625 : échec de connexion / 4634 : déconnexion
# Nécessite des droits de lecture sur le journal de sécurité (exécuter en tant qu'administrateur,
# ou ajouter au préalable le compte d'exécution au groupe Event Log Readers)
Get-WinEvent -FilterHashtable @{
    LogName   = 'Security'
    ID        = 4624, 4625, 4634
    StartTime = (Get-Date).AddDays(-1)
} | ForEach-Object {
    $xml = [xml]$_.ToXml()
    $d   = @{}
    foreach ($n in $xml.Event.EventData.Data) { $d[$n.Name] = $n.'#text' }
    [pscustomobject]@{
        Heure         = $_.TimeCreated
        Type          = switch ($_.Id) { 4624 { 'Connexion réussie' } 4625 { 'Échec de connexion' } 4634 { 'Déconnexion' } }
        Utilisateur   = $d['TargetUserName']
        TypeConnexion = $d['LogonType']    # 2=interactive 3=réseau 10=RDP
        AdresseSource = $d['IpAddress']
    }
} | Where-Object Utilisateur -notlike '*$' | Format-Table -AutoSize

C’est ici l’exemple typique de l’utilisation des données d’événement. Découper Message avec une expression régulière dépend de la langue du système d’exploitation, mais comme l’EventData de ToXml() se référence par nom, le même script fonctionne aussi bien en environnement japonais qu’en environnement anglais.6

Comment lire le résultat. La sortie comporte cinq colonnes : Heure / Type / Utilisateur / TypeConnexion / AdresseSource (comme vous les construisez vous-même avec [pscustomobject], vous décidez aussi bien du nom des colonnes que de leur ordre). En ajoutant à la fin Where-Object Utilisateur -notlike '*$', vous éliminez les comptes d’ordinateur (dont le nom se termine par $), ne laissant que les comptes de personnes. Vérifiez les lignes où TypeConnexion vaut 3 (réseau) ou 10 (RDP) et dont AdresseSource affiche une adresse IP inconnue, ainsi que si le même utilisateur enchaîne plusieurs 4625 (échecs) en peu de temps.

Notez aussi que si l’audit n’est pas activé, l’événement n’est tout simplement pas enregistré. « Aucun résultat » ne signifie pas forcément « rien ne s’est produit » — cela peut vouloir dire « ce n’est pas enregistré ».

Donner « seulement la lecture » à la personne chargée de l’investigation. Il vaut mieux éviter de distribuer des droits d’administrateur juste pour permettre la lecture du journal de sécurité. En ajoutant le compte au groupe intégré Event Log Readers (SID S-1-5-32-573), il devient possible de lire le journal d’événements sans droits d’administrateur.2

# À exécuter sur l'ordinateur cible (droits d'administrateur requis).
# Le nom d'affichage des groupes intégrés peut varier selon la langue du système, donc spécifier le SID est plus sûr
Add-LocalGroupMember -SID 'S-1-5-32-573' -Member 'EXAMPLE\auditeur'

# Vérifier que l'ajout a réussi
Get-LocalGroupMember -SID 'S-1-5-32-573'

Pour le déployer sur plusieurs machines, utilisez la stratégie de groupe « Configuration ordinateur > Stratégies > Paramètres Windows > Paramètres de sécurité > Groupes restreints », ou les préférences de stratégie de groupe « Configuration ordinateur > Préférences > Paramètres du Panneau de configuration > Utilisateurs et groupes locaux », pour distribuer une configuration qui ajoute un groupe du domaine au groupe local Event Log Readers de chaque serveur.

Si vous voulez affiner encore par canal, vérifiez et modifiez les autorisations d’accès de chaque journal (SDDL) avec wevtutil.2

wevtutil gl Security                    # Afficher la configuration actuelle (channelAccess contient le SDDL)
# wevtutil sl Security /ca:<SDDL>       # Modifier. /ca « remplace » le SDDL existant

/ca remplace la valeur, il ne l’ajoute pas. Notez toujours la sortie de wevtutil gl avant de la modifier.

(3) Arrêts anormaux d’applications

# 1000 : Application Error (plantage de l'application)
# 1026 : .NET Runtime (arrêt dû à une exception managée)
# 1001 : Windows Error Reporting (informations de bucket d'incident)
Get-WinEvent -FilterHashtable @{
    LogName   = 'Application'
    ID        = 1000, 1001, 1026
    StartTime = (Get-Date).AddDays(-14)
} | Select-Object TimeCreated, Id, ProviderName, Message |
    Sort-Object TimeCreated -Descending | Format-List

1000 contient le nom du module fautif et l’offset, 1026 contient la pile d’exception .NET. Il est efficace d’identifier une piste ici avant de passer à l’analyse de vidage (« Introduction à la collecte de vidages sur incident Windows », « Lire un vidage sur incident avec WinDbg + SOS »).

(4) Arrêts et redémarrages de services

# 7034 : le service s'est arrêté de manière inattendue / 7031 : action de récupération après l'arrêt / 7045 : un nouveau service a été installé
Get-WinEvent -FilterHashtable @{
    LogName     = 'System'
    ProviderName = 'Service Control Manager'
    ID          = 7031, 7034, 7045
    StartTime   = (Get-Date).AddDays(-30)
} | Select-Object TimeCreated, Id, Message | Format-List

7045 (installation d’un nouveau service) est aussi utile pour détecter l’installation non voulue d’un logiciel. Pour la conception opérationnelle des services Windows, consultez « Créer et exploiter des services Windows ».

(5) Historique d’exécution du planificateur de tâches

Cette section utilise XPath, alors commençons par en saisir le squelette. Pour XPath dans les journaux d’événements, il n’y a en réalité que deux formes à retenir.1

Syntaxe Ce qu’elle désigne Exemple
*[System[ ... ]] Champs communs à tout événement (ID d’événement, heure, niveau, fournisseur) *[System[EventID=41]]
*[EventData[Data[@Name='NomDuChamp']='valeur']] Champs propres à cet événement (données d’événement nommées) *[EventData[Data[@Name='TaskName']='\AgrégationNocturne']]

Il suffit de relier ces deux formes avec and / or. Comme la comparaison de valeurs utilise des guillemets simples, placer l’expression dans une chaîne ici-document PowerShell (@""@) évite de se soucier de l’imbrication des guillemets (le code ci-dessous illustre cette forme).

Plutôt que de la construire vous-même, il est plus rapide et plus sûr de laisser l’Observateur d’événements l’écrire et de la copier. Spécifiez les conditions dans l’interface graphique via « Observateur d’événements > (clic droit sur le journal cible) > Filtrer le journal actuel », puis basculez vers l’onglet « XML » de la boîte de dialogue : la même requête s’affiche sous forme XML. La partie comprise entre <Select Path="..."> et </Select> est directement la chaîne à passer à -FilterXPath.1

# [À éviter] Récupérer tous les événements puis filtrer sur le message affiché (dépendant de la langue)
Get-WinEvent -FilterHashtable @{
    LogName   = 'Microsoft-Windows-TaskScheduler/Operational'
    StartTime = (Get-Date).AddDays(-3)
} -ErrorAction SilentlyContinue |
    Where-Object { $_.Message -like '*AgrégationNocturne*' }

# [Correct] Filtrer côté serveur sur le nom de la tâche (données d'événement). Rapide et indépendant de la langue
$xpath = @"
*[System[TimeCreated[timediff(@SystemTime) <= 259200000]]]
and
*[EventData[Data[@Name='TaskName']='\AgrégationNocturne']]
"@
Get-WinEvent -LogName 'Microsoft-Windows-TaskScheduler/Operational' `
             -FilterXPath $xpath -ErrorAction SilentlyContinue |
    Select-Object TimeCreated, Id, LevelDisplayName, Message | Format-List

timediff est une fonction XPath qui indique, en millisecondes, le « temps écoulé depuis maintenant » ; 259200000 correspond à 3 jours. Le nom de la tâche se spécifie avec le chemin complet au moment de l’enregistrement (\NomDeLaTâche si elle est directement sous la racine). Le Message affiché dépend de la langue configurée, et en plus le filtrage se ferait côté client ; conformément à la politique de cet article, filtrez donc sur les données d’événement.

Ce journal peut être désactivé par défaut. La méthode d’activation et le diagnostic lorsqu’une tâche ne s’exécute pas sont détaillés dans « Les tâches du planificateur de tâches ne s’exécutent pas et se terminent avec le code 0x1 ».

5. Examiner les journaux de plusieurs machines

Méthode 1 : lecture directe à distance

Get-WinEvent -ComputerName 'srv01' -FilterHashtable @{ LogName='System'; ID=41 } -MaxEvents 10

Méthode 2 : interroger en parallèle avec Invoke-Command (à privilégier lorsque le nombre de machines est élevé)

$servers = 'srv01', 'srv02', 'srv03'
Invoke-Command -ComputerName $servers -ScriptBlock {
    Get-WinEvent -FilterHashtable @{
        LogName = 'System'; Level = 1, 2; StartTime = (Get-Date).AddDays(-1)
    } -ErrorAction SilentlyContinue |
        Select-Object TimeCreated, Id, ProviderName, LevelDisplayName
} | Sort-Object PSComputerName, TimeCreated

Invoke-Command s’exécute en parallèle sur plusieurs ordinateurs (« Introduction à PowerShell Remoting (WinRM) », « Le traitement parallèle en PowerShell »).

Méthode 3 : collecter les .evtx et les analyser localement

Vous pouvez lire directement un fichier exporté sur place. C’est plus rapide que d’interroger plusieurs fois à travers le réseau, et cela laisse aussi une trace comme preuve.

# Sur place : wevtutil epl System D:\collect\srv01_System.evtx
Get-WinEvent -Path 'D:\collect\srv01_System.evtx' -FilterXPath "*[System[(Level=1 or Level=2)]]" |
    Select-Object TimeCreated, Id, ProviderName, Message

Méthode 4 : Transfert d’événements Windows (WEF) — c’est la solution pour une centralisation permanente. C’est une fonctionnalité standard qui transfère les événements de chaque poste vers un serveur de collecte, sans nécessiter l’installation d’un agent supplémentaire.5

6. Taille des journaux et durée de rétention

« Au moment de vouloir enquêter, le journal de cette période avait déjà été écrasé » est un échec extrêmement fréquent. La taille maximale par défaut est plutôt petite, et dans un environnement à forte volumétrie d’événements, elle fait un tour complet en quelques jours.

# Vérifier la configuration de taille actuelle et l'état de la rétention
Get-WinEvent -ListLog 'System', 'Application', 'Security' |
    Select-Object LogName, IsEnabled, LogMode,
        @{ n='MaxMB'; e={ [math]::Round($_.MaximumSizeInBytes / 1MB, 1) } },
        RecordCount, OldestRecordNumber

# Modifier la taille maximale (droits d'administrateur requis. Exemple : porter le journal System à 256 Mo)
wevtutil sl System /ms:268435456

Sur un serveur destiné à être investigué, ou sur un poste où un incident se produit, la pratique établie consiste à élargir d’abord la taille du journal avant d’attendre la reproduction. Pour la gestion des générations de journaux et l’archivage automatique, voir aussi « PowerShell avancé — investigation, archivage et rapport des journaux ».

7. Bonnes pratiques du terrain (tableau de décision)

Situation Choix Remarque
Nouveau script à écrire Get-WinEvent Get-EventLog est limité à 5.1 et aux journaux classiques uniquement1
Filtrer par nom de journal, ID, période -FilterHashtable Le plus rapide et le plus lisible3
Filtrer sur le contenu des données d’événement -FilterXPath / -FilterXml Peut être copié depuis un affichage personnalisé de l’Observateur d’événements1
Volume élevé, traitement lent Réduire la période, utiliser -MaxEvents Ne pas faire le filtrage côté PowerShell
Vouloir extraire des valeurs du message EventData de ToXml() Rend le script indépendant de la langue configurée1
Investigation ponctuelle sur plusieurs machines Invoke-Command S’exécute en parallèle5
Centralisation permanente Transfert d’événements Windows (WEF) Fonctionnalité standard sans agent supplémentaire5
Les journaux passés ont disparu Augmenter la taille du journal À faire avant d’attendre une reproduction

8. Conclusion

  • Standardisez-vous sur Get-WinEvent. Get-EventLog n’est pas utilisable avec PowerShell 7 et ne traite qu’un ensemble limité de journaux.
  • Effectuez le filtrage avec -FilterHashtable ou -FilterXPath. Un filtrage en aval avec Where-Object dégrade le temps d’investigation d’un ou plusieurs ordres de grandeur.
  • Pour l’investigation d’un redémarrage, regardez 1074 (qui l’a demandé) en plus de 41 et 6008. Pour les arrêts anormaux d’application, 1000, 1026 et 1001 sont le point de départ.
  • En utilisant les données d’événement de ToXml() plutôt que la chaîne de message, votre script devient indépendant de la langue configurée.
  • Pour une investigation ponctuelle sur plusieurs machines, utilisez Invoke-Command ; pour une centralisation permanente, le Transfert d’événements Windows ; et si une preuve est nécessaire, collectez le .evtx pour l’analyser localement.
  • Si le journal de la période à examiner n’existe plus, rien n’est possible. Revoir la taille des journaux est la priorité absolue dans la préparation à la réponse aux incidents.

Téléchargement du code d’exemple

Le code présenté dans cet article est distribué sous une forme directement exécutable. Il comprend l’historique des redémarrages, l’historique des connexions, les échecs de tâches et la collecte sur plusieurs machines.

Télécharger le code d’exemple (zip)

Les exemples de cet article dépendant de Windows et du locataire, ils n’ont pas été vérifiés par exécution. Une analyse syntaxique et une analyse statique avec PSScriptAnalyzer ont été effectuées sur tous les fichiers, mais vérifiez impérativement le fonctionnement sur votre propre machine de test.

# Analyse syntaxique + analyse statique (exécutable même hors Windows)
./Invoke-SampleTests.ps1

Si vous n’avez pas d’endroit où vous exercer, il n’est pas nécessaire de vous entraîner sur des journaux de production sur un poste de travail métier. Le Bac à sable Windows permet de démarrer un Windows propre en quelques minutes, qui disparaît une fois fermé (« Accélérer la validation d’applications avec Windows Sandbox »). Cependant, comme le bac à sable est un environnement fraîchement démarré, il n’accumule presque aucun journal ; pour tester des journaux qui « s’accumulent avec le temps », comme l’historique des redémarrages ou des connexions, une machine virtuelle d’évaluation est plus adaptée. Il suffit largement de commencer par exécuter les commandes du chapitre 3 sur votre propre poste pour ressentir la différence de rapidité qu’apporte le filtrage.

Les valeurs de configuration (chemins, noms de serveurs, ID de locataire, etc.) sont des exemples. Ne les exécutez pas telles quelles en production : adaptez-les à votre propre environnement.

Articles connexes

Domaines de conseil associés

合同会社小村ソフト (Komura Software LLC) prend en charge l’investigation d’incidents en environnement Windows, l’analyse de cause des redémarrages et arrêts anormaux d’applications survenant de manière intermittente, ainsi que la mise en place de mécanismes de collecte de journaux et de surveillance.

Références

  1. Microsoft Learn, Get-WinEvent. Sur la possibilité de récupérer à la fois les journaux classiques et les journaux d’événements à partir de Windows Vista, l’obtention de listes avec -ListLog / -ListProvider, le filtrage avec -FilterHashtable / -FilterXPath / -FilterXml, la lecture de journaux archivés (.evtx) avec -Path, la récupération à distance avec -ComputerName, la limitation du nombre de résultats avec -MaxEvents, le fait que la lecture du journal de sécurité nécessite des droits d’administrateur, et la possibilité d’obtenir la représentation XML de chaque événement avec la méthode ToXml().  2 3 4 5 6 7 8 9 10 11 12 13 14 15

  2. Microsoft Learn, Active Directory security groups ─ Event Log Readers. Sur le fait que les membres du groupe intégré « Event Log Readers » peuvent lire le journal d’événements de l’ordinateur local (sans que cela n’accorde de droits d’administrateur). Pour modifier les autorisations d’accès d’un canal individuel, voir aussi sl /ca (accès au canal) de wevtutil 2 3 4

  3. Microsoft Learn, Creating Get-WinEvent queries with FilterHashtable. Sur les clés spécifiables avec -FilterHashtable (LogName, ProviderName, Path, Keywords, ID, Level, StartTime, EndTime, UserID, Data, entre autres), sur le fait que le filtrage côté serveur est plus efficace qu’un filtrage avec Where-Object, et sur la façon de spécifier les valeurs de mots-clés ou de gravité.  2 3 4 5

  4. Microsoft Learn, Event Levels. Sur les valeurs standard des niveaux de gravité des événements (1 = Critical, 2 = Error, 3 = Warning, 4 = Informational, 5 = Verbose).  2

  5. Microsoft Learn, Windows Event Forwarding. Sur la possibilité de transférer des événements depuis plusieurs machines Windows vers un serveur de collecte sans installation d’agent supplémentaire, et sur la spécification des cibles de collecte via des abonnements. Ainsi que sur l’exécution parallèle sur plusieurs ordinateurs avec Invoke-Command 2 3 4

  6. Microsoft Learn, 4624(S): An account was successfully logged on. Sur les éléments contenus dans les données d’événement d’une connexion réussie (TargetUserName, LogonType, IpAddress, entre autres), la signification des valeurs de type de connexion, et le fait que l’enregistrement dépend de la configuration de la stratégie d’audit. 

Articles récents partageant les mêmes étiquettes, pour approfondir des sujets proches.

Ces pages replacent le sujet dans un contexte plus large de services et de décisions.

Cet article est directement lié aux services suivants.

Questions fréquentes

Questions souvent posées lors d’une consultation sur le sujet de cet article.

Faut-il utiliser Get-EventLog ou Get-WinEvent ?
Get-WinEvent. Get-EventLog ne fonctionne que dans Windows PowerShell 5.1 et ne peut traiter que les journaux classiques comme System, Application et Security. Les journaux situés sous « Journaux des applications et des services », ajoutés à partir de Windows Vista — par exemple des journaux détaillés comme Microsoft-Windows-TaskScheduler/Operational — ne peuvent être lus qu'avec Get-WinEvent. Comme Get-EventLog lui-même n'est pas disponible dans PowerShell 7, tout nouveau script que vous écrivez devrait s'appuyer uniformément sur Get-WinEvent.
Get-WinEvent est trop lent, ce n'est pas utilisable pour une investigation.
Il est probable que vous filtrez avec Where-Object en aval du pipeline. Avec cette façon d'écrire, tous les événements du journal sont d'abord chargés en objets dans PowerShell, puis ceux qui ne sont pas nécessaires sont écartés ensuite. Pour un journal de plusieurs centaines de milliers d'entrées, c'est irréaliste. En utilisant -FilterHashtable ou -FilterXPath, le filtrage s'effectue côté journal d'événements, et seuls les événements nécessaires sont renvoyés, ce qui accélère les choses d'un ou plusieurs ordres de grandeur. Prenez l'habitude de spécifier d'abord le nom du journal, la période et l'ID d'événement via FilterHashtable.
Lorsque j'essaie de lire le journal de sécurité, l'accès est refusé.
La lecture du journal de sécurité nécessite par défaut des droits spéciaux. Si c'est seulement pour vérifier localement, il suffit d'exécuter PowerShell « en tant qu'administrateur », mais si vous ne voulez pas donner des droits d'administrateur à la personne chargée de l'investigation, vous pouvez l'ajouter au groupe intégré « Event Log Readers » (lecteurs du journal des événements), ou n'autoriser que la lecture via les autorisations d'accès du canal (ACL). Du point de vue du moindre privilège, la seconde option est recommandée. Notez aussi qu'il se peut que le journal d'audit ne soit tout simplement pas enregistré : l'audit des ouvertures de session, par exemple, dépend de la configuration de la stratégie d'audit, donc si aucun événement n'est trouvé, vérifiez aussi si la stratégie elle-même est activée.
Je veux extraire uniquement certaines valeurs (nom d'utilisateur, nom de processus) du message d'un événement.
Plutôt que de découper la propriété Message avec une expression régulière, il est plus fiable d'utiliser Properties ou les données d'événement. Chaque événement peut obtenir sa représentation XML via la méthode ToXml(), qui contient des éléments nommés sous EventData. La chaîne de message affichée change selon la langue du système d'exploitation, mais la structure des données d'événement, elle, ne change pas, ce qui permet d'écrire un script qui fonctionne aussi bien en environnement japonais qu'en environnement anglais.
Je veux examiner ensemble les journaux d'événements de plusieurs serveurs.
Si le nombre de machines est faible, le paramètre -ComputerName de Get-WinEvent ou une exécution à distance via Invoke-Command suffit. Invoke-Command s'exécute en parallèle sur les machines indiquées, ce qui reste pratique jusqu'à une dizaine de machines. Si vous voulez centraliser cela de façon permanente, envisagez le Transfert d'événements Windows (WEF) pour les regrouper sur un serveur de collecte. Pour une investigation ponctuelle, exporter le fichier evtx sur chaque serveur puis l'analyser localement avec Get-WinEvent -Path est aussi une méthode efficace.

Profil de l’auteur

Page de présentation de l’auteur de l’article.

Go Komura

Représentant de KomuraSoft LLC

Spécialisé dans le développement de logiciels Windows, le conseil technique et l’analyse de pannes, notamment pour les systèmes existants et les incidents difficiles à reproduire.

Retour au blog