Firmare gli script PowerShell

I ❤️ PowerShell. È uno strumento davvero utile per automatizzare quei compiti che fai più volte. Ma può anche essere un buco di sicurezza enorme se glielo permetti.

PowerShell ti permette di amministrare quasi tutto sulla tua macchina, quindi ci sono un sacco di danni che potrebbero essere fatti da qualcuno in grado di eseguire script dannosi nei tuoi ambienti.

Precedentemente confinato solo a Windows, dalla versione 6 e ora con il rilascio di PowerShell 7.0, può essere implementato anche su Linux e MacOS. Tuttavia questo articolo parla delle Execution Policies che non possono essere modificate in ambienti non Windows, quindi non fornirà alcun beneficio agli utenti Linux/MacOS (scusate).

Execution Policies

Un modo per limitare la possibilità di eseguire gli script nei vostri ambienti Windows è quello di utilizzare le execution policies di PowerShell. Il tldr è che possono essere usati per limitare gli script che verranno eseguiti nell’ambiente. Le opzioni disponibili dal meno sicuro al più sicuro sono:

Bypass

Non viene bloccato nulla.

Unrestricted (si applica sempre su macchine non Windows)

Simile a ByPass ma richiede all’utente di eseguire gli script da Internet.

RemoteSigned (default per i server Windows)

Gli script che sono stati scaricati da internet possono essere eseguiti solo se sono firmati. Gli script scritti sulla macchina possono essere eseguiti

AllSigned

Tutti gli script devono essere firmati prima di essere eseguiti

Restricted (predefinito per i client Windows)

Impedisce l’esecuzione degli script. Può eseguire solo singoli comandi.

Esecuzione degli script

Vuoi eseguire i tuoi script PowerShell sul tuo server. Ma stai ottenendo un PSSecurityException come il seguente.

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
Entra nella modalità a schermo intero Esci dalla modalità a schermo intero

Un modo per risolvere questo problema è cambiare la politica di esecuzione usando il comando Set-ExecutionPolicy e ridurre la sicurezza della macchina. Questa è generalmente una cattiva idea.

Personalmente, non userei mai niente di meno sicuro di RemoteSigned su un server, ma AllSigned idealmente.

Cos’è una firma di script?

Presumibilmente vuoi mantenere la sicurezza della macchina e non aprire una vulnerabilità, quindi l’opzione che ti rimane è quella di firmare i tuoi script.

Firmare uno script significa che qualcuno con accesso alla chiave privata per un certificato di firma del codice ha aggiunto un blocco di firma alla fine del file dello script.

function Get-Wibble { return "Wibble"}# SIG # Begin signature block# vpnIUpm2XxLRhU1no0iuA62xKxYzR6m95z9Ax21ppeTC9NoRd8ocoSGr1zAd# qlMOlz4lZoVWR4ZmtdCgzde1dVxzv4jjHb6ziDiY2o05UXswD2bl6XaOrUpd# Li0Qjg3d3y2r1nrpO8hos906bgXQswysvouegUJcpt8ftmqBKfEYNeBgnBFm# SIG # End signature block
Entrare in modalità schermo intero Uscire dalla modalità schermo intero

(Solo esempio. Il blocco della firma è solitamente molto più lungo)

Il blocco della firma conterrà un hash dello script che è stato criptato usando la chiave privata. Quando si tenta di eseguire lo script, questo viene decrittato usando la chiave pubblica e confrontato con l’hash attuale. Se corrisponde, allora possiamo confermare che lo script non è stato manomesso perché l’hash cambierebbe non appena ciò accadesse.

Certificati autofirmati

Se i tuoi script saranno eseguiti solo da macchine della tua organizzazione, allora molto probabilmente sarai in grado di autofirmare i certificati. L’alternativa è spendere $$$ e comprare un certificato di firma del codice ogni anno.

Autofirma significa che genererai tu stesso il certificato e firmerai gli script usando quello.

Come creare un certificato autofirmato

PowerShell ha il comando New-SelfSignedCertificate molto utile per produrre certificati autofirmati. Possiamo poi esportarli e metterli in diversi negozi.

Di default il comando crea un certificato che scade dopo 1 anno. Puoi cambiare questo usando il parametro -NotAfter e fornendogli la data in cui desideri che il certificato scada.

Per creare un certificato avvia una sessione PowerShell ed esegui il seguente

$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"
Entra in modalità schermo intero Esci dalla modalità schermo intero

Questo creerà il certificato e lo esporterà in due file separati con le estensioni .pfx e .cer.

PFX

Il certificato PFX è quello che dovrà essere installato sulle macchine che faranno la firma. Nel nostro caso si tratta di ogni macchina dei nostri sviluppatori.

Dovrebbe essere installato nello store cert:\CurrentUser\Root, conosciuto anche come store “Trusted Root Certification Authorities”.

Questo file dovrebbe essere tenuto in un posto sicuro. La password dovrebbe poi essere messa al sicuro separatamente (usare un gestore di password). Se un cattivo attore entra in possesso di entrambi, allora può firmare i suoi script maligni come se fosse te.

CER

Il file del certificato CER è quello che dovrai installare sulle macchine che eseguiranno gli script. Questo non richiederà una password per l’installazione ma non può essere usato per firmare gli script. Contiene solo la chiave pubblica usata per decifrare la firma.

Perché non contiene la chiave privata, questo certificato può essere distribuito liberamente a tutti gli ambienti che eseguiranno gli script.

Questo dovrà essere installato in due negozi di certificati sulle macchine che eseguiranno gli script; I negozi cert:\LocalMachine\Root e cert:\LocalMachine\TrustedPublisher.

Firmare uno script

La funzione Set-AuthenticodeSignature è fornita per firmare gli script. Dobbiamo passare il percorso dello script e il certificato del negozio. Abbiamo scritto una funzione wrapper che può firmare gli script.

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 }}
Entrare nella modalità a schermo intero Uscire dalla modalità a schermo intero

La variabile $certificateName dovrebbe contenere il nome usato per creare il certificato.

Si può usare la funzione fornendo un percorso alla directory che contiene gli script ed essa li eseguirà firmandoli tutti.

Una volta installati gli script sulla macchina di destinazione si dovrebbe ora essere in grado di eseguire gli script senza alcun problema.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.