GPO abuse — эскалация привилегий Windows: разбор атаки на AD и детект для SOC

На внутреннем пентесте Active Directory я нашёл учётную запись с правом GenericWrite на GPO, привязанный к корню домена. Три команды в терминале Kali — и аккаунт без единой привилегии стал локальным администратором контроллера домена. Вся цепочка от разведки через BloodHound до получения SeDebugPrivilege заняла 12 минут. Двенадцать. Ниже — каждый шаг атаки на групповые политики, а параллельно — что именно в логах должен увидеть SOC-аналитик, чтобы остановить GPO abuse до того, как станет поздно.
Бизнес-логика атаки: зачем злоумышленнику групповые политики
Group Policy Object (GPO — объект групповой политики) — механизм централизованного управления настройками Windows-домена. Через GPO администратор раздаёт политики паролей, ставит софт, запускает скрипты и назначает запланированные задачи на тысячи машин одновременно. Именно эта мощь делает GPO лакомой целью: право записи в GPO, привязанный к нужной OU (Organizational Unit — контейнер для объектов домена, что-то вроде папки в AD), позволяет выполнить произвольный код на каждой машине в этой OU. Включая контроллер домена.
В терминах MITRE ATT&CK (открытая база тактик и техник атак; T-коды вроде T1484.001 — её идентификаторы) атака через GPO — техника T1484.001 Group Policy Modification. Тактики: Privilege Escalation (эскалация привилегий) и Defense Evasion (обход защиты). Параллельно может сработать T1552.006 Group Policy Preferences — если в SYSVOL (сетевая папка на контроллере домена, где хранятся файлы групповых политик) остались устаревшие GPP-файлы с зашифрованными паролями. Ключ расшифровки Microsoft опубликовала ещё в 2012 году — то есть «шифрование» там чисто номинальное. Тактика: Credential Access. Разведку GPO покрывает T1615 Group Policy Discovery.
Это не учебная абстракция. В публичных отчётах описаны случаи распространения ransomware через GPO: атакующие создавали запланированную задачу, которая запускала шифровальщик на устройствах домена. В 2022 году, по данным ESET, деструктивный вайпер CaddyWiper предположительно распространялся через GPO в украинских сетях (детали атрибуции — в отчёте ESET).
Финальный импакт: одна лишняя строка в ACL (Access Control List — список контроля доступа, определяющий «кто что может делать с объектом») GPO, выданная по ошибке при делегировании полномочий helpdesk-команде, может привести к полной компрометации домена. Поэтому эта техника критична и для пентеста Active Directory, и для SOC-мониторинга.
Разведка — находим уязвимый GPO в домене
Сценарий grey box: есть доменные учётные данные низкопривилегированного пользователя — типичная ситуация на внутреннем пентесте, когда заказчик выдаёт аккаунт уровня «сотрудник». Задача — найти GPO, на которые этот пользователь имеет право записи.
BloodHound: сбор и анализ графа привилегий
BloodHound строит граф связей Active Directory. Он собирает данные об учётных записях, группах, GPO, OU и ACL, а потом визуализирует пути эскалации привилегий Windows — как маршруты на карте метро, только вместо станций узлы AD.
На атакующей машине (Kali Linux) нужен bloodhound-python — коллектор, работающий по сети без агента на целевом хосте. Между атакующей машиной и контроллером домена должен быть открыт LDAP (389/TCP) и DNS.
Зачем этот шаг: перед атакой на GPO нужно понять, какие объекты контролирует наш аккаунт. Ручной перебор ACL в домене с тысячами объектов — это часы работы. BloodHound делает то же самое за минуты.
Запускаем сбор: bloodhound-python -u raj -p 'Password@1' -ns 192.168.1.11 -d ignite.local -c all. Флаг -c all включает полный сбор, в том числе ACL — без него GPO-права не попадут в граф. Параметр -ns указывает DNS-сервер (обычно совпадает с IP контроллера домена).
В текущей директории появятся JSON-файлы: computers.json, groups.json, users.json и другие. Пустые файлы или ошибка «Connection refused» — проверяйте сетевой доступ к LDAP и правильность DNS.
Загружаем файлы в интерфейс BloodHound (кнопка Upload Data). Переходим к узлу скомпрометированного пользователя и открываем Outbound Object Control — исходящие связи контроля объектов. Три ребра, которые открывают GPO abuse:
- GenericWrite — право записи любых атрибутов объекта, включая содержимое GPO в SYSVOL. Встречается чаще всего — обычно выдаётся при делегировании helpdesk-команде или через legacy-скрипт настройки
- WriteDacl — право изменить ACL самого GPO и назначить себе полные разрешения
- WriteOwner — право стать владельцем GPO с последующим назначением любых разрешений
Любое из трёх рёбер от пользователя к GPO — достаточное условие для отравления GPO.
Извлечение GUID целевой политики
В правой панели BloodHound для узла GPO отображается Distinguished Name, содержащий GUID (глобально уникальный идентификатор) — строка формата {4B878AA9-238D-4975-B3A3-B7EE9990F66C}. Инструмент эксплуатации адресует конкретную политику в SYSVOL именно по этому GUID — запишите его, он понадобится на следующем шаге.
Эксплуатация: отравляем GPO через pyGPOAbuse
После обнаружения GPO с правом записи и извлечения GUID нужно внедрить вредоносный payload в этот GPO. При следующем обновлении групповой политики каждая машина, привязанная к GPO, выполнит нашу команду с правами NT AUTHORITY\SYSTEM — наивысшей локальной учётной записью Windows.
pyGPOAbuse — инъекция немедленной задачи
pyGPOAbuse — Python-инструмент, который модифицирует содержимое GPO в SYSVOL через SMB (протокол доступа к сетевым папкам Windows, порт 445/TCP). Он создаёт Immediate Scheduled Task — задачу, которая выполнится при ближайшем обновлении политики без ожидания расписания.
Между Kali и контроллером домена должен быть открыт SMB-порт 445/TCP.
git clone https://github.com/hackndo/pyGPOAbuse.git
cd pyGPOAbuse
python3 -m venv .venv && source .venv/bin/activate
python3 -m pip install -r requirements.txt
Запускаем эксплуатацию: python3 pygpoabuse.py ignite.local/raj:'Password@1' -gpo-id "4B878AA9-238D-4975-B3A3-B7EE9990F66C". pyGPOAbuse принимает параметры -command и -args для указания выполняемой команды. Первый запуск с -command "net.exe" -args "user john H4x00r123.. /add", затем второй с -command "net.exe" -args "localgroup administrators john /add" — и на каждой целевой машине появится новый локальный администратор.
Строка [+] ScheduledTask TASK_<random_id> created! подтверждает успешную инъекцию. Ошибка доступа — убедитесь, что у аккаунта действительно GenericWrite на этот GPO и SMB-порт доступен.
Что происходит на целевой стороне: при следующем цикле gpupdate (по умолчанию каждые 90 минут ±30 минут для рядовых машин, каждые 5 минут для контроллеров домена) или при принудительном gpupdate /force контроллер домена считывает обновлённый GPO из SYSVOL. Задача попадает в Computer Configuration → Preferences → Scheduled Tasks и выполняется с правами SYSTEM.
Проверка результата: подключаемся к контроллеру через evil-winrm -i 192.168.1.11 -u john -p 'H4x00r123..'. Успешное подключение — эскалация привилегий состоялась. whoami /priv покажет SeDebugPrivilege, SeImpersonatePrivilege, SeBackupPrivilege и другие привилегии локального администратора.
С этого момента доступен дамп NTDS.dit, извлечение хэша krbtgt и создание Golden Ticket — domain privilege escalation завершён.
SharpGPOAbuse — альтернативный toolchain [Внутренний]
SharpGPOAbuse — .NET-аналог pyGPOAbuse, работающий из Windows-сессии на скомпрометированном хосте. Удобен, когда атакуешь изнутри домена без выхода на Linux.
Три режима работы:
Immediate Scheduled Task — аналог pyGPOAbuse. Вызов: SharpGPOAbuse.exe --AddComputerTask --TaskName "Update" --Author "NT AUTHORITY\SYSTEM" --Command "cmd.exe" --Arguments "/c net localgroup administrators attacker /add" --GPOName "Vuln GPO". Задача выполняется при следующем gpupdate.
Startup Script — внедряет скрипт в автозагрузку GPO. Скрипт выполняется при каждой перезагрузке машин, привязанных к политике, — это уже persistence (закрепление в системе).
Local Admin persistence — добавляет пользователя напрямую в группу локальных администраторов через механизм GPO без промежуточных задач.
Выбор инструмента зависит от условий: pyGPOAbuse — когда атакуем с Linux, SharpGPOAbuse — когда уже есть сессия на Windows-хосте.
Предусловия и ограничения
GPO abuse работает не при любых условиях. Перед эксплуатацией стоит пройтись по чеклисту.
Когда техника работает:
- Скомпрометированный аккаунт имеет GenericWrite, WriteDacl или WriteOwner на GPO
- GPO привязан (linked) к OU с целевыми машинами и Link Enabled = True
- Между атакующей машиной и контроллером домена открыт SMB (445/TCP)
- На целевых машинах не заблокированы Immediate Scheduled Tasks через AppLocker или WDAC (Windows Defender Application Control)
Когда техника НЕ работает:
- Block Inheritance на дочерней OU — задача не применится к машинам в OU, где наследование заблокировано, даже если GPO привязан к родительскому контейнеру
- GPO с флагом Enforced — такой GPO обрабатывается вне обычного порядка приоритетов и не может быть переопределён, включая модифицированный атакующим GPO
- SYSVOL Hardening — если администратор ограничил запись в каталог SYSVOL через NTFS-разрешения, pyGPOAbuse получит Access Denied при создании файла задачи
- Современные EDR (CrowdStrike Falcon, Microsoft Defender for Endpoint с мониторингом SYSVOL) могут заблокировать запись в каталог GPO или сгенерировать немедленный алерт
- Windows Server 2019+ с аудитом Directory Service Changes и SIEM-forwarding — атака технически сработает, но будет обнаружена в реальном времени
Важный нюанс совместимости: после патча MS16-072 (2016) изменилась модель получения списка применимых GPO. Для enumeration теперь используется контекст компьютера, а не пользователя. Это требует наличия Read и Apply Group Policy permissions для Authenticated Users, Domain Computers или конкретных компьютерных объектов в ACL GPO — иначе computer-context enumeration не обнаружит GPO. Учитывайте это и при атаке, и при построении детекта.
Детект атаки на GPO: что видит SOC-аналитик
Переключаемся на сторону защиты. Каждый шаг цепочки отравления GPO оставляет следы в логах — если аудит настроен правильно.
Event ID 5136 — модификация объекта каталога
Ключевое событие для детекта GPO abuse — Windows Security Event ID 5136 («A directory service object was modified»). Генерируется на контроллере домена при любом изменении атрибутов объекта Active Directory.
Предпосылка, без которой ничего не будет: политика аудита «Audit Directory Service Changes» должна быть включена (Computer Configuration → Windows Settings → Security Settings → Advanced Audit Policy → DS Access → Audit Directory Service Changes). Без неё событие не появится в логах, и атака пройдёт незамеченной. Я видел домены с 200+ GPO, где эта политика просто не включена. Годами.
На что смотреть в событии 5136:
AttributeLDAPDisplayName: gPCMachineExtensionNames— изменение этого атрибута означает модификацию серверных расширений GPO. Появление GUID{827D319E-6EAC-11D2-A4EA-00C04F79F83A}(Security CSE) совместно с{803E14A0-B4FB-11D0-A0D0-00A0C90F574B}(Computer Restricted Groups) — прямой индикатор добавления привилегий через GPOSubjectUserName— учётная запись, внёсшая изменение. Не входит в группу GPO-администраторов — немедленный алертObjectDN— Distinguished Name изменённого GPO. По нему определяете привязанные OU и радиус поражения
В репозитории Elastic Security detection-rules есть правило детекции GPO abuse for Privilege Addition с Severity: high (точные значения Risk Score уточняйте в актуальной версии в elastic/detection-rules). Запрос работает по индексам logs-system.security* и winlogbeat-*, фильтруя события 5136 с изменением gPCMachineExtensionNames.
Корреляция событий: от алерта до расследования
Одного Event ID 5136 недостаточно. SOC-аналитик строит цепочку:
Event ID 5136 → кто изменил GPO (SubjectUserSid)
↓ связь по SubjectLogonId
Event ID 4624 → откуда пришёл логон (source.ip, logon.type)
↓ проверяем
Event ID 4648 → использовались ли альтернативные кредентиалы
↓ инспектируем SYSVOL
GptTmpl.inf → какие привилегии назначены и кому
Поле OpCorrelationID в событии 5136 связывает все изменения одной операции редактирования GPO. Несколько чувствительных атрибутов в одной корреляционной группе — сигнал повышенной вероятности атаки.
В SYSVOL по GUID GPO из ObjectDN находим файл \\<DC>\SYSVOL\<domain>\Policies\{GUID}\Machine\Microsoft\Windows NT\SecEdit\GptTmpl.inf. В секции [Privilege Rights] ищем назначение SeDebugPrivilege, SeTakeOwnershipPrivilege, SeImpersonatePrivilege за пределами baseline. В секции [Group Membership] — добавление учётных записей в SID S-1-5-32-544 (локальные администраторы).
Event ID 5137 («A directory service object was created») сработает, если атакующий создал новый GPO вместо модификации существующего. По рекомендации ManageEngine, оба события мониторятся в связке.
Делай раз, делай два, делай три
Пошаговый чеклист для отработки на лабораторном стенде (HTB Intelligence, TryHackMe или собственная AD-лаба):
Шаг 1 — Разведка. Запустите bloodhound-python с флагом -c all от имени скомпрометированного пользователя. Убедитесь, что в выводе есть непустые JSON-файлы с ACL-данными. Загрузите в BloodHound, найдите рёбра GenericWrite/WriteDacl/WriteOwner от вашего пользователя к любому GPO. Если таких рёбер нет — GPO abuse невозможен с текущими учётными данными, нужна горизонтальная эскалация к другому аккаунту.
Шаг 2 — Эксплуатация. Скопируйте GUID обнаруженного GPO. Запустите pyGPOAbuse с этим GUID. Дождитесь сообщения [+] ScheduledTask created. На контроллере выполните gpupdate /force (если есть доступ) или ждите автоматического обновления (до 90 минут).
Шаг 3 — Верификация. Подключитесь через evil-winrm с учётными данными созданного пользователя. whoami /priv — SeDebugPrivilege в выводе подтверждает успешную эскалацию привилегий Windows. net localgroup Administrators — новый пользователь должен быть в списке.
Шаг 4 — Детект. На контроллере откройте Event Viewer → Windows Logs → Security. Фильтруйте по Event ID 5136. Найдите запись с AttributeLDAPDisplayName = gPCMachineExtensionNames и SubjectUserName, совпадающим с тестовым аккаунтом. Это тот алерт, который SOC-аналитик должен отловить.
Каждый шаг маппится на модули курса SOC-аналитика: разведка в AD, эскалация привилегий Windows, верификация компрометации, мониторинг и реагирование. Прохождение этой цепочки на стенде — самый короткий путь к пониманию, как атака выглядит с обеих сторон.
GPO abuse — техника, которую SOC-команды катастрофически недооценивают. По данным CrowdStrike Global Threat Report 2025, 75% вторжений происходят с использованием действительных учётных данных (T1078 Valid Accounts, включая T1078.002 Domain Accounts), а IBM X-Force фиксирует рост атак с валидными учётными данными на 71% год к году. При этом подавляющее большинство доменов, которые я тестировал, не мониторят Event ID 5136 вообще — аудит Directory Service Changes просто не включён. Администраторы настраивают GPO для раздачи софта и политик паролей и забывают, что каждый GPO с делегированными правами записи — готовый вектор lateral movement в Active Directory.
Парадокс: включение одной политики аудита и одного правила в SIEM (фильтр на gPCMachineExtensionNames + SubjectUserName вне белого списка) закрывает этот вектор на уровне детекта за 15 минут работы. Но эти 15 минут никто не тратит, потому что «GPO — это же просто настройки».
Если переходите из IT в ИБ, именно такие задачи — аудит ACL на GPO, настройка детект-правил, построение baseline — составляют повседневную работу джуниора в SOC. На IB Basics эту базу проходят за пару месяцев, от первого Event ID до рабочего playbook.
Эту тему и смежные навыки разбирают на практике в курсе «Аналитик SOC» Codeby Academy.