Aller au contenu
09 · Sécurité de PowerShellPartie 1 sur 4Intermédiaire

Sécurité PowerShell : journalisation, v2, CLM et JEA

Rendez PowerShell transparent et borné : journalisation des blocs de script, des modules et transcription, retrait de PowerShell 2.0, CLM imposé par App Control, JEA.

Florian Amette7 min de lecture

PowerShell est la couche d'administration de Windows et l'un des outils préférés des attaquants, parce qu'il est présent partout, exécute du code en mémoire et peut atteindre presque toutes les API. Tenter de le bloquer casse généralement les outils de gestion, tandis que les attaquants motivés trouvent d'autres hôtes pour le moteur. L'approche durable est différente : rendre chaque action PowerShell visible et restreindre le langage accessible au code non approuvé.

1. Journalisation des blocs de script

La journalisation des blocs de script (script block logging) enregistre le contenu de chaque bloc de script traité par PowerShell, après désobfuscation, ce qui met en échec la plupart des charges encodées et obfusquées.

  • GPO : Computer Configuration > Administrative Templates > Windows Components > Windows PowerShell > Turn on PowerShell Script Block Logging = Enabled. Laissez Log script block invocation start / stop events décoché (très bruyant).
  • Registre : HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging EnableScriptBlockLogging = 1.
  • Événements : 4104 dans Applications and Services Logs > Microsoft > Windows > PowerShell > Operational. Les scripts longs sont répartis sur plusieurs événements 4104 reliés par un ID de bloc de script.

Même sans cette stratégie, PowerShell 5 journalise automatiquement les blocs de script qu'il juge suspects sous forme d'événements 4104 de niveau avertissement. La stratégie rend la journalisation exhaustive.

2. Journalisation des modules

La journalisation des modules (module logging) enregistre le détail de l'exécution du pipeline, y compris les valeurs des paramètres, pour les modules choisis.

  • GPO : Turn on Module Logging = Enabled, noms de modules * (tous les modules).
  • Événements : 4103 dans le même journal.

Elle recoupe la journalisation des blocs de script, mais capture des valeurs d'exécution (comme des variables développées dans une commande) que le seul texte du script ne montre pas.

3. Transcription

La transcription écrit dans des fichiers un relevé texte des entrées et sorties de chaque session, pratique pour revoir l'activité d'administration interactive.

  • GPO : Turn on PowerShell Transcription = Enabled, répertoire de sortie sur un partage réseau en écriture seule (par exemple \\logsrv\pstranscripts$), Include invocation headers coché.
  • Autorisations du partage : ordinateurs et utilisateurs peuvent créer des fichiers et écrire, mais pas lire ni lister les transcriptions des autres ; seule l'équipe sécurité peut lire.

Traitez les transcriptions et les journaux de blocs de script comme sensibles : il arrive que des administrateurs collent des mots de passe dans la console. Si ce risque est important, Protected Event Logging (Administrative Templates > Windows Components > Event Logging > Enable Protected Event Logging) chiffre le contenu du journal d'événements avec un certificat, de sorte que seul votre SIEM (détenteur de la clé privée) peut le lire.

4. Dimensionner et transférer les journaux

Le journal PowerShell Operational par défaut est petit et tourne en quelques heures sur un serveur chargé. Agrandissez-le et transférez-le :

PowerShell
wevtutil sl "Microsoft-Windows-PowerShell/Operational" /ms:268435456   # 256 MB

Transférez les 4103 et 4104 (ainsi que les 400/403 du journal classique Windows PowerShell, qui enregistrent le démarrage et l'arrêt du moteur avec la version de l'hôte) via Windows Event Forwarding ou votre agent. Voir le guide sur la stratégie d'audit et Sysmon.

5. Supprimer PowerShell 2.0

Le moteur PowerShell 2.0 est antérieur à la journalisation des blocs de script, à AMSI et au Constrained Language Mode. S'il est installé, un attaquant peut lancer powershell.exe -Version 2 et contourner tout ce qui précède. Il dépend aussi de .NET Framework 3.5, souvent présent.

PowerShell
Get-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root
Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root -NoRestart
# Windows Server
Uninstall-WindowsFeature PowerShell-V2

Microsoft a retiré PowerShell 2.0 de Windows 11 24H2 à partir des mises à jour d'août 2025 et de Windows Server 2025 à partir de septembre 2025 ; les versions et images plus anciennes l'embarquent encore. Détectez les tentatives de rétrogradation via l'événement 400 du journal Windows PowerShell dont EngineVersion vaut 2.0.

6. AMSI

L'Antimalware Scan Interface permet à PowerShell (ainsi qu'à VBScript, JScript, Office VBA et d'autres) de transmettre le contenu des scripts à l'antivirus avant exécution, là encore après désobfuscation. Elle est active par défaut avec Microsoft Defender ou tout antivirus compatible AMSI. Votre travail est de la maintenir ainsi :

  • Tenez à jour la plateforme et le moteur de Defender.
  • Alertez sur les détections mentionnant des tentatives de contournement d'AMSI et sur les événements PowerShell contenant des motifs de contournement connus (par exemple des références à AmsiUtils ou amsiInitFailed).

7. Constrained Language Mode, correctement imposé

Le Constrained Language Mode (CLM) retire les parties du langage dont dépendent les attaquants : types .NET arbitraires, Add-Type, objets COM hors liste d'autorisation et appels directs à l'API Win32. Les cmdlets de base fonctionnent toujours : la plupart des scripts d'administration qui se contentent de gérer Windows s'exécutent sans problème.

Vérifiez le mode actuel :

PowerShell
$ExecutionContext.SessionState.LanguageMode

