Все руководства, которые я смог найти, по настройке единого входа на веб-сайт, размещенный в Apache, с использованием аутентификации Active Directory, делают это путем настройки Kerberos с небезопасными настройками. Некоторое время было лучшей практикой отключить шифрование RC4-HMAC для Kerberos в Active Directory, но многие учебники призывают переопределить значения по умолчанию krb5.conf и заставить все работать с RC4-HMAC.
Я хотел попробовать настроить единый вход с шифрованием AES256, и мне удалось заставить его работать, поэтому я записываю этот вопрос и ответ для всех, кто хочет большей безопасности для своего сайта.
Мы начнем с того, что сначала заставим его работать с RC4-HMAC, так как это проще. Стандартные шаги по настройке SSO начинаются с создания учетной записи домена со связанным SPN, которое браузеры будут использовать для получения зашифрованных учетных данных для отправки на сервер. В этом примере мой пользователь REALM \ HostServiceAccount:
Мы добавляем следующие записи в /etc/krb5.conf на нашем целевом сервере:
[libdefaults]
default_realm = REALM.COM
[domain_realm]
.realm.com = REALM.COM
realm.com = REALM.COM
Мы создаем keytab и позволяем серверу читать его:
# ktutil
ktutil: add_entry -password -p HTTP/host.example.com@REALM.COM -k 1 -e rc4-hmac
Password for HTTP/host.example.com@REALM.COM: <enter password here>
ktutil: write_kt /etc/apache2/service.keytab
ktutil: q
# chown -v www-data:root /etc/apache2/service.keytab
# chmod -v 440 /etc/apache2/service.keytab
(На этом этапе вы, конечно, захотите использовать kinit -kt service.keytab -S HTTP/host.example.com@REALM.COM HostServiceAccount@REALM.COM
чтобы проверить keytab.)
Наконец, мы настраиваем Apache для аутентификации пользователей с помощью нашей keytab:
KrbDelegateBasic off
KrbAuthoritative on
KrbMethodK5Passwd off
Krb5Keytab /etc/apache2/service.keytab
KrbAuthRealms REALM.COM
LogLevel debug
После перезапуска Apache, если все пойдет хорошо, мы делаем запрос к серверу с нашего компьютера домена Windows и видим следующее в журнале ошибок Apache:
[debug] src/mod_auth_kerb.c(1641): [client ****] kerb_authenticate_user entered with user (NULL) and auth_type Kerberos, referer: ****
[debug] src/mod_auth_kerb.c(1395): [client ****] Verifying client data using KRB5 GSS-API , referer: ****
[debug] src/mod_auth_kerb.c(1411): [client ****] Client didn't delegate us their credential, referer: ****
[debug] src/mod_auth_kerb.c(1430): [client ****] GSS-API token of length 185 bytes will be sent back, ****
Запустив klist на нашей клиентской машине (или Wireshark, чтобы увидеть билет в запросе), мы видим, что действительно использовали билет RC4-HMAC для аутентификации:
#4> Client: fluggo @ REALM.COM
Server: HTTP/host.example.com @ REALM.COM
KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
Все хорошо, но опять же, это не наша цель. RC4-HMAC считается небезопасным, поэтому давайте отключим его и попробуем заставить ту же настройку работать с AES256.
Во-первых, мы попросим нашего дружелюбного администратора соседнего домена включить расширенное шифрование в REALM \ HostServiceAccount, в котором будут два флажка, помеченных:
Они появляются в разных местах в зависимости от используемых вами инструментов; Конечным результатом должно быть то, что атрибут msDS-SupportedEncryptionTypes LDAP должен иметь значение 0x18 или десятичное 24, что означает, что поддерживаются только AES128 и AES256.
Чтобы сделать это эффективным, мы уберем наши локальные клиентские билеты:
C:>klist purge
Current LogonId is 0:0xdeadbeef
Deleting all tickets:
Ticket(s) purged!
Если мы выполним наш запрос еще раз, мы увидим, что запрос не прошел, но у нас есть обновленный билет:
C:>klist
...
#3> Client: fluggo @ REALM.COM
Server: HTTP/host.example.com @ REALM.COM
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Теперь нам просто нужно обновить нашу keytab новыми алгоритмами, и мы должны стать золотыми:
# mv /etc/apache2/service.keytab ~/old.keytab
# ktutil
ktutil: add_entry -password -p HTTP/host.example.com@REALM.COM -k 1 -e aes256-cts-hmac-sha1-96
Password for HTTP/host.example.com@REALM.COM: <enter password here>
ktutil: add_entry -password -p HTTP/host.example.com@REALM.COM -k 1 -e aes128-cts-hmac-sha1-96
Password for HTTP/host.example.com@REALM.COM: <enter password here>
ktutil: write_kt /etc/apache2/service.keytab
ktutil: q
# chown -v www-data:root /etc/apache2/service.keytab
# chmod -v 440 /etc/apache2/service.keytab
Нам даже не нужно перезапускать Apache. Просто отправьте запрос еще раз.
Упс ... не работает. Если мы посмотрим на журнал ошибок Apache, мы увидим:
[debug] src/mod_auth_kerb.c(1641): [client ****] kerb_authenticate_user entered with user (NULL) and auth_type Kerberos
[debug] src/mod_auth_kerb.c(1249): [client ****] Acquiring creds for HTTP@host.example.com
[debug] src/mod_auth_kerb.c(1395): [client ****] Verifying client data using KRB5 GSS-API
[debug] src/mod_auth_kerb.c(1411): [client ****] Client didn't delegate us their credential
[debug] src/mod_auth_kerb.c(1430): [client ****] GSS-API token of length 9 bytes will be sent back
[debug] src/mod_auth_kerb.c(1110): [client ****] GSS-API major_status:000d0000, minor_status:000186a5
[error] [client ****] gss_accept_sec_context() failed: Unspecified GSS failure. Minor code may provide more information (, )
Что ж, это до смешного бесполезное сообщение об ошибке, но что пошло не так? Ответ и одно решение для подражания!
Оказывается, основная проблема здесь - это одна из проблем, для решения которой был предназначен AES256.
TL; DR: Главное имя на вкладке ключей теперь должно совпадать с именем учетной записи.
Если бы мы бежали KRB5_TRACE=/dev/stderr kinit HostServiceAccount@REALM.COM
назад, когда учетная запись была включена только для шифрования RC4-HMAC, мы увидели бы эту строку в выводе:
[8192] 1441829478.537451: Selected etype info: etype rc4-hmac, salt "", params ""
Теперь, когда у нас включен AES256, эта строка выглядит так:
[8200] 1441829508.947208: Selected etype info: etype aes256-cts, salt "REALM.COMHostServiceAccount", params ""
При переключении с аутентификации NTLM на Kerberos алгоритм RC4-HMAC был указан для повторного использования хэша NTLM. Microsoft отказалась добавить в хеш-код, чтобы облегчить взаимодействие существующих систем с Kerberos. Теперь, когда у пользователей есть возможность выполнить обновление, для алгоритмов AES256 и AES128 указана соль, а соль - это имя пользователя.
Мы можем убедиться в этом, если сгенерируем ключевые вкладки для RC4-HMAC и AES256, используя разные имена пользователей. С RC4-HMAC:
fluggo@host:~$ ktutil
ktutil: add_entry -password -p HTTP/host.example.com@REALM.COM -k 1 -e rc4-hmac
Password for HTTP/host.example.com@REALM.COM: 12345
ktutil: add_entry -password -p HostServiceAccount@REALM.COM -k 1 -e rc4-hmac
Password for HostServiceAccount@REALM.COM: 12345
ktutil: write_kt rc4.keytab
ktutil: q
fluggo@host:~$ klist -Kek rc4.keytab
Keytab name: FILE:rc4.keytab
KVNO Principal
---- --------------------------------------------------------------------------
1 HTTP/host.example.com@REALM.COM (arcfour-hmac) (0x7a21990fcd3d759941e45c490f143d5f)
1 HostServiceAccount@REALM.COM (arcfour-hmac) (0x7a21990fcd3d759941e45c490f143d5f)
... хеш одинаков, поэтому эти две записи эквивалентны. Но с AES256:
fluggo@host:~$ ktutil
ktutil: add_entry -password -p HTTP/host.example.com@REALM.COM -k 1 -e aes256-cts-hmac-sha1-96
Password for HTTP/host.example.com@REALM.COM: 12345
ktutil: add_entry -password -p HostServiceAccount@REALM.COM -k 1 -e aes256-cts-hmac-sha1-96
Password for HostServiceAccount@REALM.COM: 12345
ktutil: write_kt aes.keytab
ktutil: q
fluggo@host:~$ klist -Kek aes.keytab
Keytab name: FILE:aes.keytab
KVNO Principal
---- --------------------------------------------------------------------------
1 HTTP/host.example.com@REALM.COM (aes256-cts-hmac-sha1-96) (0x5746fa6f9b0c990ba7fb20acd85065040d66e843a043508569841768ef2b7917)
1 HostServiceAccount@REALM.COM (aes256-cts-hmac-sha1-96) (0x6a98fdccbce4db77f40192f4e916e0900a1b9cba2f6ca8bc737d968e4b961c25)
... хеши разные. Главное имя имеет значение, и оно должно соответствовать UPN учетной записи.
Поскольку имя пользователя должно быть правильным для работы keytab, мы создаем новую keytab с основным именем, которое Active Directory использует в билете:
# rm /etc/apache2/service.keytab
# ktutil
ktutil: add_entry -password -p HostServiceAccount@REALM.COM -k 1 -e aes256-cts-hmac-sha1-96
Password for HostServiceAccount@REALM.COM: <enter password here>
ktutil: add_entry -password -p HostServiceAccount@REALM.COM -k 1 -e aes128-cts-hmac-sha1-96
Password for HostServiceAccount@REALM.COM: <enter password here>
ktutil: write_kt /etc/apache2/service.keytab
ktutil: q
# chown -v www-data:root /etc/apache2/service.keytab
# chmod -v 440 /etc/apache2/service.keytab
Apache заботится об основном имени в keytab, поэтому он не найдет эти записи самостоятельно. Вместо этого мы просто указываем Apache использовать любой рабочий принцип, который он может найти:
KrbServiceName Any
Я хотел, чтобы Apache нашел принципала по правильному имени, но это вряд ли имеет значение, так как наши принципалы - единственные в keytab.
Перезапустите Apache, обновите страницу, и теперь аутентификация должна работать.
Решение для ключевых вкладок с несколькими записями (SPN), как описано здесь: https://developer.ibm.com/answers/questions/270616/how-do-you-add-multiple-spns-to-the-same-keytab-fi.html
Добавьте переключатель / RawSalt в ktpass: ktpass.... -setupn /RawSalt "REALM.COMSameAccountAsMapuser"