Поиск по сайту:

Как подписать сценарий PowerShell (PS1) с помощью сертификата подписи кода?


Скрипт или исполняемый файл с цифровой подписью позволяет пользователю убедиться в том, что файл является оригинальным и его код не был изменен третьими лицами. Текущие версии PowerShell имеют встроенные инструменты для подписи кода файлов сценариев *.ps1 с использованием цифровых сертификатов.

Вы можете подписать сценарий PowerShell, используя специальный тип сертификата — Подписание кода. Этот сертификат можно получить во внешнем коммерческом центре сертификации (AC), во внутреннем центре сертификации предприятия или использовать самозаверяющий сертификат.

Предположим, в вашем домене развернуты службы PKI (службы сертификации Active Directory). Давайте запросим новый сертификат, перейдя по адресу https://CA-server-name/certsrv и запросив новый сертификат с помощью Подписание кода. > шаблон (этот шаблон предварительно необходимо включить в консоли центра сертификации).

Также пользователь может запросить сертификат для подписи скриптов PowerShell из оснастки mmc Сертификаты -> Моя учетная запись -> Личные -> Все задачи -> Запросить новый сертификат.

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

Вы можете использовать следующие команды PowerShell, чтобы добавить сертификат к доверенным корневым сертификатам компьютера:

$certFile = Export-Certificate -Cert $cert -FilePath C:\ps\certname.cer
Import-Certificate -CertStoreLocation Cert:\LocalMachine\AuthRoot -FilePath $certFile.FullName

Если вы хотите использовать самозаверяющий сертификат, используйте командлет New-SelfSignedCertificate, чтобы создать сертификат CodeSigning с DNS-именем testPC1:

New-SelfSignedCertificate -DnsName testPC1 -Type CodeSigning
$cert = New-SelfSignedCertificate -Subject "Cert for Code Signing” -Type CodeSigningCert -DnsName test1 -CertStoreLocation cert:\LocalMachine\My

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

certmgr.msc

).

После получения сертификата вы можете настроить политику выполнения сценариев PowerShell, чтобы разрешить запуск только подписанных сценариев. По умолчанию для политики выполнения PowerShell в Windows 10/Windows Server 2016 установлено значение Ограничено (блокирует выполнение любых сценариев PowerShell).

File C:\ps\script.ps1 cannot be loaded because running scripts is disabled on this system.

Чтобы разрешить запуск только подписанных сценариев PS1, вы можете изменить PowerShell Eecution Policy на AllSigned или RemoteSigned (с той лишь разницей, что RemoteSigned требует подписи только для сценариев, загруженных из Интернета):

Set-ExecutionPolicy AllSigned -Force

В этом режиме при запуске неподписанных PowerShell-скриптов появляется ошибка:

File C:\script.ps1 cannot be loaded. The file script.ps1 is not digitally signed. You cannot run this script on the current system.

Вы также можете разрешить запуск подписанных сценариев PowerShell, используя параметр групповой политики Включить выполнение сценариев в разделе «Конфигурация компьютера» -> «Политики» -> «Административные шаблоны» -> «Компоненты Windows» -> «Windows PowerShell». Измените значение параметра на Разрешить только подписанные скрипты.

Теперь перейдем к подписанию файла сценария PowerShell. Прежде всего вам необходимо получить сертификат CodeSign из локального хранилища сертификатов текущего пользователя. Для начала перечислим все сертификаты, которые можно использовать для подписи кода:

Get-ChildItem cert:\CurrentUser\my -CodeSigningCert

В нашем случае мы возьмем первый сертификат из личного хранилища сертификатов пользователя и сохраним его в переменной $cert:

$cert = (Get-ChildItem cert:\CurrentUser\my -CodeSigningCert)[0]

Если вы переместили свой сертификат в хранилище доверенных корневых сертификатов, используйте следующую команду:

$cert = (Get-ChildItem Cert:\LocalMachine\AuthRoot -CodeSigningCert)[0]

Затем вы можете использовать этот сертификат для подписи файла PS1 с помощью сценария PowerShell:

Set-AuthenticodeSignature -Certificate $cert -FilePath C:\PS\testscript.ps1