La seule façon robuste d'imposer le CLM est le contrôle des applications. Quand une stratégie de scripts App Control for Business (WDAC) ou AppLocker est appliquée, PowerShell automatiquement :

  • exécute en Constrained Language Mode les sessions interactives et les scripts non autorisés par la stratégie ;
  • exécute en Full Language Mode les scripts autorisés par la stratégie (par exemple signés par votre certificat de signature de code interne).

On suggère parfois de fixer la variable d'environnement __PSLockdownPolicy à 4 comme raccourci. Ce n'est pas une frontière de sécurité : un utilisateur peut la supprimer. Ne l'utilisez qu'en laboratoire pour tester la compatibilité des scripts.

Signez vos scripts d'administration avec un certificat de signature de code interne pour qu'ils conservent le langage complet sous la stratégie :

PowerShell
$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1
Set-AuthenticodeSignature -FilePath .\Invoke-Maintenance.ps1 -Certificate $cert `
  -TimestampServer "http://timestamp.digicert.com"

Voir App Control ou AppLocker pour construire la stratégie elle-même.

8. Just Enough Administration (JEA)

Beaucoup de tâches du support et des opérateurs ne nécessitent pas une session d'administration complète. JEA expose un point de terminaison de communication à distance PowerShell où les utilisateurs ne peuvent exécuter que des commandes précises, sous un compte virtuel temporaire disposant des droits nécessaires, et où chaque commande est transcrite.

Exemple minimal : permettre aux opérateurs de redémarrer un service et de lire son état sur un serveur.

PowerShell
# Capacité de rôle : ce que le rôle peut faire
New-PSRoleCapabilityFile -Path "C:\Program Files\WindowsPowerShell\Modules\OpsJEA\RoleCapabilities\PrintOps.psrc" `
  -VisibleCmdlets @{ Name = 'Restart-Service'; Parameters = @{ Name = 'Name'; ValidateSet = 'Spooler' } },
                  'Get-Service'

# Configuration de session : qui obtient quel rôle, exécution sous un compte virtuel
New-PSSessionConfigurationFile -Path .\PrintOps.pssc -SessionType RestrictedRemoteServer `
  -RunAsVirtualAccount -TranscriptDirectory "C:\ProgramData\JEA\Transcripts" `
  -RoleDefinitions @{ 'CORP\Print-Operators' = @{ RoleCapabilities = 'PrintOps' } }

Register-PSSessionConfiguration -Name PrintOps -Path .\PrintOps.pssc

Les utilisateurs se connectent avec Enter-PSSession -ComputerName srv01 -ConfigurationName PrintOps et disposent exactement de ces deux commandes. Choisissez avec soin les cmdlets exposées : tout ce qui peut exécuter du code arbitraire (Invoke-Expression, Start-Process sans contraintes, Add-Type) ou écrire des fichiers dans des chemins arbitraires refait du point de terminaison un accès administrateur complet.

9. WinRM lui-même

  • N'activez l'écoute WinRM que là où elle est nécessaire et restreignez-la par pare-feu aux hôtes de gestion (guide du pare-feu).
  • Interdisez l'authentification Basic et le trafic non chiffré (Windows Components > Windows Remote Management (WinRM) > WinRM Service / Client : Allow Basic authentication = Disabled, Allow unencrypted traffic = Disabled). Ce sont les valeurs par défaut ; les référentiels les imposent pour qu'elles ne dérivent pas.
  • Désactivez Allow CredSSP authentication sauf si un flux de travail précis l'exige ; CredSSP envoie des identifiants réutilisables à l'hôte distant.

Liste de contrôle

  • Journalisation des blocs de script (4104) et des modules (4103) activée partout
  • Transcription vers un partage en écriture seule, ou Protected Event Logging là où c'est sensible
  • Journal PowerShell Operational à 256 Mo ou plus, transféré
  • PowerShell 2.0 supprimé ; alerte sur l'événement 400 avec EngineVersion 2.0
  • CLM imposé via App Control / AppLocker ; scripts d'administration signés
  • Points de terminaison JEA pour les tâches opérationnelles déléguées
  • WinRM : pas de Basic, pas de non chiffré, pas de CredSSP, restreint par pare-feu
  • Stratégies PowerShell 7 configurées si PowerShell 7 est installé

Avec tout cela en place, PowerShell reste pleinement utile aux administrateurs, tandis que le PowerShell d'un attaquant est journalisé en clair et privé des fonctionnalités dont ses outils ont besoin.

Questions fréquentes

Faut-il bloquer powershell.exe ?

En général, non. Bloquer l'exécutable casse l'administration et les agents de gestion, et les attaquants peuvent héberger le moteur PowerShell dans d'autres processus. Le journaliser en détail et imposer le Constrained Language Mode par le contrôle des applications est bien plus efficace.

La stratégie d'exécution est-elle un contrôle de sécurité ?

Non. Microsoft documente la stratégie d'exécution comme un garde-fou contre l'exécution accidentelle de scripts, pas comme une frontière de sécurité. Elle se contourne trivialement, par exemple avec -ExecutionPolicy Bypass. Utilisez-la, mais ne comptez pas dessus.

Ces paramètres s'appliquent-ils à PowerShell 7 ?

PowerShell 7 a ses propres paramètres de stratégie (dans les modèles d'administration PowerShell Core livrés avec PowerShell 7, ou dans un fichier powershell.config.json). Il peut être configuré pour utiliser les paramètres de stratégie de Windows PowerShell. Configurez les deux si PowerShell 7 est déployé.

Sécurité PowerShell : journalisation, v2, CLM et JEA

Guides associés

Sécurité de PowerShell

Just Enough Administration (JEA) pas à pas

Des points de terminaison JEA qui donnent aux opérateurs exactement les commandes utiles : capacités de rôle, configurations de session, comptes virtuels, gMSA, audit.

Avancé