# LDAP

O LDAP é um provedor ADSI (Active Directory Service Interfaces) - essencialmente uma API - que oferece suporte à funcionalidade de pesquisa em um Active Directory. Isso nos permite interagir com o Domain Controller e extrair informações não privilegiadas sobre os objetos no domínio.

O protótipo do caminho completo do provedor LDAP (que é necessário para realizar as consultas), segue a base do exemplo abaixo:

```
LDAP://HostName[:PortNumber][/DistinguishedName]
```

Para descobrirmos qual sabermos qual o caminho do nosso AD, basta executar os comandos abaixos no Powershell:

```powershell
$domainObj = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$PDC = ($domainObj.PdcRoleOwner).Name
$SearchString = "LDAP://"
$SearchString += $PDC + "/"
$DistinguishedName = "DC=$($domainObj.Name.Replace('.', ',DC='))"
$SearchString += $DistinguishedName
$SearchString
```

## Autenticação

O LDAP é configurado para autenticar credenciais no AD usando uma operação "BIND" para definir o estado de autenticação para uma sessão LDAP. Existem dois tipos de autenticação LDAP.

* `Simple Authentication` = Isso inclui autenticação anônima, autenticação não autenticada e autenticação de nome de usuário/senha. Autenticação simples significa que um nome de usuário e uma senha criam uma solicitação BIND para autenticação no servidor LDAP.
* `SASL Authentication` = A estrutura Simple Authentication and Security Layer (SASL) usa outros serviços de autenticação, como Kerberos, para vincular-se ao servidor LDAP e, em seguida, usa esse serviço de autenticação (Kerberos neste exemplo) para autenticar no LDAP. O servidor LDAP usa o protocolo LDAP para enviar uma mensagem LDAP ao serviço de autorização, que inicia uma série de mensagens de desafio/resposta resultando em autenticação bem-sucedida ou malsucedida. O SASL pode fornecer segurança adicional devido à separação dos métodos de autenticação dos protocolos de aplicação.

As mensagens de autenticação LDAP são enviadas em texto simples por padrão para que qualquer pessoa possa detectar mensagens LDAP na rede interna. Recomenda-se usar criptografia TLS (LDAPS - Porta 636) ou similar para proteger essas informações em trânsito.

## Enumeração

### LDP

Abra o `ldp`, vá na aba `Connection > connect` e digite o IP do servidor AD. A porta por padrão vem a `389` (LDAP), mas se quiser pode também utilizar a porta `3268` para pegar o Global Catalog do AD.\
Depois de estabelecer uma conexão, você pode conectar com alguma conta de usuário em `Connection > Bind`.

\
Agora que já tem uma sessão LDAP autenticada, vá na aba `View > Tree` e digite a `DN`. **Ex.:** Se o domínio for "alvo.com", digite: `dc=alvo,dc=com`. Observe que agora há uma "árvore" no lado esquedo com o nome da pesquisa que acabou de fazer. Vá na árvore e expanda em `CN=Users`, `CN=Builtin` e `CN=Computers` para ver todos os usuários, grupos do AD e Computadores.

**OBS.:** Talvez também seja possível realizar autenticação com o usuário Guest (Convidado).

### Python

Enumeração LDAP Anônimo

```bash
from ldap3 import *
s = Server('<ip>',get_info = ALL)
c =  Connection(s, '', '')
print(s.info)
```

### LDAPFilter (Windows)

Operadores

```bash
# AND
(& (..condition_1..) (..condition_2..))
(& (..condition_1..) (..condition_2..) (..condition_3..))

# OR
(| (..condition_1..) (..condition_2..))
(| (..condition_1..) (..condition_2..) (..condition_3..))

# AND e OR = Equivalente a (condition_1 AND condition_2) OR (condition_3 AND condition_4)
(|(& (..condition_1..) (..condition_2..))(& (..condition_3..) (..condition_4..)))
```

| CARACTERE | ESCAPE   |
| --------- | -------- |
| `"`       | `` `" `` |
| `'`       | `\'`     |
| `NUL`     | `\00`    |
| `\`       | `\5c`    |
| `*`       | `\2a`    |
| `(`       | `/28`    |
| `)`       | `/29`    |
| `/`       | `/2f`    |

Pegando informações sobre determinado usuários

```bash
Get-ADUser -LDAPFilter '(&(objectCategory=user)(name=<nome>))' -Properties *
```

Procurando por grupos do AD

```bash
Get-ADObject -LDAPFilter '(objectClass=group)'
```

Retorna todas as contas de usuário desabilitadas administrativamente ou `ACCOUNTDISABLE`

```bash
Get-ADObject -LDAPFilter '(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=2))'
Get-ADUser -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=2)' | select name
```

Procurando por todos os computadores do AD

```bash
# Listagem completa
Get-ADObject -LDAPFilter '(&(objectCategory=computer))'

