Categories: PowerShell

Защита и шифрование паролей в скриптах PowerShell

Администраторы часто при написании сценариев автоматизации на PowerShell сохраняют пароли непосредственно в теле PoSh скрипта. Как вы понимаете, это крайне небезопасно при использовании в продуктивной среде, т.к. пароль в открытом виде могут увидеть другие пользователи сервера или администраторы. Поэтому желательно использовать более безопасный метод использования паролей в скриптах PowerShell, или шифровать пароли, если нельзя пользоваться интерактивным вводом.

Безопасно можно запросить от пользователя ввести пароль в скрипте интерактивно с помощью командлета Get-Credential . Например, запросим имя и пароль пользователя и сохраним его в объекте типа PSCredential :

$Cred = Get-Credential

При обращении к свойствам переменной можно узнать имя ползователя, который был указан.

$Cred.Username

Но при попытке вывести пароль, вернется текст System.Security.SecureString, т.к. пароль теперь хранится в виде SecureString.

$Cred.Password

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

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

Также для запроса пароля пользователя можно использовать команлет Read-Host с атрибутом AsSecureString:
$pass = Read-Host "Введите пароль" –AsSecureString

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

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

В этом случае удобнее зашифровать данные учетной записи (имя и пароль) и сохранить их в зашифрованном виде в текстовый файл на диске или использовать непосредственно в скрипте.

Итак, с помощью комадлета ConvertFrom-SecureString можно преобразовать пароль из формата SecureString в шифрованную строку (шифрование выполняется с помощью Windows Data Protection API — DPAPI). Вы можете вывести шифрованный пароль на экран или сохранить в файл:

$Cred.Password| ConvertFrom-SecureString | Set-Content c:pspassfile.txt

Чтобы использовать зашифрованный пароль из файла нужно выполнить обратное преобразование в формат Securestring с помощью командлета ConvertTo-SecureString :

$username = ″corpadministrator″
$pass = Get-Content c:pspassfile.txt | ConvertTo-SecureString
$creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $pass

Таким образом в переменной $creds мы получили объект PSCredential с учетными данными пользователя.

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

Таким образом, если скрипт будет запускаться под другим (сервисным) аккаунтом или на другом компьютере, необходимо использовать другой механизм шифрования, отдичный от DPAPI. Внешний ключ шифрования можно указать с помощью параметров –Key или –SecureKey .

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

$AESKey = New-Object Byte[] 32
[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($AESKey)
$AESKey | out-file C:pspassword_aes.key

Теперь можно сохранить пароль в файл с помощью данного ключа:

$Cred.Password| ConvertFrom-SecureString -Key (get-content C:pspassword_aes.key)| Set-Content c:pspassfile.txt

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

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

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

$pass = Get-Content c:pspassfile.txt | ConvertTo-SecureString -Key (get-content \Server1Sharepassword_aes.key)
$pass

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

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

А для расшифровки:

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

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

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

И напоследок, самый печальный момент. Пароль из объекта PSCredential в открытом виде вытаскивается очень просто:

$Cred.GetNetworkCredential().password

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

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

Как вы понимаете, именно поэтому нежелательно сохранять пароли привилегированных учетных записей, таких как Domain Admins где бы то ни было кроме DC.

Совет. Для защиты административных учтённых записей от извлечения паролей из памяти с помощью утилит подобных Mimikatz нужно использовать комплексные мероприятия , в том числе организационного плана.
admin

Share
Published by
admin

Recent Posts

Apple: история логотипа

Как менялся логотип Apple на протяжении многих лет. Логотип Apple — это не просто символ,…

1 неделя ago

Security Boot Fail при загрузке Acer — решение проблемы

Security Boot Fail при загрузке Acer — решение проблемы При загрузке ноутбука Acer с флешки,…

3 недели ago

Ноутбук не включается — варианты решения

Ноутбук не включается — варианты решения Если при попытке включить ноутбук вы обнаруживаете, что он…

3 недели ago

The AC power adapter wattage and type cannot be determined — причины и решение

The AC power adapter wattage and type cannot be determined — причины и решение При…

3 недели ago

Свистит или звенит блок питания компьютера — причины и решения

Свистит или звенит блок питания компьютера — причины и решения Некоторые владельцы ПК могут обратить…

3 недели ago

Мигает Caps Lock на ноутбуке HP — почему и что делать?

Мигает Caps Lock на ноутбуке HP — почему и что делать? При включении ноутбука HP…

3 недели ago