Microsoft windows kerberos key distribution center

В прошлой части нашего цикла мы рассмотрели работу протоколов семейства NTLM, отметив ряд их существенных недостатков, которые невозможно решить в рамках протокола. Поэтому вместе с Active Directory на смену им пришел более совершенный протокол Kerberos, который продолжает успешно применяться до сих пор. В данном материале мы рассмотрим общие принципы функционирования данного протокола, что позволит получить начальные знания в этой области самым широким массам читателей.

Онлайн-курс по устройству компьютерных сетей
На углубленном курсе «Архитектура современных компьютерных сетей» вы с нуля научитесь работать с Wireshark и «под микроскопом» изучите работу сетевых протоколов. На протяжении курса надо будет выполнить более пятидесяти лабораторных работ в Wireshark.

Протокол Kerberos был разработан в Массачусетском технологическом институте (MIT) в рамках проекта «Афина» в 1983 году и долгое время использовался в качестве образовательного, пока версия 4 не была сделана общедоступной. В настоящий момент принята в качестве стандарта и широко используется следующая версия протокола Kerberos 5.

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

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

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

Перед тем как продолжить, следует прийти к соглашению по поводу используемых в статье терминов. Так под термином клиент будет рассматриваться любой узел сети, обращающийся к любому иному узлу — серверу — с целью доступа к любому из его ресурсов.

Основой инфраструктуры Kerberos является Центр распространения ключей (Key Distribution Center, KDC), который является доверенным центром аутентификации для всех участников сети (принципалов). Область Kerberos (Realm) — пространство имен для которых данный KDC является доверенным, как правило это область ограниченная пространством имен домена DNS, в Active Directory область Kerberos совпадает с доменом AD. Область Kerberos записывается в виде соответствующего ему доменного имени DNS, но в верхнем регистре. Принципалом или учетной записью Kerberos является любой участник отношений безопасности: учетная запись пользователя, компьютер, сетевая служба и т.д.

Центр распространения ключей содержит долговременные ключи для всех принципалов, в большинстве практических реализаций Kerberos долговременные ключи формируются на основе пароля и являются так называемым «секретом для двоих». С помощью такого секрета каждый из его хранителей может легко удостовериться, что имеет дело со своим напарником. При этом долговременные ключи не при каких обстоятельствах не передаются по сети и располагаются в защищенных хранилищах (KDC), либо сохраняются только на время сеанса.

Для принципалов, которые не являются членами домена AD, могут использоваться специальные keytab-файлы, которые содержат сведения о клиенте, домене и его долговременный ключ. В целях безопасности keytab-файл нельзя передавать по незащищенным каналам, а также следует обеспечить его безопасное хранение у принципала.

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

Рассмотрим каким образом происходит аутентификация клиента по протоколу Kerberos.

windows-authentication-2-002.png

Желая пройти проверку подлинности в сети, клиент передает KDC открытым текстом свое имя, имя домена и метку времени (текущее время клиента), зашифрованное долговременным ключом клиента. Метка времени в данном случае выступает в роли аутентификатора — определенной последовательности данных, при помощи которой узлы могут подтвердить свою подлинность.

Получив эти данные KDC извлекает долговременный ключ данного пользователя и расшифровывает метку времени, которую сравнивает с собственным текущим временем, если оно отличается не более чем на 5 минут (значение по умолчанию), то метка считается действительной. Эта проверка является дополнительной защитой, так как не позволяет использовать для атаки перехваченные и сохраненные данные.

Убедившись, что метка времени действительна KDC выдает клиенту сеансовый ключ и билет (тикет) на получение билета (ticket granting ticket, TGT), который содержит копию сеансового ключа и сведения о клиенте, TGT шифруется с помощью долговременного ключа KDC и никто кроме него билет расшифровать не может. Сеансовый ключ шифруется с помощью долговременного ключа клиента, а полученная от клиента метка времени возвращается обратно, зашифрованная уже сеансовым ключом. Билет на получение билета является действительным в течении 8 часов или до завершения сеанса пользователя.

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

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

Успешно пройдя аутентификацию, клиент будет располагать сеансовым ключом, которым впоследствии он будет шифровать все сообщения для KDC и билетом на получение билета (TGT).

Теперь рассмотрим ситуацию, когда клиент хочет обратиться к серверу.

windows-authentication-2-003.png

Для этого он снова обращается к KDC и посылает ему билет на получение билета, зашифрованную сеансовым ключом метку времени и имя сервера. Прежде всего KDC расшифровывает предоставленный ему TGT и извлекает оттуда данные о клиенте и его сеансовый ключ, обратите внимание, что сам KDC сеансовые ключи не хранит. Затем сеансовым ключом он расшифровывает данные от клиента и сравнивает метку времени с текущим. Если расхождения нет, то KDC формирует общий сеансовый ключ для клиента и сервера.

Теоретически теперь данный ключ следует передать как клиенту, так и серверу. Но KDC имеет защищенный канал и установленные доверительные отношения только с клиентом, поэтому он поступает по-другому. Экземпляр сеансового ключа для клиента он шифрует сессионным ключом, а копию сеансового ключа для сервера он объединяет с информацией о клиенте в сеансовый билет (session ticket), который шифрует закрытым ключом сервера, после чего также отправляет клиенту, дополнительно зашифровав сессионным ключом.

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

Теперь, имея новый ключ и билет, клиент обращается непосредственно к серверу:

windows-authentication-2-004.png

Он предъявляет ему сеансовый билет и метку времени, зашифрованную сессионным ключом. Сервер расшифровывает билет, извлекает оттуда свой экземпляр ключа и сведения о клиенте, затем расшифровывает метку времени и сравнивает ее с текущим. Если все нормально, то он шифрует полученную метку своим экземпляром сессионного ключа и посылает назад клиенту. Клиент расшифровывает ее своим сеансовым ключом и сравнивает с тем, что было послано серверу. Совпадение данных свидетельствует о том, что сервер тот, за кого себя выдает.

