Цифровая подпись у PowerShell скрипта (файла *.PS1) позволяет при запуске удостовериться, что скрипт подписан доверенным издателем и его код не был изменен. Для подписи кода PowerShell скрипта вам нужно получить сертификат типа Code Signing. Такой сертификат можно:
- Запросить на внутреннем корпоративном центра сертификации (Certificate Authority, CA).
- Приобрести у внешнего коммерческого центра сертификации
- Выпустить самоподписанный сертификат
Таким образом, у вас должен файл сертификата с закрытым ключом в формате .PFX (с X509. Импортируйте этот сертификат в локальное хранилище компьютера:
$PlainTextPass = "Certpass123456"
$pfxpass = $PlainTextPass |ConvertTo-SecureString -AsPlainText -Force
Import-PfxCertificate -filepath "C:\PS\test.pfx" cert:\LocalMachine\my -Password $pfxpass
Если вы хотите использовать самоподписанный сертификат, его можно сгенерировать с помощью PowerShell:
$certFile = New-SelfSignedCertificate -Subject "Certificate to sign PowerShell sсripts" -Type CodeSigningCert -DnsName $env:computername -CertStoreLocation cert:\LocalMachine\my
Подписать код PowerShell скрипта с помощью сертификата
Вывести список доступных сертификатов для подписывания кода скриптов PowerShell в указанном хранилище:
Get-ChildItem cert:\LocalMachine\my -CodeSigningCert
Выбрать сертификат можно по его отпечатку:
$signcert = Get-ChildItem -Path "cert:\LocalMachine\my" | ? Thumbprint -eq 1A719E6D14E4827370457C3DEDD2D08725BAA95B
Чтобы подписать код указанного PowerShell скрипта, выполните:
$PSScript = "C:\PS\HardwareReadiness.ps1"
$TimestampServer = "http://timestamp.verisign.com/scripts/timstamp.dll"
Set-AuthenticodeSignature -FilePath $PSScript -Certificate $signcert -TimestampServer $TimestampServer
Set-AuthenticodeSignature : Cannot sign code. The specified certificate is not suitable for code signing.
При подписывании файла PowerShell скрипта, командлет Set-AuthenticodeSignature добавляет в конец текстового файла PS1 блок сигнатуры цифровой подписи, обрамленный специальными метками:
# SIG # Begin signature block ........... ........... # SIG # End signature block
Блок сигнатуры содержит хэш скрипта, который зашифрован с помощью закрытого ключа.
В свойствах PS1 файла на вкладке Digital Signatures появится информация о наличии подписи у скрипта и информация о сертификате.
Запуск подписанных PowerShell скриптов в Windows
По умолчанию настройки политики выполнения PowerShell скриптов в Windows блокируют запуск любых PS1 скриптов (режим Restricted) и при запуске скрипта появится ошибка.
File C:\PS\HardwareReadiness.ps1 cannot be loaded because running scripts is disabled on this system.
Чтобы разрешить запуск только подписанных PowerShell скриптов, нужно изменить настройки политики на AllSigned. Настройки политики выполнения можно изменить:
- Командой:
Set-ExecutionPolicy AllSigned –Force
- Через групповые политики: Включить выполнение сценариев (Turn on Script Execution) в разделе GPO Computer Configuration -> Policies -> Administrative Templates -> Windows Components -> Windows PowerShell. Измените значение параметра на «Разрешать только подписанные сценарии» (Allow only signed scripts).
Проверьте настройки политики выполнения:
Get-ExecutionPolicy
Если попробовать запустить сейчас подписанный PowerShell скрипт, появится ошибка:
File C:\PS\HardwareReadiness.ps1 cannot be loaded. A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.
Для запуска подписанного PowerShell скрипта, нужно добавить отпечаток сертификата в корневые доверенные сертификаты. Можно скопировать сертификат из секции Personal в хранилища Trusted Root Certification Authority и Trusted Publisher с помощью графической консоли
Certlm.msc
(скопируйте сертификат из Personal хранилища и вставьте его в корневые).
Не забывайте периодически проверять хранилище сертификатов Windows на наличие недоверенных сертфикатов и обновлять списки корневых сертификатов.
Теперь подписанный PowerShell скрипт будет запускаться без предупреждений.
Чтобы проверить действительность подписи PowerShell скрипта, выполните команду:
Get-AuthenticodeSignature C:\PS\HardwareReadiness.ps1
- Статус Valid указывает, что код PowerShell скрипта подписан доверенной цифровой подписью и не был изменен
- Если команда возвращает HashMismatch, значит код скрипта был модифицирован после подписания и сейчас не валиден. Запуск такого скрипта будет заблокирован с ошибкой:
File .ps1 cannot be loaded. The contents of file .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
Таким образом, после любой модификации кода подписанного PS1 скрипта его нужно заново переподписать. Также скрипт перестанет запускаться после истечения срока действия сертификата, поэтому за этой датой также нужно следить.
Рекомендуется подписывать все PowerShell скрипты, выполняющиеся с повышенными привилегиями администраторов домена или серверов, а также скрипты, которые запускаются на компьютерах пользователей через GPO.
Можно ли использовать этот способ для подписания exe-files?
Что интересно, exe, dll и другие подобные типы файлов тоже подписываются:
Set-AuthenticodeSignature C:\PS\pngcheck.exe @(gci Cert:\LocalMachine\My -DnsName test1 -codesigning)[0]
Т.е. утилита signtool теперь не нужна
Смысл? ЕХЕ выполняется в любом случае.
Можно разрешить запуск подписанных приложений по издателю через AppLocker или WDAC ( настройка Windows Defender Application Control)
Если сервер без доступа в инет будет ли работать для него TimestampServer ?
ок скрипт подписан, что мне мешает скопировать подпись и подписать свой скрипт ?
в подписи хранится чексумма (хэш) кода скрипта. если изменится хоть один символ, интерпретатор скажет что подпись не валидна
и да и нет
я поискал ответ на свой вопрос, более менее грамотно он звучит следующим образом :
при создании некоего сферического коня по имени «подпись» создаются два объекта
приватный ключик ( ключик хозяина, имея который можно генерировать новые подписи(генерировать мусор с признаком того что это сделано мастер ключем) )
паблик ключик ( ключик в котором заложено свойство «только для просмотра»)
и вот именно это и не позволит сделать «скопировать» или «переподписать» объект без этого самого мастер ключа.
Вообще извиняюсь за каламбур, причина была в том что просто переклинило и не учел принципы сертификации
Добрый день, спасибо за статью, но возникло пару вопросов:
Почему надо свой сертификат добавлять в Trusted Publishers если там уже есть сертификат издающего CA который выдал мне сертификат подписи скриптов?
А если у нас несколько людей пишут скрипты нужно сертификат каждого добавлять получается?
Если самоподписанные сертфикаты генерятся на каждом компьюетере, придется копировать.
Если есть общий CA, то только сертификат CA
простите за глупый вопрос. А если нужно подписать скрипты которые выполняются по шедуллеру, то как правильно это всё организовать? Так как скрипты эти копируются (из шары) в папку, например, TEMP у юзеров, то для централизованного управления нужно:
1. Издать на PKI сертификат Code Signing (как я понял это именно пользовательский серт, а не машинный)
2. Получить сертификат и экспортировать его
3. GPO c добавлением сертификата Code Signing в Trusted Publishers (Computer Configuration-Policies-Windows Settings-Public Key Policies-Trusted Publishers-Import.). Добавить экспортированый сертификат в эту GPO. Но тут я не понял, так как сертификат пользовательский, с указанем имени пользователя, не помешает ли это подписыванию скриптов (тоесть на все компьютеры разольётся политика с сертификатом user1, например)
3. GPO политику по запуску Allow only signed scripts
4. GPO по запуску скрипта Computer Configuration -> Policies -> Windows Settings -> Scripts (Startup / Shutdown), а в скрипте прописать подписывание ps сертификатом тем из пункта 2?
а если не так, то буду благодарен за наводку
тупо на память так что могу что-то упустить :
1. инициатер должен обладать правьями на запуск файла
2. машинка и инициатер должны иметь доступ до файлегов
3. машинка должна знать что файлег подписан красивой подписью
4. красивая подпись должна находиться в красивом контейнере для всяких сурйозных подписей( какой то там корневой чего-то или доверенный . ащпе не помню)
5. все инструкции в файлеге должны иметь возможность быть выполнены от лица инициирующего свистопляску на момент события.
6. существуют конструктивные особенности которые кудряво реализуются по тем или иным причинам, так или иначе связанным с безопасностью, для теста используйте примитивные конструкции и если что-то пошло не так и ваш цирк с пьяными котятами не завелся, то скорее всего нужно либо котят поменять либо котята с кем-то закусились.
У нас есть пачка скриптов, которые разливаются GPO и выполняются юзерам, по шедуллеру. Скриптты берутся с шары и заливаются юзерам локально в папку ТЕМП. И задача стоит подписать только их и настроить контроль над изменениями. Это в общем такая задача…
1) Сертификат для компьютера, а не для пользователя.
4) Вы хотите чтобы сертификат подписывался сразу перез запуском через GPO. Не пойму за чем так. По идее владелец скрипта (администратора) должен вручную подписать сертификат при любом изменении кода скрипта (т.е. подписанные скрипты уже лежат в вашей шаре, откуда различаются пользователям).
Или у вас скрипты динамические и формируются каждый раз заново?
В остальном все правильно описано.
1) хм… просто темплейт Code Signing доступен только для юзеров. Или я не понял тогда какой темплейт использовать
4) Хочу, что бы уже подписаные скрипты попадали юзерам на тачки и эти скрипты выполнялись ,как и раньше.
Дело в том ,что у нас есть пачка скриптов которые выполняются по шедуллерам. Сами скрипты лежат на шаре на домен контроллере, юзеру залетают по политике (копируются с шары и кладутся в папку C\Windows\Temp, Action — Update )
Я просто думал так, подписываю сертификатом данные скрипты на шаре, юзерам раскидываю мой сертификат Code Signing в Trusted Publishers и включаю политику Allow only signed scripts.
И таким образом каждый раз когда юзер будет с шары получать скрипты, он уже будет их подписанными получать и так как имея сертификат Code Signing не будет проблем с выполнением.
Очень буду благодарен, если тапками не закидаете и подскажите, всё ли я правильно думаю? по темплейту серта наверное не до конца ясно.
Как я понял, у вас используется собственный CA на Windows.
В этом случае, и его сертификат уже распространен на клиенты? В этом случае вам сертификат подписан корневым CA и является доверенным и его не нужно комипроть пользователям повторно.
В остальном вся логика правильная.
Как всегда инструкция на высшем уровне, большое Вам спасибо!
Но как всегда не на 100% гладко всё прошло, в моё случае сертификат нужно было разместить в папке Доверенный издатель, только после этого подписанный скрипт отрабатывал без единого вопроса и как нужно.
А ещё было бы не плохо сделать инструкцию как поднять и настроить AD CS, чтобы перейти по ссылке _https://CA-server-name/certsrv и выпустить сертификат. Нашёл стороннюю инструкцию, то там много «опечаток», по инструкции одно, на самом деле нужно делать по другому. В итоге дошёл до того, что страница начала открываться, проходить авторизация, но выпустить толком сертификат не получается, так как много конфигурационных моментов пустые и ни чего не выбрать.