Почему задача «просто прочитать файл» оказывается нетривиальной

Почему задача «просто прочитать файл» оказывается нетривиальной

Ситуация, кажущаяся снаружи простой, на деле полна скрытых нюансов инфраструктуры безопасности. Вот корпоративный HR-портал, через который сотрудники получают доступ к своим расчётным листкам и другой личной информации. Портал работает как служба Windows под сервисной учётной записью svc_hrportal. Это не обычный пользователь: учётная запись создана исключительно для работы службы и не используется интерактивно.

Специалист отдела кадров с учётной записью в Active Directory, входящий в группу HR_Managers, через браузер заходит на портал и запрашивает свой расчётный листок.

Файлы хранятся локально на сервере HR-портала, в папке D:payroll с доступом, ограниченным группой HR_Managers. Структура управления доступом прозрачна: только сотрудники отдела кадров получают разрешение работать с чувствительными данными.

DACL (Discretionary Access Control List) — это набор записей, определяющих, кому и какие действия разрешены с объектом (файлом, папкой, сервисом и т.д.).

  • Записи типа allow разрешают операции определённым SID (Security Identifier).
  • Записи типа deny явно запрещают операции.
  • Всем, кто не упомянут, действует неявный отказ.

Философия DACL — владелец объекта или администратор сами определяют правила, что отличается от Mandatory Access Control, где правила навязывает система.

И тут возникает противоречие: служба Windows работает под учётной записью svc_hrportal, не входящей в HR_Managers. Если она попытается «своими» правами открыть файл — получит отказ. Хотя запрос поступает от человека, имеющего права, система проверяет полномочия не его, а технического аккаунта. Как разрешить этой службе действовать от имени реального пользователя легально?

Ответ лежит в механизме принятия решений об авторизации на самом нижнем уровне Windows.

Access token: удостоверение личности на уровне ядра

Каждый процесс и поток в Windows несёт системный объект — access token (маркер доступа). Токен — не просто имя, а полный профиль: SID пользователя, SID его групп, набор привилегий, информация о сессии входа и дополнительные атрибуты. Если представить корпоративный пропуск, где значится и имя, и должность, и права доступа — всё это «зашито» в access token.

Токен создаётся в момент успешного входа: LSA (Local Security Authority) собирает сведения из Active Directory и формирует токен. Все процессы сессии наследуют этот маркер, поэтому, открывая командную строку или браузер, Windows «знает», кто пользователь — каждый процесс унаследовал токен от своего родителя аж до winlogon.exe.

С другой стороны, каждый защищённый объект — файл, служба, канал — наделён security descriptor с собственным DACL. DACL — это список записей (ACE, Access Control Entry), по которым SRM (Security Reference Monitor) сверяет SID из токена и права доступа из DACL. Если запись разрешает доступ — он предоставляется, иначе — нет.

Получается, что даже если запрос поступает от пользователя с необходимыми правами, служба, выполнившая запрос, несёт access token сервисного аккаунта. DACL не знает о правах этого аккаунта, поэтому SRM отказывает в доступе. На этом этапе принадлежность исходного пользователя к нужной группе никак не учитывается.

[ИЗОБРАЖЕНИЕ: схема процедуры проверки доступа через сопоставление access token и DACL]

Impersonation: как служба временно «становится» другим пользователем

Для таких ситуаций предусмотрен механизм Impersonation (олицетворение). Он позволяет потоку приложения временно «надеть маску» пользователя: вернуть в обращение access token, выстроенный на основании его удостоверений. Пока поток выполняется через impersonation token, все обращения к защищённым объектам осуществляются от лица пользователя, а не службы.

Impersonation не означает, что приложение само строит токен из переданных пользователем сведений. Работу полностью выполняет LSA и связанное с ней API, включая SSPI (Security Support Provider Interface). После успешной аутентификации (например, по Kerberos или NTLM) серверный поток получает удостоверение клиента, LSA создает impersonation token. Приложение вызывает AcceptSecurityContext, затем ImpersonateSecurityContext. Для возврата к сервисному токену используется RevertToSelf.

