E-NO
Sécurité PowerShell 10 min de lecture

Renforcement de la sécurité PowerShell avec exemples pratiques : guide d'implémentation

calendar_today Publié : 2026-08-16
update Dernière mise à jour : 2026-08-16
analytics Efficacité SEO : 97%
Illustration du guide technique pour « Renforcement de la sécurité PowerShell avec exemples pratiques : guide d'implémentation ».

PowerShell occupe une place centrale dans l'automatisation Windows, ce qui le rend à la fois indispensable et à fort impact en cas de mauvaise utilisation. Renforcer PowerShell ne consiste pas à bloquer les administrateurs, mais à rendre le travail légitime observable, à réduire la surface d'attaque et à garantir que les actions risquées nécessitent une intention explicite. Ce guide praticien vous accompagne sur une voie sûre et réversible pour durcir PowerShell dans de vrais environnements. Vous ferez l'inventaire des versions et de l'exposition, définirez une politique d'exécution adaptée à votre stade, signerez les scripts avec un certificat local de signature de code, activerez une journalisation exploitable, verrouillerez l'emplacement des scripts et les droits d'écriture, utiliserez la communication à distance via HTTPS et la restreindrez, appliquerez l'administration juste nécessaire (JEA) pour limiter le rayon d'action, gérerez les secrets sans texte en clair, et vérifierez les résultats, diagnostiquerez les problèmes et annulerez proprement si nécessaire. Limitez ce travail à un projet pilote d'abord (par exemple, un poste d'administration et un serveur hors production). Étendez uniquement après avoir validé les résultats de bout en bout.

Inventaire des versions et de l'environnement

Avant de modifier quoi que ce soit, capturez l'état actuel. Exécutez les commandes suivantes sur chaque système pilote et conservez la sortie dans une note versionnée ou un ticket.

  • Versions de PowerShell et mode de langage :
  • $PSVersionTable
  • $ExecutionContext.SessionState.LanguageMode
  • Version du système d'exploitation :
  • (Get-ComputerInfo).OsName, (Get-ComputerInfo).OsVersion
  • Priorité des politiques d'exécution :
  • Get-ExecutionPolicy -List
  • Écouteurs de communication à distance existants :
  • Test-WSMan (HTTP)
  • Test-WSMan -UseSSL (HTTPS)
  • Répertoires de scripts et leurs ACL :
  • Get-Acl C:\Ops\Scripts | Format-List
  • Modules installés interagissant avec les secrets :
  • Get-Module -ListAvailable Microsoft.PowerShell.Secret*

Une fiche de capture concise aide les opérations à comparer les états avant/après :

ÉlémentCommande exempleSortie pilote attendue
Version PowerShell$PSVersionTable.PSVersion5.1.x ou 7.x.x
Mode de langage$ExecutionContext.SessionState.LanguageModeFullLanguage
Politique d'exécutionGet-ExecutionPolicy -ListMachinePolicy/AllSigned ou RemoteSigned selon l'étendue
WinRM HTTPSTest-WSMan -UseSSLRéussit sur les hôtes cibles uniquement
ACL chemin scriptsGet-Acl C:\Ops\ScriptsÉcriture restreinte aux administrateurs

Chemin de configuration sécurisé

Implémentez les contrôles dans l'ordre ci-dessous. Après chaque étape, vérifiez et capturez l'état. Appliquez d'abord à un petit pilote.

1) Choisir une politique d'exécution pratique

Pour les pilotes, utilisez RemoteSigned pour bloquer les scripts non signés téléchargés d'Internet tout en autorisant les scripts locaux. Pour des environnements plus stricts, AllSigned exige que chaque script et module soit signé.

# RemoteSigned pour les pilotes
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine -Force

# Ou, plus strict : AllSigned
# Set-ExecutionPolicy -ExecutionPolicy AllSigned -Scope LocalMachine -Force

# Vérifier que la session courante correspond à la politique voulue
Get-ExecutionPolicy -List

Notes :

  • La stratégie de groupe (GPO) prend le pas (MachinePolicy/UserPolicy). Si définie par GPO, ajustez-la là.
  • La politique d'exécution n'est pas une frontière de sécurité ; elle fait partie de la défense en profondeur.

2) Créer un certificat local de signature de code et signer les scripts

Signez vos scripts de production pour que les modifications soient intentionnelles et traçables.

# Créer un certificat auto-signé de signature de code dans le magasin CurrentUser
$cert = New-SelfSignedCertificate -Type CodeSigningCert -Subject "CN=Local Code Signing" -CertStoreLocation Cert:\CurrentUser\My