# Somente a quantidade
Get-ADObject -LDAPFilter '(&(objectCategory=computer))' | Measure-Object | select count
```

Procurando por todos os grupos do AD

```bash
Get-ADObject -LDAPFilter '(&(objectCategory=group))'
```

Verificando quais grupos um determinado usuário é membro

```bash
Get-ADGroup -LDAPFilter '(member:1.2.840.113556.1.4.1941:=CN=<name>,OU=<ou>,DC=<domain>,DC=<local>)' | select name
```

Pegando todos os usuários que possui algum conteúdo no campo `Description`. Muitos administradores deixam senhas anotadas nesses campo

```bash
Get-ADUser -Properties * -LDAPFilter '(&(objectCategory=user)(description=*))' | select samaccountname,description
```

Localizando todos os usuários e computadores que são marcados `Trusted for Delegation` (confiáveis para delegação) ou delagação irrestrita

```bash
Get-ADUser -Properties * -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=524288)' | select Name,memberof, servicePrincipalName,TrustedForDelegation | fl
Get-ADComputer -Properties * -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=524288)' | select DistinguishedName,servicePrincipalName,TrustedForDelegation | fl
```

Procurando todos os usuários com o atributo `adminCount` definido como `1`, cujo atributo `useraccountcontrol` esteja definido com o sinalizador "PASSWD\_NOTREQD". Isso significa que a conta pode ter uma senha em branco

```bash
Get-AdUser -LDAPFilter '(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=32))(adminCount=1)' -Properties * | select name,memberof | fl
```

Vendo todos os grupos que um usuários pertence, incluindo grupos aninhados. Isso também pode ser útil para pesquisar em qual grupo, um determinado grupo está aninhado. O campo `DistinguishedName` irá mostrar o nome do grupo que ele está aninhado.

```bash
Get-ADGroup -Filter 'member -RecursiveMatch "CN=<user>,OU=<ou>,DC=<domain>,DC=<local>"' | select name
Get-ADGroup -LDAPFilter '(member:1.2.840.113556.1.4.1941:=CN=<user>,OU=<ou>,DC=<domain>,DC=<local>)' | select Name

# Pegando informações sobre qual o grupo, que determinado grupo está aninhado
Get-ADGroup -Filter 'member -RecursiveMatch "CN=<name>,OU=<ou>,DC=<domain>,DC=<local>"' | select name

# Pegando nome de grupos que estão aninhados a um determinado grupo
Get-ADGroup -Filter 'memberof -RecursiveMatch "CN=<name>,CN=<name>,DC=<domain>,DC=<local>"'

# Pegando o nome de um usuário que está em um determinado grupo, através de um anihamento
Get-ADUser -Filter 'memberof -RecursiveMatch "CN=<name>,CN=<name>,DC=<domain>,DC=<local>"'
```

Pegando todas as OUs

```bash
Get-ADOrganizationalUnit -Filter * | select name,DistinguishedName
```

UAC (User Account Control)

```bash
Get-DomainUser * -AdminCount | select samaccountname,useraccountcontrol
```

####

#### ADSI

Pegando path LDAP de objetos do AD

```bash
# Usuários
([adsisearcher]"(&(objectClass=User))").FindAll() | select Path

# Grupos
([adsisearcher]"(&(objectClass=Group))").FindAll() | select Path

