Как подписать скрипт powershell
Перейти к содержимому

Как подписать скрипт powershell

  • автор:

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

date

24.02.2021

user

itpro

directory

PowerShell, Windows 10, Windows Server 2016

comments

комментариев 17

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

Для подписывания скриптов PowerShell нужно использовать специальный сертификат типа Code Signing. Этот сертификат может быть получен от внешнего коммерческого центра сертификации, внутреннего корпоративного Certificate Authority (CA) или можно даже самоподписанный сертификат.

Предположим, у нас в домене развернуты службы PKI — Active Directory Certificate Services. Запросите новый сертификат, перейдя на страницу https://CA-server-name/certsrv . Нужно запросить новый сертификат с шаблоном Code Signing (данный шаблон должен быть предварительно разрешен в консоли Certification Authority).

Шаблон сертификата code signing

Также пользователь может самостоятельно запросить сертификат для подписи PowerShell скриптов из mmc оснастки Certificates -> My user account -> Personal -> All task -> Request New Certificate.

консоль certificates запросить новый сертификат

Если вы запросили сертификат вручную, у вас должен получится файл сертификат 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 c DNS именем test1:

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

После генерации сертификата, его нужно будет в консоли управления хранилищем сертификатов ( certmgr.msc ) перенести из контейнера Intermediate в Trusted Root.

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

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

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

Set-ExecutionPolicy AllSigned –Force

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

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

Разрешить выполнение подписанных скриптов PowerShell также можно с помощью параметра групповых политик Включить выполнение сценариев (Turn on Script Execution) в разделе GPO Computer Configuration -> Policies -> Administrative Templates -> Windows Components -> Windows PowerShell. Измените значение параметра на ” Разрешать только подписанные сценарии ” (Allow only signed scripts).

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

Get-ChildItem cert:\CurrentUser\my –CodeSigningCert

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

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

Затем можно использовать данный сертификат, чтобы подписать файл PS1 с вашим скриптом PowerShell:

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

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

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

Совет. У командлета Set-AuthenticodeSignature есть специальный параметр TimestampServer, в котором указывается URL адрес Timestamp службы. Если этот параметр оставить пустым, то PS скрипт перестанет запускаться после истечения срока действия сертификата. Например -TimestampServer «http://timestamp.verisign.com/scripts/timstamp.dll» .

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

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

Можно подписать сразу все файлы PowerShell скриптов в папке:

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

Теперь можно проверить, что скрипт подписан. Можно использовать командлет Get-AuthenticodeSignature или открыть свойства PS1 файла и перейдти на вкладку Digital Signatures.

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

powershell скрипт с цифровой подписью

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

Set-AuthenticodeSignature UnknownError

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

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

используем командлет Set-AuthenticodeSignature чтобы подписать файл с powershell скриптом

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

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

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

PS1 файл с блоком цифровой подписи # SIG # Begin signature block

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

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

Если выбрать [A] Always run, то при запуске любых PowerShell скриптов, подписанных этим сертификатом, предупреждение появляться больше не будет.

ps1 is published by CN=test1 and is not trusted on your system. Only run scripts from trusted publishers

Чтобы это предупреждения не появлялось нужно скопировать сертификат также в раздел Trusted Publishers. С помощью обычной операции Copy-Paste в консоли Certificates скопируйте сертификат в раздел Trusted Publishers -> Certificates.

скопировать сертфика codesigning в Trusted Publishers

Теперь подписанный PowerShell скрипт будет запускаться без уведомления об untrusted publisher.

Совет. Корневой сертификат CA и сертификат, которым подписан скрипт, должен быть доверенным (иначе скрипт вообще не запустится). Вы можете централизованно установить сертификаты на все компьютеры домена с помощью GPO. Сертфикаты нужно поместить в следующие разделы GPO:

Computer Configuration -> Policies -> Windows Settings -> Security Settings -> Public Key Policies -> Trusted Root Certification Authorities и Trusted Publishers.

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

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