Как можно заметить, сеансовые ключи никогда не передаются по незащищенным каналам и не передаются узлам, с которыми нет доверительных отношений. У KDC нет доверительных отношений с сервером, и он не может передать ему сессионный ключ, так как нет уверенности, что ключ будет передан кому надо. Но у него есть долговременный ключ этого сервера, которым он шифрует билет, это гарантирует, что никто иной не прочитает его содержимое и не получит сессионный ключ.

Клиент имеет билет и свой экземпляр ключа, доступа к содержимому билета у него нет. Он передает билет серверу и ждет ответ в виде посланной метки времени. Сервера, как и KDC, не хранят сеансовые ключи, а, следовательно, расшифровать метку времени сервер может только в том случае, если сможет расшифровать билет и получить оттуда сеансовый ключ, для чего нужно обладать долговременным ключом. Получив ответ и расшифровав его, клиент может удостоверить подлинность сервера, так как прочитать аутентификатор и извлечь из него метку времени сервер сможет только при условии расшифровки билета и получения оттуда сеансового ключа.

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

Онлайн-курс по устройству компьютерных сетей
На углубленном курсе «Архитектура современных компьютерных сетей» вы с нуля научитесь работать с Wireshark и «под микроскопом» изучите работу сетевых протоколов. На протяжении курса надо будет выполнить более пятидесяти лабораторных работ в Wireshark.

Уровень сложностиСредний

Время на прочтение3 мин

Количество просмотров12K

Всем привет!

Вот такой вопрос прозвучал в комментариях к этой статье, спасибо автору, а еще, нам на предприятие пришло вот такое распоряжение:

Если бы мы уже использовали инфраструктуру Microsoft AD, то выбрали бы миграцию на Samba 4, но задача касалась только вводимых в эксплуатацию рабочих станций Linux и мы выбрали “ванильный” MIT Kerberos.

В двух словах про Kerberos, это протокол аутентификации, позволяющий использовать свой логин и пароль на любом компьютере, подключенном к kerberos сфере (входящем в домен, в терминах Microsoft). Кроме того, он реализует технологию единого входа (Single Sign-On) что позволяет, например, предоставить “прозрачный” доступ в Интернет через прокси сервер с аутентификацией пользователей.

Итак, реализация:

Разворачиваем в сети kerberos сервер (Центр распределения ключей — Key distribution center — KDC). Очень важно правильно указать hostname системы и сделать соответствующие A и SRV записи в DNS:

# hostnamectl set-hostname kdc.corp.ru

$ nslookup -q=SRV _kerberos._udp.corp.ru
...
_kerberos._udp.corp.ru service = 1 0 88 kdc.corp.ru.
...
kdc.corp.ru    internet address = A.B.C.D

Устанавливаем программное обеспечение и инициализируем kerberos сферу — realm или домен, в терминах Microsoft (далее все инструкции приведены для Debian/Ubuntu)

kdc# apt install krb5-kdc krb5-admin-server

kdc# krb5_newrealm
...

kdc# service krb5-kdc restart

Добавляем учетные записи пользователей (в kerberos называются principal)

kdc# kadmin.local -q 'addprinc -pw somepassword1 ivanovii'

kdc# kadmin.local -q 'addprinc -pw somepassword2 petrovpp'

...

Теперь можно подключать к kerberos сфере (вводить в домен) рабочие станции, например, таким способом, и пользователи смогут работать на них, используя свои логины и пароли.

Далее, разворачиваем прокси сервер для аутентификации и учета доступа пользователей в Интернет (тоже, очень важно, указать корректный hostname и соответствующую A запись в DNS)

# hostnamectl set-hostname authproxy.corp.ru

authproxy# apt install squid

Добавляем в kdc principal сервиса HTTP, работающего на authproxy (у нас он будет использоваться браузером для SSO аутентификации в squid, но так же, может быть использован и c web сервером, например — apache) выгружаем ключи и копируем их на authproxy:

kdc# kadmin.local -q 'addprinc -randkey HTTP/authproxy.corp.ru'

kdc# kadmin.local -q 'ktadd -k authproxyhttp.keytab HTTP/authproxy.corp.ru'

kdc# scp authproxyhttp.keytab admin@authproxy:

Подключаем прокси сервер к kerberos сфере, копируем ключи в системный файл и предоставляем доступ к нему для сервиса squid:

authproxy# apt install krb5-user

authproxy# nano /etc/krb5.conf
[libdefaults]
default_realm = CORP.RU
authproxy# ktutil
ktutil:  rkt /home/admin/authproxyhttp.keytab
ktutil:  wkt /etc/krb5.keytab
ktutil:  exit
authproxy# chgrp proxy /etc/krb5.keytab

authproxy# chmod 640 /etc/krb5.keytab

Настраиваем прокси сервис на использование kerberos аутентификации:

authproxy# nano /etc/squid/conf.d/corp.conf
auth_param negotiate program /usr/lib/squid/negotiate_kerberos_auth -d
acl authuser proxy_auth REQUIRED
http_access allow authuser
authproxy# service squid restart

Для работы через proxy на рабочих станциях Linux достаточно установить переменные окружения:

linuxclientN# nano /etc/environment
export http_proxy=http://authproxy.corp.ru:3128/
export https_proxy=http://authproxy.corp.ru:3128/
export no_proxy=localhost,127.0.0.1,corp.ru

Происходящие процессы аутентификации можно наблюдать в этих журнальных файлах (частой причиной проблем в работе протокола kerberos, кроме DNS, может быть расхождение времени в системах более чем на 5 минут).

kdc# tail -f /var/log/auth.log

authproxy# tail -f /var/log/squid/access.log

Аналогично можно настроить “прозрачный” доступ соответствующих программ к сервисам SMTP, IMAP, LDAP, XMPP, CIFS и, даже, SSH:)

