Запретить чтение сценария PowerShell

#powershell

#powershell

Вопрос:

У меня есть приведенный ниже скрипт PowerShell (myscript.ps1), в котором я запрашиваю имя пользователя и пароль. В зависимости от имени пользователя и пароля он копирует файл в определенное место назначения.

 $credentials = Get-Credential
if ($credentials.Username -eq "user1" -And $credentials.GetNetworkCredential().password -eq "pass1") 
{ Copy-Item "test1.pdf" "testtest1.pdf"; } 
else 
{ Copy-Item "test2.pdf" "testtest2.pdf"; }
  

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

PS2EXE

Я нашел решение, найденное здесь, которое преобразует сценарий PowerShell в .exe файл. При первоначальном запуске сценария с помощью PowerShell появляется диалоговое окно, позволяющее ввести имя пользователя и пароль:

Диалоговое окно получения учетных данных

После создания .exe и при его запуске диалоговое окно учетных данных больше не отображается. Вместо этого на консоли появляется надпись «Учетные данные:»

Консоль PS2EXE

Я не знаю, почему? Я хочу, чтобы форма учетных данных по-прежнему отображалась при запуске exe. Какие-нибудь мысли, пожалуйста?

Комментарии:

1. Вы не можете защитить скрипт. Но вы можете сохранить uname и пароль в зашифрованном файле и прочитать их во время выполнения.

2. @RyanBemrose не могли бы вы прислать мне ссылку, как это можно сделать, пожалуйста?

3. Это звучит небезопасно, в этом случае скрипту потребуется жестко заданный ключ шифрования, что так же плохо, как и наличие пароля. Почему бы просто не применить ACL к файлу сценария?

4. В этой статье показано, как хранить зашифрованные пароли в диспетчере учетных данных Windows или в защищенной строке. Вы можете найти в Интернете «безопасный пароль powershell» для других руководств по хранению паролей в зашифрованном файле.

5. @Burt_Harris Можно ли применить ACL, который позволяет выполнить файл, но не читать его?

Ответ №1:

Вопрос: Почему EXE запрашивает «Учетные данные»?

Это не ответ на реальный вопрос и основано на догадках о PS2EXE, но я надеюсь, что это полезно для устранения некоторой путаницы.

После краткого просмотра страницы PS2EXE, на которую дана ссылка выше, кажется, что эта утилита кодирует скрипт в Base64 и связывает его с облегченным (?) пользовательским хостом PowerShell. При запуске, я полагаю, EXE запускает хост, декодирует скрипт и запускает его.

Проблема в том, что Get-Credential командлет выполняется на узле PS, который, вероятно, не может взаимодействовать с рабочим столом. То есть он не может отправить запрос GUI для ввода учетных данных. Поэтому ему необходимо запросить свойство Credential в командной строке, объясняя, почему вы видите такое поведение.

Обходной путь с помощью Read-Host?

Вместо того, чтобы пытаться использовать Get-Credential запрос имени пользователя и пароля, вы могли бы использовать то, что, похоже, делает PS2EXE, и просто использовать Read-Host :

 $UserName = Read-Host "Enter username"
$Password = Read-Host "Enter password" -AsSecureString

$Credentials = New-Object System.Management.Automation.PSCredential $UserName,$Password

if ($credentials.Username -eq "user1" -And $credentials.GetNetworkCredential().password -eq "pass1") 
{ ... }
  

Использование -AsSecureString скроет пароль на экране. Переменная $Password будет иметь тип System.Security.SecureString , который можно использовать для создания объекта PSCredential, как показано.

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

И просто для ясности: ничто из этого и близко не подходит к передовой практике обеспечения безопасности. Если вам требуется проверка подлинности / авторизация для этих действий, сделайте шаг назад и посмотрите на проблему еще раз.

Обходной путь с двумя сценариями?

Похоже, что PS2EXE не поддерживает -AsSecureString так же, как обычный PowerShell, то есть он не скрывает символы. Возможным обходным путем для этого было бы собрать имя пользователя и пароль от пользователя в одном скрипте, а затем передать их в скрипт, преобразованный в PS2EXE, для обработки.

Запуск-MyScript.ps1:

 $Credentials = Get-Credential
amp; MyScript.exe $Credentials.Username $Credentials.Password
  

MyScript.exe (скрыто с помощью PS2EXE):

 param($Username,$Password)

$Credentials = New-Object System.Management.Automation.PSCredential $Username,$Password

if ($Credentials.Username -eq "user1" -and
  $Credentials.GetNetworkCredential().password -eq "pass1")
{
  ...
}
  

Пользователь запускает Launch-MyScript.ps1 и завершает запрос пароля. Затем исполняемый файл запускается автоматически с именем пользователя и паролем, переданными в качестве аргументов. Обратите внимание, что, как показано выше, пароль представляет собой защищенную строку. Протестируйте это; я не использую PS2EXE, так что на данный момент это теоретическое решение.

Если вы не можете передать $Password по конвейеру в виде защищенного строкового объекта, вы можете преобразовать его в текст с помощью ConvertFrom-SecureString в первом скрипте, затем преобразовать его обратно с помощью ConvertTo-SecureString во втором.

Комментарии:

1. спасибо за объяснение. Итак, что мне делать, когда в командной строке появится свойство Credential?

2. Если запросы командной строки приемлемы, то вы могли бы запрашивать имя пользователя и пароль по отдельности с помощью Read-Host и вообще отказаться от любых попыток использования объекта PSCredential.

3. не могли бы вы показать мне, как, пожалуйста? поскольку я не знаком с этим. Также нет способа преобразовать его в .exe и появляется ли форма Get-Credential?

4. Обновлено по ответу. Мне действительно кажется, что мы идем по неверному пути, чтобы решить то, что вы в конечном итоге пытаетесь сделать.

5. Большое вам спасибо. Я сделал это, но теперь я пытаюсь замаскировать пароль, но это не работает, используя $Password = Read-Host -assecurestring "Enter password" какие-либо мысли?

Ответ №2:

Согласно этой статье http://windowsitpro.com/powershell/protect-your-powershell-scripts сначала вам следует установить для политики выполнения ur значение AllSigned с помощью Set-ExecutionPolicy AllSigned, затем создать сертификат с помощью командлета makecert.

Затем вы можете подписать отдельный скрипт с помощью командлета Set-AuthenticodeSignature или использовать файл .pfx для подписи скрипта, который кажется еще более безопасным.

Надеюсь, это немного поможет.

Комментарии:

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