Ochrana heslem a šifrování ve skriptech PowerShell

Správci často při psaní automatizačních skriptů v PowerShell zapisují hesla přímo do těla skriptu PoSh. Jak víte, je to extrémně nebezpečné, když se používá v produktivním prostředí, protože ostatní uživatelé serveru nebo administrátoři mohou heslo vidět jasně. Proto je vhodné použít bezpečnější metodu pro použití hesel ve skriptech PowerShell nebo šifrování hesel, pokud nelze použít interaktivní vstup.

Je bezpečné požádat uživatele, aby do skriptu zadal heslo interaktivně pomocí rutiny cmdlet Získejte pověření. Například požadujeme uživatelské jméno a heslo a uložíme je do objektu typu Pscredential:

$ Cred = Získejte pověření

Při přístupu k vlastnostem proměnné můžete zjistit jméno zadaného uživatele.

$ Cred.Username

Když se však pokusíte zobrazit heslo, bude vrácen text System.Security.SecureString, protože heslo je nyní uloženo jako SecureString.

$ Cred.Password

Objekt PSCredential, který jsme uložili do proměnné $ Cred, lze nyní použít v cmdletech, které podporují tento typ objektu.

Parametry $ Cred.Username a $ Cred.Password lze použít v cmdletech, které nepodporují objekty PSCredential, ale vyžadují samostatné uživatelské jméno a heslo.

Můžete také použít cmdlet Read-Host s atributem AsSecureString a požádat o heslo uživatele:
$ pass = Read-Host "Zadejte heslo" -AsSecureString

V tomto případě také nebudete moci vidět obsah proměnné $ pass, ve které je heslo uloženo.

Ve výše uvedených metodách použití hesla ve skriptech PowerShell se předpokládalo, že při spuštění skriptu bylo heslo zadáno interaktivně. Tato metoda však není vhodná pro různé scénáře, které se spouští automaticky nebo prostřednictvím plánovače.

V tomto případě je vhodnější zašifrovat data účtu (jméno a heslo) a uložit je v zašifrované podobě do textového souboru na disku nebo použít přímo ve skriptu.

Takže pomocí rutiny ConvertFrom-SecureString Heslo můžete převést z formátu SecureString na šifrovaný řetězec (šifrování se provádí pomocí rozhraní Windows Data Protection API - DPAPI). Šifrované heslo můžete zobrazit na obrazovce nebo uložit do souboru:

$ Cred.Password | ConvertFrom-SecureString | Set-Content c: \ ps \ passfile.txt

Chcete-li použít šifrované heslo ze souboru, musíte provést zpětný převod do formátu Securestring pomocí cmdlet ConvertTo-SecureString:

$ username = "corp \ administrator"
$ pass = Get-Content c: \ ps \ passfile.txt | ConvertTo-SecureString
$ creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ username, $ pass

V proměnné $ creds jsme tedy získali objekt PSCredential s uživatelskými přihlašovacími údaji.

Pokud se však pokusíte zkopírovat soubor passfile.txt na jiný počítač nebo jej použít pod jiným uživatelem (nikoli s uživatelem, pod kterým bylo heslo vytvořeno), uvidíte, že proměnná $ creds.password je prázdná a neobsahuje heslo. Skutečností je, že šifrování pomocí DPAPI se provádí pomocí klíčů uložených v uživatelském profilu. Bez těchto klíčů na jiném počítači nelze dešifrovat soubor heslem.
ConvertTo-SecureString: Klíč nelze použít ve specifikovaném stavu.
"Nelze zpracovat argument, protože hodnota argumentu hesla je NULL.
Pro argument hesla zadejte hodnotu jinou než NULL. "

Pokud tedy bude skript spuštěn pod jiným (servisním) účtem nebo na jiném počítači, musíte použít jiný šifrovací mechanismus, který je jedinečný pro DPAPI. Cizí šifrovací klíč lze zadat pomocí parametrů -Klíč nebo -SecureKey.

Například můžete použít PowerShell ke generování 256bitového klíče AES, který můžete použít k dešifrování souboru. Uložte klíč do textového souboru password_aes.key.

$ AESKey = Byte nového objektu [] 32
[Security.Cryptography.RNGCryptoServiceProvider] :: Create (). GetBytes ($ AESKey)
$ AESKey | out-file C: \ ps \ password_aes.key

Nyní můžete heslo uložit do souboru pomocí tohoto klíče:

$ Cred.Password | ConvertFrom-SecureString -Key (get-content C: \ ps \ password_aes.key) | Set-Content c: \ ps \ passfile.txt

Nezapomeňte, že pokud zadáte účet domény ve skriptu Powershell a máte v něm pravidelnou politiku změny hesla, budete muset tento soubor aktualizovat pokaždé, když se heslo změní (pro určité účty můžete vytvořit samostatnou politiku hesel pomocí více hesel FGPP).

Dostali jsme tedy dva soubory: soubor se šifrovaným heslem (passfile.txt) a soubor se šifrovacím klíčem (password_aes.key).

Můžete je přenést do jiného počítače a pokusit se získat heslo ze souboru z prostředí PowerShell (soubor klíče můžete umístit do síťového adresáře)

$ pass = Get-Content c: \ ps \ passfile.txt | ConvertTo-SecureString -Key (get-content \\ Server1 \ Share \ password_aes.key)
$ pass

Pokud se nechcete obtěžovat samostatným souborem s klíčem AES, můžete zašifrovat šifrovací klíč přímo do skriptu. V tomto případě musíte místo klíče v obou případech použít

[Byte []] $ key = (1 ... 16)
$ Cred.Password | ConvertFrom-SecureString -Key $ key | Set-Content c: \ ps \ passfile.txt

A pro dešifrování:

[Byte []] $ key = (1 ... 16)
$ pass = Get-Content c: \ ps \ passfile.txt | ConvertTo-SecureString -Key $ key

Jak vidíte, heslo není prázdné, což znamená, že bylo úspěšně dešifrováno a může být použito na jiných počítačích.

Tip. Je nutné omezit přístup k souboru pomocí klíče AES, aby k němu měl přístup pouze uživatel nebo účet, pod kterým je skript spuštěn. Při umísťování do síťového adresáře pečlivě zkontrolujte oprávnění NTFS v souboru password_aes.key.

A konečně nejsmutnější okamžik. Heslo z objektu PSCredential v paměti je vytaženo velmi jednoduše:

$ Cred.GetNetworkCredential (). Heslo

Heslo můžete extrahovat v textové podobě z SecureString:

$ BSTR = [System.Runtime.InteropServices.Marshal] :: SecureStringToBSTR ($ pass)
[System.Runtime.InteropServices.Marshal] :: PtrToStringAuto ($ BSTR)

Jak pochopíte, je proto nežádoucí ukládat hesla pro privilegované účty, jako jsou Domain Admins, kdekoli kromě DC.

Tip. Chcete-li chránit administrativní záznamy před extrahováním hesel z paměti pomocí nástrojů, jako je Mimikatz, musíte použít komplexní opatření, včetně organizačního plánu.