В следующей статье планирую рассказать как мы дополнили “Cамое простое решение для Kerberos” реализацией GPO на основе ansible-pull и GitLab.

На этом все, спасибо, буду рад ответить на вопросы в комментариях!

So, you’ve decided to embark on a quest to reliably select a specific KDC certificate in Active Directory, because randomly-selected certificates that you think you have control over are not a desirable thing? Here’s what happened to the last person that went down this path:

Kerberos KDC he tried selecting a kdc certificate

The Kerberos KDC certificate is used in PKINIT, a Kerberos extension used in Windows smartcard authentication, among other things. Contrary to popular belief, it is possible to select a different certificate for PKINIT and LDAPS, but the magical recipe had long been lost to time.

Buckle up, because if you thought selecting a specific LDAPS server certificate in Active Directory was painful, this is nothing in comparison.

Analysis Technique

I have used IDA Pro to look at the specific private functions located in kdcsvc.dll:

  • KdcInitializeCerts
  • KdcMyStoreWaitHandler
  • KdcEventWriteKdcCertLog
  • KdcCheckKdcCertificate
  • KdcCheckLegacyKdcCertificate
  • KdcGetKdcCertificate
  • KdcCheckPkinitPreAuthData

Please note that the KDC service is hosted inside lsass.exe despite being primarily handled by the code from kdcsvc.dll. I have mostly done static analysis combined with a lot of PowerShell code to try and confirm the actual application behavior.

Preparing Test Certificates

To properly test the KDC service selects its certificate from multiple valid candidates, I have duplicated the built-in «Kerberos Authentication» certificate template with the following modifications:

  • On the Request Handling tab, check Allow private key to exported
  • On the Subject Name tab, select Supply in the request

Kerberos Certificate Template - Allow Private Key Export

I have then manually generated 5 certificates with numbers from to 1 to 5 to make them easier to distinguish. The certificate subject name and subject alternative names (SANs) are not relevant to the selection process itself, even if invalid names can cause trouble down the road. To manually specify valid subject name information, generate a certificate using the original «Kerberos Authentication» built-in template and then use the same values. When Subject Name is set to Build from Active Directory information in the template, only SANs are used, with no subject name:

Kerberos Certificate Template - Subject Name Information

Last but not least, to test certificate selection behavior with the same certificates, I have exported the test certificates to .pfx files with their private keys:

Kerberos Test Certificates

Now that the certificates are prepared, I am free to delete them from the Windows certificate store and re-import them as desired to see what happens.

KDC Certificate Event Logs

The KDC service only looks in the local machine personal certificate store (cert:\LocalMachine\My) for its KDC certificate, which is different from the LDAPS certificate selection process that looks in both the NTDS service certificate store and only then the local machine personal certificate store.

So, how does one tell which KDC certificate was selected? Believe it or not, this time, there are logs you can enable! In the Windows Event Viewer (eventvwr.msc), go to Applications and Services Logs / Microsoft / Windows / Kerberos-Key-Distribution-Center, right-click Operational, then select Enable Log:

The Key Distribution Center (KDC) uses the below KDC certificate for smart card or certificate authentication.

Windows Event Viewer - KDC selected certificate

Once the logs are enabled, you can reboot the domain controller, or force a KDC certificate reload by «touching» the certificate store, causing new events to appear in the Event Viewer (don’t forget to refresh!):

$dummyCert = New-SelfSignedCertificate -DnsName "dummy.local" -CertStoreLocation "cert:\LocalMachine\My"
Get-ChildItem -Path "cert:\LocalMachine\My" | Where-Object { $_.Thumbprint -eq $dummyCert.Thumbprint } | Remove-Item

You can also get the thumbprint of the currently selected KDC certificate in PowerShell by extracting it from the last Windows event:

$KdcLogName = 'Microsoft-Windows-Kerberos-Key-Distribution-Center/Operational'
Get-WinEvent -FilterHashtable @{LogName=$KdcLogName; ID=302} -MaxEvents 1 | ForEach-Object {
    $_.Properties[2].Value
}

The KDC service watches the local machine personal certificate store (cert:\LocalMachine\My) for changes using the CertControlStore function with the CERT_STORE_CTRL_NOTIFY_CHANGE type and calls the internal KdcMyStoreWaitHandler function when triggered.

The Key Distribution Center (KDC) cannot find a suitable certificate to use. This KDC is not enabled for smart card or certificate authentication.

KDC no suitable certificate found warning event

The Key Distribution Center (KDC) failed to validate its current KDC certificate. This KDC might not be enabled for smart card or certificate authentication.

KDC certificate revocation check failure event

Enumerating KDC Certificates

The KDC service calls CertEnumCertificatesInStore to enumerate certificates from the local machine personal store, and picks the first valid KDC server certificate. Easy enough, right? Let’s call the same Windows API from PowerShell to enumerate the certificates and filter them in the same way KdcMyStoreWaitHandler does it:

Import-Module -Name Microsoft.PowerShell.Security

