从 RC4-HMAC 开始

从 RC4-HMAC 开始

我能找到的所有关于使用 Active Directory 身份验证设置单点登录 Apache 托管网站的教程都是通过使用不安全的设置配置 Kerberos 来实现的。一段时间以来,最佳做法是在 Active Directory 中禁用 Kerberos 的 RC4-HMAC 加密,但很多教程要求覆盖 krb5.conf 的默认值并使一切都使用 RC4-HMAC 工作。

我想尝试使用 AES256 加密设置单点登录,并且我设法使其工作,所以我将这个问题和答案记录下来,以供任何想要为其网站提供更好安全性的人使用。

从 RC4-HMAC 开始

我们首先让它与 RC4-HMAC 一起工作,因为这比较简单。设置 SSO 的标准步骤首先是创建一个具有关联 SPN 的域帐户,浏览器将使用该帐户获取要发送到服务器的加密凭据。在此示例中,我的用户是 REALM\HostServiceAccount:

  • 统一号码:[电子邮件保护](因此 Kerberos 主体名称是[电子邮件保护]
  • servicePrincipalName 属性(也可以通过 setspn 设置):HTTP/host.example.com;HTTP/host(Kerberos:HTTP/[电子邮件保护]
  • 保留加密设置;默认情况下,这会使 RC4-HMAC 成为允许的最强加密,因此来自域的票证将使用此加密

我们在目标服务器上的 /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/[email protected] -k 1 -e rc4-hmac
Password for HTTP/[email protected]: <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

(当然,此时您可能想要使用它来测试 keytab。)kinit -kt service.keytab -S HTTP/[email protected] [email protected]

最后,我们设置 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 上启用高级加密,这将是两个标记为的复选框:

  • 此帐户支持 Kerberos AES 128 位加密
  • 此帐户支持 Kerberos AES 256 位加密

这些会出现在不同的位置,具体取决于您使用的工具;最终结果应该是 LDAP 属性 msDS-SupportedEncryptionTypes 应该是 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

现在我们只需要用新算法更新我们的密钥表,我们就应该成功了:

# mv /etc/apache2/service.keytab ~/old.keytab
# ktutil
ktutil:  add_entry -password -p HTTP/[email protected] -k 1 -e aes256-cts-hmac-sha1-96
Password for HTTP/[email protected]: <enter password here>
ktutil:  add_entry -password -p HTTP/[email protected] -k 1 -e aes128-cts-hmac-sha1-96
Password for HTTP/[email protected]: <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 [email protected]
[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 (, )

好吧,这是一条毫无帮助的错误信息,但到底出了什么问题?答案和解决方案如下!

答案1

事实证明,这里的主要问题是 AES256 旨在解决的问题之一。

总结:keytab 中的主体名称现在需要与帐户名称匹配。

问题

如果我们在帐户仅启用 RC4-HMAC 加密时运行,我们会在输出中看到以下行:KRB5_TRACE=/dev/stderr kinit [email protected]

[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 哈希。微软拒绝在哈希中添加盐,以便现有系统更容易与 Kerberos 进行互操作。现在用户有机会升级,为 AES256 和 AES128 算法指定了盐,盐就是用户名。

如果我们使用不同的用户名生成 RC4-HMAC 和 AES256 的密钥表,我们可以看到这一点。使用 RC4-HMAC:

fluggo@host:~$ ktutil
ktutil:  add_entry -password -p HTTP/[email protected] -k 1 -e rc4-hmac
Password for HTTP/[email protected]: 12345
ktutil:  add_entry -password -p [email protected] -k 1 -e rc4-hmac
Password for [email protected]: 12345
ktutil:  write_kt rc4.keytab
ktutil:  q
fluggo@host:~$ klist -Kek rc4.keytab
Keytab name: FILE:rc4.keytab
KVNO Principal
---- --------------------------------------------------------------------------
   1 HTTP/[email protected] (arcfour-hmac)  (0x7a21990fcd3d759941e45c490f143d5f)
   1 [email protected] (arcfour-hmac)  (0x7a21990fcd3d759941e45c490f143d5f)

...哈希值相同,因此这两个条目是等效的。但使用 AES256:

fluggo@host:~$ ktutil
ktutil:  add_entry -password -p HTTP/[email protected] -k 1 -e aes256-cts-hmac-sha1-96
Password for HTTP/[email protected]: 12345
ktutil:  add_entry -password -p [email protected] -k 1 -e aes256-cts-hmac-sha1-96
Password for [email protected]: 12345
ktutil:  write_kt aes.keytab
ktutil:  q
fluggo@host:~$ klist -Kek aes.keytab
Keytab name: FILE:aes.keytab
KVNO Principal
---- --------------------------------------------------------------------------
   1 HTTP/[email protected] (aes256-cts-hmac-sha1-96)  (0x5746fa6f9b0c990ba7fb20acd85065040d66e843a043508569841768ef2b7917)
   1 [email protected] (aes256-cts-hmac-sha1-96)  (0x6a98fdccbce4db77f40192f4e916e0900a1b9cba2f6ca8bc737d968e4b961c25)

...哈希值不同。主体名称很重要,它需要与帐户的 UPN 匹配。

一个办法

由于用户名必须正确才能使 keytab 正常工作,因此我们使用 Active Directory 在票证上使用的主体名称生成一个新的 keytab:

# rm /etc/apache2/service.keytab
# ktutil
ktutil:  add_entry -password -p [email protected] -k 1 -e aes256-cts-hmac-sha1-96
Password for [email protected]: <enter password here>
ktutil:  add_entry -password -p [email protected] -k 1 -e aes128-cts-hmac-sha1-96
Password for [email protected]: <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 使用它能找到的任何工作主体:

KrbServiceName Any

我希望 Apache 能够通过正确的名称找到主体,但这并不重要,因为我们的主体是密钥表中唯一的主体。

重新启动 Apache,刷新页面,身份验证现在就可以正常工作了。

答案2

针对具有多个条目 (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"

相关内容