Ogni informatico che si rispetti possiede delle password complesse e capita molto spesso di doverle digitare molte volte in una giornata quando si eseguono degli script powershell che devono inferfacciarsi con il cloud. Alcuni di noi hanno a che fare con diversi set di credenziali in base allo scopo all’interno dello stesso script per compiere operazioni contemporaneamente su sistemi onprem e online. Il disagio maggiore ce l’abbiamo quando il nostro script deve essere programmato in un server per eseguire periodicamente una certa operazione. La tentazione di scrivere in chiaro la password all’interno dello script è forte ma scopriremo una valida e semplice alternativa per dormire sonni tranquilli.
Windows Data Protection
A partire da Windows 2000 è stato introdotto un sistema integrato nel sistema operativo per la protezione delle informazioni utilizzando la password dell’utente. E’ molto semplice, per un malintenzionato, collegare il disco di un computer rubato ed accedere ai file che contengono il Gestore delle Credenziali (Credential Manager) salvate da un utente. Le coppie di nomi e password associate ai servizi o ai siti web sono solo uno dei dati che il sistema operativo protegge con il Data Protection API (DPAPI). Tramite il protocollo a chiave simmetrica 3-DES (Triple Des) le informazioni vengono cifrate utilizzando la password dell’utente e vincolando la lettura del segreto al solo utente nel pc o server utilizzato per la cifratura. Per intenderci meglio e semplificare, è simile al bancomat dove la tessera è il computer dove siamo loggati ed il PIN è la nostra password. Nel corso degli anni il sistema di protezione si è evoluto ed adattato all’ambiente di dominio Active Directory per fare in modo che il cambio della password dell’utente potesse avvenire centralmente senza pregiudicare la protezione dei dati in ogni computer dove l’utente aveva fatto accesso.
Scopo dello script
Per proteggere le password che utilizzeremo nei nostri script andremo a memorizzarle all’interno dei registri dell’utente nel pc o server dove avvieremo lo script. Successivamente, e per tutte le volte che vorremo, basterà richiamare le corrette chiavi di registro per avere una variabile con le credenziali pronte all’uso. Avremo anche la certezza che le chiavi di registro create non potranno essere riutilizzate in un altro computer da noi stessi e, men che meno, da altri utenti. Le credenziali memorizzate potranno essere sia locali (SERVER\utente) che di dominio (DOMINIO\utente) come anche di Azure Active Directory (utente@azienda.it oppure utente@azienda.onmicrosoft.com).
Funzionamento
Potete creare lo script sul vostro computer partendo dalla richiesta delle credenziali da memorizzare ed un controllo sull’esistenza dello username:
# Richiesta delle credenziali da memorizzare $secureCredential = Get-Credential -Message "Inserire le credenziali nel formato DOMAIN\Username oppure Username@Domain.com" # Controllo sull'esistenza dello username inserito If ($secureCredential.UserName -eq $null) { Write-Host -Foreground Red "Credenziali non inserite" Break; }
In seguito viene creata una chiave di registro (HKCU:\Software\SecStoreCred) che conterrà tutte le credenziali diverse che potrete memorizzare nello stesso computer. Molto utile nel caso in cui abbiate diverse credenziali per accedere a molti servizi o portali. Questa operazione verrà compiuta solo la prima volta che avviate lo script nel computer. In seguito le credenziali che avete inserito vengono memorizzate in una chiave di registro nel percorso precedente. Lo Username inserito viene copiato in una variabile ed opportunamente bonificato per decidere in quale percorso memorizzare i dati. L’uso del DPAPI per la cifratura della password avviene col comando ConvertFrom-SecureString e successivamente vengono scritte le credenziali protette nel registro.
# Creazione percorso nei registri per la memorizzare di tutte le credenziali If (!(Test-Path "HKCU:\Software\SecStoreCred")) { Try { Write-Host -ForegroundColor Green "Creazione percorso nei registri" New-Item -Path "HKCU:\Software" -Name "SecStoreCred" -Force } Catch { [System.Exception] Write-Host -Foreground Red "Creazione percorso HKCU:\Software\SecStoreCred nei registri non riuscito" } Finally {} } # Adattamento dello username per la scrittura del percorso nei registri $userNameString = $secureCredential.UserName.Replace(".","") $userNameString = $userNameString -replace "@","" -replace "-","" -replace "_","" $userNameString = $userNameString.Replace("\","") If ($userNameString.Length -ge 31) {$userNameString = $userNameString.Substring(0,30)} # Cifratura delle credenziali con Windows Data Protection, credenziali utilizzabili solo dall'utente corrente in questo pc/server $securePasswordString = $secureCredential.Password | ConvertFrom-SecureString # Scrittura delle credenziali salvate nel registro, in caso esistano già vengono cancellate le credenziali precedenti Write-Host -ForegroundColor Green "Memorizzazione credenziali in HKCU:\Software\SecStoreCred\$userNameString." If (Test-Path "HKCU:\Software\SecStoreCred\$userNameString") { Write-Host -ForegroundColor Red "Credenziali esistenti, cancellazione salvataggio precedente" Remove-Item -Path "HKCU:\Software\SecStoreCred\$userNameString" -Force } New-Item -Path HKCU:\Software\SecStoreCred\$userNameString New-ItemProperty -Path HKCU:\Software\SecStoreCred\$userNameString -PropertyType String -Name UserName -Value $secureCredential.UserName New-ItemProperty -Path HKCU:\Software\SecStoreCred\$userNameString -PropertyType String -Name Password -Value $securePasswordString
Al termine dello script appare il codice da inserire nei nostri script al fine di richiamare e decodificare la password memorizzata nel registro dal DPAPI. Basterà copiarlo dalla finestra PowerShell e tenerlo pronto per i futuri script da avviare in questo computer con questo utente (esempio: Connect-AzureAD -Credential $cred). L’uso del DPAPI per la de-cifratura della password avviene col comando ConvertTo-SecureString appena prima della preparazione della variabile $cred.
# Stampa delle istruzioni per l'uso delle credenziali salvate in altri script powershell solo dall'utente corrente in questo pc/server Write-Host -ForegroundColor Green "Per utilizzare le credenziali inserite devi essere loggato/a in questo pc/server con questo utente," Write-Host -ForegroundColor Green copiare questo script PowerShell e riferire le credenziali salvate con la variabile '$cred' Write-Host -ForegroundColor Cyan `n Write-Host -ForegroundColor Cyan '$secCredUser' "= (Get-ItemProperty -Path HKCU:\Software\SecStoreCred\$userNameString).UserName" Write-Host -ForegroundColor Cyan '$secCredPwd' "= (Get-ItemProperty -Path HKCU:\Software\SecStoreCred\$userNameString).Password" Write-Host -ForegroundColor Cyan '$secPwd' "= ConvertTo-SecureString" '$secCredPwd' Write-Host -ForegroundColor Cyan '$cred' "= New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList" '$secCredUser, $secPwd'
Suggerimenti
- Se dovete utilizzare diverse credenziali nel medesimo script abbiate premura di definire delle variabili diverse per contenerle ($cred1, $cred2) quando richiamerete le chiavi di registro memorizzate.
- Se lo script che dovrà contenere le credenziali verrà avviato da un account di servizio all’interno di un’attività programmata (Scheduled Task) abbiate premura di eseguire lo script di creazione delle chiavi di registro per la memorizzazione delle credenziali con l’utenza di servizio da una finestra Powershell con Shift+Tasto destro del mouse e “Esegui come altro utente” (Run as different user). In questo modo verranno popolate le credenziali protette nella chiave di registro HKCU dell’utenza di servizio.
Conclusioni
La gestione delle credenziali per gli amministratori è sempre difficile e poco pratico. Quando si usano credenziali di servizio o si eseguono script programmati la pigrizia prende il sopravvento e si tende a scrivere le password in chiaro. Lo script descritto nel presente articolo permette di memorizzare le credenziali in maniera sicura ed utilizzarle velocemente in tutta tranquillità.