Impersonation token имеет уровень доверия (SecurityImpersonationLevel):

  • SecurityIdentification: только узнаёт, кто пользователь, неприменим для обращения к ресурсам.
  • SecurityImpersonation: позволяет обращаться к локальным ресурсам от имени пользователя. Используется для «чтения файлов» и требуется в нашем сценарии.
  • SecurityDelegation: даёт право осуществлять сетевые запросы от лица пользователя, даже к другим сервисам. Должно быть особенно разрешено.
  • SecurityAnonymous: никакой информации, практически не встречается.

В нашем случае достаточно уровня SecurityImpersonation. После получения токена с SID пользователя (члена HR_Managers) DACL пускает поток к файлу. По окончании запроса вызывается RevertToSelf — и поток возвратился к аккаунту svc_hrportal.

Delegation: когда сервис должен говорить с другим сервисом от вашего имени

Архитектура не ограничится одним сервисом — HR-портал часто обращается к другим компонентам, например, к сервису analytics-engine на сервере analytics-srv. Проблема: аналитический сервис должен понимать, от чьего имени пришёл запрос. Если HR-портал работает только со своим токеном, analytics-engine не сможет отделить простого сотрудника от финансового директора. Выходит, доступ к аналитике должен идти с удостоверениями реального пользователя пользователя, а не от имени портала.

Здесь нужен уровень SecurityDelegation. Требуется возможность предъявить удостоверения пользователя на другом сервере в сети, что предполагает новую полноценную logon-сессию и подтверждение личности. Данные, передаваемые по impersonation token, не подходят — только Kerberos решает эту задачу на системном уровне.

[ИЗОБРАЖЕНИЕ: схема обращения HR-портала к аналитическому сервису с delegation]

Kerberos: три понятия, которые постоянно путают

Распространённая путаница — смешивание понятий идентификации, аутентификации и авторизации:

  • Идентификация: пользователь заявляет имя, не предоставляя доказательств.
  • Аутентификация: получение подтверждения личности через надёжный источник (например, проверка пароля или тикета).
  • Авторизация: определение полномочий (например, список разрешённых действий).

Kerberos — строго про аутентификацию. Авторизационные решения далее принимает служба и операционная система.

Как Kerberos подтверждает личность: shared secret и тикеты

Ключевая идея Kerberos — обмен защищёнными тикетами, секрет которых известен только участнику и контроллеру домена (KDC). Ключи производятся из паролей; передача по сети не требуется.

Весь обмен делится на две основные фазы.

Фаза первая: AS-обмен и получение TGT

Пользователь входит в Windows и вводит пароль. Его Kerberos-клиент через LSA отправляет AS-REQ KDC и запрашивает тикет. KDC проверяет учётную запись и выдаёт TGT (Ticket-Granting Ticket), который клиент не может расшифровать, но может предъявить для последующего получения тикетов сервисов. Срок жизни обычно 10 часов.

Фаза вторая: TGS-обмен и получение service ticket

При обращении к сервису (например, HTTP/hr-portal.corp.local), клиент отправляет запрос на выдачу сервисного тикета, подтверждая свою личность TGT. KDC выдает service ticket, зашифрованный на ключе сервиса (svc_hrportal). Клиент не может читать его содержимое — только переслать целевому сервису. По получении тикета портал проверяет его и строит impersonation token через LSA.

Весь процесс невидим для конечного пользователя.

PAC: почему в тикете хранится полный профиль пользователя

Обычный Kerberos-токен (по RFC 4120) содержит только имя принципала. Для Windows этого недостаточно — требуется полный набор SID и информации о доменных группах. Поэтому Microsoft реализовал PAC (Privilege Attribute Certificate) — вложение в тикет, содержащее идентификаторы пользователя и групп, а также флаги учётной записи. Благодаря PAC, LSA строит access token, пригодный для DACL Windows-объектов.

