摘要
樹系信任為 Active Directory 樹系中的資源提供信任來自另一個樹系的識別的方法。 這個信任可以雙向設定。 受信任的樹系是使用者識別的來源。 信任的樹系包含使用者進行驗證的資源。 受信任的樹系可以對信任樹系的使用者進行驗證,而不允許進行相反的操作。
不受限制的 Kerberos 委派是使用者將其認證傳送到服務,讓服務可以代表使用者存取資源的機制。若要啟用不受限制的 Kerberos 委派,Active Directory 中服務的帳戶必須標示為受信任可以委派。 如果使用者和服務屬於不同樹系,則會造成問題。 服務樹系負責允許委派。 委派包括使用者樹系中的使用者認證。
允許一個樹系訂定影響另一個樹系帳戶的安全性決策,將會違反樹系之間的安全性界限。若攻擊者擁有信任的樹系,則可以對受信任樹系中的識別要求 TGT 委派,進而存取受信任樹系中的資源。 這不適用於 Kerberos 限制委派 (KCD)。
Windows Server 2012 引進對 Kerberos 完整委派的樹系界限強制執行 (英文)。 這個功能為受信任的網域新增原則,可根據信任來停用不受限制的委派。 這個功能的預設設定允許不受限制的委派,而且不安全。
下列 Windows Server 版本具有提供安全性強化的更新可供使用:
-
Windows Server 2019
-
Windows Server 2016
-
Windows Server 2012 R2
-
Windows Server 2012
這個功能及安全性強化中的變更已移植到下列版本:
-
Windows Server 2008 R2
-
Windows Server 2008
這些安全性變更會進行下列變更:
-
安裝 5 月 14 日更新和以後的更新之後,依預設停用新樹系和新外部信任上不受限制的 Kerberos 委派。
-
安裝 2019 年 7 月 9 日更新和以後的更新之後,停用樹系 (新的和現有的) 和外部信任上不受限制的 Kerberos 委派。
-
系統管理員可以使用 5 月以後版本的 NETDOM 和 AD PowerShell 模組,藉此啟用不受限制的 Kerberos 委派。
這些更新可能會對樹系或外部信任間目前需要不受限制的 Kerberos 委派的應用程式造成相容性衝突。 對於依預設啟用隔離旗標 (也稱為 asSID 篩選) 的外部信任尤其如此。 具體來說,當您要求新票證時,對於透過所列信任類型使用不受限制委派的服務,驗證要求將會失敗。
如需發行日期,請參閱更新時間表。
因應措施
若要在具有對 Kerberos 完整委派的樹系界限強制執行 (英文) 功能的 Windows Server 版本上提供資料和帳戶安全性,您可以在安裝 2019 年 3 月更新之後,將 netdom 旗標 EnableTGTDelegation 設定為 No,如下所示,藉此封鎖連入信任間的 TGT 委派:
netdom.exe trust fabrikam.com /domain:contoso.com /EnableTGTDelegation:No
分別安裝 2019 年 5 月和 7 月更新之後,新的和現有的樹系及外部信任上的 TGT 委派遭到封鎖。
若要重新啟用信任間的委派並回復原始的不安全設定,直到可以啟用限制或資源型委派,請將 EnableTGTDelegation 旗標設定為 Yes。
啟用 TGT 委派的 NETDOM 命令列如下所示:
netdom trust <TrustedDomainName > /domain:<TrustingDomainName > /EnableTgtDelegation:Yes
概念上,您可以將用來啟用 TGT 委派的 NETDOM 語法想成:
netdom trust <domain that you are administering> /domain:<domain whose trust NETDOM is modifying> /EnableTgtDelegation:Yes
用來在 contoso.com 伺服器上啟用 fabrakam.com 使用者的 TGT 委派的 NETDOM 語法如下所示:
netdom.exe trust fabrikam.com /domain:contoso.com /EnableTGTDelegation:Yes
注意事項
-
每個信任網域 (例如 contoso.com) 的 EnableTGTDelegation 旗標都應在受信任的網域 (在這個案例中,即為 fabrikam.com) 中設定。 設定旗標之後,受信任的網域將不再允許將 TGT 委派給信任網域。
-
EnableTGTDelegation 的安全狀態為 No。
-
若任何應用程式或服務依賴樹系間不受限制的委派,將會在以手動或程式設計方式將 EnableTGTDelegation 設定為 Yes 時發生失敗。 安裝 2019 年 5 月更新和 2019 年 7 月更新之後,新的和現有的信任上的 EnableTGTDelegation 會預設為 NO。 如需有關如何偵測這個失敗的詳細資訊,請參閱尋找依賴不受限制委派的服務。 請參閱更新時間表,以取得影響此因應措施套用方式的時間表變更。
-
如需有關 NETDOM 的詳細資訊,請參閱 Netdom.exe 文件 (英文)。
-
如果您必須啟用信任上的 TGT 委派,建議您在用戶端電腦上啟用 Windows Defender Credential Guard,以避免這個風險。 這可以防止已啟用並執行 Windows Defender Credential Guard 的電腦中的所有不受限制委派。
-
如果您擁有樹系或外部信任,並且其中一個設定為隔離,則無法啟用 TGT 委派,因為兩個旗標具有相反的語意。 隔離位元會強化參與網域之間的安全界限。 啟用 TGT 委派會將信任的網域存取權提供給受信任網域中的使用者認證,藉此清除網域之間的安全性界限。 您無法兩者都擁有。
如果 [隔離] 旗標目前已啟用,請將 quarantine:no 旗標新增到 NETDOM 命令列語法。
-
如果您已將 EnableTGTDelegation 變更為 Yes,請視需要刪除原始呼叫者和中繼呼叫者上的 Kerberos 票證。 要刪除的相關票證是相關信任間用戶端的轉介 TGT。 這可能牽涉不只一個裝置,視指定的環境中委派躍點的數目而定。
如需有關此程序的詳細資訊,請參閱下列 Windows IT Pro Center 文章:
更新時間表
2019 年 3 月 12 日
Kerberos 完整委派的樹系界限強制執行將以更新形式提供使用,以便在本文頂端<適用於>一節中所列、所有支援的 Windows Server 版本上啟用這個功能。 我們建議您在連入樹系信任上設定此功能。
此更新會將對 Kerberos 完整委派的樹系界限強制執行 (英文) 新增至下列系統:
-
Windows Server 2008 R2
-
Windows Server 2008
2019 年 5 月 14 日
已發行更新,將新的安全預設設定新增至新的樹系統和外部信任。 如果您需要信任間的委派,應在安裝 2019 年 7 月 9 日更新之前,先將 EnableTGTDelegation 旗標設定為 Yes。 如果您不需要信任間的委派,則不應設定 EnableTGTDelegation 旗標。 EnableTGTDelegation 旗標將會遭到忽略,直到安裝 2019 年 7 月 9 日更新為止,這讓系統管理員在需要時有時間可以重新啟用不受限制的 Kerberos 委派。
在此更新中,EnableTGTDelegation 旗標將會針對任何新建立的信任,依預設設定為 No。 這與先前的行為相反。 我們建議系統管理員改為重新設定受影響的服務,以便使用資源型限制委派。
如需有關如何偵測相容性問題的詳細資訊,請參閱尋找依賴不受限制委派的服務。
2019 年 7 月 9 日
已發行更新,以便在樹系和外部信任的輸入端強制執行新的預設行為。 對於透過所列信任類型使用不受限制委派的服務,驗證要求將會經過驗證,但不包含委派。 當服務嘗試執行委派的操作時,將會發生失敗。
如需緩和措施,請參閱因應措施一節。
尋找依賴不受限制委派的服務
若要掃描具有允許 TGT 委派的連入信任的樹系,並尋找允許不受限制委派的任何安全性主體,請在指令碼檔案中執行下列 PowerShell 指令碼 (例如,Get-RiskyServiceAccountsByTrust.ps1 -Collect):
注意
您也可以傳遞 -ScanAll 旗標,以便在不允許 TGT 委派的信任間進行搜尋。
[CmdletBinding()]
Param
(
[switch]$Collect,
[switch]$ScanAll
)
if ($Debug) {
$DebugPreference = 'Continue'
}
else {
$DebugPreference = 'SilentlyContinue'
}
function Get-AdTrustsAtRisk
{
[CmdletBinding()]
Param
(
[string]$Direction = "Inbound",
[switch]$ScanAll
)
if ($ScanAll) {
return get-adtrust -filter {Direction -eq $Direction}
}
else {
return get-adtrust -filter {Direction -eq $Direction -and TGTDelegation -eq $false}
}
}
function Get-ServiceAccountsAtRisk
{
[CmdletBinding()]
Param
(
[string]$DN = (Get-ADDomain).DistinguishedName,
[string]$Server = (Get-ADDomain).Name
)
Write-Debug "Searching $DN via $Server"
$SERVER_TRUST_ACCOUNT = 0x2000
$TRUSTED_FOR_DELEGATION = 0x80000
$TRUSTED_TO_AUTH_FOR_DELEGATION= 0x1000000
$PARTIAL_SECRETS_ACCOUNT = 0x4000000
$bitmask = $TRUSTED_FOR_DELEGATION -bor $TRUSTED_TO_AUTH_FOR_DELEGATION -bor $PARTIAL_SECRETS_ACCOUNT
$filter = @"
(&
(servicePrincipalname=*)
(|
(msDS-AllowedToActOnBehalfOfOtherIdentity=*)
(msDS-AllowedToDelegateTo=*)
(UserAccountControl:1.2.840.113556.1.4.804:=$bitmask)
)
(|
(objectcategory=computer)
(objectcategory=person)
(objectcategory=msDS-GroupManagedServiceAccount)
(objectcategory=msDS-ManagedServiceAccount)
)
)
"@ -replace "[\s\n]", ''
$propertylist = @(
"servicePrincipalname",
"useraccountcontrol",
"samaccountname",
"msDS-AllowedToDelegateTo",
"msDS-AllowedToActOnBehalfOfOtherIdentity"
)
$riskyAccounts = @()
try {
$accounts = Get-ADObject -LDAPFilter $filter -SearchBase $DN -SearchScope Subtree -Properties $propertylist -Server $Server
}
catch {
Write-Warning "Failed to query $Server. Consider investigating seperately. $($_.Exception.Message)"
}
foreach ($account in $accounts) {
$isDC = ($account.useraccountcontrol -band $SERVER_TRUST_ACCOUNT) -ne 0
$fullDelegation = ($account.useraccountcontrol -band $TRUSTED_FOR_DELEGATION) -ne 0
$constrainedDelegation = ($account.'msDS-AllowedToDelegateTo').count -gt 0
$isRODC = ($account.useraccountcontrol -band $PARTIAL_SECRETS_ACCOUNT) -ne 0
$resourceDelegation = $account.'msDS-AllowedToActOnBehalfOfOtherIdentity' -ne $null
$acct = [PSCustomobject] @{
domain = $Server
sAMAccountName = $account.samaccountname
objectClass = $account.objectclass
isDC = $isDC
isRODC = $isRODC
fullDelegation = $fullDelegation
constrainedDelegation = $constrainedDelegation
resourceDelegation = $resourceDelegation
}
if ($fullDelegation) {
$riskyAccounts += $acct
}
}
return $riskyAccounts
}
function Get-RiskyServiceAccountsByTrust
{
[CmdletBinding()]
Param
(
[switch]$ScanAll
)
$riskyAccounts = @()
$trustTypes = $("Inbound", "Bidirectional")
foreach ($type in $trustTypes) {
$riskyTrusts = Get-AdTrustsAtRisk -Direction $type -ScanAll:$ScanAll
foreach ($trust in $riskyTrusts) {
$domain = $null
try {
$domain = Get-AdDomain $trust.Name -ErrorVariable eatError -ErrorAction Ignore
} catch {
write-debug $_.Exception.Message
}
if($eatError -ne $null) {
Write-Warning "Couldn't find domain: $($trust.Name)"
}
if ($domain -ne $null) {
$accts = Get-ServiceAccountsAtRisk -DN $domain.DistinguishedName -Server $domain.DNSRoot
foreach ($acct in $accts) {
Write-Debug "Risky: $($acct.sAMAccountName) in $($acct.domain)"
}
$risky = [PSCustomobject] @{
Domain = $trust.Name
Accounts = $accts
}
$riskyAccounts += $risky
}
}
}
return $riskyAccounts
}
if ($Collect) {
Get-RiskyServiceAccountsByTrust -ScanAll:$ScanAll | Select-Object -expandProperty Accounts | format-table
}
PowerShell 指令碼的輸出會列出網域中設定用於連入信任 (來自已設定不受限制委派的執行網域) 的 Active Directory 安全性主體。 輸出會類似下列範例。
domain |
sAMAccountName |
objectClass |
partner.fabrikam.com |
dangerous |
user |
partner.fabrikam.com |
labsrv$ |
computer |
透過 Windows 事件偵測不受限制的委派
發行 Kerberos 票證時,Active Directory 網域控制站會記錄下列安全性事件。 這些事件包含有關目標網域的資訊。 您可以使用這些事件來判斷不受限制的委派是否用於連入信任之間。
注意
請檢查包含與受信任網域名稱相符之 TargetDomainName 值的事件。
事件記錄檔 |
事件來源 |
事件識別碼 |
詳細資料 |
安全性 |
Microsoft-Windows-Security-Auditing |
4768 |
Kerberos TGT 已發行。 |
安全性 |
Microsoft-Windows-Security-Auditing |
4769 |
Kerberos 服務票證已發行。 |
安全性 |
Microsoft-Windows-Security-Auditing |
4770 |
Kerberos 服務票證已更新。 |
疑難排解驗證失敗
停用不受限制的委派時,如果應用程式依賴不受限制的委派,則應用程式可能會遇到與這些變更相關的相容性問題。 這些應用程式應設定為使用限制委派或以資源為主的限制委派。 如需詳細資訊,請參閱 Kerberos 限制委派概觀 (部分機器翻譯)。
依賴信任間來回行程驗證的應用程式並未受支援使用限制委派。 例如,如果樹系 A 中的使用者向樹系 B 中的應用程式驗證,並且樹系 B 中的應用程式嘗試將票證委派回樹系 A,則委派會失敗。