요약
포리스트 트러스트를 사용하면 Active Directory 포리스트의 리소스가 다른 포리스트의 ID를 안전하게 신뢰할 수 있습니다. 이 트러스트는 두 가지 방법으로 구성할 수 있습니다. 트러스트된 포리스트는 사용자 ID의 소스입니다. 트러스팅 포리스트에는 사용자가 인증하는 리소스가 포함되어 있습니다. 트러스팅 포리스트가 트러스트된 포리스트에 사용자를 인증하지 않더라도 트러스트된 포리스트는 트러스팅 포리스트에 사용자를 인증할 수 있습니다.
무제한 Kerberos 위임은 사용자가 자격 증명을 서비스로 전송하여 서비스가 사용자를 대신하여 리소스에 액세스하는 메커니즘입니다. 무제한 Kerberos 위임을 사용하려면 Active Directory의 서비스 계정이 위임에 트러스트된 것으로 표시되어야 합니다. 이때 사용자와 서비스가 다른 포리스트에 속할 경우 문제가 발생할 수 있습니다. 서비스 포리스트는 위임 허용 여부를 결정합니다. 위임에는 사용자 포리스트에서 사용자의 자격 증명이 포함됩니다.
어떤 포리스트가 다른 포리스트의 계정에 영향을 미치는 보안을 결정하도록 허용하는 것은 포리스트 간 보안 경계를 위반하는 것입니다. 트러스팅 포리스트를 보유한 공격자는 트러스트된 포리스트에서 ID용 TGT 위임을 요청하여 트러스트된 포리스트에 있는 리소스에 액세스할 수 있습니다. 이것은 KCD(Kerberos 제한 위임)에는 적용되지 않습니다.
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 위임이 포리스트(신규 및 기존 모두) 및 외부 트러스트에서 사용되지 않습니다.
-
관리자는 NETDOM 및 AD PowerShell 모듈의 5월 또는 이후 버전을 사용하여 무제한 Kerberos 위임을 사용할 수 있습니다.
이 업데이트를 설치하면 포리스트 또는 외부 트러스트 전반에 걸친 무제한 위임이 필요한 응용 프로그램에 호환성 충돌이 발생할 수 있습니다. 이것은 격리 플래그(SID 필터링이라고도 함)를 기본적으로 사용하는 외부 트러스트에는 더욱 그렇습니다. 특히, 새 티켓을 요청할 경우 목록으로 나열된 신뢰 유형에 제한되지 않은 위임을 사용하는 서비스의 인증 요청이 실패합니다.
릴리스 날짜는 업데이트 타임라인을 참조하세요.
해결 방법
Kerberos 완전 위임을 위해 포리스트 경계 강화 기능이 있는 Windows Server 버전에서 데이터와 계정의 보안을 강화하기 위해 다음과 같이 netdom 플래그 EnableTGTDelegation을 No로 설정하여 수신 트러스트 전반에 2019년 3월 업데이트를 설치한 후 TGT 위임을 차단할 수 있습니다.
netdom.exe trust fabrikam.com /domain:contoso.com /EnableTGTDelegation:No
TGT 위임은 2019년 5월 및 7월 업데이트를 각각 설치한 후 신규 및 기존 포리스트와 외부 트러스트에서 차단됩니다.
제한 또는 리소스 기반 위임을 사용할 수 있을 때까지 트러스트 전반에서 위임을 다시 사용하고 원래의 안전하지 않은 구성으로 돌아가려면 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월 및 7월 업데이트를 설치한 후 신규 및 기존 트러스트에서 EnableTGTDelegation의 기본값은 NO입니다. 이 오류를 검색하는 방법에 대한 자세한 내용은 무제한 위임을 사용하는 서비스 찾기를 참조하세요. 이 해결 방법을 적용할 수 있는 방식에 영향을 주는 변경 타임라인은 업데이트 타임라인을 참조하세요.
-
NETDOM에 대한 자세한 내용은 Netdom.exe 설명서를 참조하세요.
-
트러스트에서 TGT 위임을 사용해야 한다면 클라이언트 컴퓨터에서 Windows Defender Credential Guard를 사용하여 위험을 완화할 것을 권장합니다. 이렇게 하면 Windows Defender Credential Guard가 사용하도록 설정되어 있으며 실행 중인 컴퓨터에서 모든 무제한 위임이 차단됩니다.
-
포리스트 또는 외부 트러스트가 있고, 이중 하나가 격리로 구성되어 있다면 두 플래그의 의미 체계가 정반대이기 때문에 TGT 위임을 사용할 수 없습니다. 격리 비트는 참여 도메인 간 보안 경계를 강화합니다. TGT 위임을 사용하면 트러스팅 도메인이 트러스트된 도메인에서 사용자의 자격 증명에 액세스할 수 있도록 하여 도메인 간 보안 경계를 제거합니다. 두 가지 방법을 사용할 수는 없습니다.
quarantine 플래그가 현재 사용 중이라면 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로 기본 설정됩니다. 이러한 동작은 이전과는 반대되는 동작입니다. Microsoft는 관리자가 리소스 기반의 제한을 받는 위임을 사용하도록 영향을 받는 서비스를 다시 구성할 것을 권장합니다.
호환성 문제를 검색하는 방법에 대한 자세한 내용은 무제한 위임을 사용하는 서비스 찾기를 참조하세요.
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 값이 포함된 이벤트를 확인합니다.
이벤트 로그 |
이벤트 원본 |
이벤트 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에 다시 위임하려고 하면 위임은 실패합니다.