Protezione dell’ambiente PowerShell mediante Script Firmati (con certificati Self-Signed)

L’esecuzione di script in PowerShell può rappresentare un problema dal punto di vista della sicurezza.

In molte situazioni gli script vengono eseguiti in contesto macchina e quindi con privilegi elevati, è prassi comune mantenere gli script in una share di rete da cui eseguirli, è da considerare anche il fatto che molti degli attacchi Cyber e delle tecniche utilizzate hanno PowerShell come veicolo principale.

Se ad esempio uno script che viene eseguito su tutte le postazioni di lavoro è residente su una share di rete e questa non è adeguatamente protetta da accessi illeciti, è sufficiente modificarlo per far eseguire codice malevolo su tutta l’infrastruttura di rete.

Esistono alcuni accorgimenti per rendere maggiormente sicura l’esecuzione degli script, alcuni mirano ad analizzare, verificare ed eventualmente bloccare comportamenti che possono essere a rischio.

L’abilitazione delle funzioni di Logging relative all’esecuzione degli script PowerShell può essere un valido aiuto nella verifica di quanto viene eseguito, ma con una mole di eventi notevole quindi difficilmente analizzabile se non con l’aiuto di un SIEM.

In questo articolo ci occuperemo di comprendere come è possibile utilizzare PowerShell in un ambiente “Protetto” ossia con la ragionevole certezza che gli script che vengono eseguiti, sia nel contesto utente che nel contesto macchina, siano eseguiti solamente se dispongono di una firma digitale.

Per poter firmare lo script è necessario disporre di un certificato che abbia dichiarato l’uso per il Code Signing, il certificato può essere Autofirmato (Self-Signed) oppure richiesto ad una Certification Authority interna, se questa è disponibile, in questa prima guida analizzeremo passo passo la procedura da adottare per la firma di script con un certificato Autofirmato.

Preparazione dell’ambiente di sicurezza per PowerShell

Ancor prima di procedere con la vera e propria procedura di firma è necessario impostare l’ambiente PowerShell in modo che vengano eseguiti esclusivamente Script firmati digitalmente.

È quindi necessario creare una GPO che attiva questo comportamento, la Group Policy può essere definita sia nel contesto macchina che in quello utente (l’impostazione di macchina ha priorità nell’applicazione rispetto a quella per utente).

Figura 1: Creazione della GPO per la definizione della Execution policy di PowerShell

Le impostazioni possibili all’interno della GPO prevedono che si possa modulare l’esecuzione degli script in tre modi:

  • Solo esecuzione di script firmati.
  • Esecuzione di qualunque script locale e se da remoto solo script firmati.
  • Esecuzione di script libera e senza vincoli.

Quando viene impostata l’esecuzione degli script in “Consenti solo Script Firmati” oppure “Allow only signed scritps” per i sistemi in lingua inglese, ogni script deve disporre di una firma digitale per poter essere eseguito, in caso contrario all’utente verrà presentato il messaggio seguente:

Figura 2: Messaggio relativo al tentativo di ‘esecuzione di uno Script non firmato

Procedura per la firma di uno script in PowerShell

Generazione di un certificato di tipo Self-Signed

Per poter eseguire il processo di firma è necessario disporre di un certificato Auto Firmato, esistono diverse modalità per generarlo, di seguito vedremo come è possibile utilizzare PowerShell.

Il cmd-let utilizzato per questo scopo è Get-Certificate, il certificato deve avere specificato l’utilizzo che verrà fatto del certificato ed in questo contesto bisogna specificare che l’uso sarà per il Code Signing.

Qui sotto è riportato il comando completo per la generazione:

Di default, se non viene specificato altrimenti, il certificato viene generato con la validità di un anno, tuttavia può essere utile prevedere una validità temporalmente più lunga, altrimenti si dovrà procedere ad una nuova firma dei vari script.

Sempre nell’esempio sopra la validità è di 5 anni.

Il valore dichiarato in CN=PsScriptSigning è il nome vero e proprio del certificato che vedremo nello store dell’utente come riportato nella figura 3.

Figura 3: Visualizzazione del certificato Auto Firmato

Importazione del certificato come “Autorità di Certificazione Radice Attendibile” nello store Utente

Avendo così ottenuto il certificato dobbiamo dapprima esportarlo in un file e successivamente importarlo nell’area relativa alle “Autorità di Certificazione Radice Attendibili” o “Trusted Root Certification Authority“.

