Linux

在 Win2008 域中啟用對 Apache 的 AES 加密單點登錄

  • January 31, 2018

我可以找到的所有關於使用 Active Directory 身份驗證設置單點登錄到 Apache 託管網站的教程都是通過使用不安全設置配置 Kerberos 來實現的。一段時間以來,在 Active Directory 中禁用 Kerberos 的 RC4-HMAC 加密一直是最佳實踐,但是很多教程都要求覆蓋 krb5.conf 的預設值並讓一切都與 RC4-HMAC 一起工作。

我想嘗試使用 AES256 加密設置單點登錄,並且我設法讓它工作,所以我正在記錄這個問題和答案,以供其他任何希望為他們的網站提供更好安全性的人使用。

從 RC4-HMAC 開始

我們將首先讓它與 RC4-HMAC 一起工作,因為這更容易。設置 SSO 的標準步驟從創建具有關聯 SPN 的域帳戶開始,瀏覽器將使用該帳戶獲取加密憑據以發送到伺服器。對於這個例子,我的使用者是 REALM\HostServiceAccount:

  • UPN:HostServiceAccount@realm.com(因此 Kerberos 主體名稱為 HostServiceAccount@REALM.COM
  • servicePrincipalName 屬性(也可由 setspn 設置):HTTP/host.example.com;HTTP/主機(Kerberos:HTTP/host.example.com@REALM.COM)
  • 不理會加密設置;預設情況下,這使 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/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來測試密鑰表。)

最後,我們將 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

現在我們應該只需要用新算法更新我們的 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:keytab 中的主體名稱現在需要與帳戶名稱匹配。

問題

如果我們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 雜湊。微軟拒絕在雜湊中添加鹽,以使現有系統更容易與 Kerberos 進行互操作。現在使用者有機會升級了,為AES256和AES128算法指定了一個salt,salt就是使用者名。

如果我們使用不同的使用者名為 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,刷新頁面,現在應該可以進行身份驗證了。

引用自:https://serverfault.com/questions/721497