LDAP (Lightweight Directory Access Protocol) is a software protocol for enabling anyone to locate organizations, individuals, and other resources such as files and devices in a network, whether on the public Internet or on a corporate intranet. LDAP is a "lightweight" (smaller amount of code) version of Directory Access Protocol (DAP).
An LDAP directory is organized in a simple "tree" hierarchy consisting of the following levels:
The root directory (the starting place or the source of the tree), which branches out to
Countries, each of which branches out to
Organizations, which branch out to
Organizational units (divisions, departments, and so forth), which branches out to (includes an entry for)
Individuals (which includes people, files, and shared resources such as printers)
It run on port TCP 389 and 636(ldaps). The Global Catalog (LDAP in ActiveDirectory) is available by default on ports 3268, and 3269 for LDAPS.
Practice
A lot of information on an AD domain can be obtained through LDAP. Most of the information can only be obtained with an authenticated bind but metadata (naming contexts, DNS server name, Domain Functional Level (DFL)) can be obtainable anonymously, even with anonymous binding disabled.
UNIX-Like
The ldapsearch command is a shell-accessible interface to the ldap_search_ext(3) library call. It can be used to enumerate essential informations.
Anonymous Enumeration:
Enumerate the base domain.
#Simple bind authentification (-x) as anonymous.ldapsearch-Hldap://$IP -x-sbasenamingcontexts
Dump all readable ldap information as anonymous.
ldapsearch-Hldap://$IP -x-b"DC=contoso,DC=local"
Dump ldap information as anonymous and filter.
#With (objectClass=User) as the query and sAMAccountName the filter.ldapsearch-Hldap://$IP -x-b"DC=contoso,DC=local"'(objectClass=User)'sAMAccountName
Authenticated Enumeration:
Dump readable ldap informations with NTLM based authentication
#With (objectClass=User) as the query and sAMAccountName the filter.ldapsearch -H ldap://$IP -x -D "CN=MyUser,CN=Users,DC=contoso,DC=local" -w Password1 -b "DC=contoso,DC=local" '(objectClass=User)' sAMAccountName
ldapsearch -H ldap://$IP -x -D "MyUser@contoso.local" -w Password1 -b "DC=contoso,DC=local" '(objectClass=User)' sAMAccountName
Dump all readable ldap informations with Kerberos based authentication
We may use ldapsearch output (also known as LDIF files) and covert it into JSON files ingestible by BloodHound using ldif2bloodhound. See this page for more informations.
Powerview.py is an alternative for the original PowerView.ps1 script that allow us to perform Powerview commands directly from our attacking host using LDAP.
First we need to authenticate using similar commands
### Authenticate# Simplepowerview $DOMAIN/$USER:$PASSWORD@$TARGET_IP --dc-ip $DC_IP# Pass the ticketpowerview $DOMAIN/$USER@$TARGET_IP --dc-ip $DC_IP -k--no-pass# Pass the keypowerview $DOMAIN/$USER@$TARGET_IP --dc-ip $DC_IP --aes-key $AES_KEY# Pass the hashpowerview $DOMAIN/$USER@$TARGET_IP --dc-ip $DC_IP -H $NTLM_HASH### Protocols# Use LDAP (Port 389)powerview $DOMAIN/$USER:$PASSWORD@$TARGET_IP --dc-ip $DC_IP --ldap# Use LDAPS (Port 636)powerview $DOMAIN/$USER:$PASSWORD@$TARGET_IP --dc-ip $DC_IP --ldap# Use LDAP Global Catalog (Port 3268)powerview $DOMAIN/$USER:$PASSWORD@$TARGET_IP --dc-ip $DC_IP --ldap# Use LDAPS Global Catalog (Port 3269)powerview $DOMAIN/$USER:$PASSWORD@$TARGET_IP --dc-ip $DC_IP --ldap
Once connected, we should be able to use the powerview.py console. Here are a few examples.
# list PKIs/CAsnetexecldap"domain_controller"-d"domain"-u"user"-p"password"-Madcs# list subnets referenced in AD-SSnetexecldap"domain_controller"-d"domain"-u"user"-p"password"-Msubnets# machine account quotanetexecldap"domain_controller"-d"domain"-u"user"-p"password"-Mmaq# users descriptionnetexecldap"domain_controller"-d"domain"-u"user"-p"password"-Mget-desc-users
The PowerShell equivalent to NetExec's subnets modules is the following
The ldapsearch-ad Python script can also be used to enumerate essential information like domain admins that have their password set to never expire, default password policies and the ones found in GPOs, trusts, kerberoastable accounts, and so on.
The FFL (Forest Functional Level), DFL (Domain Functional Level), DCFL (Domain Controller Functionality Level) and naming contexts can be listed with the following command.
With Impacket's ntlmrelayx (Python), it is possible to gather lots of information regarding the domain users and groups, the computers, ADCS, etc. through a NTLM authentication relayed within an LDAP session.
Using PowerShell and .NET classes, we can enumerate the domain using LDAP. This can be very handy if we have compromised a computer in the domain with no administrative access and no RSAT module installed.
To acheive this, we can use the following function.
Then, we can use it as in following examples, by specifing our filter.
# Dump all objectsLDAPSearch -LDAPQuery '(objectClass=*)'# Enum Users## Filter on UsersLDAPSearch -LDAPQuery "(objectClass=User)"## Print some properties for each users$res = foreach ($obj in $(LDAPSearch -LDAPQuery "objectClass=User")) {$obj.properties | select {$_.name}, {$_.memberof}}
$res|fl# Enum Groups##ย Filter on GroupsLDAPSearch -LDAPQuery "(objectClass=Group)"## Print some properties for each groups$res =foreach ($obj in$(LDAPSearch -LDAPQuery "objectClass=Group")) {$obj.properties | select {$_.cn}, {$_.member}}$res|fl## Query for specific group and print a property$res = LDAPSearch -LDAPQuery "(&(objectCategory=group)(cn=Domain Admins))"$res.properties.member
Some PowerView functions use LDAP to retreive information.
Fore more powerview commands and enumeration, refer to this page.
LDAP anonymous binding is usually disabled but it's worth checking. It could be handy to list the users and test for ASREProasting (since this attack needs no authentication).
Automation and scripting
A more advanced LDAP enumeration can be carried out with BloodHound (see this).
The enum4linux tool can also be used, among other things, for LDAP recon (see this).