jeek_

Get-KerberosDelegation

Aug 26th, 2025
424
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PowerShell 10.37 KB | Software | 0 0
  1. function Get-KerberosDelegation {
  2.     <#
  3.     .SYNOPSIS
  4.     Return the Kerberos Delegation settings.
  5.  
  6.     .DESCRIPTION
  7.     Return the Kerberos Delegation settings for the specified AD object.
  8.     If no AD object is specified then all AD Objects with Delegation are returned.
  9.  
  10.     .PARAMETER SamAccountName
  11.     SamAccountName of the AD object. If specifying computer or managed service accounts drop the "$" from the name.
  12.  
  13.     .PARAMETER DistinguishedName
  14.     The distinguishedName of the AD object.
  15.  
  16.     .PARAMETER ExcludeDomainControllers
  17.     Exclude Domain Controllers.
  18.  
  19.     .EXAMPLE
  20.     $dn = (Get-ADServiceAccount 'MSA-TST02').distinguishedName
  21.     Get-KerberosDelegation -DistinguishedName $dn
  22.  
  23.     .EXAMPLE
  24.     Get-KerberosDelegation -SamAccountName 'MSA-TST02$'
  25.  
  26.     .EXAMPLE
  27.     Get-ADServiceAccount 'MSA-TST02' | Get-KerberosDelegation
  28.  
  29.     .EXAMPLE
  30.     Get-ADObject -Filter "SamAccountName -eq 'MSA-TST02$'" | Get-KerberosDelegation
  31.  
  32.     .NOTES
  33.     Kerberos Delegation is a security sensitive configuration. Especially full (unconstrained) delegation has significant impact: any service
  34.     that is configured with full delegation can take any account that authenticates to it, and impersonate that account for any other network
  35.     service that it likes. So, if a Domain Admin were to use that service, the service in turn could read the hash of KRBRTG and immediately
  36.     effectuate a golden ticket. Etc :)
  37.  
  38.     If a specific account isn't supplied then this script will search AD for regular forms of delegation: full, constrained,
  39.     and resource based. It dumps the account names with relevant information (flags) and adds a comment field for special cases.
  40.     The output is a PSObject that you can use for further analysis.
  41.  
  42.     Note regarding Resource Based Delegation: the script dumps the target services, not the actual service doing the delegation.
  43.  
  44.     Main takeaway: chase all services with unconstrained delegation. If these are Not DC accounts, reconfigure them with constrained delegation.
  45.  
  46.     Properties
  47.     PrincipalsAllowedToRetrieveManagedPassword  - Group Managed Service Account setting. gMSA that can retrieve the managed password
  48.     PrincipalsAllowedToDelegateToAccount        - Resource Based Constrained Delegation, list of accounts that the account will allow delegation from
  49.     TrustedForDelegation                        - Unconstrained Delegation
  50.     TrustedToAuthForDelegation                  - Kerberos Constrained Delegation with Protocol Transition, allows any authentication service to delegate
  51.     msDSAllowedToDelegateTo                     - list of SPNs the account is allowed to delegate to
  52.  
  53.     .LINK
  54.     UserAccountControl flags to manipulate user account properties
  55.     https://learn.microsoft.com/en-GB/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties
  56.     https://learn.microsoft.com/en-us/windows-server/security/group-managed-service-accounts/configure-kerberos-delegation-group-managed-service-accounts
  57.     #>
  58.  
  59.     [CmdletBinding(DefaultParameterSetName='sam')]
  60.     param (
  61.         [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'sam', Position=0)]
  62.         [Alias('sam')]
  63.         [String[]]$SamAccountName,
  64.  
  65.         [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'dn', Position=0)]
  66.         [Alias('dn')]
  67.         [String[]]$DistinguishedName,
  68.  
  69.         [Switch]$ExcludeDomainControllers
  70.     )
  71.  
  72.     begin {
  73.         $properties = @(
  74.             'ServicePrincipalName'
  75.             'UserAccountControl'
  76.             'SamAccountName'
  77.             'msDS-AllowedToDelegateTo'
  78.             'msDS-AllowedToActOnBehalfOfOtherIdentity'
  79.         )
  80.  
  81.         $domain = (Get-ADDomain).DistinguishedName
  82.  
  83.         $SERVER_TRUST_ACCOUNT           = 0x2000
  84.         $TRUSTED_FOR_DELEGATION         = 0x80000
  85.         $TRUSTED_TO_AUTH_FOR_DELEGATION = 0x1000000
  86.         $PARTIAL_SECRETS_ACCOUNT        = 0x4000000
  87.         $bitmask                        = $TRUSTED_FOR_DELEGATION -bor $TRUSTED_TO_AUTH_FOR_DELEGATION -bor $PARTIAL_SECRETS_ACCOUNT
  88.  
  89.         # LDAP filter to find all accounts having some form of delegation.
  90.         # 1.2.840.113556.1.4.804 is an OR query.
  91. $filter = @"
  92. (&
  93.    (servicePrincipalName=*)
  94.    (|
  95.    (msDS-AllowedToActOnBehalfOfOtherIdentity=*)
  96.    (msDS-AllowedToDelegateTo=*)
  97.    (UserAccountControl:1.2.840.113556.1.4.804:=$bitmask)
  98.    )
  99.    (|
  100.    (objectcategory=computer)
  101.    (objectcategory=person)
  102.    (objectcategory=msDS-GroupManagedServiceAccount)
  103.    (objectcategory=msDS-ManagedServiceAccount)
  104.    )
  105. )
  106. "@ -replace "[\s\n]", ''
  107.     }
  108.  
  109.     process {
  110.         $object = if ($PSBoundParameters.ContainsKey('SamAccountName')) {
  111.             Write-Verbose 'BySamAccountName'
  112.             $samAccountName | foreach { Get-ADObject -Filter "SamAccountName -eq '$_'" -Properties $properties }
  113.         }
  114.         elseif ($PSBoundParameters.ContainsKey('distinguishedName')) {
  115.             Write-Verbose 'ByDistinguishedName'
  116.             $distinguishedName | foreach { Get-ADObject -Identity $dn -Properties $properties }
  117.         }
  118.         else {
  119.             Write-Verbose 'All'
  120.             Get-ADObject -LDAPFilter $filter -SearchBase $domain -SearchScope Subtree -Properties $properties
  121.         }
  122.  
  123.         $result = $object | ForEach-Object {
  124.             if ($_ -is [Microsoft.ActiveDirectory.Management.ADObject]) {
  125.                 $dn                                      = $_.DistinguishedName
  126.                 $isDomainController                      = ($_.UserAccountControl -band $SERVER_TRUST_ACCOUNT) -ne 0
  127.                 $isReadOnlyDC                            = ($_.UserAccountControl -band $PARTIAL_SECRETS_ACCOUNT) -ne 0
  128.                 $unconstrainedDelegation                 = ($_.UserAccountControl -band $TRUSTED_FOR_DELEGATION) -ne 0
  129.                 $constrainedDelegationProtocolTransition = ((($_.'msDS-AllowedToDelegateTo').count -gt 0) -and $adObject.TrustedToAuthForDelegation)
  130.                 $constrainedDelegation                   = ($_.'msDS-AllowedToDelegateTo').count -gt 0
  131.                 $msDSAllowedToDelegateTo                 = ($_.'msDS-AllowedToDelegateTo') -join ','
  132.                 $resourceDelegation                      = ($null -ne $_.'msDS-AllowedToActOnBehalfOfOtherIdentity')
  133.  
  134.                 switch ($_.ObjectClass) {
  135.                     'computer' {
  136.                         Write-Verbose 'computer'
  137.                         $adObject = Get-ADComputer -Filter "DistinguishedName -eq '$dn'" -Properties ServicePrincipalName, PrincipalsAllowedToDelegateToAccount, TrustedForDelegation, TrustedToAuthForDelegation, 'msDS-AllowedToActOnBehalfOfOtherIdentity'
  138.                         break
  139.                     }
  140.                     'user' {
  141.                         Write-Verbose 'user'
  142.                         $adObject = Get-ADUser -Filter "DistinguishedName -eq '$dn'" -Properties ServicePrincipalName, PrincipalsAllowedToDelegateToAccount, TrustedForDelegation, TrustedToAuthForDelegation, 'msDS-AllowedToActOnBehalfOfOtherIdentity'
  143.                         break
  144.                     }
  145.                     'msDS-ManagedServiceAccount' {
  146.                         Write-Verbose 'msDS-ManagedServiceAccount'
  147.                         $adObject = Get-ADServiceAccount -Filter "DistinguishedName -eq '$dn'" -Properties ServicePrincipalName, PrincipalsAllowedToDelegateToAccount, TrustedForDelegation, TrustedToAuthForDelegation, 'msDS-AllowedToActOnBehalfOfOtherIdentity'
  148.                         break
  149.                     }
  150.                     'msDS-GroupManagedServiceAccount' {
  151.                         Write-Verbose 'msDS-GroupManagedServiceAccount'
  152.                         $adObject = Get-ADServiceAccount -Filter "DistinguishedName -eq '$dn'" -Properties ServicePrincipalName, PrincipalsAllowedToDelegateToAccount, TrustedForDelegation, TrustedToAuthForDelegation, 'msDS-AllowedToActOnBehalfOfOtherIdentity'
  153.                         break
  154.                     }
  155.                     Default {
  156.                         Write-Verbose 'Default'
  157.                         Write-Warning "Unknown Class type"
  158.                     }
  159.                 }
  160.  
  161.                 [PSCustomObject] @{
  162.                     SamAccountName                          = $adObject.SamAccountName
  163.                     Name                                    = $adObject.Name
  164.                     Enabled                                 = $adObject.Enabled
  165.                     objectClass                             = $adObject.ObjectClass
  166.                     UnconstrainedDelegation                 = $unconstrainedDelegation
  167.                     ConstrainedDelegation                   = $constrainedDelegation
  168.                     ConstrainedDelegationProtocolTransition = $constrainedDelegationProtocolTransition
  169.                     ResourceBasedConstrainedDelegation      = $resourceDelegation
  170.                     UserAccountControl                      = $_.UserAccountControl
  171.                     UserAccountControlHex                   = ('{0:x}' -f $_.UserAccountControl)
  172.                     UserAccountControlFlag                  = (Get-UserAccountControlFlag $_.UserAccountControl)
  173.                     TrustedForDelegation                    = $adObject.TrustedForDelegation
  174.                     TrustedToAuthForDelegation              = $adObject.TrustedToAuthForDelegation
  175.                     isDomainController                      = $isDomainController
  176.                     isReadOnlyDC                            = $isReadOnlyDC
  177.                     msDSAllowedToDelegateTo                 = $msDSAllowedToDelegateTo
  178.                     ServicePrincipalName                    = $adObject.ServicePrincipalName
  179.                     PrincipalsAllowedToDelegateToAccount    = $($adObject.principalsAllowedToDelegateToAccount -join '; ')
  180.                     # msDSAllowedToActOnBehalfOfOtherIdentity = $($adObject.'msDS-AllowedToActOnBehalfOfOtherIdentity'.Access)
  181.                     # Comment                                 = $($comment -join '; ')
  182.                 }
  183.             }
  184.             else {
  185.                 Write-Warning "AD Object not found. If the account is a computer or MSA account then ensure it includes the '$'"
  186.             }
  187.         }
  188.     }
  189.  
  190.     end {
  191.         if ($ExcludeDomainControllers) {
  192.             $result | Where-Object isDomainController -eq $false
  193.         }
  194.         else {
  195.             $result
  196.         }
  197.     }
  198. }
  199.  
Tags: powershell
Advertisement
Add Comment
Please, Sign In to add comment