# Computadores
([adsisearcher]"(&(objectClass=Computer))").FindAll() | select Path
```

###

### LDAPSearch (Linux)

Pegando o DC's

```bash
ldapsearch -H ldap://<ip>:389 -x
ldapsearch -H ldap://<ip>:389 -x -s base namingcontexts
```

Enumeração Geral

```bash
ldapsearch -LLL -x -H ldap://<domain.com> -b '' -s base '(objectclass=*)'
```

Enumerando todas as informações

```bash
ldapsearch -H ldap://<ip_dc>:389 -x -b "DC=<domain>,DC=<local>"
```

Enumeração LDAP Anônimo

```bash
ldapsearch -H ldap://<ip_dc>:389 -x -b "dc=<domain>,dc=<local>"
ldapsearch -x -H ldap://<ip_dc>:389 -s sub -b 'DC=<domain>,DC=<local>'
ldapsearch -x -H ldap://<ip_dc> -s sub -b 'DC=<domain>,DC=<local>'
```

Enumerando usuários

```bash
ldapsearch -H ldap://<ip_dc>:389 -x -b "DC=<domain>,DC=<local>" '(objectClass=User)' sAMAccountName | grep sAMAccountName
ldapsearch -x -H ldap://<ip_dc>:389 -b 'dc=<domain>,dc=<com>' "(&(objectClass=user))"
```

Enumerando pessoas

```bash
ldapsearch -H ldap://<ip_dc>:389 -x -b "DC=<domain>,DC=<local>" '(objectClass=Person)'
```

Enumerando sAMAccount

```bash
ldapsearch -H ldap://<ip_dc>:389 -x -b "DC=<domain>,DC=<local>" '(objectClass=Person)' sAMAccountName
```

Pegando todos os Domain Admins

```bash
ldapsearch -H ldap://<ip_dc>:389 -x -LLL -w <pass> -D '<CN=user,OU=users,DC=domain,DC=local>' -b "<dc=domain,dc=local>" '(memberOf=cn=Domain Admins,cn=Users,<dc=domain,dc=local>)' cn
```

ldapsearch -LLL -x -H ldap\://\<domain.com> -b '' -s base '(objectclass=\*)'

> **EXPLICAÇÃO**:
>
> **-LLL** = Retorna somente o necesśario\
> \&#xNAN;**-x** = Tenta realizar autenticação anônima (Simple Authentication)\
> \&#xNAN;**-b** = Utiliza a Base DN para pesquisa<br>

Caso possua a senha para realizar uma conexão do tipo `bind`, utilize o seguinte comando:

```
ldapsearch -H ldap://<ip> -x -D "cn=<admin>,dc=<domain>,dc=<com>" -W
```

Pesquisa pelo Search  Base (entrada dentro do DIT) e Scope, que pode retornar senhas em base64.

```
ldapsearch -H ldap://<ip> -x -D "cn=<admin>,dc=<domain>,dc=<com>" -w <password> -b "dc=<domain>,dc=<com>"
```

### WindapSearch

Windapsearch é um script Python usado para realizar a enumeração LDAP anônima e autenticada de usuários, grupos e computadores do AD usando consultas LDAP.

Enumeração LDAP Anônimo

```bash
python3 windapsearch.py --dc-ip <ip> -u "" --functionality
```

Pegando todos os usuários do AD

```bash
python3 windapsearch.py --dc-ip <ip> -d <domain.local> -u <domain>\\<user> -U --attrs '*'
python3 windapsearch.py --dc-ip <ip> -u "" -U
```

Pegando todos os usuários com Delegação Irrestrita

```bash
python3 windapsearch.py --dc-ip <ip> -d <domain.local> -u <domain>\\<user> --unconstrained-users
python3 windapsearch.py --dc-ip <ip> -u "" --unconstrained-users
```

Pegando todos os computadores do AD

```bash
python3 windapsearch.py --dc-ip <ip> -u "" -C
```

Enumerando Domain Admin

```bash
# Utilize somente o <domain>, não o "<domain.local>"
python3 windapsearch.py --dc-ip <ip> -u <domain>\\<user> --da
```

### LdapSearch-AD.py

```bash
python3 ldapsearch-ad.py -l <ip> -t info
```

Enumeração completa

```bash
python3 ldapsearch-ad.py -l <ip> -d <domain> -u <user> -p <pass> -t all
```

Enumerando usuários

```
python3 ldapsearch-ad.py -l <ip> -d <domain.local> -u <user> -p '<pass>' -t show-user -s '(samaccountname=*)'
```

Enumerando políticas de senha

```bash
python3 ldapsearch-ad.py -l <ip> -d <domain> -u <user> -p <pass> -t pass-pols
```

Possíveis usuários vulneráveis a Kerberoasting

```bash
python3 ldapsearch-ad.py -l <ip> -d <domain> -u <user> -p <pass> -t kerberoast | grep servicePrincipalName:
```

Usuários que podem estar vulneráveis a ASREPRoasted

```bash
python3 ldapsearch-ad.py -l <ip> -d <domain> -u <user> -p <pass> -t asreproast
```

### NMAP

Diferente do resultado do `ldapsearch`, o nmap já decodifica a senha base64.

```bash
nmap --script ldap-search --script-args 'ldap.username="cn=<admin>,dc=<domain>,dc=<local>",ldap.password="<password>"' <ip> -p 389
```

## Brute Force

ldap\_search

```bash
python3 ldap_search.py -u <user> -p <wordlist.txt> -d <domain.local> -s <dc.domain.local>
```

nmap

```bash
nmap -p 389 --script ldap-brute --script-args ldap.base='"cn=users,dc=<domain>,dc=<local>"' <host>
```

#### Sites

```bash
# LDAP queries relacionadas a computadores do AD
https://ldapwiki.com/wiki/Active%20Directory%20Computer%20Related%20LDAP%20Query

# LDAP queries relacionadas a usuários do AD
https://ldapwiki.com/wiki/Active%20Directory%20User%20Related%20Searches

# LDAP queries relacionadas a grupos do AD
https://ldapwiki.com/wiki/Active%20Directory%20Group%20Related%20Searches

# LdapSearch
https://linux.die.net/man/1/ldapsearch

# WindapSearch
https://github.com/ropnop/windapsearch

# LdapSearch-AD.py
https://github.com/yaap7/ldapsearch-ad
```


---

# 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://mysther.gitbook.io/knowledge-base/ataques/windows/active-directory/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.