Что произойдет, если изменить код подписанного файла со скриптом PowerShell? Его запуск будет заблокирован, с ошибкой, что содержимое скрипта было изменено:

C:\PS\test_script.ps1 : File C:\PS\test_script.ps1 cannot be loaded. The contents of file C:\PS\test_script.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.

ошибка при запуске модифицированного powershell скрипта The contents of file have been changed

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

Get-AuthenticodeSignature ошибка HashMismatch

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

Предыдущая статьяПредыдущая статья Следующая статья Следующая статья

Подписать PowerShell скрипт с помощью сертификата

PowerShell

В домене усилили безопасность и запретили запуск PowerShell скриптов (ps1). Все мои скрипты на серверах перестали работать. Спорить бесполезно, нужно подписать все PowerShell скрипты с помощью сертификата.

Для подписывания PowerShell скриптов нужно использовать специальный сертификат типа Code Signing. Для того чтобы скрипты работали на всех серверах домена, этот сертификат должен быть получен от внутреннего корпоративного центра сертификации Certificate Authority (CA).

Коллеги уже разрешили тип сертификата Code Signing в центре сертификации и активировали соответствующий шаблон.

ssl

Подписывать сертификаты я буду на своём компьютере, поэтому нужно сгенерировать сертификат. Открываем оснастку mmc, добавляем «Сертификаты(текущий пользователь)».

powershell

В личных сертификатах делаем запрос запрос на создание нового сертификата.

powershell

powershell

powershell

powershell

Делаем запрос на Code Signing сертификат, ставим галку. Заявка.

powershell

powershell

powershell

Таких сертификатов может быть несколько. Посмотреть список сертификатов, которыми можно подписать:

Get-ChildItem cert:\CurrentUser\my -CodeSigningCert

powerchell

У меня один сертификат, загоняем первый серт в переменную:

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

Подписываем наш PowerShell скрипт:

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

powershell

Можно подписать сразу все файлы в папке:

Get-ChildItem C:\PS\*.ps1 | Set-AuthenticodeSignature -Certificate $cert

Копирую сертификат на нужные сервера и проверяю, что он подписан:

Get-AuthenticodeSignature C:\PS\netbox_vm_backup_schedule.ps1 | ft -AutoSize

powershell

На одном сервере Valid.

powershell

А на другом HashMismatch. Вот это поворот. Оказалось, что в коде скрипта у меня комментарии на кириллице, а на одном из серверов нет русского языка. вот и комментируй после этого. Проблема устраняется накатыванием русского языка на сервер.

При подписывании PowerShell скрипта, в код скрипта добавляется в конец блок сигнатуры цифровой подписи:

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

powershell

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

Do you want to run software from this untrusted publisher?

powershell

Выбираем [A] Always run. При запуске любых PowerShell скриптов на этом сервере, подписанных этим сертификатом, предупреждение появляться не будет.

P.S.

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

Как подписать скрипт powershell

Как известно практически всем пользователям PowerShell, в целях безопасности была введена политика запуска скриптов. Которая имеет 4 режима:

  • Restricted – запрещено исполнять любые скрипты, возможна работа только в интерактивной консоли
  • AllSigned – все скрипты должны быть криптографически подписаны
  • RemoteSigned – только полученные из недоверенных источников (например, интернет) скрипты должны быть подписаны
  • Unrestricted – наименее безопасный уровень, допускается исполнение любых скриптов

В версии V2 (пока ещё CTP3) скрипты PowerShell приравняли к исполняемым файлам и эти файлы стали неотключаемо мониториться политикой Software Restriction Policies. Я об этом уже писал ранее: PowerShell V2 и Software Restriction Policies. Поначалу меня это сильно напрягало, но после пришёл к мнению, что это правильно. Неправильно только то, что мы этого не видим (ps1 расширение нигде не фигурирует). С этим бороться можно двумя методами – явно указывать пути, откуда разрешён запуск .ps1 файлов или подписать их все.

