Привет, коллеги. Хочу поделиться опытом, который накопился за годы настройки безопасности в корпоративных средах. Если коротко: скриптовые атаки через PowerShell — это не теория, это ежедневная реальность. По данным отчётов 2024–2025 годов, более 70% инцидентов с использованием техник Living-off-the-Land начинаются именно с PowerShell.
И знаете, что меня удивляет? Многие админы до сих пор помечают настройку Constrained Language Mode (CLM) как риск: средний и откладывают её внедрение. Я сам так делал, пока не увидел, как один пропущенный скрипт стал точкой входа для целой цепочки атак.
Мой вывод простой: CLM — это не галочка для аудита. Это реальный инструмент, который отсекает 60–80% опасных возможностей языка, оставляя работоспособными 90% штатных задач. Ниже — мой личный разбор: как включить, что сломается, как починить, и как встроить это в современные практики без боли.
🔍 Что такое CLM на самом деле
Давайте без воды. Constrained Language Mode — это режим, в котором PowerShell работает как в «песочнице». Он не запрещает скрипты вообще, но физически не даёт выполнять опасные операции на уровне движка.
Вот что я обычно объясняю новичкам:
• Если скрипт пытается загрузить случайный .NET-тип через Add-Type — CLM скажет нет
• Если код использует рефлексию или COM-объекты — доступ заблокирован
• Если кто-то пытается обойти защиту через in-memory инъекции — AMSI + CLM остановят это
А что остаётся? Всё, что нужно для повседневной работы: базовые cmdlet, работа с файлами, реестром, сетью, утверждённые модули.
Проверить режим проще простого — одна команда:
$ExecutionContext.SessionState.LanguageMode
Увидели ConstrainedLanguage? Значит, защита работает. Если FullLanguage — самое время задуматься.
🛠️ Как включить: инструкция, с которой справится даже школьник
Я специально пишу этот раздел так, чтобы его понял любой. Без жаргона, без предположений.
Шаг 1. Открываем редактор политик
Нажмите Win + R, введите gpedit.msc, нажмите Enter.
Важно: в Windows 10/11 Home этого редактора нет по умолчанию. Для домашних версий переходите сразу к Шагу 4.
Шаг 2. Ищем нужный параметр
Переходим по пути:
Конфигурация компьютера → Административные шаблоны → Компоненты Windows → Windows PowerShell
Шаг 3. Включаем защиту
Находим политику Включить режим ограниченного языка, дважды кликаем, выбираем Включено → Применить → ОК.
Шаг 4. Проверяем результат
Откройте PowerShell от обычного пользователя и введите:
$ExecutionContext.SessionState.LanguageMode
Если видите ConstrainedLanguage — поздравляю, вы справились. Если нет — закройте все окна терминала и откройте заново. Политика применяется только к новым сессиям.
🔹 Для Windows Home или быстрых тестов
Запустите PowerShell от имени администратора и выполните:
[Environment]::SetEnvironmentVariable("__PSLockdownPolicy", "4", "Machine")
Перезапустите терминал. Готово. Для отката замените 4 на 0.
Личный лайфхак: перед массовым внедрением протестируйте на виртуалке. Это сэкономит нервы и время.
✅ ПОДПИСКА, ❤️ ЛАЙК, 🔄 РЕПОСТ друзьям, 💰 ДОНАТ на сбер по QR 👇
📌 2200 2803 3202 5362 💯 МТС-Банк *** СПАСИБО за Вашу поддержку ***
💰ПОДДЕРЖКА АВТОРА - ДЕЛО ДОБРОЙ ВОЛИ💰
⚠️ Пять типичных проблем и как я их решаю
Когда я впервые включал CLM в продакшене, думал: «всё сломается». Реальность оказалась проще — но только если знать, что ждать. Делюсь своим чек-листом.
🔸 Проблема 1: скрипты с Add-Type перестали работать
Почему: CLM блокирует динамическую компиляцию .NET в памяти.
Моё решение: выношу код в отдельную DLL, подписываю сертификатом, добавляю в AppLocker как доверенный. Если нужно быстро — использую __PSLockdownPolicy=0 только для конкретного сервисного аккаунта через GPO Preferences.
🔸 Проблема 2: SCCM, Exchange Shell или дашборды «потеряли» функции
Почему: легаси-утилиты часто используют COM или рефлексию.
Моё решение: создаю исключения в AppLocker по хэшу или пути. Да, CLM включается автоматически при Enforcement, но вы можете точечно разрешить нужным .exe работать в полном режиме.
🔸 Проблема 3: CI/CD пайплайны падают на этапе сборки
Почему: build-агенты используют PowerShell для упаковки и деплоя.
Моё решение: изолирую среду. Использую отдельные пулы агентов или ephemeral-контейнеры, где для build-аккаунтов явно отключаю CLM. Никогда не применяю глобальный CLM к сборочным серверам — это правило, которое я вывел на своих ошибках.
🔸 Проблема 4: IntelliSense в VS Code ведёт себя странно
Почему: расширение пытается загрузить метаданные через ограниченные API.
Моё решение: обновляю расширение до последней версии. В настройках VS Code добавляю:
"powershell.integratedConsole.languageMode": "Constrained"
Или работаю через Remote-SSH / Dev Containers — там изоляция уже «из коробки».
🔸 Проблема 5: политика не применяется на отдельных хостах
Почему: конфликт политик, медленная репликация AD, блокировка антивирусом.
Моё решение: выполняю gpupdate /force, проверяю журнал Microsoft-Windows-GroupPolicy/Operational, убеждаюсь, что хост в нужном OU. Если мешает AV — добавляю gpsvc.exe и svchost.exe (PolicyAgent) в исключения сканирования.
💻 Что я рекомендую разработчикам и DevOps-инженерам
Если вы пишете код или управляете инфраструктурой, CLM — не враг, а союзник. Вот как я встраиваю его в рабочие процессы.
✨ IaC и провижининг
Terraform сам по себе не использует PowerShell для основной логики, но local-exec/remote-exec могут. Я всегда проверяю, в каком контексте выполняются команды. Для Ansible указываю ansible_shell_type: cmd или явно задаю путь к pwsh с предварительной проверкой режима.
✨ Контейнеризация
В официальных образах mcr.microsoft.com/powershell CLM выключен по умолчанию. Я добавляю в Dockerfile одну строку:
ENV __PSLockdownPolicy=4
Это гарантирует, что даже в ephemeral-средах образ соответствует принципу least privilege.
✨ Тестирование до продакшена
Я пишу простой Pester-тест, который запускает скрипт в изолированном процессе:
It "Скрипт должен выполняться в CLM без ошибок" {
[Environment]::SetEnvironmentVariable("__PSLockdownPolicy", "4", "Process")
$result = & { .\MyScript.ps1 } 2>&1
$result | Should -Not -Match "LanguageMode"
}
Интегрирую в CI — и сплю спокойнее.
✨ Секреты и переменные
Важно помнить: CLM не шифрует данные. Я комбинирую его с Windows DPAPI, Azure Key Vault или HashiCorp Vault. Никогда не хардкодлю пароли в скриптах — даже если они «безопасны» для CLM.
✨ JEA или CLM? Что выбрать
JEA работает в Full Language Mode, но с ограниченным набором команд. Я использую JEA для делегирования админ-прав, а CLM — для пользовательских и фоновых задач. Это даёт точечный контроль без компромиссов.
✨ PowerShell 7+ или 5.1?
CLM работает одинаково, но в PS7 некоторые модули требуют явного указания доверенных путей. Я обновляю PSModulePath, избегаю Import-Module -SkipEditionCheck без крайней нужды и всегда тестирую критические сценарии в обеих версиях.
📊 Мониторинг: как я не теряю контроль после включения
Включить CLM — это только начало. Без видимости вы слепы. Вот мой минимальный набор для контроля.
🔹 Script Block Logging
В том же разделе GPO включаю Turn on PowerShell Script Block Logging. Это записывает каждый выполненный блок кода — даже если он закодирован или обфусцирован.
🔹 Модульное логирование
Добавляю Turn on PowerShell Module Logging и указываю модули для отслеживания: Microsoft.PowerShell.*, ActiveDirectory, Exchange.
🔹 Анализ событий
Мониторю Event ID 4103 (выполнение блока), 4104 (завершение) и события смены контекста в журнале:
Applications and Services Logs → Microsoft → Windows → PowerShell → Operational
🔹 Zero Trust
В современных стеках (Intune, Entra ID, WDAC) CLM — базовое требование для уровней Managed Device и Secure Core. Без него хост может быть изолирован политиками Conditional Access.
🔹 Авто-откат и алертинг
Настраиваю скрипт входа, который проверяет $ExecutionContext.SessionState.LanguageMode. Если значение не совпадает с ожидаемым — автоматически применяется __PSLockdownPolicy=4 и уходит алерт в SIEM или мессенджер.
✅ Мой итог и приглашение к диалогу
Если резюмировать мой опыт: Constrained Language Mode — это не «ещё одна галочка». Это сдвиг мышления: от разрешить всё к разрешить только доказанное безопасным.
Я начинаю с пилотной группы из 5–10 хостов, включаю логирование, проверяю совместимость через AppLocker или переменные среды — и только потом масштабирую. Так я закрываю вектор LotL-атак до того, как он станет инцидентом.
Подписывайтесь на канал, чтобы не пропустить разборы инфраструктуры, security-гайды и автоматизацию без боли. Новые материалы выходят каждую неделю — с живым опытом, без воды.
#PowerShell #ConstrainedLanguageMode #CLM #InfoSec #CyberSecurity #DevOps #SRE #SysAdmin #WindowsSecurity #GPO #AppLocker #WDAC #ZeroTrust #Automation #Scripting #LotL #EDR #SIEM #ITInfrastructure #SysOps #PowerShellCore #Pester #DockerSecurity #CICD #ITAdmin #CyberDefense #WindowsAdmin #ScriptSecurity #TechGuide #SecureAutomation