# Faire confiance au certificat pour cet utilisateur (portée pilote). Pour une portée plus large, importer dans le magasin TrustedPublisher de la machine.
Export-Certificate -Cert $cert -FilePath "$env:TEMP\codesign.cer" | Out-Null
Import-Certificate -FilePath "$env:TEMP\codesign.cer" -CertStoreLocation Cert:\CurrentUser\TrustedPublisher | Out-Null

# Signer un script
Set-AuthenticodeSignature -FilePath .\Maintenance.ps1 -Certificate $cert | Format-List Status, StatusMessage, SignerCertificate

# Vérifier le statut de la signature
Get-AuthenticodeSignature .\Maintenance.ps1 | Format-List Status, IsOSBinary, SignerCertificate

Résultats attendus :

  • Le statut doit être Valid.
  • Si AllSigned est activé, les scripts non signés échouent avec une erreur claire.

Gardez la clé privée en sécurité. Pour les certificats auto-signés sans horodatage, les scripts doivent être re-signés avant l'expiration du certificat.

3) Activer la journalisation PowerShell exploitable

Activez la transcription, la journalisation des blocs de script et (optionnellement) la journalisation des modules. Appliquez via le registre sur les pilotes ; migrez vers GPO pour l'échelle.

# Transcription
New-Item -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription' -Force | Out-Null
New-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription' -Name EnableTranscripting -PropertyType DWord -Value 1 -Force | Out-Null
New-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription' -Name IncludeInvocationHeader -PropertyType DWord -Value 1 -Force | Out-Null
New-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription' -Name OutputDirectory -PropertyType String -Value 'C:\PowerShellTranscripts' -Force | Out-Null

# Journalisation des blocs de script
New-Item -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging' -Force | Out-Null
New-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging' -Name EnableScriptBlockLogging -PropertyType DWord -Value 1 -Force | Out-Null

# Optionnel : Journalisation des modules pour modules spécifiques
New-Item -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging' -Force | Out-Null
New-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging' -Name EnableModuleLogging -PropertyType DWord -Value 1 -Force | Out-Null
New-Item -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging\ModuleNames' -Force | Out-Null
New-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging\ModuleNames' -Name '*' -PropertyType String -Value '*' -Force | Out-Null

# S'assurer que le chemin de transcription existe et est protégé
New-Item -ItemType Directory -Path 'C:\PowerShellTranscripts' -Force | Out-Null
icacls C:\PowerShellTranscripts /inheritance:r /grant:r Administrators:(OI)(CI)(F) System:(OI)(CI)(F) /deny Users:(OI)(CI)(W)

Résultats attendus :

  • Transcriptions sous C:\PowerShellTranscripts avec fichiers horodatés.
  • L'Observateur d'événements affiche les événements de blocs de script dans Microsoft-Windows-PowerShell/Operational (ID souvent 4104).

4) Verrouiller l'emplacement des scripts

Stockez les scripts dans un dossier contrôlé et restreignez l'accès en écriture.

New-Item -ItemType Directory -Path 'C:\Ops\Scripts' -Force | Out-Null
icacls C:\Ops\Scripts /inheritance:r /grant:r Administrators:(OI)(CI)(M) System:(OI)(CI)(F) /grant:r Users:(OI)(CI)(RX)

# Confirmer les ACL
Get-Acl C:\Ops\Scripts | Format-List

Résultats attendus :

  • Seuls les administrateurs peuvent modifier.
  • Les utilisateurs non-admin peuvent seulement lire et exécuter.

5) Configurer la communication à distance PowerShell via HTTPS et la restreindre

Si vous utilisez la communication à distance, privilégiez HTTPS sur le port 5986 et limitez qui peut se connecter et d'où.

# Créer un certificat machine pour WinRM HTTPS
$cert = New-SelfSignedCertificate -DnsName $(hostname) -CertStoreLocation Cert:\LocalMachine\My -FriendlyName 'WinRM HTTPS'

# Supprimer l'écouteur HTTP (si présent)
Get-ChildItem WSMan:\Localhost\Listener | Where-Object { $_.Keys -match 'Transport=HTTP' } | ForEach-Object { Remove-Item $_.PSPath -Recurse -Force }

# Créer l'écouteur HTTPS
New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $cert.Thumbprint -Force | Out-Null

# Ouvrir le pare-feu seulement vers un sous-réseau de gestion (exemple 10.0.0.0/24)
New-NetFirewallRule -DisplayName 'WinRM HTTPS Inbound 5986 (Mgmt Subnet)' -Direction Inbound -Action Allow -Protocol TCP -LocalPort 5986 -RemoteAddress 10.0.0.0/24

# Tester localement
Test-WSMan -UseSSL

Résultats attendus :

  • Test-WSMan -UseSSL réussit.
  • La communication à distance HTTP sur 5985 n'est pas disponible.
  • L'accès distant n'est autorisé que depuis les sous-réseaux spécifiés.

6) Appliquer l'administration juste nécessaire (JEA)

Limitez ce que les utilisateurs distants peuvent faire en n'exposant que les commandes dont ils ont besoin.

# Créer un fichier de configuration de session JEA autorisant un ensemble minimal de cmdlets
$jeaConfig = @{
    SessionType = 'RestrictedRemoteServer'
    TranscriptDirectory = 'C:\PowerShellTranscripts'
    RunAsVirtualAccount = $true
    VisibleCmdlets = @(
        'Get-Service',
        @{ Name = 'Restart-Service'; Parameters = @{ Name = 'Name'; ValidateSet = 'Spooler','W32Time' } },
        'Get-EventLog'
    )
}
New-PSSessionConfigurationFile -Path .\JEA-Maint.pssc @jeaConfig

# Enregistrer la configuration
Register-PSSessionConfiguration -Name 'JEA_Maint' -Path .\JEA-Maint.pssc -Force

# Vérifier que la configuration est active
Get-PSSessionConfiguration -Name 'JEA_Maint' | Format-List Name, Permission

Résultats attendus :

  • L'entrée dans une session avec Enter-PSSession -ComputerName <hôte> -ConfigurationName JEA_Maint -UseSSL fournit un ensemble restreint de commandes.
  • Les commandes non autorisées échouent avec une erreur claire.

7) Gérer les secrets de manière sûre

Évitez le texte en clair. Utilisez SecretManagement avec SecretStore pour le développement local et les opérations.

# Installer une fois par machine (nécessite admin pour l'étendue système)
Install-Module Microsoft.PowerShell.SecretManagement, Microsoft.PowerShell.SecretStore -Scope CurrentUser -Force

# Enregistrer un coffre local
Register-SecretVault -Name 'LocalStore' -ModuleName Microsoft.PowerShell.SecretStore -DefaultVault

# Initialiser le coffre (demande de définir un mot de passe)
Set-Secret -Name 'TestSecret' -Secret (ConvertTo-SecureString 'example-value' -AsPlainText -Force)

# Récupérer de manière sécurisée
$secret = Get-Secret -Name 'TestSecret'
$plain = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($secret))

# Nettoyer rapidement le texte en clair sensible
$plain = $null; [GC]::Collect(); [GC]::WaitForPendingFinalizers()

Résultats attendus :

  • Get-Secret retourne un SecureString ou un secret typé.
  • Le matériel secret n'est pas stocké dans les fichiers de scripts ou les variables d'environnement.

Vérification et diagnostics

Après chaque contrôle, testez le comportement prévu et observez les journaux.

  1. Politique d'exécution et signature
  • Essayez d'exécuter un script non signé depuis votre dossier contrôlé.
  • Attendu : RemoteSigned bloque les scripts avec la marque Internet Mark of the Web ; AllSigned bloque tous les scripts non signés.
  • Vérifiez :
  • Get-ExecutionPolicy -List
  • Get-AuthenticodeSignature .\Maintenance.ps1
  1. Journalisation
  • Exécutez quelques commandes, puis vérifiez :
  • Transcriptions : dir C:\PowerShellTranscripts
  • Journal d'événements : Observateur d'événements -> Journaux des applications et services -> Microsoft -> Windows -> PowerShell -> Operational
  • Recherchez les ID d'événements tels que 4103 (journalisation des modules) et 4104 (journalisation des blocs de script).
  1. Contrôle d'accès sur les scripts
  • En tant qu'utilisateur non-admin, tentez de créer un fichier sous C:\Ops\Scripts.
  • Attendu : Accès refusé.
  • Vérifiez les ACL : Get-Acl C:\Ops\Scripts | Format-List
  1. Communication à distance via HTTPS
  • Depuis un hôte autorisé : Test-WSMan <serveur> -UseSSL -> succès.
  • Depuis un hôte non autorisé : Test-WSMan <serveur> -UseSSL -> échec.
  • Confirmez l'écouteur : Get-ChildItem WSMan:\LocalHost\Listener
  1. Point de terminaison JEA
  • Entrez dans la session JEA et listez les commandes :
  • Enter-PSSession -ComputerName <serveur> -ConfigurationName JEA_Maint -UseSSL
  • Get-Command
  • Essayez une commande non autorisée comme Get-Process.
  • Attendu : Erreur d'accès refusé pour les commandes non autorisées.
  1. Secrets
  • Get-Secret -Name TestSecret retourne sans écrire les secrets en clair dans stdout.
  • Recherchez les secrets codés en dur dans les scripts : Select-String -Path C:\Ops\Scripts\*.ps1 -Pattern 'password|token|secret'