Если компьютеров в сети больше одного, то самое идеальное для решения задачи будет наличие домена Active Directory и, по возможности, Enterprise Certification Authity (CA). Наличие домена решит массу задач, как распространение политики SRP в пределах домена, распространение сертификата в пределах домена, контроль версии сертификата, которым подписаны скрипты.

Итак, для начала нам нужно получить сертификат, которым будут подписываться скрипты. В целях безопасности следует создать ограниченную учётную запись пользователя из под которой администратор (в большинстве случаев) будет подписывать скрипты. В книге PowerShell In Action для генерации сертификата предлагается использовать makecert.exe, который входит в состав Visual Studio SDK, но как мне кажется более правильным будет использование CA. В Windows Server CA для этих целей есть уже готовый шаблон, который называется Code Signing. Но принципиальной разницы нету, каким инструментом вы будете генерировать сертификат и я опишу процесс получения сертификата с использованием доменного CA.

Если CA у нас уже установлен, то открываем оснастку Certification Authority и переходим в раздел Certificate Templates. Нажимаем правой кнопкой и выбираем Manage. Откроется редактор шаблонов. Если у вас Enterprise или Datacenter редакции Windows Server, то вы можете создать свой настроенный шаблон. Но я не вижу в этом необходимости. На данном этапе нам необходимо разрешить ограниченному пользователю запрашивать сертификаты этого шаблона. Для этого в закладке Security шаблона Code Signing нужно разрешить чтение и запрос сертификата ограниченному пользователю. Когда эта процедура проделана, редактор шаблонов можно закрыть. После чего в оснастке Certification Authority снова нажать правой кнопкой на разделе Certificate Templates –> New –> Certificate Template to Issue и в списке выбрать шаблон Code Signing.

После чего нужно залогиниться этим пользователем, запустить оснастку Certificate Manager ( Start –> Run… –> certmgr.msc ) и выполнить запрос сертификата. В списке шаблонов должен быть и добавленный нами Code Signing. Когда сертификат будет запрошен не надо закрывать оснастку сертификатов. Далее нам потребуется экспортировать открытую часть сертификата в x509 файл (с расширением .cer). Экспорт открытой части нам потребуется для проверки подписи и организации доверия подписи в пределах домена. Экспортированный сертификат необходимо теперь доставить администратору(-ам), который отвечает за групповую политику.

В групповых политиках (чаще всего в доменной политике) необходимо создать новую политику Software Restriction Policies и в Additiona Rules добавить правило сертификата (Certificate Rule) и указать экспортированный сертификат. Это необходимо затем, что PowerShell для проверки доверия сертификата ищет его в контейнере Trusted Publishers и только Software Restriction Policies позволяет централизовано распространять сертификаты в этот контейнер.

Теперь можно приступать к подписыванию скриптов. Для этих целей используется командлет Set-AuthenticodeSignature и синтаксис его такой:

Set-AuthenticodeSignature $file $cert

Где $file – путь к скрипту и $cert – объект сертификата, который получается следующим образом:

$cert = @(dir cert:\CurrentUser\My -codesigning)[0]

здесь мы явно указываем, что нам нужен сертификат, у которого в EKU (Enchanced Key Usage) указан Code Sgining. В нашем случае он будет всего 1. Но если их окажется несколько, то мы выберем самый первый. Вот как это будет выглядеть на практике:

