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

Да, бесчисленные руководства по кибербезопасности не устают повторять, что скрипты, требующие повышенных разрешений, должны запускаться только в защищенных системах, из каталогов, в которые имеют доступы только администраторы. Однако, при пентестах сетей Windows постоянно приходится сталкиваться со скриптами, содержащими жестко зашитые ученые данные. Причем очень часто это данные от привилегированных учеток. Очень часто так получается, что со временем уровень защищенности скриптов ослабевает. Бесчисленные копии, бекапы, старые версии – доступ к ним уже не так сильно ограничивается, в результате чего посторонним проще получить к ним доступ.

Поэтому администраторам важно помнить, что жестко вводить пароль в скрипт - плохая идея. Хотя можно зашифровать пароль в файл, как показано на рисунке, такие файлы лишь ненамного лучше, чем зашифрованный пароль с открытым текстом.

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

Поэтому нужен более безопасный способ предоставления учетных данных автоматизированным сценариям PowerShell. В доменной инфраструктуре Active Directory мы можем использовать Windows Credential Manager для получения разрешений.

Хотя Windows Credential Manager существует в автономных системах, иногда его поведение может быть довольно странным. Например, если автономная система настроена без пароля (вообще без аутентификации), кэшированные учетные данные в диспетчере учетных данных часто не предоставляют доступ к подключенным сетевым дискам, даже если сохраненные учетные данные верны.

Специальные учетки

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

Принцип минимальных привилегий предполагает, что учетная запись должна иметь только те разрешения, которые необходимы для выполнения поставленной задачи, – ни больше, ни меньше.

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

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

Настройка Windows Credential Manager

Чтобы настроить PowerShell на использование сохраненных учетных данных, необходимо открыть сеанс с повышенными правами (временно войти в систему с правами администратора) и установить модуль Credential Manager. Для установки модуля используйте следующую команду:

Install-Module CredentialManager

На скриншоте PowerShell показано, что модуль Credential Manager успешно установлен

После установки модуля вы можете добавить сохраненные учетные данные в Windows Credential Manager. Это уже можно делать в окне PowerShell без привилегированных прав доступа, используя учетную запись обычного пользователя. В переменной $Password мы сохраняем пароль.

$Username = PowerShellDemo@poseylab.com

$Password = ConvertTo-SecureString “P@ssw0rd” -AsPlainText -Force

$Credential = New-Object -TypeName PSCredential -ArgumentList $UserName, $Password

New-StoredCredential -Target PowerShell -Credential $Credential -Type Generic -Persist LocalMachine 

Стоит отметить, что параметр Target, используемый в последней команде, по сути, присваивает понятное имя учетным данным (PowerShell). В принципе, вы можете назвать целевой объект как угодно. Однако важно запомнить присвоенное целевое имя, поскольку вам нужно будет ссылаться на него всякий раз, когда вы будете использовать сохраненные учетные данные.

На скриншоте ниже показано, что учетные данные были записаны в диспетчер учетных данных Windows.

Соответственно, для получения сохраненных учетных данных достаточно просто использовать эту команду:

Get-StoredCredential -Target <Target Name>

Теперь давайте рассмотрим практический пример, а именно создание нового пользователя Active Directory из сеанса PowerShell.  При этом, у нас не будет прав доступа, позволяющих выполнить данную операцию, и нам придется использовать сохраненные учетные данные. Для этого добавим параметр -Credential в командлет New-ADUser, чтобы указать сохраненные учетные данные:

$Cred = Get-StoredCredential -Target PowerShell

 New-ADUser -Credential $Cred -Name “TestUser” -SamAccountName “TestUser” -UserPrincipalName TestUser@poseylab.com -AccountPassword (ConvertTo-SecureString “P@ssw0rd” -AsPlainText -Force) -Enabled $True

Следует отметить, что, хотя в команде New-ADUser отображается пароль в виде открытого текста, этот пароль присваивается новой учетной записи пользователя, которую мы создаем. Он не используется для повышения прав доступа, чтобы мы могли создать учетную запись. Повышение привилегий осуществляется с помощью параметра -Credential.

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

 Get-ADUser -Filter {SamAccountName -eq “TestUser”}

 Вот что мы получили в итоге:

Заключение

Используя Windows Credential Manager, мы можем использовать в скриптах Powershell привилегированные учетные записи Active Directory, не снижая при этом общий уровень защищенности инфраструктуры.


18 июня для системных администраторов пройдет открытый урок, посвященный GPO: «Групповые политики как средство автоматизации». Записаться бесплатно можно на странице курса «Администратор Windows».

Комментарии (7)


  1. say_TT_plz
    14.06.2024 10:21
    +2

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

    $pwd = read-host "password:" -AsSecureString

    $Encrypted = ConvertFrom-SecureString -SecureString $pwd Для шифрования используется API защиты данных Windows (DPAPI), расшифровать можно только из профиля пользователя(сеанса). Если просто получить доступ к строке, то без доступа к учетке пользователя не получится расшифровать.

    С тем же успехом можно утверждать, что пароль можно дернуть из кред менеджера через

    $Cred = Get-StoredCredential -Target PowerShell

    $pass = [Net.NetworkCredential]::new('', $cred.Password).Password


    1. grumbler70
      14.06.2024 10:21

      +1
      К тому же эту шифрованную строку можно расшифровать только на той же машинке, где её создали. Запустите на двух разных машинах под одной и той же доменной учетной записью и сравните выдачу $SecureString:

      $PlainPassword = "P@ssw0rd!"
      $SecurePassword = ConvertTo-SecureString $PlainPassword -AsPlainText -Force
      $SecurePassword
      $SecureString = ConvertFrom-SecureString -SecureString $SecurePassword
      $SecureString
      $secString2 = ConvertTo-SecureString -String $SecureString
      $PlainPasswordRecovered =  [Net.NetworkCredential]::new('', $SecString2).Password
      $PlainPasswordRecovered


  1. DikSoft
    14.06.2024 10:21

    Как вариант, можно запускать скрипт из планировщика под сервисной учетной записью, сохраняя её пароль, а креды этой учетки для использования в явном виде в скрипте получать командой:

     $cred = [System.Net.CredentialCache]::DefaultNetworkCredentials


  1. exchange12rocks
    14.06.2024 10:21

    Может быть в 2024 году лучше использовать https://github.com/powershell/SecretManagement ?


  1. Kononvaler
    14.06.2024 10:21

    У нас выключили в АД повершел совсем для безопасности.

    Для скриптов есть линукс..


    1. DikSoft
      14.06.2024 10:21
      +1

      У нас выключили в АД повершел совсем для безопасности.

      Странное решение. У вас плоская сеть, нет PKI, безопасники ещё учатся?

      Для скриптов есть линукс..

      PowerShell скрипты, оперирующие объектами, а не строками с адским выводом и парсингом, на порядок удобнее для административных и регламентных задач Windows инфраструктуры, чем бардачный bash-инг / питонинг.


      1. Kononvaler
        14.06.2024 10:21

        Ну конечно, виндус же в разы безопаснее.