ldapsearch Overview
LDAP is extremely hard for blue teams/IR to investigate as it is a critical function of AD
Log event ID 4648 will be generated from LDAP enumeration, which does not occur in normal AD LDAP traffic
It defaults to plain text authentication, so use TLS if you dont want to send creds in the clear
-ZZ forces the use of TLS
If you use -ZZ and port 636 is not open you will recieve an error message LDAP server is unavailable
Add TLS_REQCERT ALLOW
to /etc/ldap/ldap.conf
to disable certificate validation if you plan on using TLS LDAP
To use SSL with LDAP use -H option with ldaps://DC.domain.local
If SSL is not set up on the DC you will recieve the error Cant contact LDAP server
Copy --help--
-D --> DN (username to bind with)
-w --> password
-p --> port (depricated option)
-b --> base location to begin your search
-s --> scope, defaults to subtree
-h --> name to append to ldap://
-H --> LDAP server with port specified (ldap://server.org:389)
-P --> protocol (2|3) default is 3
-Z --> start with TLS failover if unavailable
-ZZ --> force the use of TLS
-L --> restrict stdout to LDIFUL, -LL also disable comments
-LLL --> same as above + disable LDIF verion print if you want to export to LDAPAdmin.exe
-E pr=1000/noprompt --> perform up to 1000 requests w/o user prompt to continue
To use this tool you need at least the domain for DC --> whoami /fqdn
/ other enumeration
ldapsearch Generated Logs
Copy 4776 credential validation event
4672 special logon (if utilizing admin creds)
4648 logon with credentials specified explicitly
4624/4634 login/logoff for queries
ldapsearch
ldapsearch is a great utility to solicit information from a domain controller.
Start with attempting to see the scope
Copy ldapsearch -H ldap://10.10.10.161 -x
#output
# extended LDIF
#
# LDAPv3
# base <> (default) with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# search result
search: 2
result: 32 No such object
text: 0000208D: NameErr: DSID-0310021B, problem 2001 (NO_OBJECT), data 0, best
match of:
''
# numResponses: 1
From there the next step is to get the DN
Copy ldapsearch -H ldap://10.10.10.161 -x -s base namingcontexts
#output
# extended LDIF
#
# LDAPv3
# base <> (default) with scope baseObject
# filter: (objectclass=*)
# requesting: namingcontexts
#
#
dn:
namingContexts: DC=htb,DC=local
namingContexts: CN=Configuration,DC=htb,DC=local
namingContexts: CN=Schema,CN=Configuration,DC=htb,DC=local
namingContexts: DC=DomainDnsZones,DC=htb,DC=local
namingContexts: DC=ForestDnsZones,DC=htb,DC=local
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
Note: The DN in the above query is DC=htb,DC=local
, which you will need later
For this DN it is essentially the name of the domain you are targeting, in this example the target domain was htb.local
.
At this point take your new found DN and use this query
Copy ldapsearch -H ldap://10.10.10.161 -x -b "DC=htb,DC=local"
Recommend directing this output to a file so you can grep
Copy ldapsearch -H ldap://10.10.10.161 -x -b "DC=htb,DC=local" > ldap.out
This command will produce a ton of output as it is all the ldap information that you can query
Copy --snip--
name: Security Administrator
objectGUID:: klxj80zg9EmTbS/Pjp/57w==
objectSid:: AQUAAAAAAAUVAAAALB4ltxV1shXFsPNPXQQAAA==
sAMAccountName: Security Administrator
sAMAccountType: 268435456
managedBy: CN=Organization Management,OU=Microsoft Exchange Security Groups,DC
=htb,DC=local
groupType: -2147483640
objectCategory: CN=Group,CN=Schema,CN=Configuration,DC=htb,DC=local
dSCorePropagationData: 20220922021046.0Z
dSCorePropagationData: 20220922021046.0Z
dSCorePropagationData: 20220922021046.0Z
dSCorePropagationData: 20220922021045.0Z
dSCorePropagationData: 16010101000000.0Z
msExchVersion: 44220983382016
msExchGroupJoinRestriction: 0
msExchProvisioningFlags: 0
msExchMailboxAuditEnable: FALSE
msExchUserBL: CN=Security Admin-Security Administrator,CN=Role Assignments,CN=
RBAC,CN=First Organization,CN=Microsoft Exchange,CN=Services,CN=Configuration
,DC=htb,DC=local
--snip--
With your output in a text file, use these grep commands
Copy cat ldap.out| grep -i samaccountname
--snip--
sAMAccountName: test
sAMAccountName: sebastien
sAMAccountName: santi
sAMAccountName: lucinda
sAMAccountName: andy
sAMAccountName: mark
--snip--
cat ldap.out| grep -i samaccountname | awk '{print $2}'
#use this to just get the usernames to make your user.txt list
cat ldap.out| grep -i memberof
--snip--
memberOf: CN=Guests,CN=Builtin,DC=htb,DC=local
memberOf: CN=System Managed Accounts Group,CN=Builtin,DC=htb,DC=local
memberOf: CN=Denied RODC Password Replication Group,CN=Users,DC=htb,DC=local
memberOf: CN=Users,CN=Builtin,DC=htb,DC=local
memberOf: CN=Guests,CN=Builtin,DC=htb,DC=local
--snip--
Building an LDAP Query
once we have the above information we can run this ldap query to get all the the object class of person
Copy ldapsearch -H ldap://10.10.10.161 -x -b "DC=htb,DC=local" '(objectClass=Person)'
--snip--
name: Santi Rodriguez
objectGUID:: VSlmUT29FkGHUAJ12EnggA==
userAccountControl: 66048
badPwdCount: 367
codePage: 0
countryCode: 0
badPasswordTime: 133082459752791259
lastLogoff: 0
lastLogon: 0
pwdLastSet: 132134941751348277
primaryGroupID: 513
--snip--
For a more specific query where you just want the usernames you can use this query which is an alt method to our above command that utilized awk
Copy ldapsearch -H ldap://10.10.10.161 -x -b "DC=htb,DC=local" '(objectClass=Person)' sAMAccountName
ldapsearch -H ldap://10.10.10.161 -x -b "DC=htb,DC=local" '(objectClass=User)' sAMAccountName sAMAccountType
ldapsearch -H ldap://10.10.10.161 -x -b "DC=htb,DC=local" '(objectClass=Person)' sAMAccountName | grep sAMAccountName
Note if you see the above commands return something like this:
Copy requesting:
Guest
DefaultAccount
FOREST$
EXCH01$
$331000-VK4ADACQNUCA
SM_2c8eef0a09b545acb
SM_ca8c2ed5bdab4dc9b
SM_75a538d3025e4db9a
SM_681f53d4942840e18
SM_1b41c9286325456bb
SM_9b69f1b9d2cc45549
SM_7c96b981967141ebb
SM_c75ee099d0a64c91b
SM_1ffab36a2f5f479cb
HealthMailboxc3d7722
HealthMailboxfc9daad
HealthMailboxc0a90c9
HealthMailbox670628e
HealthMailbox968e74d
HealthMailbox6ded678
HealthMailbox83d6781
HealthMailboxfd87238
HealthMailboxb01ac64
HealthMailbox7108a4e
HealthMailbox0659cc1
sebastien
lucinda
andy
mark
santi
Most of those accounts are either machine accounts (those that end in $) or exchange accounts that do not allow login or user interaction.
For the above example the only account we would be interested in are:
Copy sebastien
lucinda
andy
mark
santi
ldapsearch with creds
Copy ldapsearch -LLL -h 127.0.0.1 -b "dc=rastalabs,dc=local" -x -D "RLAB\ngodfrey_adm" -w "PASSWORD" '(ms-Mcs-AdmPwdExpirationtime=*)' ms-Mcs-AdmPwd
Other Common Queries
Query all users collecting login infomation
Copy #no TLS
ldapsearch -D "cn=epugh_adm,dc=rastalabs,dc=local" -w password123 -h 10.10.120.1 -b "dc=rastalabs,dc=local" -S logoncount "samAccountType=805306368" displayname, lastlogon, logoncount, memberof
#TLS
ldapsearch -ZZ -D "cn=epugh_adm,dc=rastalabs,dc=local" -w password123 -p 636 -h 10.10.120.1 -b "dc=rastalabs,dc=local" -S logoncount "samAccountType=805306368" displayname, lastlogon, logoncount, memberof
Copy #no TLS
ldapsearch -D "cn=epugh_adm,dc=rastalabs,dc=local" -w password123 -h 10.10.120.1 -b "dc=rastalabs,dc=local" "samAccountType=805306368" servicePrincipalName admincount
#TLS
ldapsearch -ZZ -D "cn=epugh_adm,dc=rastalabs,dc=local" -w password123 -p 636 -h 10.10.120.1 -b "dc=rastalabs,dc=local" "samAccountType=805306368" servicePrincipalName admincount
Copy #no TLS
ldapsearch -D "cn=epugh_adm,dc=rastalabs,dc=local" -w password123 -h 10.10.120.1 -b "(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=4194304))" displayName lastlogon badpasswordtime
#TLS
ldapsearch -ZZ -D "cn=epugh_adm,dc=rastalabs,dc=local" -w password123 -p 636 -h 10.10.120.1 -b "(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=4194304))" displayName lastlogon badpasswordtime
Pull all DCs in domain in addition to their Operating System
Copy #no TLS
ldapsearch -D "cn=epugh_adm,dc=rastalabs,dc=local" -w password123 -H ldap://10.10.120.1 -b "(&(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))" operatingSystem
#TLS
ldapsearch -ZZ -D "cn=epugh_adm,dc=rastalabs,dc=local" -w password123 -p 636 -H ldap://10.10.120.1 -b "(&(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))" operatingSystem
Dump all of AD *This is alot of output*
Copy #no TLS
ldapsearch -D "cn=epugh_adm,dc=rastalabs,dc=local" -w password123 -H ldap://10.10.120.1 -b "(objectClass=*)" > Output.ldif
#TLS
ldapsearch -ZZ -D "cn=epugh_adm,dc=rastalabs,dc=local" -w password123 -p 636 -H ldap://10.10.120.1 -b "(objectClass=*)" > Output.ldif
See the size of the domain
Copy #no TLS
ldapsearch -LLL -h 10.10.120.1 -D "CN=epugh,OU=ServiceAccounts,DC=rastalabs,DC=local" -w password123 -E pr=1000/noprompt -b "dc=rastalabs,dc=local" -s sub '(objectClass=*)' distinguishedName > AD_Size.ldif
#TLS
ldapsearch -ZZ -LLL -h 10.10.120.1 -p 636 -D "CN=epugh,OU=ServiceAccounts,DC=rastalabs,DC=local" -w password123 -E pr=1000/noprompt -b "dc=rastalabs,dc=local" -s sub '(objectClass=*)' distinguishedName > AD_Size.ldif