Add-Type -TypeDefinition @"
    using System;
    using System.Runtime.InteropServices;
    
    public class Crypt32 {
        [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr CertOpenStore(
            int storeProvider,
            int messageAndCertEncodingType,
            IntPtr cryptProvHandle,
            int certStoreFlags,
            string storeName);
            
        [DllImport("crypt32.dll", SetLastError = true)]
        public static extern IntPtr CertEnumCertificatesInStore(
            IntPtr storeProvider,
            IntPtr prevCertContext);
            
        [DllImport("crypt32.dll", SetLastError = true)]
        public static extern bool CertCloseStore(
            IntPtr certStoreHandle,
            int flags);
    }
"@

function Get-KdcCertStoreEnumeratedCerts {
    [CmdletBinding()]
    Param(
        [switch] $SkipFilter
    )

    $storeProvider = 0xA # CERT_STORE_PROV_SYSTEM
    $storeFlag = 0x20000 -bor 1 # CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG
    $storeHandle = [Crypt32]::CertOpenStore($storeProvider, 0, [IntPtr]::Zero, $storeFlag, "MY")

    if ($storeHandle -eq [IntPtr]::Zero) {
        throw "Failed to open certificate store"
    }

    try {
        $certContext = [Crypt32]::CertEnumCertificatesInStore($storeHandle, [IntPtr]::Zero)
        while ($certContext -ne [IntPtr]::Zero) {
            $cert = (New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $certContext)
            if ($SkipFilter -or ($cert.HasPrivateKey -and
                ($cert.EnhancedKeyUsageList.ObjectId -contains "1.3.6.1.5.2.3.5"))) { # KDC Authentication
                Write-Output $cert
            }
            $certContext = [Crypt32]::CertEnumCertificatesInStore($storeHandle, $certContext)
        }
    }
    finally {
        [void][Crypt32]::CertCloseStore($storeHandle, 0)
    }
}

Let’s give our new Get-KdcCertStoreEnumeratedCerts PowerShell cmdlet a try, and list candidate KDC certificates:

Get-KdcCertStoreEnumeratedCerts | Select-Object -Property Thumbprint,Subject,SerialNumber

Thumbprint                               Subject          SerialNumber
----------                               -------          ------------
E7BD43BC57EC891EDD630CD8A58F264550A9214B CN=IT-HELP-TEST1 2B0000002FEB4AA6D7E7A1177400000000002F
9FDEBF3E1FF9C1124E582D1E725D00A1601192CB CN=IT-HELP-TEST3 2B00000031C26575890844C2E5000000000031
9CEAA4D79905047605671A3FC8AFCB1D39FAF4A8 CN=IT-HELP-TEST5 2B0000003356E7262CEB5B1EE1000000000033
78690FD0A7CE804D02511E03662801162D6A25D6 CN=IT-HELP-TEST4 2B000000328F9E1508D59AACEC000000000032
4020607270DCCDB7EF0B383EAB3AF88F62BF52E4 CN=IT-HELP-TEST2 2B00000030B74823097E00754F000000000030

Notice how the ordering doesn’t seem to follow a specific pattern. If you look at the certificate store registry keys, we can see they are in the reverse order than what CertEnumCertificatesInStore returns:

Kerberos certificate store ordering registry keys

So, which order is the correct one to predict KDC server certificate selection? Neither, because experimentally, the order doesn’t match the KDC service certificate selection ordering! We’ll come back to this later, since we still need to cover certificate validation rules.

KDC Certificate Validation

Our previous Get-KdcCertStoreEnumeratedCerts PowerShell cmdlet enumerates candidate KDC certificates with some filtering, but it does not validate them. The subject name and subject alternative names on the certificate are not checked, so dummy certificates with incorrect subject names could accidentally be selected if you’re not careful.

CA Chain

The root CA needs to be in the machine Trusted Root Certification Authorities store, and the issuer CA needs to be in the machine Intermediate Certification Authorities store. The CA chain also needs to suitable for Kerberos authentication with the right EKU (1.3.6.1.5.2.3.5).

NTAuth Store

The issuer CA certificate needs to be in the NTAuth store of the domain controller, otherwise CertVerifyCertificateChainPolicy with CERT_CHAIN_POLICY_NT_AUTH will fail. This is the exact same requirement for strict KDC validation on the client that can result in «the specified user name does not exist» errors in mstsc.

You can view the list of certificates in the machine NTAuth store using certutil.exe -viewstore -enterprise ntauth.

If your issuer CA certificate is missing from the NTAuth store, you can add it from an elevated shell with the

certutil.exe -enterprise -addstore NTAuth .\ISSUER-CA.cer

Revocation Checks

Certificate revocation checks need to work during the certificate selection process. This can be a problem during boot time, if the check happens before the network is fully available. For CRL-based checks, the CRLTimeoutPeriod registry key can be used to set a timeout:

$KdcRegPath = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System\Kdc\Parameters'
Set-ItemProperty -Path $KdcRegPath -Name 'CRLTimeoutPeriod' -Value '15' -Type DWORD

You can also disable revocation checking by the KDC service when it selects its KDC certificate:

$KdcRegPath = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System\Kdc\Parameters'
Set-ItemProperty -Path $KdcRegPath -Name 'UseCachedCRLOnlyAndIgnoreRevocationUnknownErrors' -Value '1' -Type DWORD

However, you should not leave revocation checking issues unresolved, as they will likely cause problems with the Kerberos clients down the road.

Legacy KDC Certificates

Domain controllers with AD CS enabled usually have a certificate generated using the Domain Controller built-in template. This is a legacy certificate, identified as such using the certificate template name extension (1.3.6.1.4.1.311.20.2) with the string value DomainController:

Kerberos Legacy KDC certificate

Unlike «modern» KDC certificates, legacy KDC certificates do not have the Kerberos authentication EKU (1.3.6.1.5.2.3.5). The KDC service selects the first legacy KDC certificate only if no suitable modern KDC certificate can be found in the certificate store. Since legacy certificates require DomainController as the template name encoded inside the X.509 certificate, it is not possible to use a custom template, as it would result in a different name. For all of these reasons, it is recommended to use modern KDC certificates generated using the Kerberos Authentication built-in template (or equivalent).

KDC Certificate Selection

Through a lot of trial and error, and I have devised a method to select a specific KDC certificate. I can’t explain why, but experimentally, the certificate ordering as seen by the KDC service matches the certificate import order. In other words, the first suitable certificate imported in the certificate store will be picked. This means that if we export, delete and re-import all the other certificates, we should have a working Select-KdcCertificate cmdlet! Here’s the additional PowerShell code for KDC certificate selection:

function Reset-KdcCertificate {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=0)]
        [string] $Thumbprint
    )

    $Certificate = Get-Item "cert:\LocalMachine\My\$Thumbprint"

    if ($Certificate -eq $null) {
        throw "Certificate $Thumbprint count not be found!"
    }

    $SerialNumber = $Certificate.SerialNumber
    $ExportPath = Join-Path $Env:TEMP $Thumbprint
    Export-Certificate -Cert $Certificate -FilePath $ExportPath | Out-Null
    Remove-Item -Path $Certificate.PSPath # delete cert, but leave private key intact
    Import-Certificate -FilePath $ExportPath -CertStoreLocation "cert:\LocalMachine\My" | Out-Null
    & certutil.exe -repairstore My $SerialNumber | Out-Null # relink cert with private key
    Remove-Item $ExportPath -ErrorAction SilentlyContinue
}

