Как зашифровать пароли в PowerShell

How to Encrypt Passwords in PowerShellДанный материал является переводом оригинальной статьи "Altaro : Luke Orellana : How to Encrypt Passwords in PowerShell".

С точки зрения компании - MSP (Managed Service Provider), управление паролями в скриптах PowerShell может быть сложной задачей. Всегда есть риск, что кто-то может найти пароль, просто получив его из кода. Тем не менее, существуют определенные сценарии, которые требуют хранить где-то пароль и ссылаться на него в скрипте для аутентификации. Например, допустим, вам необходимо регулярно запускать сценарий для группы серверов, не подключенных к домену, или вы хотите разрешить пользователям запускать определенную задачу с повышенными правами, но не хотите давать им учетные данные с повышенными правами. Существует несколько решений, связанных с этим, но следует помнить про правильный баланс между безопасностью и доступностью, и требуется определенное понимание того, является ли решение достаточно безопасным, чтобы его можно было принять. К счастью, с PowerShell есть несколько хитростей, которые мы можем использовать, чтобы скрыть наши пароли, и хотя они не являются на 100% безопасными, это все равно снижает риск.

Как указывает здравый смысл, вы не будете "жестко прописывать" пароли в любом виде сценария, как показано ниже:

$password = "MYPASSWORD"

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

Использование планировщика задач

Это самый простой метод из всех. При настройке задачи планировщик задач позволяет сохранить учетные данные вашей учетной записи и выполнить указанный сценарий, используя следующие учетные данные:

Save password in Windows Task Scheduler

Это полезно при запуске сценария, которому требуется доступ к общим файлам или любой конечной точке, прошедшей проверку подлинности домена. Однако планировщик задач будет хранить только 1 набор учетных данных и использует API защиты данных Windows для шифрования / дешифрования пароля. Этот метод использует учетные данные для входа в учетную запись пользователя в качестве "ключа" для доступа к сохраненному паролю. Преимущество этого метода заключается в том, что, поскольку учетные данные для входа хранятся локально на сервере, сценарий можно запустить только на сервере, на котором есть кэшированные учетные данные и настроенный планировщик задач.

Создание зашифрованного файла паролей

Другой способ скрыть пароли, используемые в наших скриптах PowerShell, - это создать зашифрованный файл паролей и затем ссылаться на этот файл паролей в вашем скрипте. Как и планировщик заданий, этот метод будет шифроваться с использованием API защиты данных Windows, что также означает, что мы попадаем в те же ограничения, что и возможность доступа к файлу паролей только с одной учетной записи и только на том же устройстве, на котором был создан файл паролей. Учетные данные для входа пользователя по сути являются "ключом" к файлу паролей. Однако этот метод позволяет нам сохранять несколько паролей и ссылаться на них в нашем скрипте.

Для начала мы создадим файл паролей, введя следующую команду в консоли PowerShell. Также обратите внимание, что учетная запись пользователя, которую вы используете для создания файла пароля, - это та же учетная запись, которую необходимо использовать для открытия файла пароля (помните API защиты данных Windows?):

(Get-Credential).password | ConvertFrom-SecureString | Set-Content "C:\Passwords\password.txt"

Вы получите запрос на ввод пароля, введёте свои учетные данные, которые хотите сохранить. В нашем примере, зашифрованный файл паролей будет сохранен в "C:\Passwords\password.txt":

PowerShell ConvertFrom-SecureString save to File

Когда мы открываем файл, мы видим, что наши учетные данные зашифрованы:

PowerShell ConvertFrom-SecureString File Content

Теперь, как мы получаем обратно эти учетные данные? Легко, если нам когда-нибудь понадобится получить их, мы включим следующие команды в наши скрипты, чтобы предоставить полномочия:

$password = Get-Content "C:\Passwords\password.txt" | ConvertTo-SecureString 
$credential = New-Object System.Management.Automation.PsCredential("Luke",$password)

Затем просто передайте $credential всем командлетам, которым требуется pscredential для аутентификации. Если мы посмотрим, что находится в переменной $credential, то увидим наше имя пользователя и его зашифрованный пароль:

System.Management.Automation.PsCredential

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

Создание файла ключа и файла пароля

С PowerShell мы можем сгенерировать 256-битный ключ шифрования AES и использовать этот ключ для доступа к нашему файлу паролей. Сначала мы вводим следующие команды для создания нашего файла ключей. Вы можете взять этот ключ и поместить его в общий сетевой ресурс, предоставив доступ к ключу только определенным пользователям вместе с файлом паролей. Но в этом примере мы просто сохраним его в C:\Passwords с нашим файлом паролей:

$Key = New-Object Byte[] 32
[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($Key)
$Key | Out-File C:\passwords\aes.key

Если мы откроем aes.key в блокноте, мы увидим, что наш ключ теперь сгенерирован:

Security.Cryptography.RNGCryptoServiceProvider

Теперь мы создаем файл паролей, как и выше, но используем параметр -Key, чтобы указать, что мы хотим использовать ключ, и ввести местоположение файла ключа. Затем, создаем файл паролей. В этом примере мы выведем файл паролей в наш каталог C:\Passwords:

(Get-Credential).Password | ConvertFrom-SecureString -key (get-content C:\passwords\aes.key) | Set-Content "C:\Passwords\password.txt"

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

$password = Get-Content C:\Passwords\password.txt | ConvertTo-SecureString -Key (Get-Content C:\Passwords\aes.key)
$credential = New-Object System.Management.Automation.PsCredential("Luke",$password)

Когда мы смотрим на данные внутри переменной $credential, то видим, что у нас теперь есть имя пользователя и пароль.

Заключение

У каждого метода есть свои плюсы и минусы. Однако, имейте в виду, что все эти способы не являются 100-процентной защитой. Поэтому мы бы не советовали делать это с учетной записью администратора домена. Просто достаточный доступ (JEA — Just enough access) - это способ выполнить задачу, поэтому стоит  создать учетную запись с минимально достаточным доступом, чтобы делать то, что нужно.

Добавить комментарий