PAC не включает набор привилегий (SeBackupPrivilege и прочие) — их LSA определяет на месте, исходя из локальных политик. Это важно для разделения полномочий между доменом и сервером.

В роли принципалов Kerberos могут выступать не только пользователи, но и объекты компьютеров, а также сервисные gMSA-аккаунты. Благодаря этому службы могут аутентифицировать себя и получать тикеты без участия человека.

Delegation в Kerberos: unconstrained и constrained

Чтобы HR-портал мог получать тикеты к аналитическому сервису от имени сотрудников, Kerberos поддерживает два режима delegation.

Unconstrained delegation: мощно, но опасно

В этом режиме сервису выдают forwardable TGT пользователя, с помощью которого можно запросить тикеты к любым сервисам. Если сервер будет скомпрометирован, злоумышленник получит полный доступ к инфраструктуре от лиц всех обращавшихся пользователей. Такой режим считается опасным и не рекомендуется.

Constrained delegation: контролируемый список назначений

Безопасный способ — constrained delegation. В Active Directory на сервисном аккаунте прописывается список целевых SPN, к которым разрешено делегирование. С помощью расширения протокола S4U2Proxy портал может получать тикеты только к заранее определённым сервисам. У компрометированного сервера вредонос получит ограниченный доступ.

Современный подход — Resource-Based Constrained Delegation (RBCD), где список разрешённых делегирующих сервисов хранится на целевом ресурсе — контроль принадлежит владельцу ресурса.

Кросс-доменная аутентификация: когда структура разрастается

В крупных компаниях с дочерними структурами пользователи часто работают через доверительные отношения между доменами. Например, специалисты из subsidiary.local должны обращаться к HR-порталу домена corp.local.

Как работает trust account

При создании trust-отношений между доменами в доверяющем домене (corp.local) автоматически формируется специальный INTERDOMAIN_TRUST_ACCOUNT (например, SUBSIDIARY$). Его цель — обладать общим секретом между KDC обоих доменов, ключ синхронизируется автоматически и не используется для обычной работы.

Поток кросс-доменной аутентификации

Пользователь из дочернего домена получает у себя TGT, потом запрашивает сервисный тикет для внешнего сервиса. KDC выдаёт referral ticket, зашифрованный общим секретом. Второй KDC расшифровывает тикет и выдаёт локальный сервисный тикет — всё прозрачно для приложений.

PAC через границу домена

PAC тикета внешнего пользователя содержит SID домена-источника. Чтобы с ними работали DACL-ы corp.local, при первом обращении создаются специальная сущность — Foreign Security Principals. Они используются для включения пользователей другого домена, например, в локальные группы и авторизационные списки.

Итоговая цепочка: от нажатия Enter до разрешения на файл

Алгоритм полного пути доступа таков:

  1. При входе в Windows LSA получает TGT от KDC.
  2. При обращении к HR-порталу Kerberos-клиент запрашивает сервисный тикет.
  3. Браузер пересылает тикет сервису через Negotiate.
  4. LSA на сервере расшифровывает тикет, извлекает PAC, строит impersonation token.
  5. Поток переключается на impersonation token пользователя.
  6. Поток пытается открыть нужный файл.
  7. SRM сравнивает SID из токена с DACL — если права есть, доступ разрешён.
  8. По завершении работы вызывается RevertToSelf, поток возвращается к токену сервисного аккаунта.

Kerberos не решает вопрос «к чему можно дать доступ», он подтверждает личность, чьи SID будут участвовать в сопоставлении с DACL. Логика «можно — нельзя» заложена в SRM и проектах файловых разрешений. Понимание этой архитектуры критично: почти все атаки на инфраструктуру строятся на компрометации звеньев цепочки — Pass-the-Ticket, Golden Ticket, Kerberoasting, злоупотребление delegation. Без точного понимания штатной работы невозможно ни выявление, ни предотвращение атак.

[ИЗОБРАЖЕНИЕ: диаграмма полного процесса от входа пользователя до проверки DACL SRM-ом]

Оставьте комментарий