Il comando esporta il certificato, senza la sua chiave privata nel file C:\Temp\PsCodeSigning.cer:

Il comando successivo importa la chiave pubblica del certificato esportato prima, nell’area delle Autorità di Certificazione che devono essere considerate attendibili:

L’azione di import origina un messaggio di avviso a cui dovremo dare conferma per completare l’importazione

Figura 4: Accettazione e conferma del salvataggio in “Autorità di Certificazione Radice Attendibili”

Firma dello Script PowerShell

La procedura seguita finora ha permesso di creare la struttura di base per permetterci di firmare gli script che andremo produrre, in questo esempio lo script in PowerShell è collocato nella cartella C:\Temp ed ha nome MsgboxSigned.ps1, per la firma è necessario utilizzare il cmd-let SetAuthenticodeSignature:

Se i passi sono stati completati in modo corretto il comando termina senza errori e con lo stato di Valido.

È importante tenere bene presente che la firma degli script in PS può avvenire esclusivamente sulla postazione che ha generato il certificato stesso, in quanto è presente anche la chiave privata.

Qualora fosse necessario utilizzare un’altra postazione per la firma, dovremo esportare il certificato in un formato che contenga anche la chiave privata, copiare il file esportato nella nuova postazione e reimportarlo.

Figura 5: Utilizzo del cmd-let di firma dello script

L’apposizione della firma sullo script esegue già di per sé la verifica, se tuttavia volessimo ri-verificare il file oppure fosse necessario verificare un altro file è possibile utilizzare il cmd-let Get-AuthenticodeSignature:

Che riporterà la condizione di validità o meno di una firma sullo script.

Distribuzione del Certificato Auto firmato tramite GPO

Per poter essere correttamente eseguito dalle varie postazioni il certificato utilizzato per la firma dello script deve poter essere disponibile su tutte le postazioni che dovranno eseguirlo, la via più breve è quella di creare una Group Policy ad hoc all’interno della quale importare il certificato creato in precedenza.

Figura 6: Creazione della GPO per la distribuzione del Certificato

Al punto 1 è riportata lo store certificati macchina dove importare il certificato successivamente al punto 2 confermiamo l’operazione con Import e la creazione della GPO prosegue.

Figura 7: Selezione del Certificato di firma dal percorso di esportazione

Proseguiamo con NEXT

Figura 8: Richiesta della posizione di Import del Certificato

Figura 9: È richiesta un’ulteriore conferma per l’import

Figura 10: Messaggio di conferma dell’avvenuta importazione del Certificato

Sempre nella stessa GPO è necessario importare, (con le operazioni viste nelle figure dalla 6 alla 10), lo stesso certificato nello store relativo agli “Autori Attendibili” o “Trusted Publisher” altrimenti lo script, in prima esecuzione su ogni postazione si ferma e chiede una conferma ulteriore all’utente analoga a quella della figura sottostante.

L’articolo di Ermanno Goletto PowerShell AllSigned execution policy e warning al primo avvio di uno script firmato – DevAdmin Blog spiega in modo preciso e dettagliato questo comportamento.

Figura 11: Warning relativo a “Trusted Publisher” sconosciuto

La GPO completa dovrà quindi avere lo stesso certificato all’interno dei due Store.

Figura 12: Group Policy completa per la distribuzione del certificato Auto Segnato

Terminato anche questo passaggio l’ambiente è pronto e permette l’esecuzione esclusivamente di Script Firmati digitalmente con il certificato generato in precedenza, questa procedura non solo garantisce che solamente chi è autorizzato (in quanto ha firmato gli script) possa effettivamente eseguirli, ma anche che questi rimangano integri.

Infatti se in uno di questi ne viene alterato il contenuto, anche di un solo carattere, la validazione relativa alla firma fallisce e l’esecuzione ne viene impedita.

Considerazioni

Un ambiente in cui è attivata una protezione di questo tipo è sicuramente più controllato e sicuro di un ambiente dove l’esecuzione di script è libera, ovviamente la sicurezza è anche in funzione della protezione dei certificati che vengono utilizzati. E’ chiaro che deve essere accuratamente protetto il certificato utilizzato per la firma degli script.

La soluzione più robusta è quella in cui internamente all’infrastruttura è presente una Certification Authority con permessi di rilascio dei certificati molto più controllati e con possibilità di revoca, questo scenario sarà oggetto in un prossimo articolo di approfondimento.

Riferimenti