function Select-KdcCertificate {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=0)]
        [string] $Thumbprint
    )

    $Certificate = Get-Item "cert:\LocalMachine\My\$Thumbprint"

    if ($Certificate -eq $null) {
        throw "Certificate $Thumbprint count not be found!"
    }

    $CandidateThumbprints = Get-KdcCertStoreEnumeratedCerts | Select-Object -ExpandProperty Thumbprint
    $CandidateThumbprints | Where-Object { $_ -ne $Thumbprint } | ForEach-Object { Reset-KdcCertificate $_ }
}

function Get-SelectedKdcCertificate {
    [CmdletBinding()]
    Param()

    $KdcLogName = 'Microsoft-Windows-Kerberos-Key-Distribution-Center/Operational'
    Get-WinEvent -FilterHashtable @{LogName=$KdcLogName; ID=302} -MaxEvents 1 | ForEach-Object {
        $Thumbprint = $_.Properties[2].Value
        Get-Item "cert:\LocalMachine\My\$Thumbprint"
    }
}

The tricky part is to remove certificates from the store without touching the private key, and to re-import the certificate with a proper link to the same private key. Some certificates also don’t have exportable private keys, so even if wanted to make a temporary copy of the keys, it would not be possible. Let’s give those new PowerShell cmdlets a try!

PS > Get-KdcCertStoreEnumeratedCerts | Select-Object -Property Thumbprint,Subject

Thumbprint                               Subject
----------                               -------
E7BD43BC57EC891EDD630CD8A58F264550A9214B CN=IT-HELP-TEST1
9FDEBF3E1FF9C1124E582D1E725D00A1601192CB CN=IT-HELP-TEST3
9CEAA4D79905047605671A3FC8AFCB1D39FAF4A8 CN=IT-HELP-TEST5
78690FD0A7CE804D02511E03662801162D6A25D6 CN=IT-HELP-TEST4
4020607270DCCDB7EF0B383EAB3AF88F62BF52E4 CN=IT-HELP-TEST2

PS > Get-SelectedKdcCertificate | Select-Object -Property Thumbprint,Subject

Thumbprint                               Subject
----------                               -------
E7BD43BC57EC891EDD630CD8A58F264550A9214B CN=IT-HELP-TEST1

The currently selected certificate is IT-HELP-TEST1 (E7BD43BC57EC891EDD630CD8A58F264550A9214B). Let’s select IT-HELP-TEST5 instead (9CEAA4D79905047605671A3FC8AFCB1D39FAF4A8) using Select-KdcCertificate:

PS > Select-KdcCertificate -Thumbprint 9CEAA4D79905047605671A3FC8AFCB1D39FAF4A8
PS > Get-SelectedKdcCertificate | Select-Object -Property Thumbprint,Subject

Thumbprint                               Subject
----------                               -------
9CEAA4D79905047605671A3FC8AFCB1D39FAF4A8 CN=IT-HELP-TEST5

It worked! Now let’s try it with IT-HELP-TEST3 (9FDEBF3E1FF9C1124E582D1E725D00A1601192CB), just to be sure it’s not a fluke:

PS > Select-KdcCertificate -Thumbprint 9FDEBF3E1FF9C1124E582D1E725D00A1601192CB
PS > Get-SelectedKdcCertificate | Select-Object -Property Thumbprint,Subject

Thumbprint                               Subject
----------                               -------
9FDEBF3E1FF9C1124E582D1E725D00A1601192CB CN=IT-HELP-TEST3

It worked again! We’ve finally cracked it!

Closing Thoughts

This blog has been way harder to write than I originally expected, mostly because I couldn’t figure out the certificate ordering. Active Directory is arguably one of the most important Microsoft products in existence alongside Windows, but even then, things as simple as selecting a certificate in a predictable and reliable manner have been overlooked. It’s not rocket science, a simple registry key with a certificate thumbprint like what the RDP server uses would have been enough. Instead, we have this semi-random, opaque, undocumented just-pick-any-cert-that-might-work selection process.

Хотя использование Kerberos порой напоминает черную магию, это одна из ключевых технологий Active Directory (AD). Большинство настроек Kerberos абстрагировано, и взаимодействовать с протоколом приходится нечасто. Тем не менее Kerberos применяется всякий раз, когда пользователь регистрируется на компьютере, присоединенном к AD, а также при доступе к сетевым ресурсам, таким как общие папки и приложения.

Вместо того чтобы передавать через сеть собственно пароль, Kerberos работает с последовательностью билетов. На высоком уровне это выглядит так: при регистрации пользователя на компьютере формируется серия обменов данными с контроллером домена (DC), и в случае успеха пользователю назначается билет на право получения билетов (TGT). Впоследствии при каждом обращении к службе, такой как общая папка или приложение, TGT используется, чтобы получить билет для доступа к службе или приложению.

Проверка подлинности

Рисунок 1. Сообщение AS_REQ Authentication Service Request

