«Злоупотребление ограниченным делегированием Kerberos на основе ресурсов» — как много в этом звуке! Точнее  уже не просто звуке и даже не словосочетании, а целом классе  наступательных техник в доменной среде Active Directory. Вот уже как  больше трех лет, казалось бы, вполне себе легитимный механизм,  помогающий трехголовому псу стоять на страже даже там, где нет этих  ваших «тикетов», служит грозным оружием всех пенетраторов Windows-сетей.  Не знаю никого, кто использовал бы RBCD по назначению, честно. В  этой статье хотелось бы остановиться на таком интересном пограничном  случае применения этой атаки, как RBCD с UPN-ами, но не SPN-ами. Ограниченное делегирование на основе ресурсов (Resource-Based Constrained Delegation, RBCD) появилось в ОС Windows Server 2012 и представляет из себя концепцию олицетворения пользователей сервером (то есть сервисной учетной записью) в ситуации, когда пользователь проходит проверку подлинности по паролю, а серверу нужно выполнить то или иное действие от его имени по Kerberos-билету в информационной системе по соседству. Классический пример, который приводится для объяснения, зачем вообще нужны разные виде делегирования в AD — это пример с веб-сервером и базой данных. Не будем отходить от этой традиции и мы, поэтому посмотрим на рисунок ниже. Что здесь происходит: Пользователь snovvcrash проходит проверку подлинности на веб-сервере WEB01, предоставляя в качестве «доказательства аутентичности» свой пароль. Аутентификация проходит по протоколу NTLM, потому что snovvcrash находится за пределами доменной сети и не обладает возможностью передать билет Kerberos. Веб-сервер видит, что ему не дали тикета в ходе аутентификации, поэтому в игру вступает транзитное расширение протокола Kerberos S4U2self (Service for User to Self), предназначенное для получения «пробрасываемого» (Forwardable, билет с правом передачи) TGS-билета на самого себя у контроллера домена от имени целевого пользователя. Это позволит веб-серверу запросить следующий TGS-билет на службу БД SQL01 в шаге 3. Активация следующей фазы транзитного расширения Kerberos – S4U2proxy (Service for User to Proxy). В ходе этой процедуры веб-сервер может предоставить в качестве доказательства TGS-билет из шага 2 для получения TGS-билета на службу SQL01 от имени целевого пользователя snovvcrash. Веб-сервер получает возможность получения доступа к базе данных SQL01, олицетворяя пользователя snovvcrash. Важно отметить, что в концепции RBCD-делегирования право получения доступа к службе SQL01 веб-сервером WEB01 с олицетворением других пользователей определяет сама служба SQL01. Данный процесс происходит путем записи в свойство с непроизносимым называнием msDS-AllowedToActOnBehalfOfOtherIdentity объекта службы (компьютера) SQL01 значения SID-а учетной записи WEB01$. Это отличает ограниченное делегирование на основе ресурсов от классического ограниченного делегирования (Kerberos Constrained Delegation, KCD). — «Круто, и что со всем этим делать?», — спросил системный администратор. — «Злоупотребл#ть, разумеется», — ответил пентестер. В 2019 году исследователь Элад Шамир (@elad_shamir) опубликовал пугающий своими размерами ресерч Wagging the Dog: Abusing Resource-Based Constrained Delegation to Attack Active Directory, ставший краеугольным камнем в развитии методов злоупотребления механизмом ограниченного делегирования на основе ресурсов. В этом пункте я не буду подробно останавливаться на теоретической части эксплуатации RBCD Abuse, так как материалов на просторах Интернета хватает (в конце оставлю ссылки). Вместо этого давайте лучше вместе проведем эту атаку «вживую», чтобы более плавно подойти к тем самым нововведениям, которые недавно были открыты специалистом Джеймсом Форшоу (@tiraniddo). Нетерпеливые могут сразу прыгать в пункт 3. С данной атакой я впервые познакомился в момент прохождения лаборатории Hades на Hack The Box, и в тот момент это казалось самым сложным, что вообще бывает в AD-эксплуатации (как же я ошибался, да?). Классический вариант абьюза RBCD проводится с Windows с помощью тройки благородных инструментов: Powermad, PowerView, Rubeus. Допустим, мы скомпрометировали доменного пользователя TINYCORP\AngaraUser, обладающего правом на запись в объект машины MOSCOW.tinycorp.net. В этом случае для получения административного доступа к службам MOSCOW нам понадобится вспомогательный машинный аккаунт (или любая другая УЗ с записью SPN) для того, чтобы вписать значение его SID-а в свойство msDS-AllowedToActOnBehalfOfOtherIdentity объекта MOSCOW и далее делегировать этой вспомогательной машине право олицетворения привилегированных (или других) пользователей в отношении атакуемого хоста MOSCOW. Машинный аккаунт (или, другими словами, сервисную учетку с записями SPN) атакующий может создать в домене Active Directory, обладая минимальным аутентифицированным доступом. Свойство ms-DS-MachineAccountQuota, по умолчанию равное 10, определяет количество компьютеров, разрешенных для ввода в домен обычными пользователями одновременно. Этим и пользуется инструмент Powermad.  Теперь, обладая подконтрольной УЗ TINYCORP\AngaraMachine$, мы можем скрафтить дескриптор безопасности DACL, разрешающий доступ (Allow) AngaraMachine$, и присвоить его свойству msDS-AllowedToActOnBehalfOfOtherIdentity машинного объекта MOSCOW. Сделать это можно, например, с помощью PowerView, если нет возможности использовать стандартный модуль ActiveDirectory.  Ну а теперь мы просто используем Rubeus для проведения полной цепочки атаки S4U, в ходе которой, как было описано раньше, будут выполнены задействованы процедуры S4U2self & S4U2proxy для получения TGS-билета Kerberos и олицетворения привилегированной УЗ TINYCORP\Administrator в отношении служб HOST и HTTP (целимся в WinRM) компьютера MOSCOW.  Если лень делать все вышеописанное вручную, можно воспользоваться актуальным форком PowerView, где появился командлет Set-DomainRBCD, частично автоматизирующий процесс, описанный выше. Пример использования можно подсмотреть в моем прохождении другой лабы RPG с Hack The Box. То же самое может быть легко проделано с Linux-хоста благодаря коллекции скриптов Impacket. Покажем это. Создаем машинную учетку с помощью addcomputer.py.  Навешиваем ее на атакуемый хост MOSCOW, как разрешенную для делегирования S4U с помощью rbcd.py.  Запрашиваем тикет с олицетворением администратора домена в отношении службы CIFS (целимся в DCE/RPC) компьютера MOSCOW с помощью getST.py.  Это всего лишь один пример, как можно злоупотреблять механизмом RBCD «в лоб». В связке с другими цепочками атак такое злоупотребление мутирует, превращаясь в очень опасные формы повышения привилегий — от локальных атак для LPE (например, в связке с относительно новой атакой Kerberos Relay) до получения прав администратора домена в несколько команд (говорили об этом в этой статье). S4U2Pwnage | by Will Schroeder | Medium Wagging the Dog: Abusing Resource-Based Constrained Delegation to Attack Active Directory | Shenanigans Labs A Case Study in Wagging the Dog: Computer Takeover | by Will Schroeder | Posts By SpecterOps Team Members SensePost | Chaining multiple techniques and tools for domain takeover using rbcd CVE-2020-17049: Kerberos Bronze Bit Attack - Theory CVE-2020-17049: Kerberos Bronze Bit Attack - Practical Exploitation eXploit – Delegate 2 Thyself eXploit – Revisiting 'Delegate 2 Thyself' Red Team Privilege Escalation - RBCD Based Privilege Escalation - Praetorian  «Итак, а в чем же новый взгляд, snovvcrash?» — спросите вы. Так вот. Несколько месяцев назад исследователь команды Google Project Zero Джеймс Форшоу в треде обсуждения недавнего на тот момент вторника обновлений Microsoft в Твиттере выдвинул поистине гениальное в своей простоте предположение о том, что нам по сути-то и не нужна машинная учетная запись для делегирования ей привилегий — для этого хватит и учетки простого пользователя. В последствии это предположение было подтверждено им же в небольшой заметке, легшей в основу этой публикации. Почему вообще это важно? Все чаще и чаще на проектах мы сталкиваемся с тем, что свойство ms-DS-MachineAccountQuota в AD равно 0 (как мы и рекомендуем в своих отчетах). Таким образом, у низкопривилегированных пользователей больше нет прав для создания сервисных учеток, а ввод новых компьютеров в домен делегирован системным администраторам. Но продолжать ломать же нужно 😈 Поэтому предлагаю рассмотреть новый вектор абьюза RBCD с единственной подконтрольной УЗ обычного пользователя. Но для начала постараемся понять, а для чего вообще нам была нужна машинная учетка? Все просто. Для того, чтобы служба KDC (Key Distribution Center) контроллера домена могла зашифровать TGS-билеты, выдаваемые нам в процессе взаимодействий S4U, она должна знать, какой ключ для этого использовать. В случае с машинной УЗ это не вызывает проблем, так как ее долговременный ключ ищется KDC по значению записей SPN (Service Principal Name), по умолчанию создаваемых для нового хоста. Однако, если я укажу другую (свою же) пользовательскую учетку для записи в дескриптор свойства msDS-AllowedToActOnBehalfOfOtherIdentity, цепочка S4U сфейлится, не пройдя фазу S4U2self. Ошибка KDC_ERR_S_PRINCIPAL_UNKNOWN непрозрачно намекает на свою природу: KDC не может найти ключ по значению SPN в силу его отсутствия.  Но! Мы не должны забывать, что у пользовательских УЗ также есть принципиал, однозначно их характеризующий — это UPN (User Principal Name). Из исследования Элада Шамира о злоупотреблении механизмом Shadow Credentials мы знаем о существовании механизма U2U (User to User), подобного S4Uself, однако применяемого к пользовательским учетным записям. Будучи используемым как составляющая протокола PKINIT, U2U позволяет пользователю получить доступ к своему же долговременному ключу (хешированному паролю) для того, чтобы использовать его в ходе NTLM-аутентификации в приложениях, не поддерживающих Kerberos-аутентификацию. В ходе процедуры U2U пользователь запрашивает у KDC билет TGS, содержащий NT-хеш пользователя в структуре PAC_CREDENTIAL_INFO, зашифрованной на кратковременном сессионном ключе. Таким образом пользователь может расшифровать эту структуру и извлечь свой NT-хеш. В Rubeus есть возможность запроса TGS-билета, используя U2U. Поэтому почему бы нам с этим не поиграть? Для начала я запрошу самый обычный TGT-билет.  Запомним его сессионный ключ, он понадобится нам позже. Далее, согласно схеме выше, я запрошу TGS-билет по протоколу U2U, предоставляя в качестве «доказательства» свой TGT-билет. Согласно документации Rubeus мы можем отправить этот же TGT-билет вместе с аргументом /tgs (этого требует PKINIT), а также указать опцию /targetuser для того, чтобы в структуре PAC_CREDENTIAL_INFO оказался аутентификатор пользователя, которого мы хотим олицетворить (например, администратора).  Теперь я могу использовать этот TGS в роли доказательства того, что я прошел этап S4Uself, и таким образом пропустить его инициирование в модуле s4u. Однако нас ждет новая сложность.  Ошибка KDC_ERR_BADOPTION, по словам автора оригинального исследования, может означать, что KDC не смог расшифровать TGS-билет, отправленный ему на шаге S4U2proxy. Почему так произошло? В силу того, что мы «считерили» на этапе S4Uself, оправив собственный TGS-билет, полученный в результате U2U, контроллер домена не смог его расшифровать, так как попытался это сделать с помощью долговременного ключа (NT-хеша) пользователя AngaraUser. Но этот билет зашифрован на сессионном ключе, а не на долговременном! Что если сменить пароль пользователю AngaraUser на значение кратковременного сессионного ключа его TGT? Возможно, в этом случае, KDC пойдет в NTDS, извлечет NT-хеш AngaraUser (уже совпадающий с сессионным ключом билета TGT) и сумеет успешно расшифровать тикет? Спойлер: да. Как мы можем изменить NT-хеш пароля AngaraUser, а не само значение пароля? Некоторое время назад я портировал скрипт NTLMInjector.ps1 на Python для Impacket (см. smbpasswd.py), где использовал вызов мало документированной функции SamrSetInformationUser, принимающей в качестве одного из аргументов структуру SamrSetInformationUser.Buffer. Внутри этой структуры мы можем указать новую пару LM:NT хешей, которые будут установлены для целевого пользователя. Однозначно нет. Однако почти всегда при проведении атак Password Spraying (T1110.003) мы обнаруживаем Богом заказчиком забытые учетки, пароли которых давно просрочены. Это может означать, что ими уже давно никто не пользуется и что смена их пароля не принесет вреда бизнес-процессам / рабочим процессам сотрудников компании. После согласования такого вмешательства мы можем это сделать, ведь у реальных злоумышленников не будет этических ограничений 😉 Я использую тот сессионный ключ, который мы запомнили, для смены долговременного ключа пользователя AngaraUser с помощью smbpasswd.py. Примечание № 1: в ходе тестирования я использую креды доменадмина для инжекта NTLM-хешей, однако чуть позже мы сделаем так, чтобы такую смену «пароля» (хешей) мог проворачивать сам низкопривилегированный пользователь AngaraUser. Примечание № 2: прежде чем менять хеш УЗ, из-под которой вы работаете в текущем сеансе, рекомендую убедиться, что парольная политика в домене впоследствии позволит сменить его еще раз на такое значение, для которого вы знаете пароль в открытом виде (другими словами, что максимальный срок действия пароля > 0). В противном случае, придется довольствоваться лишь аутентификацией по техникам Pass-the-Hash / Overpass-the-Hash.  И теперь я снова попробую провести атаку S4U.  Вот и все, мы провели классическую RBCD-атаку без вспомогательной УЗ с записью SPN! Все это, конечно, круто, но у нас есть одна неразрешенная проблема: пароль пользовательской УЗ мы поменяли с Linux-тачки, кустарным методом, да еще и заюзали для этого привилегированные креды. На наше счастье рядом со скриптом NTLMInjector.ps1 лежит SetNTLM.ps1, еще и писанный на C#. Он позволит нам изменить пароль целевой УЗ с ее же привилегиями через вызов недокументированной функции SamiChangePasswordUser. В smbpasswd.py тоже есть реализация этого API, но почему-то мне не удалось завести это дело так, чтобы хеш не помечался как STATUS_PASSWORD_EXPIRED после его установки через Impacket. Это даже к лучшему, потому что было решено допилить функционал Рубеуса для полной автоматизации описанного процесса. Как говорит автор изначального ресерча, в Рубеусе уже все готово для проведения атаки, просто в CLI модуля s4u нет нужных аргументов. Чтобы исправить это, достаточно «протащить» флаг bool u2u = true до функции NewTGSReq класса Rubeus/lib/krb_structures/TGS_REQ.cs, вызываемой в Rubeus/lib/S4U.cs. Ну и, разумеется, позаимствовать сам код установки NTLM-хешей из скрипта, указанного выше. Компилируем, и вуаля — у нас готов кастомный Рубеус с новым флагом /u2u для модуля s4u, умеющий проводить S4U-атаку с пользюковой учеткой! Мой PR доступен на Гитхабе, однако не думаю, что мы увидим его в «мастере», так как @exploitph отчетливо дал понять, что этот функционал слишком инвазивный, чтобы быть в апстриме утилиты. Но и это еще не все! Заказывая у нас пентест, вы получите Я также решил форкнуть нашумевший недавно KrbRelayUp, чтобы вооружить модуль RELAY для проведения этого подвида RBCD-атаки, что привело к появлению в нем опции -u2u. Там было совсем немного изменений, но если кто-то захочет посмотреть — вам сюда. Следуя хорошей традиции усложнения себе, как пентестерам, жизни, приведем перечень рекомендаций для снижения риска от подобных атак: Первое и, пожалуй, самое главное — включаем механизмы защиты служб LDAP (LDAP Signing) и LDAPS (LDAP Channel Binding). Нет релея на LDAP(S) — нет львиной доли злонамеренных изменений свойства msDS-AllowedToActOnBehalfOfOtherIdentity у объектов машин в Active Directory. Второе и почти не менее важное — запрещаем олицетворение критически важных УЗ (например, администраторов домена) при делегировании привилегий путем включения их в группу «Защищенные пользователи» или установкой флага AccountNotDelegated в UAC. Третье — если в вашем домене ms-DS-MachineAccountQuota все еще равна 10, пора задуматься о пентесте безопасности и срочно сбросить его до нуля. Четвертое — мониторить попытки эксплуатации RBCD Abuse и Kerberos Relay. Для этого рекомендуем обратить внимание на следующие события ИБ: 4741, 4673, 5156, 5136, 4768 и 4769. Пятое и заключительное — убедиться в активности сильного антивирусного решения на всех сетевых узлах, до которых могут дотянуться обычные пользователи (рабочие станции, терминальники). Cheers!  Sr. Penetration Tester / Red Team Operator