[Desktop] Set-ExecutionPolicy allsigned [Desktop] Get-ExecutionPolicy AllSigned [Desktop] .\uptime.ps1 File C:\Documents and Settings\Signer\Desktop\uptime.ps1 cannot be loaded. The file C:\Documents and Settings\Signer \Desktop\uptime.ps1 is not digitally signed. The script will not execute on the system. Please see "get-help about_signing" for more details.. At line:1 char:13 + .\uptime.ps1 [Desktop] $cert = @(dir cert:\currentuser\my -codesigning)[0] [Desktop] $cert Directory: Microsoft.PowerShell.Security\Certificate::currentuser\my Thumbprint Subject ---------- ------- 42E5B32A19885C6ADCF9683BDA1C871E0FE5E0DB CN=Signer, CN=Users, DC=contoso, DC=com [Desktop] Set-AuthenticodeSignature uptime.ps1 $cert Directory: C:\Documents and Settings\Signer\Desktop SignerCertificate Status Path ----------------- ------ ---- 42E5B32A19885C6ADCF9683BDA1C871E0FE5E0DB Valid uptime.ps1 [Desktop] .\uptime.ps1 System Uptime for DC1 is: 1 days 4 hours 19 minutes 20 seconds [Desktop]

Я наглядно показал, как это работает. Мы сначала перевели политику исполнения скриптов в AllSigned и убедились, что неподписанный скрипт не исполняется. После чего я подписал этот скрипт и попробовал снова. Как видите, скрипт теперь исполнился.

Если не будет выполнено условие распространения сертификата посредством политики SRP в контейнер Trusted Publishers, то вы получите вот такое сообщение:

[Desktop] .\uptime.ps1 Do you want to run software from this untrusted publisher? File C:\Documents and Settings\Signer\Desktop\uptime.ps1 is published by CN=Signer, CN=Users, DC=contoso, DC=com and is not trusted on your system. Only run scripts from trusted publishers. [V] Never run [D] Do not run [R] Run once [A] Always run [?] Help (default is "D"):d File C:\Documents and Settings\Signer\Desktop\uptime.ps1 cannot be loaded because you have elected to no t run this software now. At line:1 char:12 + .\uptime.ps1 [Desktop]

Вот таким образом мы решаем задачу исполнения только проверенного набора скриптов. В этом смысле PowerShell 1.0 менее безопасный и удобный, поскольку мы не можем политикой SRP блокировать исполнение PS1 файлов как класс и имеем только один выход – принудительное подписывание скриптов. В версии V2 политика исполнения скриптов удобно интегрируется с SRP. Удобство интегрирования в том, что SRP помимо распространения сертификата в пределах домена так же на основе этого правила разрешает исполнять эти скрипты в обход общего ограничения на PS1 файлы.

В следующем посте я расскажу, как можно упростить процесс подписывания скриптов. Так что не отключаемся 🙂

Цифровая подпись PowerShell скрипта

Для того, что б подписать скрипт надо иметь такие програмки:

makecert.exe. Она входит в состав Microsoft .NET Framework SDK или Microsoft Windows Platform SDK.

  • cert2spc.exe. Она тоже входит в состав Microsoft .NET Framework SDK или Microsoft Windows Platform SDK.

Теперь, если у Вас все это есть в наличии — приступаем!

Надо выполнить следующие команды:

  • makecert -n «CN=PowerShell Local Certificate Root» -a sha1 -eku 1.3.6.1.5.5.7.3.3 -r -sv root.pvk root.cer -ss Root -sr localMachine. В окнах надо просто вводить запрашиваемые данные. Это нужно для создания сертификатов. Результатом будут два файла: root.cer и root.pvk.
  • 3. cert2spc.exe root.cer root.spc. Постоянно жмем Next. Где будут лежать файлы root.cer root.spc не имеет никакого значения. Это проделывается для создания сертификата издателя программного обеспечения (Software Publisher’s Certificate, SPC).

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

Set-AuthenticodeSignature “c:\script_name.ps1” @(Get-ChildItem cert:\CurrentUser\My –codesigning)[0]

Эта команда добавит у конец вашего скрипта подпись, которая будет разрешать выполнение скриптов.

(вместо script_name.ps1 надо подставить имя вашего скрипта).

Компании из статьи

Ищите нас в интернетах!

Комментарии

Свежие вакансии

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

© 2008-2012 Microsoft User Group Community

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *