====== Politique de sécurité et signature de script ====== --- //[[nekan@shyrkasystem.com|Nicolas THOREZ]] 2019/03/28 20:50// La sécurisation de l'exécution de script est importante. En effet, les scripts sont utilisés pour automatiser des actions et surtout les exécuter sans nécessiter la présence de l'utilisateur. Cela entraîne invariablement des dérives et si le processus est très exploité par des administrateurs dans leur tâches quotidiennes, il l'est aussi par des pirates et autres. A ce titre, il faut pouvoir contrôler l'exécution d'un script sur nos infrastructures. ===== Politique d'exécution ===== En Powershell, la politique d'exécution est gérer par les commandes ''Get-ExecutionPolicy'' et ''Set-ExecutionPolicy''. * Référence pour ''Get-ExecutionPolicy'' : [[https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/get-executionpolicy?view=powershell-6|Microsoft]] * Référence pour ''Set-ExecutionPolicy'' : [[https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy?view=powershell-6|Microsoft]] * Référence pour ''ExecutionPolicy'' : [[https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-6|Microsoft]] ==== Les différentes politiques ==== L'exécution de ''Get-ExecutionPolicy'' nous retournera la politique de sécurité actuelle sur le poste. Parmi ces politiques, nous trouverons : * **AllSigned** * Permet l'exécution des scripts. * Nécessite que tous les scripts et les fichiers de configuration qu'ils utilisent soient signés par une autorité de confiance, même en local. * Interroge l'utilisateur lors de l'exécution d'un script signé par une autorité non reconnue. Nécessite des droits d'administrateur pour valider l'autorité. * Présente un risque d'exécution de code malicieux signé. * **Bypass** * Aucun blocage, ni aucun avertissement. * Ce mode est surtout conçu pour les tests de scripts et les environnements sécurisés faisant appel à des routines en Powershell. * **Default** * Applique les règles de sécurité par défaut. * ''Restricted'' pour les postes de travail. * ''RemoteSigned'' pour les serveurs. * **RemoteSigned** * Permet l'exécution des scripts * Nécessite que tous les scripts extérieurs soient signés par une autorité de confiance. * Par conséquent, les scripts créés en local n'ont pas besoin de signature. * Permet d'exécuter des scripts extérieurs si ces derniers ont été débloqués en local avec la commande ''Unblock-File''. * Risque d'exécution de script malicieux signés et non signés. * **Restricted** * Permet d'exécuter des commandes Powershell. * Interdit l'exécution de scripts, de modules et de pages de configuration Powershell. * **Undefined** * Aucune politique particulière n'est appliquée * Si ''Undefined'' est défini sur tous les périmètres d'activité, alors la politique ''Restricted'' s'applique. * **Unrestricted** * Permet l'exécution des scripts. * Affiche un avertissement concernant l'exécution de scripts en provenance d'une source extérieure. * Référence pour ''Unblock-File'' : [[https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/unblock-file?view=powershell-6|Microsoft]] ==== Les différents périmètres ==== Les différentes politiques peuvent s'appliquer à différents périmètres d'activité, indépendants les uns des autres. Parmi ces périmètres, nous avons : * **MachinePolicy** : Tous les utilisateurs d'un poste. * **UserPolicy** : L'utilisateur actuel du poste. * **Process** : La politique n'est appliqué qu'au processus Powershell actuel. Dès que ce processus se termine, la politique globale se réapplique à tous les autres processus Powershell. * **CurentUser** : Equivalent à ''UserPolicy'' mais avec inscription de la politique en base de registre (HKCU). * **LocalMachine** : Equivalent à ''MachinePolicy'' mais avec inscription de la politique en base de registre (HKLM). C'est le périmètre par défaut. ==== Exemple de manipulation ==== * Obtenir la politique d'exécution Get-ExecutionPolicy AllSigned * Obtenir la politique d'exécution pour tous les périmètres d'activité Get-ExecutionPolicy -List Scope ExecutionPolicy ----- --------------- MachinePolicy Undefined UserPolicy Undefined Process Undefined CurrentUser Undefined LocalMachine AllSigned * Définir la politique ''Restricted'' Set-ExecutionPolicy -ExecutionPolicy Restricted * Définir la politique ''Unrestricted'' sur le périmètre ''CurrentUser'' Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser ===== Signature des scripts ===== Comme on vient de le voir, on peut renforcer la sécurité d'un script et de son exécution en le signant. La signature d'un script le protège de toute modification. En effet, si le script est modifié après signature alors cette dernière sera corrompu et ne pourra pas être authentifiée par l'autorité de certification. Si vous voulez modifié un script signé, il faudra alors le signer à nouveau. Pour cela, la procédure est assez simple mais nécessite quelques prérequis tels que : * Disposer d'un autorité de certification de confiance (**[[administration_ca|Lien]]**) * Disposer d'un certificat pour la signature (**[[administration_ca2|Lien]]**) Si les prérequis sont remplis, alors la signature d'un script, par exemple un script ''Hello-World.ps1'' qui serait enregistré dans le dossier ''C:\Scripts\'', devient possible via les commandes suivantes : # On stocke les différentes informations nécessaires dans des variables # D'abord le script à signer $Script = "C:\Scripts\Hello-World.ps1" # Ensuite le certificat $Certificat = Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert # Finalement la commande de signature Set-AuthenticodeSignature -FilePath $Script -Certificate $Certificat # Si notre certificat est sécurisé par un mot de passe, alors ce dernier sera demandé pour valider la signature. # Le retour console est alors : Répertoire : C:\Scripts SignerCertificate Status Path ----------------- ------ ---- DDDDCD0C34FE6993EBDA34F436ADAF1EF3ADBF37 Valid Hello-World.ps1 A noter que lors de la première exécution du script signé, un avertissement sera émis afin de vous permettre de valider l'autorité en tant qu'autorité de confiance. Si bien sûr, cela n'a pas déjà été fait. Ce script nouvellement signé pourra désormais être exécuté sur le système de manière sécurisée et ce, tant que sera valide la certificat utilisé pour la signature. Du coup, certains pourraient avoir envie de signer définitivement un script quelle que soit la durée de vie du certificat. Powershell nous en donne la possibilité via la variable ''-TimestampServer'' qui permet d'ajouter une date validé lors de la signature. Dans ce cas alors lorsque que la signature sera vérifié, elle le sera par rapport à la validité du certificat au moment de la signature. Cette variable nécessite de faire appel à un serveur spécifique, appelé ''Timestamp Server'', mais Powershell ne peut y accéder que via ''HTTP'' et non ''HTTPS'', ce qui à mon goût représente un risque. Cependant, une rapide recherche sur Internet permet de trouver des serveurs utilisables gratuitement. La syntaxe devient alors : # On stocke les différentes informations nécessaires dans des variables # D'abord le script à signer $Script = "C:\Scripts\Hello-World.ps1" # Ensuite le certificat $Certificat = Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert # Puis le serveur d'horodatage $Server = "http://time.certum.pl" # Finalement la commande de signature Set-AuthenticodeSignature -FilePath $Script -Certificate $Certificat -TimestampServer $Server # Là encore, si notre certificat est sécurisé par un mot de passe, alors ce dernier sera demandé pour valider la signature. # Le retour console est alors : Répertoire : C:\Scripts SignerCertificate Status Path ----------------- ------ ---- DDDDCD0C34FE6993EBDA34F436ADAF1EF3ADBF37 Valid Hello-World.ps1 * Référence pour ''Set-AuthenticodeSignature'' : [[https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-authenticodesignature?view=powershell-6|Microsoft]] * Recherche pour les serveurs d'horodatage : [[https://stackoverflow.com/questions/25052925/does-anyone-know-a-freetrial-timestamp-server-service|Stack Overflow]] ~~DISCUSSION~~