Une matrice de vérification compacte aide pendant les fenêtres de changement :

ContrôleObjectifVérification cléRésultat attendu
Politique d'exécutionBloquer le code non fiableGet-ExecutionPolicy -ListRemoteSigned/AllSigned en vigueur
SignatureAutoriser seulement scripts signésGet-AuthenticodeSignatureStatut = Valid
JournalisationObserver les actionsVérifier transcriptions, Événements 4103/4104Événements et fichiers présents
Communication à distanceAccès chiffré, limitéTest-WSMan -UseSSLUniquement depuis sous-réseaux autorisés
JEATâches moindre privilègeGet-Command en sessionSeules cmdlets autorisées visibles
SecretsPas de texte en clairGet-Secret, analyse dépôtAucun secret dans code/fichiers

Modes de défaillance et récupération

Prévoyez la casse et gardez les étapes de retour prêtes.

  1. AllSigned casse l'automatisation existante
  • Symptôme : Les scripts non signés échouent.
  • Diagnostic : L'erreur mentionne l'exigence de signature.
  • Récupération :
  • Définir temporairement un contournement au niveau processus pendant la fenêtre de maintenance seulement : powershell.exe -ExecutionPolicy Bypass
  • Préférer la correction plus sûre : signer les scripts avec votre certificat de signature de code.
  • Ou assouplir à RemoteSigned sur le pilote : Set-ExecutionPolicy RemoteSigned -Scope LocalMachine -Force.
  1. Volume de journaux excessif ou données sensibles dans les transcriptions
  • Symptôme : Journaux d'événements volumineux ou transcriptions.
  • Diagnostic : Croissance disque sur le dossier de transcription ; événements 4103/4104 très actifs.
  • Récupération :
  • Limiter ModuleLogging à des modules spécifiques par nom au lieu de *.
  • Faire pivoter et archiver le répertoire de transcription ; ajuster les ACL ; envisager d'exclure les hôtes de laboratoire à haut volume.
  1. La communication à distance HTTPS échoue à cause de la confiance du certificat
  • Symptôme : Test-WSMan -UseSSL échoue ; erreurs de certificat sur le client.
  • Diagnostic : Incompatibilité de nom d'hôte ou émetteur non fiable.
  • Récupération :
  • Réémettre le certificat avec le nom DNS exact utilisé par les clients.
  • Distribuer le certificat d'émission aux magasins Trusted Root et Trusted Publisher là où requis.
  • Pour les tests seulement, Enter-PSSession -UseSSL -SkipCACheck -SkipCNCheck (ne pas utiliser en production).
  1. JEA refuse les tâches requises
  • Symptôme : Cmdlet nécessaire manquante ; erreurs de visibilité.
  • Diagnostic : Examiner VisibleCmdlets dans le fichier .pssc.
  • Récupération :
  • Modifier le fichier de configuration pour ajouter les cmdlets/paramètres exacts.
  • Register-PSSessionConfiguration -Name 'JEA_Maint' -Path .\JEA-Maint.pssc -Force.
  1. Coffre de secrets verrouillé ou indisponible
  • Symptôme : Get-Secret demande ou échoue.
  • Diagnostic : SecretStore est verrouillé ou le profil a changé.
  • Récupération :
  • Unlock-SecretStore et réessayer.
  • Réenregistrer le coffre si le profil a changé : Register-SecretVault -Name 'LocalStore' ....
  • Faire pivoter le mot de passe du coffre et réinjecter les secrets minimaux.
  1. Changement d'ACL bloque les tâches planifiées
  • Symptôme : La tâche planifiée échoue à écrire les journaux ou importer les modules depuis C:\Ops\Scripts.
  • Diagnostic : L'Observateur d'événements et l'historique des tâches montrent un accès refusé.
  • Récupération :
  • Accorder les droits de modification au compte de service de la tâche sur les dossiers spécifiques.
  • Re-tester avec whoami dans la tâche et revue icacls.
  1. Contraintes de mode de langage apparaissent inopinément
  • Symptôme : Certains types .NET ou Add-Type bloqués.
  • Diagnostic : $ExecutionContext.SessionState.LanguageMode affiche ConstrainedLanguage.
  • Récupération :
  • Examiner les politiques Device Guard/WDAC et ajuster les signataires de confiance ou les listes d'autorisation selon les besoins.