Когда компьютер выполняет проверку подлинности при регистрации, в контроллер домена отправляется сообщение AS_REQ или Authentication Service Request. В Kerberos контроллер домена именуется центром распространения ключей Key Distribution Center (KDC). На рисунке 1 показаны важнейшие элементы запроса AS_REQ. Имя клиента представляет собой основное имя пользователя (UPN) или унаследованное имя пользователя (sAMAccountName). Имя службы в этом случае всегда одно и то же, запрос к службе krbtgt в контексте домена или пользователя. Чтобы предотвратить атаки с повторной передачей пакетов, в ходе которой злоумышленник повторно использует сообщение AS_REQ, текущее время шифруется с использованием хеша пароля пользователя. Допустимое расхождение при этом — пять минут. Если зашифрованная отметка времени отличается от текущего времени более чем на пять минут, то запрос отвергается.

Рисунок 2. Сообщение AS_REP Authentication Service Reply

Когда KDC получает сообщение AS_REQ, в первую очередь предпринимается попытка расшифровать отметку времени с использованием локальной копии хеша пароля пользователя. Если попытка заканчивается неудачей, клиент получает сообщение об ошибке, и обработка запроса прекращается. Если дешифрация проходит удачно, а значение отметки времени находится в приемлемых пределах, KDC выдает пользователю сообщение AS_REP (Authentication Service Reply) от службы проверки подлинности со встроенным билетом TGT. На рисунке 2 показано содержимое сообщения AS_REP. На данном этапе компьютер пользователя сохраняет в кэше билет TGT и сеансовый ключ на время существования TGT и удаляет пароль пользователя. По умолчанию время существования билетов TGT, сформированных центрами KDC AD, истекает через десять часов.

В AD для Kerberos требуется зашифрованная отметка времени в сообщении AS_REQ. Первоначальный обмен известен как предварительная проверка подлинности. В Kerberos в стандартном виде не обязательно шифровать отметки времени; вполне достаточно сообщения AS_REQ, содержащего имя клиента и имя службы. Недостаток такого подхода заключается в уязвимости для атаки методом перебора по словарю, так как каждый запрос, содержащий уникальное имя клиента, будет возвращать ошибку, указывающую, что клиент не обнаружен, или выдаст действительный TGT данному пользователю.

Как показано на рисунке 2, сообщение AS_REP содержит два блока зашифрованных данных. Первый шифруется с применением хеша пароля пользователя и содержит сеансовый ключ и отметку времени окончания существования билета. Сеансовый ключ используется для шифрования будущих соединений с центром KDC. Второй компонент, билет TGT, шифруется с помощью секрета KDC. Секрет KDC в реализации Kerberos в AD хранится как пароль учетной записи пользователя krbtgt, существующей в каждом домене AD. Учетная запись krbtgt создается, когда назначается первый DC в домене; этой учетной записи принадлежит решающая роль в функционировании домена.

Получение билета службы

Рисунок 3. Сообщение TGS_REQ Ticket Granting Service Request

В Kerberos любой объект, к которому требуется получить доступ, называется службой. К службам относятся серверы файлов и печати, серверы базы данных и внутренние веб-приложения. Для доступа к службе пользователь предоставляет билет службы. Первый шаг — определить имя участника службы service principal name (SPN), к которой нужно получить доступ. Задача формирования SPN возлагается на компьютер или приложение пользователя.

В случае с сервером файлов с именем srv01.contoso.com, SPN службы файлов будет cifs/srv01.contoso.com. Аналогично для веб-приложения на сайте web01.contoso.com имя SPN может быть http/web01.contoso.com. Типичная проблема, с которой сталкиваются администраторы AD, — дублирование имен SPN, при котором более одного пользователя или компьютера в каталоге имеют одно и то же имя SPN, зарегистрированное в атрибуте servicePrincipalName. В этом случае центру KDC неизвестно, как отвечать на запрос билета службы, так как существует несколько служб с одним именем.

Если взглянуть на атрибут servicePrincipalName в AD, можно заметить, что ни одно из двух упомянутых образцовых имен SPN не определено ни в одной учетной записи компьютера в AD. Чтобы уменьшить количество дублированных данных, сохраненных в каталоге, AD обеспечивает сопоставление на уровне леса стандартных имен SPN для каждой учетной записи компьютеров в каталоге. Буквально десятки встроенных имен SPN применяются к каждому компьютеру, определенному в атрибуте. Данные хранятся в атрибуте spnMappings объекта Directory Service в разделе Configuration (=Directory Service, CN=Windows NT, CN=Services, CN=Configuration); этот атрибут сопоставляет службу HOST объекта со множеством других служб, среди которых службы CIFS и HTTP. Если нужно определить конкретную службу для каждой системы в лесу, не составляет труда изменить этот атрибут, чтобы добавить службу к списку заранее определенных служб.

Рисунок 4. Сообщение TGS_REP Ticket Granting Service Reply

На рисунке 3 показано содержимое сообщения TGS_REQ (Ticket Granting Service Request), которое KDC получает от клиента, если тот пытается обратиться к службе. Первый фрагмент информации — имя SPN службы, для которой клиент запрашивает билет. Имя клиента и отметка времени зашифрованы с помощью сеансового ключа, полученного клиентом в переданном ранее сообщении AS_REP. Эта информация повторно используется для предотвращения атак, в ходе которых злоумышленник повторно задействует сообщение запроса. Также прилагается экземпляр билета TGT, ранее полученного клиентом.

Если KDC получает сообщение TGS_REQ и указан один элемент для SPN, отметка времени находится в допустимом диапазоне и билет TGT действителен (не просрочен), то клиенту предоставляется билет службы как часть сообщения TGS_REP (рисунок 4). Сообщение TGS_REP содержит все данные, необходимые клиенту для доступа к службе.

С помощью секрета службы (например, пароля учетной записи компьютера или учетной записи службы) шифруется билет службы, который клиент кэширует и использует всегда, когда необходим доступ к службе. Так же как у билетов TGT, время, в течение которого разрешено повторно использовать билеты службы, ограничено (десять часов по умолчанию в реализации Kerberos в AD). Имея билет службы, клиент может запросить доступ к ней.

Доступ к службам

Рисунок 5. Сообщение AP_REQ Application Request

