Политика выполнения PowerShell и подпись скриптов — как отказаться от Bypass в роли постоянной заглушки
· Обновлено: · Го Комура · PowerShell, Windows, Политика выполнения, Подпись кода, Безопасность, Скрипты, Эксплуатация, Автоматизация
История изменений (1 обновлений, последнее 30 Aug 2026)
Журнал изменений этой статьи. Там, где версия до правки была заархивирована, она остаётся доступной для чтения по постоянной ссылке с DOI.
- Русский текст переписан как полноценный технический перевод, а не калька с японского. Утверждения статьи не менялись.
- Первая публикация
Цитирование статьи(DOI (зарегистрированный архив): 10.5281/zenodo.21620108)
Приведённые ниже DOI относятся к ранее зарегистрированным архивным версиям, которые могут отличаться от текущего текста. Для ссылки на текущий текст используйте URL этой страницы.
Го Комура (2026). Политика выполнения PowerShell и подпись скриптов — как отказаться от Bypass в роли постоянной заглушки. KomuraSoft LLC. https://comcomponent.com/ru/blog/powershell-execution-policy-script-signing/
- DOI (зарегистрированный архив)
- 10.5281/zenodo.21620108
- DOI (последняя зарегистрированная версия)
- 10.5281/zenodo.21620109
«На новом ПК скрипт не запускается: „выполнение сценариев в данной системе отключено…“». «Добавили -ExecutionPolicy Bypass — заработало, теперь так прописано во всех задачах». «Файл .ps1 из общей папки выдаёт ошибку подписи только на одном компьютере». Политика выполнения PowerShell — почти неизбежный барьер, когда внутри компании начинают автоматизировать работу. И на многих площадках без понимания механизма копится практика «закрыть проблему Bypass».
Сложность в том, что легко неверно понять, что именно эта политика защищает. Одни принимают её за функцию безопасности, закручивают слишком туго — и останавливается работа. Другие решают, что «всё равно обходится», ставят Bypass везде и снимают последний защитный механизм против случайного запуска. Обе крайности отпадают, если знать, как устроена политика.
Статья рассчитана на сотрудников ИТ малых и средних компаний и на тех, кто автоматизирует внутренние рутинные задачи в PowerShell. По официальной документации разберём, чем на самом деле является политика выполнения, как устроен приоритет областей действия, как она связана с Zone.Identifier (Mark of the Web) и как раздавать скрипты с подписью.
1. Сначала выводы
- Политика выполнения — защитный механизм, а не граница безопасности. Официальная документация прямо говорит: «это не система безопасности, ограничивающая действия пользователя» и «её легко обойти, введя содержимое скрипта в командную строку». Цель — задать базовые правила и не дать случайно запустить не то, что собирались.1
- Политика влияет только на запуск скриптов. Интерактивные команды всегда доступны. В Windows PowerShell 5.1 по умолчанию на клиентских ОС стоит Restricted (скрипты запрещены), на Windows Server — RemoteSigned. В PowerShell 7 по умолчанию считается RemoteSigned.21
- Политику задают в пяти областях действия. Приоритет: MachinePolicy > UserPolicy > Process > CurrentUser > LocalMachine. MachinePolicy и UserPolicy существуют только для групповой политики:
Set-ExecutionPolicyих не меняет, параметр командной строки тоже не перекрывает.13 - RemoteSigned требует подпись только у скриптов «из интернета». Происхождение смотрят по альтернативному потоку данных Zone.Identifier (Mark of the Web). Проверили содержимое — сняли поток
Unblock-Fileи запустили, политику не трогая.14 - AllSigned требует подпись доверенного издателя у всех скриптов, включая созданные локально. Подпись ставит
Set-AuthenticodeSignatureи встраивает её в конец файла блоком комментариев# SIG #.15 - При подписи всегда ставьте метку времени (-TimestampServer). С ней скрипт остаётся действительным после истечения сертификата. У большинства сертификатов подписи кода срок — год; без метки это ежегодная бомба замедленного действия.65
- Самоподписанный сертификат — только для тестов. Скрипт, подписанный таким сертификатом, на других компьютерах не запускается. Для раздачи в организации нужен сертификат подписи кода от удостоверяющего центра (внутреннего ЦС или коммерческого).57
- Чтобы управлять политикой в организации, задайте её централизованно параметром групповой политики «Включить выполнение сценариев». Этот параметр имеет приоритет над всеми областями действия на стороне PowerShell.1
На схеме сплошная линия обозначает отношение, которое выполняется всегда, а пунктирная — условное отношение (условия указаны в пояснении к каждому отношению на странице сведений). Полный список отношений (всего 18, с доказательствами и степенью уверенности) и определения основных понятий собраны на странице сведений карты знаний (на японском). Данные: JSON-LD / Turtle
2. Что это на самом деле: не «граница безопасности», а «защитный механизм»
Сначала исходная посылка. Формулировка официальной документации (about_Execution_Policies) прямая. Политика выполнения — это «функция безопасности» (safety feature): она задаёт условия, при которых PowerShell загружает файлы конфигурации и выполняет скрипты, и «не является системой безопасности, ограничивающей действия пользователя». Даже тот, кому запрещено запускать скрипт, выполнит ту же обработку, вставив содержимое в командную строку. Роль политики — задать базовые правила и не дать нарушить их непреднамеренно.1 Во вводной документации то же самое: «это не граница безопасности; она не остановит пользователя, который сознательно пытается запустить скрипт».2
Если принять эту рамку, становится ясно, как проектировать эксплуатацию. Оба утверждения ошибочны: и «ужесточили политику — атаки закрыты», и «раз обходится, смысла нет». Защита от атак — работа другого уровня (контроль приложений, минимизация прав, журналы аудита). Политика выполнения отвечает за предотвращение случайного запуска.8
Различия основных политик выглядят так.1
| Политика | Запуск скриптов | Требование подписи | Роль |
|---|---|---|---|
| Restricted | Запрещён (только отдельные команды) | — | Значение по умолчанию на клиентских ОС в Windows PowerShell 5.12 |
| AllSigned | Разрешён | Нужна у всех скриптов и файлов конфигурации. Перед запуском от неклассифицированного издателя — подтверждение | Для организаций, где процесс подписи уже есть |
| RemoteSigned | Разрешён | Нужна только у скриптов из интернета. У локально созданных — нет | Практический стандарт. Значение по умолчанию в PowerShell 71 |
| Unrestricted | Разрешён | Нет (предупреждение вне зоны интрасети) | Значение по умолчанию вне Windows (изменить нельзя)1 |
| Bypass | Разрешён | Нет. Ни предупреждений, ни запросов | Для встраивания PowerShell в приложение с собственной моделью безопасности1 |
Часто не замечают, что Restricted останавливает не только рабочие скрипты, но и загрузку профилей (.ps1), модулей (.psm1) и файлов конфигурации форматирования (.ps1xml).1 Типичное обращение: «на новом компьютере не загружается профиль» — и причина оказывается в политике выполнения.
3. Области действия и приоритет: почему «настроил, а ничего не изменилось»
Политика выполнения — не одно значение. Её задают отдельно в каждой из пяти областей, а действующим становится значение с наивысшим приоритетом.1
| Область действия | Как задают | Где хранится | Приоритет |
|---|---|---|---|
| MachinePolicy | Групповая политика (конфигурация компьютера) | GPO | 1 (наивысший) |
| UserPolicy | Групповая политика (конфигурация пользователя) | GPO | 2 |
| Process | Параметр запуска -ExecutionPolicy / -Scope Process |
Переменная окружения $Env:PSExecutionPolicyPreference (пропадает при завершении сеанса) |
3 |
| CurrentUser | Set-ExecutionPolicy -Scope CurrentUser |
Конфигурация пользователя | 4 |
| LocalMachine | Set-ExecutionPolicy (область по умолчанию, нужны права администратора) |
Конфигурация, общая для всех пользователей | 5 |
Стандартный способ разобрать «настроил, а ничего не изменилось» — смотреть не действующее значение, а полный список.
# Смотрите не только действующую политику, но и то, какая область её задаёт
Get-ExecutionPolicy -List
# Пример: LocalMachine стоит AllSigned, но побеждает RemoteSigned из CurrentUser
# Scope ExecutionPolicy
# ----- ---------------
# MachinePolicy Undefined
# UserPolicy Undefined
# Process Undefined
# CurrentUser RemoteSigned
# LocalMachine AllSigned
# Чтобы изменить только своё окружение, удобна CurrentUser — права администратора не нужны
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
CurrentUser выше LocalMachine, поэтому в примере действующая политика — RemoteSigned.1 Set-ExecutionPolicy по умолчанию пишет в LocalMachine и требует права администратора; в CurrentUser обычный пользователь может изменить её сам.3
Главный инструмент управления в организации — групповая политика. Параметр «Включить выполнение сценариев» (Turn on Script Execution) имеет приоритет над всеми областями, заданными на стороне PowerShell. Если его отключить, эффект как у Restricted; если включить, выбирают один из вариантов: «Разрешить все сценарии» (Unrestricted), «Разрешить локальные сценарии и подписанные удалённые сценарии» (RemoteSigned) или «Разрешить только подписанные сценарии» (AllSigned). Параметр лежит в административных шаблонах, в разделе Компоненты Windows\Windows PowerShell. Конфигурация компьютера сильнее конфигурации пользователя.1 В среде под GPO Set-ExecutionPolicy настройку сохранит, но она не будет действовать, и появится сообщение о конфликте.3
Отсюда один важный вывод. Если политикой управляет GPO, -ExecutionPolicy Bypass в задаче или ярлыке не действует. Документация прямо говорит: указание области Process побеждает LocalMachine/CurrentUser, но не групповую политику.1 Приём «пропиши Bypass — как-нибудь заработает» срабатывает только там, где организация политикой выполнения вообще не управляет.
4. Zone.Identifier (Mark of the Web) и Unblock-File
«Удалённый (из интернета)» в RemoteSigned определяется не местом файла, а меткой. Браузеры и похожие программы прикрепляют к скачанным файлам альтернативный поток данных и помечают их как «файл из интернета».1 Этот поток — Zone.Identifier, в нём значение 3, то есть интернет-зона. Это и есть Mark of the Web.4
Альтернативные потоки данных (Alternate Data Streams) — функция NTFS. Один файл на NTFS может нести несколько потоков; привычное «содержимое файла» лежит в безымянном потоке по умолчанию. Отдельно к файлу можно прикрепить именованный поток в виде имя_файла:имя_потока.9 Zone.Identifier — один из таких потоков, поэтому текст скрипта не меняется ни на байт, а возможность запуска — меняется. Один и тот же файл на разных машинах то работает, то нет именно из-за этого. Если файл прошёл через файловую систему без NTFS (например FAT32 на USB-накопителе), поток теряется, метка исчезает — и скрипт вдруг начинает запускаться.
В среде RemoteSigned неподписанный скрипт с этой меткой блокируется ошибкой «не имеет цифровой подписи». Действуют в два шага.
# 1) Сначала посмотрите, какие файлы заблокированы (только чтение, безопасно)
Get-Item -Path C:\Tools\*.ps1 -Stream Zone.Identifier -ErrorAction SilentlyContinue
# 2) Снимайте блокировку только с тех файлов, чьё содержимое вы проверили и признали безопасным
# (Unblock-File удаляет поток Zone.Identifier; сама политика выполнения не меняется)
Unblock-File -Path C:\Tools\Get-InventoryReport.ps1
Unblock-File удаляет альтернативный поток Zone.Identifier — это та же операция, что кнопка «Разблокировать» (Unblock) в свойствах файла в Проводнике. Суть в том, что пропускают только проверенные файлы, политику не ослабляя.4 Официальная документация требует как обязательный шаг: перед использованием проверить файл и источник и убедиться, что они безопасны.43
Есть ловушка и в обратную сторону. Не каждый способ получения файла ставит Mark of the Web. Прямо сказано: файлы, скачанные через curl.exe, Invoke-WebRequest или Invoke-RestMethod, метку интернет-зоны иногда не получают.1 RemoteSigned не гарантирует, что «все опасные скачанные файлы будут остановлены» — именно поэтому это защитный механизм, а не граница. Есть и предупреждение: в системах, которые не различают UNC-пути и интернет-пути, скрипт на общей папке при RemoteSigned иногда отклоняется.1 Если «.ps1 из общей папки останавливается только на части компьютеров», смотрите настройки зон и наличие Zone.Identifier.
Похожий симптом у скачанных исполняемых файлов (.exe) даёт SmartScreen — об этом в статье «Почему Windows показывает «Windows защитил ваш компьютер»».
5. Практика подписи скриптов: Set-AuthenticodeSignature и метка времени
Чтобы перейти к AllSigned или подписывать раздаваемые файлы в среде RemoteSigned, нужен сертификат подписи кода. Способы получения сводятся к трём.5
| Откуда берут | Кому доверяют | Оценка |
|---|---|---|
Самоподписанный (New-SelfSignedCertificate) |
Только свой компьютер, на других не запускается | Только тесты и проверка. Для раздачи не использовать57 |
| Выдан внутренним ЦС | Машины организации, настроенные доверять внутреннему ЦС | Основной вариант в AD-домене. Выдачу и отзыв контролирует организация |
| Выдан коммерческим ЦС (платно) | Windows в целом (публичным ЦС уже доверяют) | Если скрипты уходят за пределы организации |
Официальная документация даёт ту же картину: «сертификат удостоверяющего центра доверяют и на других компьютерах», а «самостоятельно созданный бесплатен, но только для вашего компьютера и только для тестов».5 Если цель — внутренняя раздача, на практике сертификат подписи кода выдают внутренним ЦС, например Active Directory Certificate Services (AD CS).
Если выдаёте через внутренний ЦС: что делать дальше
Фраза «внутренний ЦС — реалистичный вариант» сама по себе не даёт следующего шага, поэтому распишем порядок. AD CS — роль Windows Server, которая даёт инфраструктуру открытых ключей (PKI): помимо роли удостоверяющего центра (ЦС) туда входят веб-регистрация, сетевой ответчик (OCSP) и другие службы роли.10
- Проверьте, есть ли внутренний ЦС. Сначала ИТ смотрит, есть ли в компании корпоративный ЦС AD CS. Если нет, поднимать ЦС только ради подписи кода — тяжёлое решение. Сравните стоимость одного коммерческого сертификата с затратами на развёртывание ЦС, резервное копирование, публикацию списка отзыва (CRL) и защиту ключей.
- Попросите подготовить шаблон сертификата для подписи кода. Это работа на стороне ЦС. Дублируют стандартный шаблон «Подпись кода», на копии задают срок, длину ключа и группу безопасности, которой разрешено запрашивать (только те, кто подписывает), и добавляют копию в список шаблонов, доступных для выдачи, в оснастке «Центр сертификации». Стандартный шаблон не правят напрямую: изменение бьёт по всему домену и его трудно откатить.
-
Тот, кто подписывает, запрашивает сертификат. На компьютере для подписи вызывают
Get-Certificateс именем шаблона. После выдачи сертификат сразу попадает в личное хранилище (этот командлет умеет класть сертификаты только в хранилищеMy).11# Запрос к корпоративному ЦС по имени шаблона (встроенная проверка подлинности Windows) # 'CodeSigning' замените на имя шаблона, которое опубликовал администратор ЦС $result = Get-Certificate -Template 'CodeSigning' -Url ldap: ` -CertStoreLocation Cert:\CurrentUser\My $result.Status # Issued — выдан, Pending — ждёт одобрения - Раздайте доверие на машины. Корневой сертификат внутреннего ЦС — в хранилище «Доверенные корневые центры сертификации», сертификат издателя, которым подписывают, — в «Доверенные издатели». Раздают групповой политикой (Конфигурация компьютера > Политики > Конфигурация Windows > Параметры безопасности > Политики открытого ключа). Официально описан путь: в каждом хранилище под политиками открытого ключа — правый щелчок и импорт сертификата.12 После этого из эксплуатации пропадает запрос AllSigned «Выполнить программное обеспечение от этого ненадежного издателя?».15
Шаг 2 на стороне ЦС часто нельзя закрыть одним ИТ-отделом, поэтому сначала зафиксируйте проверку из шага 1 и схему раздачи из шага 4 — и уже с этим идите к администратору ЦС. Так разговор идёт быстрее.
Если компьютеры не в домене (рабочая группа)
У малых и средних компаний часто нет AD-домена или в нём только часть машин. Если нет ни GPO, ни внутреннего ЦС, реалистичные решения складывают в таком порядке.
- Политику выполнения задают на каждой машине и проверяют, что она совпадает. В чек-лист подготовки ПК включают
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser(если нужно на всех пользователей — LocalMachine с правами администратора).3 Раз GPO ничего не фиксирует, значение всё ещё можно сменить локально, поэтому инвентаризацию дополняют проверкойGet-ExecutionPolicy -List. - Эталон скрипта — в одном месте, запись — узкому кругу. Одну общую папку объявляют эталоном, писать туда могут только администраторы. Политика выполнения ловит только «случайный запуск»; за то, чтобы скрипт не правили, отвечают права доступа NTFS.
- Если нужна и подпись, сравнивают стоимость: раздать самоподписанный сертификат или купить коммерческий ЦС. Документация пишет: «скрипт с самоподписанным сертификатом на других компьютерах не запускается» и «для скриптов, которыми хотят делиться, это не подходит».5 Это описание состояния по умолчанию: другие машины сертификату не доверяют, поэтому и не запускают. Иначе говоря, если раздать доверие, запустится. Ниже это разведено отдельно.
- Обращение с Mark of the Web запишите в инструкцию. У
.ps1, пришедших почтой или с внешнего ресурса, метка часто есть, поэтому в процедуру явно включают: «сначала ревью содержимого, потомUnblock-File» (глава 4).4
Если самоподписанный сертификат всё же используют в рабочей группе
Если остановиться на «самоподписанный работает только на той машине, где подписали», компанию с 10–20 компьютерами фактически заставляют покупать коммерческий ЦС. На практике AllSigned проходит, если открытую часть сертификата раздать на каждую машину. Отличие от GPO только в канале: руками, установщиком или MDM (Intune и аналоги).
Раздают только открытую часть. Закрытый ключ с компьютера, на котором подписывают, не выносят.
# 【один раз на компьютере подписи】экспорт только открытой части (-Cert закрытый ключ не включает)
$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert |
Where-Object Subject -eq 'CN=KomuraSoft Code Signing (Test)'
Export-Certificate -Cert $cert -FilePath .\KomuraSoftCodeSigning.cer
# 【один раз на каждой машине, нужны права администратора】кладём и в корень, и к издателям.
# Без корня проверка подписи не проходит (самоподписанный сертификат сам себе корень),
# без издателей AllSigned продолжает спрашивать подтверждение
Import-Certificate -FilePath .\KomuraSoftCodeSigning.cer `
-CertStoreLocation Cert:\LocalMachine\Root
Import-Certificate -FilePath .\KomuraSoftCodeSigning.cer `
-CertStoreLocation Cert:\LocalMachine\TrustedPublisher
Дальше сразу посмотрите, какую цену вы за это принимаете. Здесь и проявляется разница с коммерческим ЦС.
| Вопрос | Раздаём самоподписанный | Покупаем коммерческий ЦС |
|---|---|---|
| Стартовые затраты | 0 ¥, но нужно разнести сертификат на все машины | Стоимость сертификата (годовая) |
| Защита закрытого ключа | Вся защита сводится к компьютеру подписи. Утечка ключа позволяет подписывать код, которому доверяют все машины, куда сертификат раздали. Зафиксируйте, где лежит ключ, и запретите его выносить | Тоже критично, но есть HSM и облачные службы подписи |
| Отзыв | Механизма нет. Утёк — обходите машины и чистите хранилища | Можно отозвать через CRL/OCSP |
| Истечение срока | При каждом обновлении снова разносите на все машины (если ставили метку времени, уже поставленные подписи после истечения остаются действительными5) | На машинах ничего делать не нужно |
| Новый компьютер | Нужно встроить в процедуру подготовки ПК | Не нужно |
| Эффект помещения в «Доверенные корневые» | Машина доверяет этому одному сертификату. Это не ЦС, нижестоящие сертификаты он выпускать не может, но всё, что подписано этим ключом, проходит | Ничего не меняется |
Если машин мало, подготовка ПК описана и компьютер подписи можно защитить, раздачи самоподписанного сертификата достаточно. Если машины постоянно прибывают, подготовка держится на одном человеке или до компьютера подписи может добраться кто угодно — дешевле отдать отзыв и обновление коммерческому ЦС.
Хранилище сертификатов и диск Cert:
Перед кодом подписи коротко про Cert:. Это виртуальный диск провайдера сертификатов PowerShell: хранилища обходят как файловую систему по путям.13 Два уровня: Cert:\<расположение>\<имя хранилища>. Расположения — CurrentUser (текущий вошедший пользователь) и LocalMachine (весь компьютер). Имена хранилищ — My (личное), Root (доверенные корневые центры сертификации), TrustedPublisher (доверенные издатели) и другие. Каждый сертификат идентифицируют по отпечатку (Thumbprint), список даёт Get-ChildItem.13
То есть Cert:\CurrentUser\My — «личное хранилище текущего пользователя», а Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert — «покажи все сертификаты подписи кода оттуда». -CodeSigningCert — параметр именно этого провайдера: оставляет сертификаты, у которых в расширенном использовании ключа (EKU) есть подпись кода.13
Сначала прогоните весь поток на тестовом самоподписанном сертификате.
# Тестовый сертификат подписи кода (самоподписанный — ему доверяют только на этой машине)
$params = @{
Subject = 'CN=KomuraSoft Code Signing (Test)'
Type = 'CodeSigningCert'
CertStoreLocation = 'Cert:\CurrentUser\My'
HashAlgorithm = 'sha256'
}
$cert = New-SelfSignedCertificate @params
New-SelfSignedCertificate создаёт самоподписанный сертификат для тестов; -Type CodeSigningCert добавляет расширение для подписи кода. Срок по умолчанию — один год.7 Если таким сертификатом проверяете AllSigned, его нужно положить в хранилище доверенных корневых центров сертификации на этой же машине.5
Сама боевая подпись — одна команда.
# Берём сертификат подписи кода из хранилища и подписываем
# -CodeSigningCert только сужает выбор до «пригодных для подписи кода»,
# поэтому оставляем действующие с закрытым ключом,
# а если их несколько — уточняем по Subject или Thumbprint
$cert = Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert |
Where-Object { $_.HasPrivateKey -and $_.NotAfter -gt (Get-Date) -and
$_.Subject -eq 'CN=KomuraSoft Code Signing (Test)' } |
Sort-Object NotAfter -Descending |
Select-Object -First 1 # Если из-за продления несколько с одним Subject, берём тот, у которого срок дальше
# Метка времени обязательна. Благодаря ей подпись живёт после истечения сертификата
# URL — служба меток времени по RFC 3161. В первую очередь берите ту, которую указывает издатель сертификата (продавец).
# Пример: сервер меток времени DigiCert http://timestamp.digicert.com
Set-AuthenticodeSignature -FilePath .\Invoke-NightlyBatch.ps1 -Certificate $cert `
-HashAlgorithm SHA256 -TimestampServer 'http://timestamp.digicert.com'
# Состояние подписи смотрят Get-AuthenticodeSignature (Valid/NotSigned/HashMismatch и т. д.)
# Если TimeStamperCertificate не пуст, метка времени стоит
Get-AuthenticodeSignature -FilePath .\Invoke-NightlyBatch.ps1 |
Format-List -Property Status, SignerCertificate, TimeStamperCertificate
Три свойства, которые стоит зафиксировать.65
- Подпись встраивается в конец файла блоком комментариев
# SIG #. Если подпись уже была, её заменяют. Достаточно изменить скрипт на один символ после подписи — и подпись станет недействительной. Именно так обнаруживают правки. - Если указать
-TimestampServer, скрипт не перестанет работать после истечения сертификата. Подпись действительна «пока действителен сертификат подписи» либо «пока сервер меток может подтвердить, что подписали, когда сертификат ещё был действителен». У большинства сертификатов подписи кода срок — год, поэтому метка времени — основа долгой эксплуатации.65 URL должен указывать на реальную службу по RFC 3161, не на выдуманное значение. Первый кандидат — URL, который даёт издатель сертификата (ЦС, у которого покупали). Например, DigiCert публикуетhttp://timestamp.digicert.com.14 Среди служб роли AD CS ответа меток времени нет10, поэтому даже при сертификате внутреннего ЦС метку обычно берут у внешней службы. Это часто забывают, когда только обсуждают внутренний ЦС: проверьте, что до URL можно достучаться по сети (прокси, разрешение на брандмауэре). После подписи смотрите, чтоTimeStamperCertificateуGet-AuthenticodeSignatureне пуст — так убеждаетесь, что метка действительно встала. - В Windows PowerShell 5.1 и в PowerShell до 7.2 подписываемый скрипт нужно было сохранять в ASCII или UTF8NoBOM. С PowerShell 7.2 подписанные скрипты работают с любой кодировкой.5 Там, где ещё живёт 5.1, из-за кодировки часто ломается проверка подписи у скриптов с комментариями на японском. Общие различия 5.1 и 7 — в статье «Различия между Windows PowerShell 5.1 и PowerShell 7 и переход».
В среде AllSigned даже подписанный скрипт, если издатель ещё не отнесён к доверенным или отклонённым, при запуске спрашивает: «Выполнить программное обеспечение от этого ненадежного издателя?». Если выбрать «Всегда выполнять», для этого издателя больше не спрашивают.15 При внутреннем ЦС сертификат издателя дополнительно разносят в «Доверенные издатели» на каждой машине — и этот запрос из эксплуатации исчезает.
6. Рабочая таблица решений: от «заглушки Bypass» до процесса подписи
Распространение и запуск внутренних скриптов удобно продумывать по такой таблице.
| Вопрос | Варианты | Ориентир |
|---|---|---|
| Политика окружения | Оставить Restricted / RemoteSigned / AllSigned | Если развиваете автоматизацию, минимум — RemoteSigned. Если процесс подписи есть — AllSigned1 |
| Как раздавать настройку | Каждый сам вызывает Set-ExecutionPolicy / групповая политика | В домене выбор один — GPO. Она сильнее всех областей и закрывает самовольные изменения1 |
| Доверие к раздаваемым файлам | Без подписи + общая папка / подпись кода | Без подписи правки не видно. Переходите к подписи начиная с рабочих скриптов, которые запускаются регулярно |
| Сертификат | Самоподписанный / внутренний ЦС / коммерческий ЦС | Для внутренней раздачи — внутренний ЦС. Самоподписанный только для тестов, наружу — коммерческий ЦС5 |
| Скачанные файлы | Ослаблять политику / ревью и Unblock-File | Политику не трогать, пропускать только проверенные файлы4 |
| Запуск регулярных задач | Постоянно -ExecutionPolicy Bypass / настроить политику окружения + подпись |
Постоянный Bypass — отказ от защитного механизма. Под GPO он и вовсе не действует1 |
Последнюю строку стоит пояснить. Проблема эксплуатации, которая «закрывает дыру ExecutionPolicy Bypass», не в том, что открывается дыра в безопасности (политика выполнения границей и не была). Проблема в трёх пунктах.
- Отказ от защитного механизма. Вы навсегда снимаете последнюю сетку, которая ловит случайный запуск другого скрипта и запуск уже изменённого скрипта, которого не заметили.
- Расхождение с управлением. Как только политикой начинает управлять GPO, Bypass перестаёт действовать, и все задачи, которые им «закрывали», падают разом.1 Это технический долг: «почему работало» оказалось неуправляемой лазейкой.
- Путаница при разборе причин. Если Bypass разбросан по задачам, по действующей политике окружения поведение уже не угадаешь, и разбор «почему падает только на этой машине» затягивается.
Сам Bypass предусмотрен для приложений, которые встраивают PowerShell и держат собственную модель безопасности.1 Это не опция запуска, которую стоит постоянно вешать на рабочие скрипты, написанные людьми. Как собрать безопасный регулярный запуск в Планировщике заданий — в статье «Почему задачи Планировщика не запускаются или завершаются с кодом 0x1 — разбор причин и безопасная эксплуатация».
7. Итог
- Политика выполнения — защитный механизм, а не граница безопасности. Защиту от атак делайте на другом уровне; политике выполнения оставьте предотвращение случайного запуска.
- У политики пять областей действия с приоритетом MachinePolicy > UserPolicy > Process > CurrentUser > LocalMachine. Диагностику начинайте с
Get-ExecutionPolicy -List. - RemoteSigned смотрит на Zone.Identifier (Mark of the Web). Проверенные файлы пропускайте
Unblock-File, политику не ослабляя. - Подписывайте
Set-AuthenticodeSignatureи всегда указывайте-TimestampServer. Для внутренней раздачи — сертификат внутреннего ЦС; самоподписанный только для тестов. - Управление в организации централизуйте параметром групповой политики «Включить выполнение сценариев». Он сильнее всех областей и параметра
-ExecutionPolicy. - Постоянный
-ExecutionPolicy Bypass— отказ от защитного механизма, и под GPO он не действует. Правильный путь — настроить политику окружения и подпись, чтобы «заглушка» стала не нужна.
Похожие статьи
- Основы команд PowerShell — что выучить в первую очередь и как пользоваться безопасно
- Почему Windows показывает «Windows защитил ваш компьютер»
- Почему задачи Планировщика не запускаются или завершаются с кодом 0x1 — разбор причин и безопасная эксплуатация
- Обработка ошибок и повторные попытки (retry) в скриптах PowerShell
- Различия между Windows PowerShell 5.1 и PowerShell 7 и переход
- Переход с bat-файлов на PowerShell: как принять решение
Смежные области консультирования
KomuraSoft LLC (合同会社小村ソフト) проектирует политику выполнения и процесс подписи внутренних скриптов PowerShell, рассматривает развёртывание через групповую политику и разбирает различия окружения вроде «скрипт не работает только на некоторых машинах». Можем помочь перевести существующие bat-файлы и скрипты на безопасную эксплуатацию.
- Техническая консультация и ревью проекта
- Расследование сбоев и анализ причин
- Модернизация и сопровождение Windows-приложений
- Связаться с нами
Справочные ссылки
-
Microsoft Learn, about_Execution_Policies. О том, что политика выполнения — функция безопасности, а не система, ограничивающая пользователя; определения политик (AllSigned/Bypass/RemoteSigned/Restricted/Unrestricted и др.); пять областей действия и их приоритет; область Process хранится в $Env:PSExecutionPolicyPreference и не перебивает GPO; групповая политика «Turn on Script Execution» сильнее всех областей; к скачанным файлам прикрепляют альтернативный поток данных, а curl.exe и аналоги иногда метку не ставят; предупреждение про UNC-пути. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12 ↩13 ↩14 ↩15 ↩16 ↩17 ↩18 ↩19 ↩20 ↩21 ↩22 ↩23 ↩24 ↩25 ↩26
-
Microsoft Learn, Chapter 1 - Getting started with PowerShell. О том, что политика выполнения не граница безопасности; по умолчанию на Windows 10/11 — Restricted, на Windows Server 2016/2019/2022 — RemoteSigned; политика влияет только на скрипты, интерактивные команды всегда доступны. ↩ ↩2 ↩3
-
Microsoft Learn, Set-ExecutionPolicy. Область по умолчанию — LocalMachine, нужны права администратора; MachinePolicy/UserPolicy изменить нельзя; групповую политику не перекрыть, при конфликте выводится сообщение; пример, где Unblock-File снимает блокировку скрипта, не меняя политику выполнения. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Unblock-File. Unblock-File удаляет альтернативный поток Zone.Identifier со значением 3 (интернет-зона); это та же операция, что кнопка «Разблокировать» в свойствах файла в Проводнике; перед использованием нужно проверить безопасность файла и источника; файлы с Zone.Identifier находят Get-Item -Stream. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, about_Signing. Какие типы файлов подписывают; разница между сертификатом удостоверяющего центра и самоподписанным (самоподписанный только для тестов и на других компьютерах не запускается); подпись добавляется блоком комментариев # SIG #; до PowerShell 7.2 нужно было сохранять в ASCII/UTF8NoBOM; сервер меток времени сохраняет действительность подписи после истечения сертификата; запрос про ненадежного издателя. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12 ↩13 ↩14 ↩15
-
Microsoft Learn, Set-AuthenticodeSignature. Наложение подписи Authenticode, замена существующей; параметр -TimestampServer не даёт скрипту сломаться после истечения сертификата; пример получения сертификата подписи кода с закрытым ключом через -CodeSigningCert на диске Cert:. ↩ ↩2 ↩3
-
Microsoft Learn, New-SelfSignedCertificate. Командлет создаёт самоподписанный сертификат для тестов; параметр -Type позволяет указать сертификат подписи кода; срок по умолчанию — один год. ↩ ↩2 ↩3
-
Microsoft Learn, PowerShell security features. Политика выполнения — одна из нескольких функций, повышающих безопасность среды запуска скриптов, и рассматривается как защитный механизм, который помогает не запускать вредоносные скрипты. ↩
-
Microsoft Learn, File Streams. В файловой системе NTFS данные файла хранятся как потоки, один файл может иметь несколько потоков; у потока данных по умолчанию нет имени; именованный поток задают в виде «имя_файла:имя_потока:тип_потока». ↩
-
Microsoft Learn, Active Directory Certificate Services documentation. AD CS даёт инфраструктуру открытых ключей (PKI) для шифрования, цифровых сертификатов и подписи; состоит из служб роли: удостоверяющий центр, веб-регистрация, сетевой ответчик (OCSP), служба регистрации сетевых устройств, веб-служба регистрации сертификатов и др. (службы ответа меток времени среди них нет). ↩ ↩2
-
Microsoft Learn, Get-Certificate. Командлет отправляет запрос сертификата на сервер регистрации и устанавливает ответ; -Template задаёт имя шаблона или OID; если учётные данные не указаны, используется проверка подлинности Kerberos; -CertStoreLocation принимает только хранилище My; после выдачи Status равен Issued, при ожидании — Pending. ↩
-
Microsoft Learn, Configure trusted roots and disallowed certificates in Windows. Как через групповую политику (Конфигурация компьютера > Политики > Конфигурация Windows > Параметры безопасности > Политики открытого ключа) импортировать сертификаты в хранилища вроде «Доверенные корневые центры сертификации» и раздавать их. ↩
-
Microsoft Learn, about_Certificate_Provider. Провайдер сертификатов PowerShell даёт доступ к хранилищам и сертификатам как к диску
Cert:; два расположения — CurrentUser и LocalMachine — и хранилища под ними; сертификаты идентифицируют по отпечатку; Get-ChildItem и аналоги обходят их как файловую систему; параметр -CodeSigningCert выбирает сертификаты с подписью кода в расширенном использовании ключа. ↩ ↩2 ↩3 -
DigiCert, RFC 3161 compliant Time Stamp Authority server. DigiCert публикует сервер меток времени по RFC 3161
http://timestamp.digicert.com, его можно использовать для метки времени подписи Authenticode. ↩
Похожие статьи
Недавние статьи с теми же тегами помогут подробнее изучить близкие темы.
PowerShell на практике — безопасная автоматизация анализа логов, архивирования и отчётов
Разбираем практический порядок безопасной работы со скриптами PowerShell: анализ логов, CSV-отчёты, архивирование старых логов, сохранени...
Политика аудита безопасности Windows и расследование журнала событий на практике — как стать ИТ-службой, которая умеет читать 4625
Практическое руководство, чтобы ответить на просьбу «посмотрите журналы неудачных входов». Разбирает связь базовой и расширенной политики...
Windows LAPS на практике — больше не используем один локальный пароль администратора на всех ПК
Один локальный пароль администратора на всех ПК — благодатная почва для Pass-the-Hash: компрометация одной машины открывает остальные. Ра...
Хранилище сертификатов Windows на практике — пользователь или компьютер
Куда помещать клиентский сертификат — в хранилище пользователя или компьютера. Практическое руководство закрывает типичные сбои: разница ...
Брандмауэр Windows и бизнес-приложения — входящие правила регистрирует установщик
«На машине разработчика работает, у заказчика не соединяется» почти всегда упирается в брандмауэр Windows. Разбираем блокировку входящих ...
Связанные темы
Эти страницы показывают тему статьи в более широком контексте услуг и решений.
Технические темы Windows
Раздел о разработке Windows, расследовании сбоев и использовании существующих активов.
Услуги по этой теме
Статья напрямую связана со следующими услугами.
Разработка приложений для Windows
Бизнес-приложения, интеграция оборудования и средства связи — от требований до разработки.
Частые вопросы
Вопросы, которые часто возникают при консультациях по теме статьи.
- Является ли политика выполнения PowerShell функцией безопасности?
- Официальная документация прямо говорит: «политика выполнения — это не система безопасности, ограничивающая действия пользователя». Её легко обойти: достаточно вставить содержимое скрипта в командную строку. Политика задаёт базовые правила и служит защитным механизмом против случайного запуска не того скрипта. На ней нельзя строить границу, которая должна останавливать злоумышленника. Защиту от атак делают на другом уровне: контроль приложений, минимизация прав и так далее.
- Чем RemoteSigned отличается от AllSigned?
- RemoteSigned требует подпись доверенного издателя только у скриптов из интернета (с Mark of the Web). Скрипты, созданные локально, запускаются без подписи. AllSigned требует подпись у всех скриптов и файлов конфигурации, включая локальные, и перед запуском скрипта от ещё не классифицированного издателя спрашивает подтверждение. Если в компании можно выстроить процесс подписи (раздача сертификатов подписи кода и сама процедура), выбирайте AllSigned. Если такой инфраструктуры нет, реалистичнее RemoteSigned.
- Почему скачанный скрипт не запускается с ошибкой «не имеет цифровой подписи»?
- К файлам, скачанным через браузер и похожие программы, прикрепляется альтернативный поток данных Zone.Identifier, и Windows считает их «файлами из интернета». При политике RemoteSigned неподписанный скрипт с этой меткой блокируется. Если вы проверили содержимое и признали его безопасным, снимите Zone.Identifier командлетом Unblock-File или флажком «Разблокировать» в свойствах файла в Проводнике. Политику выполнения менять не нужно.
- Как реалистично раздавать внутренние скрипты PowerShell?
- Два основных варианта. Первый — RemoteSigned плюс размещение на файловом сервере: можно начать без инфраструктуры подписи, но в зависимости от канала раздачи может появиться Mark of the Web и заблокировать запуск, а изменение скрипта никто не заметит. Второй — AllSigned плюс процесс подписи: скрипты подписывают Set-AuthenticodeSignature сертификатом подписи кода (на практике чаще внутренним ЦС), а политику задают централизованно через групповую политику. Контроль политики и обнаружение изменений есть, но появляются затраты на раздачу и обновление сертификатов.
- Можно ли и дальше указывать -ExecutionPolicy Bypass в Планировщике заданий?
- Запустится, но так делать не стоит. Если политикой выполнения управляет групповая политика, параметр ExecutionPolicy в командной строке её не перебивает и просто не действует. Постоянный Bypass сам снимает защитный механизм против случайного запуска и со временем разводит официальную политику организации и то, что происходит на местах. Для постоянной эксплуатации задайте политику окружения через групповую политику или Set-ExecutionPolicy от имени администратора, а доверие к скриптам подтверждайте подписью.
- Зачем при подписи скрипта нужна метка времени (-TimestampServer)?
- Действительность подписи в общем случае привязана к сроку сертификата. Если есть метка времени, сервер меток подтверждает, что подпись поставили, пока сертификат ещё был действителен, и скрипт можно использовать после истечения срока. У большинства сертификатов подписи кода срок около года: без метки каждый год есть риск, что в один день все подписанные внутренние скрипты перестанут запускаться. При подписи всегда указывайте -TimestampServer.
Об авторе
Страница с профилем автора статьи.
Го Комура
Представитель KomuraSoft LLC
Специализируется на разработке программного обеспечения для Windows, техническом консалтинге и расследовании сбоев, особенно в проектах с унаследованными системами и трудно воспроизводимыми ошибками.