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