Также можно использовать следующую команду (в данном случае мы выбираем самозаверяющий сертификат, созданный ранее DNSName):

Set-AuthenticodeSignature C:\PS\test_script.ps1 @(gci Cert:\LocalMachine\AuthRoot -DnsName testPC1 -codesigning)[0]

Подсказка. Командлет Set-AuthenticodeSignature имеет специальный параметр TimestampServer, который указывает URL-адрес временной метки службы. Если этот параметр оставить пустым, сценарий PS прекратит работу после истечения срока действия сертификата. Например, вы можете установить сервер временных меток следующим образом:

-TimestampServer "http://timestamp.verisign.com/scripts/timstamp.dll"

Если вы попытаетесь использовать общий сертификат SSL/TLS для подписи скрипта, появится ошибка:

Set-AuthenticodeSignature: Cannot sign code. The specified certificate is not suitable for code signing.

Вы можете подписать все файлы сценариев PowerShell одновременно в папке:

Get-ChildItem c:\ps\*.ps1| Set-AuthenticodeSignature -Certificate $Cert

Теперь вы можете проверить, правильно ли подписан файл сценария PowerShell. Вы можете использовать командлет Get-AuthenticodeSignature или открыть свойства файла PS1 и перейти на вкладку Цифровые подписи.

Get-AuthenticodeSignature c:\ps\test_script.ps1 | ft -AutoSize

Если

UnknownError

предупреждение появляется при выполнении команды Set-AuthenticodeSignature, то этот сертификат не является доверенным, поскольку находится в личном хранилище сертификатов пользователя.

Вам необходимо переместить его в Доверенные корневые сертификаты (не забывайте периодически проверять хранилище сертификатов Windows на наличие подозрительных сертификатов и обновлять списки доверенных корневых сертификатов):

Move-Item -Path $cert.PSPath -Destination "Cert:\LocalMachine\Root"

Теперь при проверке подписи файла PS1 должен возвращаться статус Valid.

При подписании файла сценария PowerShell командлет Set-AuthenticodeSignature добавляет блок цифровой подписи в конец текстового файла PS1:

# SIG # Begin signature block
...........
...........
# SIG # End signature block

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

При первой попытке запуска скрипта появится предупреждение:

Do you want to run software from this untrusted publisher?
File C:\PS\script.ps1 is published by CN=testPC1 and is not trusted on your system. Only run scripts from trusted publishers.

Если вы выберете [A] Всегда запускать при первом запуске сценария, при следующем запуске сценария, подписанного с использованием этого сертификата, предупреждение больше не появится.

Чтобы это предупреждение не появлялось, вам также необходимо скопировать сертификат в центр сертификации Доверенные издатели. Используйте операцию копирования и вставки в консоли «Сертификаты», чтобы скопировать сертификат в «Доверенные издатели» -> «Сертификаты».

Подписанный сценарий PowerShell теперь будет выполняться без отображения уведомления ненадежного издателя.

Совет. Корневой сертификат CA и сертификат, используемый для подписи сценария, должны быть надежными (в противном случае сценарий не запустится). Вы можете централизованно развертывать сертификаты на компьютерах домена с помощью объекта групповой политики. Сертификаты необходимо разместить в следующих разделах открытого ключа объекта групповой политики: Конфигурация компьютера -> Политики -> Настройки Windows -> Настройки безопасности -> Политики открытого ключа -> Доверенные корневые центры сертификации и Надежные издатели.

Если корневой сертификат недоверенный, то при запуске скрипта PowerShell появится ошибка:

A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.

Что произойдет, если вы измените код подписанного файла сценария PowerShell? Попытка его запуска будет заблокирована с уведомлением об изменении содержимого скрипта.

File xx.ps1 cannot be loaded. The contents of file xx.ps1 might  have been changed by an unauthorized user or process, because the hash of the file does not match the hash stored in the digital signature. The script cannot run on the specified system.

Попробуйте проверить подпись скрипта с помощью командлета Get-AuthenticodeSignature. Если вычисленный хэш не совпадает с хешем в подписи, сообщение

HashMismatch

появляется.

Таким образом, любая модификация кода подписанного скрипта PS1 потребует его переподписания.

Статьи по данной тематике