Защита на паролата и криптиране в скриптове на PowerShell

Често администраторите пишат пароли директно в тялото на скрипта на PoSh, когато пишат скриптове за автоматизация в PowerShell. Както знаете, това е изключително опасно, когато се използва в продуктивна среда, защото паролата може да се види в ясна форма от други потребители или администратори на сървъра. Ето защо е препоръчително да използвате по-сигурен метод за използване на пароли в скриптове на PowerShell или да шифровате паролите, ако не можете да използвате интерактивен вход.

Безопасно е да помолите потребителя да въведе паролата в скрипта интерактивно, като използва командлета Вземете идентификационни данни. Например, ние искаме потребителското име и парола и ги запазваме в обект от тип PSCredential:

$ Cred = Получете доверие

Когато осъществявате достъп до свойствата на променлива, можете да разберете името на потребителя, който е бил посочен.

$ Cred.Username

Но когато се опитате да покажете паролата, текстът System.Security.SecureString ще бъде върнат, защото паролата вече се съхранява като SecureString.

$ Cred.Password

Обектът PSCredential, който записахме в променлива $ Cred, вече може да се използва в командлети, които поддържат този тип обект.

Параметрите $ Cred.Username и $ Cred.Password могат да се използват в командлети, които не поддържат PSCredential обекти, но изискват отделно потребителско име и парола.

Можете също да използвате командлета Read-Host с атрибута AsSecureString, за да поискате потребителска парола:
$ pass = Прочетете-домакин "Въведете парола" -AsSecureString

В този случай вие също няма да можете да видите съдържанието на променливата $ pass, в която се съхранява паролата.

В горните методи за използване на парола в скриптове на PowerShell беше прието, че паролата е въведена интерактивно при изпълнение на скрипта. Но този метод не е подходящ за различни сценарии, които се изпълняват автоматично или чрез програмиста.

В този случай е по-удобно да шифровате данните на акаунта (име и парола) и да ги запишете в криптиран вид в текстов файл на диск или да използвате директно в скрипта.

Така че, използвайки командлета ConvertFrom-SecureString Можете да конвертирате паролата от SecureString формат в шифрован низ (криптирането се извършва с помощта на API за защита на данните на Windows - DPAPI). Можете да покажете шифрованата парола на екрана или да я запишете във файл:

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

За да използвате криптирана парола от файл, трябва да извършите обратната конверсия във формат Securestring, като използвате командлета ConvertTo-SecureString:

$ username = "corp \ administrator"
$ pass = Get-Content c: \ ps \ passfile.txt | ConvertTo-SecureString
$ creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ потребителско име, $ pass

Така в променливата $ creds получихме обект PSCredential с потребителски идентификационни данни.

Ако обаче се опитате да копирате файла passfile.txt на друг компютър или да го използвате под друг потребител (не този, под който е създадена паролата), ще видите, че променливата $ creds.password е празна и не съдържа парола. Факт е, че криптирането чрез DPAPI се извършва с помощта на ключовете, съхранени в потребителския профил. Без тези ключове на друг компютър не можете да декриптирате файл с парола.
ConvertTo-SecureString: Ключът не може да се използва в посоченото състояние.
„Не мога да обработя аргумента, защото стойността на аргумента за паролата е NULL.
Задайте стойност, която не е NULL за аргумента за паролата. "

По този начин, ако скриптът ще се изпълнява под различен (услуга) акаунт или на друг компютър, трябва да използвате различен механизъм за криптиране, който е уникален за DPAPI. Чуждият ключ за криптиране може да бъде зададен с помощта на параметрите -ключ или -SecureKey.

Например, можете да използвате PowerShell за генериране на 256-битов AES ключ, който можете да използвате за дешифриране на файл. Запазете ключа към текстовия файл password_aes.key.

$ AESKey = Байт за нов обект [] 32
[Security.Cryptography.RNGCryptoServiceProvider] :: Създаване (). GetBytes ($ AESKey)
$ AESKey | изходящ файл C: \ ps \ password_aes.key

Сега можете да запазите паролата във файл с този ключ:

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

Не забравяйте, че ако посочите домейн акаунт в скрипта на Powershell и имате правилна политика за промяна на паролата върху него, ще трябва да актуализирате този файл при всяка промяна на паролата (можете да създадете отделна политика за парола за определени акаунти, като използвате няколко правила за паролата на FGPP.

Така получихме два файла: файл с криптирана парола (passfile.txt) и файл с ключ за криптиране (password_aes.key).

Можете да ги прехвърлите на друг компютър и да опитате да получите паролата от файла от PowerShell (можете да поставите ключовия файл в мрежовата директория)

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

Ако не искате да се занимавате с отделен файл с AES ключ, можете да шиете ключа за шифроване директно в скрипта. В този случай, вместо ключа и в двата случая, трябва да използвате

[Байт []] $ ключ = (1 ... 16)
$ Cred.Password | ConvertFrom-SecureString -Key $ key | Set-Content c: \ ps \ passfile.txt

И за дешифриране:

[Байт []] $ ключ = (1 ... 16)
$ pass = Get-Content c: \ ps \ passfile.txt | ConvertTo-SecureString -Key $ ключ

Както можете да видите, паролата не е празна, което означава, че е дешифрирана успешно и може да се използва на други компютри.

съвет. Необходимо е да се ограничи достъпът до файла с клавиша AES, така че само потребителят или акаунтът, под който се изпълнява скриптът, да има достъп до него. Внимателно проверете разрешенията за NTFS във файла password_aes.key, когато го поставите в мрежовата директория.

И накрая, най-тъжният момент. Паролата от PSCredential обект в прозореца се изважда много просто:

$ Cred.GetNetworkCredential (). Парола

Можете да извлечете паролата в текстова форма от SecureString:

$ BSTR = [System.Runtime.InteropServices.Marshal] :: SecureStringToBSTR ($ пропуск)
[System.Runtime.InteropServices.Marshal] :: PtrToStringAuto ($ BSTR)

Както разбирате, затова е нежелателно да запазвате пароли за привилегировани акаунти, като администратори на домейни, където и да е, освен DC.

На Съвета. За да защитите административните записи от извличане на пароли от паметта с помощта на помощни програми като Mimikatz, трябва да използвате цялостни мерки, включително организационен план.