Livre de recettes pour retour rapide

  • Politique d'exécution :
  • Set-ExecutionPolicy -ExecutionPolicy Undefined -Scope LocalMachine -Force
  • Désactiver transcription/journalisation (retour pilote) :
  • Remove-Item 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription' -Recurse -Force
  • Remove-Item 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging' -Recurse -Force
  • Remove-Item 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging' -Recurse -Force
  • Écouteurs de communication à distance :
  • Get-ChildItem WSMan:\Localhost\Listener | Remove-Item -Recurse -Force
  • Réactiver les valeurs par défaut seulement si nécessaire : Enable-PSRemoting -Force
  • Point de terminaison JEA :
  • Unregister-PSSessionConfiguration -Name 'JEA_Maint' -Force
  • Nettoyage certificats de confiance (portée utilisateur pilote) :
  • Get-ChildItem Cert:\CurrentUser\TrustedPublisher | Where-Object { $_.Subject -like 'Local Code Signing' } | Remove-Item -Force

Liste de contrôle opérationnelle

Exécutez cette liste lors du déploiement initial et à intervalles réguliers (par exemple, trimestriellement ou après mises à jour OS/PowerShell).

  • Inventaire
  • Capturer $PSVersionTable, mode de langage, et Get-ExecutionPolicy -List.
  • Confirmer l'écouteur WinRM HTTPS et le pare-feu limité.
  • Exécution et signature
  • S'assurer que RemoteSigned ou AllSigned est appliqué comme prévu.
  • Vérifier que tous les scripts/modules de production ont des signatures valides.
  • Journalisation et observabilité
  • Confirmer la transcription vers le répertoire protégé et la présence des ID d'événements 4103/4104.
  • Examiner un échantillon aléatoire de transcriptions pour la complétude et les données sensibles.
  • Contrôle d'accès
  • Revérifier les ACL sur C:\Ops\Scripts et le dossier de transcription.
  • Tenter une écriture en tant qu'utilisateur non-admin (attendre un refus).
  • Communication à distance
  • Test-WSMan -UseSSL depuis hôtes autorisés et non autorisés (attendre autorisation/refus).
  • Examiner Get-PSSessionConfiguration pour les points de terminaison JEA seulement si nécessaires.
  • JEA
  • Entrer en session JEA et confirmer que seules les cmdlets requises sont visibles.
  • Tenter une commande non autorisée (attendre un refus).
  • Secrets
  • Get-Secret retourne sans fuite ; faire pivoter le mot de passe du coffre si planifié.
  • Analyser les scripts pour secrets codés en dur avec Select-String.
  • Documentation et récupération
  • Valider que les étapes de retour sont à jour et testées sur un hôte de laboratoire.
  • Capturer les configurations et journaux d'événements pour l'audit.

Conclusion

Vous pouvez durcir PowerShell sans bloquer le développement ni les opérations en travaillant par étapes petites et vérifiables. Commencez par un pilote étroit, capturez la ligne de base, et implémentez la politique d'exécution, la signature, la journalisation, le contrôle d'accès, la communication à distance HTTPS, JEA et une gestion saine des secrets. Après chaque changement, vérifiez le comportement et l'observabilité, documentez le résultat, et gardez un chemin de retour testé. Une fois le pilote stable et mesurable, élargissez la portée par phases en utilisant la même liste de contrôle et les mêmes diagnostics. Le renforcement n'est pas un seul paramètre ; c'est un ensemble de contrôles pratiques et observables qui limitent ce qui peut mal tourner et rendent le travail légitime traçable. Avec les étapes ci-dessus, vous relèverez votre posture de sécurité tout en gardant l'automatisation quotidienne productive.

Recherches connexes

Score de qualité de l’article

Utilité pour le lecteur 97%
  • check_circle Guide prêt à lire
  • check_circle Exemples pratiques inclus
  • check_circle URL d’article optimisée pour le SEO