# Pentesting LDAP

### 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`

```
--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

```
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

```
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

```
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

```
ldapsearch -H ldap://10.10.10.161 -x -b "DC=htb,DC=local"
```

* Recommend directing this output to a file so you can grep

```
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

```
--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

```
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

```
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`

```
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:

```
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:

```
sebastien
lucinda
andy
mark
santi
```

### ldapsearch with creds

```
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

<pre><code><strong>#no TLS 
</strong><strong>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
</strong><strong>#TLS
</strong>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
</code></pre>

* kerberostable accounts

```
#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
```

* ASREP Roastable accounts

```
#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

```
#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\*

<pre><code>#no TLS
ldapsearch -D "cn=epugh_adm,dc=rastalabs,dc=local" -w password123 -H ldap://10.10.120.1 -b "(objectClass=*)" > Output.ldif
#TLS
<strong>ldapsearch -ZZ -D "cn=epugh_adm,dc=rastalabs,dc=local" -w password123 -p 636 -H ldap://10.10.120.1 -b "(objectClass=*)" > Output.ldif
</strong></code></pre>

* See the size of the domain

```
#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
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.ice-wzl.xyz/recon-enumeration/pentesting-ldap.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
