概要
フォレストの信頼は、ある Active Directory フォレスト内のリソースが別のフォレストの ID を信頼できる方法を提供しています。 この信頼は双方向に構成できます。 信頼される側のフォレストがユーザー ID のソースです。 信頼する側のフォレストには、ユーザーが認証を受けるリソースが含まれています。 信頼される側のフォレストは、その逆方向を許可することなく、信頼する側のフォレストに対してユーザーを認証できます。
制約のない Kerberos 委任は、ユーザーが自分の資格情報をサービスに送信し、サービスがユーザーに代わってリソースにアクセスできるようにするメカニズムです。制約のない Kerberos 委任を有効にするには、Active Directory 内のサービスのアカウントを委任に対して信頼済みとしてマークする必要があります。 この結果、ユーザーとサービスが異なるフォレストに属している場合に問題が生じます。 サービス フォレストが委任を許可する責任があります。 委任には、ユーザーのフォレストからのユーザーの資格情報が含まれています。
あるフォレストが別のフォレストのアカウントに影響するセキュリティ上の決定を下すことを許可すると、フォレスト間のセキュリティ境界が侵害されます。信頼する側のフォレストを所有する攻撃者は、信頼される側のフォレストから ID に関して 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 月 15 日以降の更新プログラムをインストールした後、 新しいフォレストおよび新しい外部の信頼では、制約のない Kerberos 委任は既定で無効になります。
-
2019 年 7 月 10 日以降の更新プログラムをインストールした後、フォレスト (新規と既存の両方) および外部の信頼では、制約のない Kerberos 委任は無効になります。
-
管理者は、5 月以降のバージョンの NETDOM および AD PowerShell モジュールを使用して、制約のない Kerberos 委任を有効にすることができます。
これらの更新プログラムによって、フォレストまたは外部の信頼を越える制約のない委任を現在必要としているアプリケーションについて、互換性の競合が発生する可能性があります。 これは、特に検疫フラグ (SID フィルター処理とも呼ばれます) が既定で有効な外部の信頼に当てはまります。 具体的に説明すると、登録されている信頼の種類に対して制約のない委任を使用するサービスに対する認証要求は、新しいチケットを要求するときに失敗します。
リリース日については、「更新プログラムのタイムライン」を参照してください。
回避策
Kerberos 完全委任のフォレスト境界の強化が含まれる Windows Server バージョンにデータとアカウントのセキュリティを提供するには、2019 年 3 月の更新プログラムをインストールした後、次のように netdom フラグ EnableTGTDelegation を No に設定して着信信頼全体の TGT の委任をブロックします。
netdom.exe trust fabrikam.com /domain:contoso.com /EnableTGTDelegation:No
2019 年 5 月と 2019 年 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
注:
-
EnableTGTDelegation フラグは、信頼する側のドメイン (contoso.com など) ごとに信頼される側のドメイン (この場合は 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 が有効で実行されているコンピューターからの制約のない委任がすべて防止されます。
-
フォレストまたは外部の信頼があり、いずれかが検疫済みとして構成されている場合、2 つのフラグの意味は反対になるため、TGT の委任を有効にすることはできません。 検疫ビットによって、参加ドメイン間のセキュリティ境界が強化されます。 TGT の委任を有効にすると、信頼される側のドメインのユーザーの資格情報へのアクセスが信頼する側のドメインに許可されるので、ドメイン間のセキュリティ境界がなくなります。 これを双方向で行うことはできません。
quarantine フラグが現在有効な場合は、NETDOM コマンド ライン構文に quarantine:no フラグを追加します。
-
EnableTGTDelegation を Yes に変更した場合は、必要に応じて発信元と中間発信者の Kerberos チケットを削除します。 削除する関連チケットは、関連する信頼を越えるクライアントの参照 TGT です。 特定の環境の委任ホップ数によっては、この処理に複数のデバイスが関係する可能性があります。
この手順の詳細については、以下の Windows IT Pro Center の資料を参照してください。
更新プログラムのタイムライン
2019 年 3 月 13 日
Kerberos の完全な委任に対するフォレスト境界の強制は更新プログラムとしてリリースされ、この資料で前述した「対象製品」に記載されているすべてのサポートされるバージョンの Windows Server 上で、この機能を有効にすることができるようになります。 入力方向のフォレストの信頼にこの機能この機能を設定することをお勧めします。
この更新プログラムで、次のシステムに Kerberos の完全な委任に対するフォレスト境界の強化機能が追加されます。
-
Windows Server 2008 R2
-
Windows Server 2008
2019 年 5 月 15 日
新しいフォレストと外部の信頼に新しい安全な既定の構成を追加する更新プログラムがリリースされました。 信頼を越える委任が必要な場合は、EnableTGTDelegation フラグを Yes に設定してから、2019 年 7 月 10 日の更新プログラムをインストールします。 信頼を越える委任が不要な場合は、EnableTGTDelegation フラグを設定しないでください。 EnableTGTDelegation フラグは 2019 年 7 月 10 日の更新プログラムがインストールされるまで無視されるので、管理者には、必要に応じて制約のない Kerberos 委任を再度有効にするまで時間があります。
この更新プログラムの一環として、新しく作成される信頼には EnableTGTDelegation フラグが既定で No に設定されます。 これは以前とは反対の動作です。 代わりに、管理者は、リソースベースの制約付き委任を使用するように、影響を受けるサービスを再構成することをお勧めします。
この互換性の問題を検出する方法の詳細については、「制約のない委任を利用するサービスを見つける」を参照してください。
2019 年 7 月 10 日
フォレストと外部の信頼の受信側に新しい既定の動作を強制する更新プログラムがリリースされました。 登録されている信頼の種類に対して制約のない委任を使用するサービスに対する認証要求は、認証されますが、委任は行われません。 サービスで委任された操作を実行しようとすると失敗します。
緩和策については、「回避策」セクションを参照してください。
制約のない委任を利用するサービスを見つける
TGT の委任を許可する入力方向の信頼があるフォレストをスキャンし、制約のない委任を許可するセキュリティ プリンシパルを見つけるには、スクリプト ファイル (たとえば、Get-RiskyServiceAccountsByTrust.ps1 -Collect) で次の PowerShell スクリプトを実行します。
注:
-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 値を含むイベントを確認してください。
イベント ログ |
イベント ソース |
イベント ID |
詳細 |
セキュリティ |
Microsoft-Windows-Security-Auditing |
4768 |
Kerberos TGT が発行されました。 |
セキュリティ |
Microsoft-Windows-Security-Auditing |
4769 |
Kerberos サービス チケットが発行されました。 |
セキュリティ |
Microsoft-Windows-Security-Auditing |
4770 |
Kerberos サービス チケットが更新されました。 |
認証エラーのトラブルシューティング
アプリケーションが制約のない委任を利用している場合、制約のない委任を無効にすると、このような変更との互換性の問題がアプリケーションに生じる可能性があります。 このようなアプリケーションは、制約付きの委任またはリソース ベースの制約付き委任を使用するように構成する必要があります。 詳細については、「Kerberos の制約付き委任の概要」を参照してください。
信頼を越えたラウンドトリップ認証を利用するアプリケーションは、制約付き委任を使用してもサポートされません。 たとえば、フォレスト A のユーザーがフォレスト B のアプリケーションに認証されている場合、フォレスト B のアプリケーションがフォレスト A にチケットを委任しようとすると、委任は失敗します。