После того как клиент получает билет службы, приложение, обращающееся к службе, может предъявить этот билет службе и запросить доступ. Механика предъявления билета службы не так стандартизована, как получение билета, из-за различий, свойственных приложениям. В случае со службой HTTP билет службы встраивается в заголовки запроса HTTP.

Билет службы предъявляется приложению в форме сообщения AP_REQ Kerberos, как показано на рисунке 5. Служба дешифрует билет службы и получает сеансовый ключ, который можно использовать для дешифрации полей отметки времени и имени клиента, которые в свою очередь используются для проверки подлинности билета службы. Даже если служба принимает билет службы, на данном этапе клиент просто прошел проверку в службе. Выполнить задачу авторизации службе предстоит на основе информации о клиенте.

В билет службы также обычно входят данные, известные как сертификат атрибута привилегий Privilege Attribute Certificate (PAC). На рисунке 5 сертификат PAC именуется информацией маркера Token Information. Это та же информация маркера, которую KDC включает в билет TGT пользователя (рисунок 2). Сертификат PAC составлен из такой информации, как идентификатор безопасности (SID) пользователя, сведения о членстве в группе и правах безопасности/привилегиях пользователя. Когда пользователь предъявляет билет TGT в центр KDC, чтобы запросить билет службы, KDC копирует информацию маркера из TGT и вставляет в поле PAC билета службы. Служба использует эту информацию, чтобы подготовить маркер доступа для пользователя и проверить авторизацию пользователя, обычно на основе членства в группе.

Допускается передача дополнительного сообщения Kerberos, известного как AP_REP или Application Reply, после того как пользователь предъявляет билет службы в сообщении AP_REQ, показанном на рисунке 5. Сообщение Application Reply — необязательное; как правило, приложение не отправляет такое сообщение, если не происходит ошибки. Пример ситуации, когда формируется сообщение AP_REP: клиент запрашивает (в сообщении AP_REQ) у службы подтверждение подлинности через процесс, известный как обоюдная проверка подлинности.

Обзор процесса

На рисунке 6 показана схема потока сообщений, когда пользователь решает обратиться к службе на сервере приложений. Пользователь регистрируется на своей рабочей станции, которая выдает последовательность сообщений AS_REQ и AS_REP в центр KDC, откуда пользователь получает билет TGT, если учетные данные верны. Затем TGT пользователя кэшируется в памяти, и каждый раз, когда пользователю нужно получить доступ к службе (например, к серверу файлов, серверу печати, веб-приложению), пользователь предъявляет TGT центру KDC и запрашивает билет службы для службы. Пользователь получает билет службы и предъявляет его приложению, чтобы запросить доступ.

Рисунок 6. Поток сообщений проверки подлинности и доступа к службам Kerberos

Если используются контроллеры домена только для чтения (RODC), поток сообщений немного отличается от показанного на рисунке 6, в зависимости от политик репликации паролей и места кэширования паролей. Следует иметь в виду, что центру KDC требуется доступ к секретам службы и пользователя или компьютера, чтобы издавать билеты службы или билеты TGT соответственно. По умолчанию RODC не кэширует пароли, поэтому у него нет доступа к необходимым секретам.

Если RODC получает запрос для TGT или билета службы, который контроллер не может выполнить (из-за некэшированного пароля), запрос передается доступному для записи контроллеру домена, обладающему необходимыми секретами для шифрования ответа. Доступный для записи DC отправляет ответ в RODC, который в свою очередь передает его клиенту. Если RODC располагает кэшированным паролем для пользователя или службы, к которой пользователь хочет получить доступ, то RODC просто выдает билет TGT и/или службы таким же способом, как показано на рисунке 6.

Если вернуться к рисунку 2, можно увидеть, что билет TGT пользователя зашифрован с помощью секрета KDC. Этот секрет — пароль для учетной записи krbtgt, которая имеется во всех доменах AD. Учитывая положения, заложенные в основу RODC (то есть его уязвимость по умолчанию), было бы потенциально опасно хранить в RODC пароль доменной учетной записи krbtgt. Если RODC будет скомпрометирован, взломщик сможет самостоятельно издавать билеты TGT. В целях снижения риска каждый RODC располагает собственной учетной записью krbtgt и никогда не осведомлен о паролях учетных записей домена или другого RODC. Доступные для записи контроллеры домена имеют доступ к паролям всех учетных записей krbtgt, поэтому они могут расшифровать билеты TGT, изданные любым RODC в домене.

Прозрачная проверка подлинности

Kerberos почти прозрачен для администраторов AD. В отличие от многих схем проверки подлинности, в Kerberos никогда не требуется передавать пароли через сеть, как и нет необходимости хранить пароль пользователя в памяти после начального процесса регистрации. Благодаря этим преимуществам существенно снижается уязвимость, свойственная другим протоколам проверки подлинности.

Брайан Десмонд (brian@briandesmond.com) — старший консультант компании Moran Technology Consulting (Чикаго). Имеет сертификат Directory Services MVP. Автор книги «Active Directory», ведет блог www.briandesmond.com

Сегодня мы с вами рассмотрим протокол аутентификации Kerberos. Пройдемся по самому протоколу и рассмотрим его работу в рамках Microsoft Active Directory.

Kerberos – протокол взаимной аутентификации сервера и клиента, основан на использовании симметричных ключей и может использоваться в незащищенной среде. По сути, протокол выполняет роль третьей стороны, благодаря которой клиент и сервер могут однозначно идентифицировать друг друга.

История

Самая первая версия протокола была разработана в далеком 1988 году в MIT для проекта «Афина». Версии с 1 по 3 использовались исключительно внутри MIT.

4 версия была разработана Стивеном Миллером и Клиффордом Нейманном, она хоть и была публичной, но для очень ограниченного количества компаний, включая проект «Афина». И только 5 версия протокола Kerberos, которая вышла в 1993 году уже стала по настоящему публичной и была описана в RFC 1510.  

