Signering af PowerShell-scripts
I ❤️ PowerShell. Det er et virkelig nyttigt værktøj til automatisering af de opgaver, du udfører flere gange. Men det kan også være et gabende sikkerhedshul, hvis du lader det være.
PowerShell giver dig mulighed for at administrere næsten alt på din maskine, så der er meget skade, der kan gøres af en person, der er i stand til at køre ondsindede scripts i dine miljøer.
Den var tidligere begrænset til kun Windows, men siden version 6 og nu med udgivelsen af PowerShell 7.0 kan den også implementeres på Linux og MacOS. Denne artikel handler dog om eksekveringspolitikker, som ikke kan ændres i miljøer, der ikke er Windows-miljøer, så de vil ikke være til gavn for Linux/MacOS-brugere (beklager).
Eksekveringspolitikker
En måde, hvorpå du kan begrænse muligheden for at køre scripts i dine Windows-miljøer, er ved at bruge PowerShells eksekveringspolitikker. Tldr er, at de kan bruges til at begrænse de scripts, der vil blive kørt i miljøet. De tilgængelige muligheder fra mindst sikker til mest sikker er:
Bypass
Ingen blokeres.
Ubegrænset (gælder altid på ikke-Windows-maskiner)
Samme som ByPass
, men advarer brugeren, før han/hun kører scripts fra internettet.
RemoteSigned (standard for Windows-servere)
Skripter, der er hentet fra internettet, kan kun køres, hvis de er signeret. Skripter, der er skrevet på maskinen, kan køres
AllSigned
Alle scripts skal være signeret, før de kan køres
Restricted (standard for Windows-klienter)
Forhindrer, at scripts kan køres. Kan kun køre individuelle kommandoer.
Kørsel af scripts
Så du ønsker at køre dine egne PowerShell-scripts på din server. Men du får en PSSecurityException
som følgende.
PS C:\Users\Administrator\Downloads> .\wibble.ps1.\wibble.ps1 : File .\wibble.ps1 cannot be loaded. The file.\wibble.ps1 is not digitally signed. You cannot run this script on the current system.For more information about running scripts and setting execution policy, see about_Execution_Policies athttp://go.microsoft.com/fwlink/?LinkID=135170.At line:1 char:1+ .\wibble.ps1+ ~~~~~~~~~~~~ + CategoryInfo : SecurityError: (:) , PSSecurityException + FullyQualifiedErrorId : UnauthorizedAccess
En måde at løse dette problem på er at ændre eksekveringspolitikken ved hjælp af kommandoen Set-ExecutionPolicy
og reducere sikkerheden på maskinen. Dette er en generelt en dårlig idé.
Personligt ville jeg aldrig bruge noget mindre sikkert end RemoteSigned
på en server, men AllSigned
ideelt set.
Hvad er en script-signatur?
Formentlig ønsker du at opretholde sikkerheden på maskinen og ikke åbne op for en sårbarhed, så den mulighed, der er tilbage for dig, er at signere dine scripts.
Signering af et script betyder, at en person med adgang til den private nøgle til et kodeunderskrivningscertifikat har tilføjet en signaturblok i slutningen af scriptfilen.
function Get-Wibble { return "Wibble"}# SIG # Begin signature block# vpnIUpm2XxLRhU1no0iuA62xKxYzR6m95z9Ax21ppeTC9NoRd8ocoSGr1zAd# qlMOlz4lZoVWR4ZmtdCgzde1dVxzv4jjHb6ziDiY2o05UXswD2bl6XaOrUpd# Li0Qjg3d3y2r1nrpO8hos906bgXQswysvouegUJcpt8ftmqBKfEYNeBgnBFm# SIG # End signature block
(Kun eksempel. Signaturblokken er normalt meget længere)
Signaturblokken vil indeholde en hash af scriptet, der er blevet krypteret ved hjælp af den private nøgle. Når man forsøger at køre scriptet, dekrypteres dette ved hjælp af den offentlige nøgle og sammenlignes med den faktiske hash. Hvis den stemmer overens, kan vi bekræfte, at scriptet ikke er blevet manipuleret, da hash-koden ville ændre sig, så snart det sker.
Selvsignerende certifikater
Hvis dine scripts kun skal køres af maskiner i din organisation, vil du højst sandsynligt kunne selvsignere certifikaterne. Alternativet er at bruge $$$$ og købe et kodeunderskriftscertifikat hvert år.
Selvunderskrift betyder, at du selv genererer certifikatet og underskriver scriptsene ved hjælp af det.
Sådan oprettes et selvunderskriftscertifikat
PowerShell har den meget nyttige New-SelfSignedCertificate
-kommando til at fremstille selvunderskriftscertifikater. Vi kan derefter eksportere dem og placere dem i forskellige lagre.
Som standard vil kommandoen oprette et certifikat, der udløber efter 1 år. Du kan ændre dette ved at bruge parameteren -NotAfter
og give den den dato, du ønsker, at certifikatet skal udløbe.
For at oprette et certifikat skal du starte en PowerShell-session og køre følgende
$CertificateName = Read-Host "Input your certificate name"$OutputPFXPath = "$CertificateName.pfx"$OutputCERPath = "$CertificateName.cer"$Password = Get-Credential -UserName Certificate -Message "Enter a secure password:"$certificate = New-SelfSignedCertificate -subject $CertificateName -Type CodeSigning -CertStoreLocation "cert:\CurrentUser\My"$pfxCertificate = Export-PfxCertificate $certificate -FilePath $OutputPFXPath -password $Password.passwordExport-Certificate -Cert $certificate -FilePath $OutputCERPathImport-PfxCertificate $pfxCertificate -CertStoreLocation cert:\CurrentUser\Root -Password $password.passwordWrite-Output "Private Certificate '$CertificateName' exported to $OutputPFXPath"Write-Output "Public Certificate '$CertificateName' exported to $OutputCERPath"
Dette vil oprette certifikatet og eksportere det til to separate filer med extensionerne .pfx
og .cer
.
PFX
PFX-certifikatet er det certifikat, der skal installeres på de maskiner, der skal foretage signeringen. I vores tilfælde er det hver af vores udviklere.
Det skal installeres i cert:\CurrentUser\Root
-lageret, også kendt som “Trusted Root Certification Authorities”-lageret.
Denne fil skal opbevares et sikkert sted. Adgangskoden skal derefter sikres separat (brug en adgangskodeadministrator). Hvis en ond aktør får fat i begge disse, kan de underskrive deres ondsindede scripts, som om de var dig.
CER
CER-certifikatfilen er det, du skal installere på de maskiner, der skal køre scriptsene. Den vil ikke kræve en adgangskode for at blive installeret, men kan ikke bruges til at signere scripts. Den indeholder kun den offentlige nøgle, der bruges til at dekryptere signaturen.
Da den ikke indeholder den private nøgle, kan dette certifikat distribueres frit til alle miljøer, der skal køre scripts.
Dette skal installeres i to certifikatlagre på de maskiner, der skal køre scripts; cert:\LocalMachine\Root
og cert:\LocalMachine\TrustedPublisher
-lagrene.
Signering af et script
Den Set-AuthenticodeSignature
-funktion er til rådighed til at signere scripts. Vi skal indgive stien til scriptet og certifikatet fra lageret. Vi har skrevet en wrapperfunktion, der kan signere scripts.
function Set-ScriptSignatures { param ( $pathToScripts = "." ) $certificateName = "PowerShell Signing Certificate" $scripts = Get-ChildItem -Path "$pathToScripts\*" -Include *.ps1, *.psm1 -Recurse $certificate = @(Get-ChildItem cert:\CurrentUser\My -codesign | Where-Object { $_.issuer -like "*$certificateName*" } ) foreach ($script in $scripts) { Write-Host "Signing $script" Set-AuthenticodeSignature $script -Certificate $certificate }}
Variablen $certificateName
skal indeholde det navn, der blev brugt ved oprettelsen af certifikatet.
Du kan bruge funktionen ved at angive en sti til den mappe, der indeholder scripts, og den vil løbe gennem dem og signere dem alle.
Når du har installeret scripts på målmaskinen, bør du nu være i stand til at køre scriptsene uden problemer.