Microsoft Windows Server и Active Directory используют расширенный протокол Kerberos 5 версии, описанный в RFC 4120.

Kerberos в Active Directory

Kerberos сейчас считается основным протоколом при работе в домене Microsoft Windows и состоит из набора компонентов:

Компонент

Описание

Область Kerberos

Сеть, в которой расположен наш KDC. Если мы говорим про Active Directory – то в качестве области может восприниматься домен.

KDC (Key Distribution Centre)

Центр выдачи ключей. Роль состоит из AS и TGS и занимается выдачей билетов. KDC располагается на контроллере домена.

AS (Authentication Server)

Выполняет авторизацию пользователя и затем передает данные в KDC для выдачи билета.

TGS (Ticket Granting Service)

Билет сервиса. Данный билет клиент предоставляет сервису для проверки. Он зашифрован сервисным ключом.

TGT (Ticket Granting Ticket)

Билет клиента, предоставленный KDC после успешной аутентификации.

Описание работы протокола Kerberos

 Для общего понимания для начала нарисуем схему и потом пройдем по всем пунктам. Схема работы протокола представлена ниже:

Рассмотрим каждый шаг более подробно:

1. AS_REQ (Preauthentication Request). Данный этап мы проходим, когда авторизуемся на нашей рабочей станции в домене (вводим наш логин и пароль). Формат отправляемого запроса выглядит следующим образом:

Client Name – имя пользователя;

Service Name – обращение к сервису krbtgt на стороне контроллера домена;

Client Time – метка времени с рабочей станции, откуда мы пытаемся авторизоваться. Метка шифруется хэшем пароля пользователя для предотвращения атак с повторной передачей.

По умолчанию, разница во времени между клиентом и KDC должна быть не более 5 минут, иначе запрос будет отклонен;

2. AS_REP. После того, как контроллер домена получит наш пакет – он сразу же попытается расшифровать присланную метку времени используя локальную копию хэша пароля пользователя из базы Active Directory. Если провести операцию не получается, то такой запрос будет отклонен, а клиенту возвращена ошибка. Если же все проходит успешно, то формируется сообщение AS_REP. Формат данного сообщения приведен ниже:

Client Name – имя пользователя;

Session Key – случайно сгенерированный криптографический ключ, который в дальнейшем будет использоваться для взаимодействия между пользователем и AD;

Token Information – токен пользователя, содержащий все данные по пользователю – состав групп, права и т.д.;

Lifetime/Expiry – время жизни TGT;

По умолчанию время жизни TGT составляет 10 часов.

В сообщении AS_REP у нас 2 блока – один шифруется хэшем пароля пользователя, второй – шифруется секретом KDC. Секрет KDC хранится в AD на контроллере. Клиент расшифровывает свою часть сообщения, а TGT просто сохраняется в памяти. Именно внутри блока TGT у нас хранится Token Information.

После успешно принятого сообщения AS_REP нам уже не требуется пароль, поскольку дальнейшее взаимодействие между клиентом и контроллером AD будет происходит посредством защищенного Session Key;

3. TGS_REQ. Вот и настал момент, когда нам необходимо обратиться к какому – либо сервису по Kerberos. В случае с AD это практически любой сервис (Exchange, SharePoint, файловые серверы и т.д.). Для того, чтобы мы смогли запросить доступ к сервису, данный сервис должен иметь свой SPN.

Итак, мы хотим обратиться к сервису через Kerberos – для этого мы посылаем на KDC сообщение TGS_REQ следующего содержания:

Service Principal – SPN запрашиваемого сервиса;

Client Name – имя пользователя;

Time Stamp – метка времени;

Как видно по изображению выше – имя пользователя и метка времени у нас зашифрованы сессионным ключом, который мы получили еще на этапе аутентификации. Блок TGT, который мы получили ранее, также передается на сервер KDC для обработки;

4. TGS_REP. Если на предыдущем этапе у нас все прошло хорошо, то в ответ KDC формирует нам TGS_REP пакет со следующим содержимым:

Service Principal – SPN сервиса;

Time Stamp – метка времени;

Service Session Key – это сессионный ключ, который будет использоваться уже при общении со службой;

Client Name – имя пользователя.

Здесь у нас также ответ представлен из двух блоков: первый блок – шифруется сессионным ключом клиента, который был получен на этапе AS_REP, второй блок – шифруется хэшем пароля службы;

5. AP_REQ. После того, как клиент получит ответ TGS_REP, он «идет» с ним к целевому сервису уже с запросом AP_REQ следующего содержания:

Client Name – имя пользователя;

Time Stamp – метка времени;

Service Principal – SPN запрашиваемого сервиса;

Service Session Key – это сессионный ключ, который будет использоваться уже при общении со службой;

Token Information – токен пользователя, содержащий все данные по пользователю – состав групп, права и т.д.;   

Здесь у нас также представлены 2 блока – один блок шифруется сессионным ключом службы, второй – секретом службы;

6. После поступления запроса AP_REQ служба дешифрует свой блок, получая Service Session Key, которым затем дешифрует первый блок, обеспечивая проверку подлинности;

7. AP_REP. Данный пакет у нас на рисунке выше помечен пунктирной стрелкой. По сути, после получения AP_REQ и его расшифровки у службы нет обязательного требования отправки данного пакета. Он может быть отправлен в случае, например, возникшей ошибки или если была запрошена взаимная проверка подлинности.

Итог

В этой статье мы с вами расмотрели, как происходит взаимодействие по протоколу Kerberos в среде Active Directory. Естественно, сам протокол не ограничивается только этими пакетами. Гораздо больше технической информации можно найти в RFC 1510 и RFC 4120.

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Windows 10 1607 ltsb обновить до 1903
  • Hp laserjet 1536dnf mfp driver windows 10
  • Windows 7 бесконечная загрузка пожалуйста подождите
  • Вылетают все приложения на windows 10
  • Как запустить обновления windows 7 от имени администратора