この記事はLDAPというディレクトリーサービスにアクセスするためのプロトコルについて説明します。また、Hack The BoxのReturnというマシンを使ってBindRequestの通信を見て見たいと思います。
LDAPとは?
LDAP(Lightweight Directory Access Protocol)は、ディレクトリサービスにアクセスするためのプロトコルです。ディレクトリサービスは、ネットワーク上のユーザー、デバイス、リソース(プリンター、サーバーなど)を効率的に管理するためのデータベースのようなもので、階層構造(ツリー構造)を持ちます。
LDAPは、TCP/IP上で動作し、デフォルトでは次のポートを使用します。
- 389/tcp(プレーンなLDAP通信)
- 636/tcp(LDAPS、TLS/SSLを使用した暗号化通信)
Active Directory(AD)などのディレクトリサービスでもLDAPが使われます。
仕様書
LDAP(Lightweight Directory Access Protocol)の仕様は、IETF(Internet Engineering Task Force)によって定義されており、主に RFC(Request for Comments) 文書に記載されています。以下が主な仕様です。
理解を深めるのに重要なRFC 4511(プロトコル仕様) や RFC 4513(認証・セキュリティ) のURLをリンクしておきます。
LDAPの主要な仕様(RFC)
- LDAPv3 の基本仕様(最新版)
- RFC 4510 – LDAPv3 の概要
- RFC 4511 – LDAP のプロトコル仕様(通信の仕組み)
- RFC 4512 – LDAP のデータモデル(スキーマの定義)
- RFC 4513 – LDAP の認証とセキュリティ(SASL や TLS の使用)
- RFC 4514 – DN(Distinguished Name)の書式
- RFC 4515 – LDAP の検索フィルターの構文
- RFC 4516 – LDAP の URL(ldap:// のフォーマット)
- LDAPv2(旧仕様・非推奨)
- RFC 1777 – 旧 LDAPv2 の仕様(現在は LDAPv3 に移行)
メッセージの種類
以下はRFC4511で定義されているLDAPのメッセージの種類です。
この後認証部分について深堀したいと思います。
メッセージ種類 | 説明 | リクエスト | レスポンス |
---|
認証(Bind) | クライアントがサーバーに認証を要求 | BindRequest | BindResponse |
検索(Search) | ディレクトリ内の情報を検索 | SearchRequest | SearchResultEntry / SearchResultDone |
追加(Add) | 新しいエントリをディレクトリに追加 | AddRequest | AddResponse |
変更(Modify) | 既存のエントリの属性を変更 | ModifyRequest | ModifyResponse |
削除(Delete) | 既存のエントリを削除 | DeleteRequest | DeleteResponse |
接続終了(Unbind) | サーバーとの接続を終了 | UnbindRequest | (レスポンスなし) |
拡張操作(Extended) | LDAPの標準操作にない特殊な処理(例: パスワード変更) | ExtendedRequest | ExtendedResponse |
Bind Requestについて
BindRequest は、LDAP クライアントがディレクトリサーバーに対して認証を試みる際に使用するメッセージです。
2つの認証方式
シンプル認証(Simple Authentication)
authentication
フィールドに プレーンテキストのパスワード が含まれる。LDAP://
で通信すると 暗号化されずにパスワードが送信 されるため危険。LDAPS://
やSTARTTLS
を使用して暗号化するのが推奨。
SASL 認証
- Kerberos や NTLM などの安全な認証方式を使用可能。
authentication
フィールドが[3] SaslCredentials
になり、SASL プロトコルで処理される。
RFC 4511 による定義
RFC 4511 では、BindRequest は以下のように定義されています。
BindRequest ::= [APPLICATION 0] SEQUENCE {
version INTEGER (1 .. 127),
name LDAPDN,
authentication CHOICE {
simple [0] OCTET STRING,
sasl [3] SaslCredentials
}
}
※EXPLICIT TAG[0] ⇒ バイナリでは[80]となります(下の通信データ例参照)
※EXPLICIT TAG[3] ⇒ バイナリでは[A3]となります
各フィールドの詳細
フィールド名 | 型 | 説明 |
---|---|---|
version | INTEGER (1..127) | LDAP のバージョン。一般的には 3 が使われる。 |
name | LDAPDN | バインドするユーザーの識別名(DN: Distinguished Name)。 |
authentication | CHOICE | 認証方法を示す。 |
├─ simple | [0] OCTET STRING | プレーンテキストのパスワード(基本認証)。 |
├─ sasl | [3] SaslCredentials | SASL 認証(Kerberos, DIGEST-MD5 などの方式をサポート)。 |
Bind Request の例
それではHack The BoxのReturnというマシンとのLDAPの通信内容を見ていきます。
通信内容を見る前に前提の説明をさせていただきます。
- 10.10.11.108 = Return (クライアント)
- 10.10.16.2 = 私(疑似サーバ)
- ReturnはAD(ActiveDirectory)配下のプリンター
- Returnの管理画面からADの接続先を私に変更している(Returnは私をADコントローラーだと思って接続しにきます)
- こちらではResponderというツールで擬似的に応答を返している
- 上記やりとりをWiresharkを使って監視
Wiresharkの通信状況
ポート389でフィルターすると、上から4つ目にBind Requestがあります。

3ハンドシェイクの流れ
BindRequestの上にある3つの通信は3ハンドシェイク(Three-Way Handshake)と言われるものです。3ハンドシェイクはTCP通信の接続を確立するために行われる3回のメッセージ交換のプロセスです。このプロセスによって、クライアントとサーバーが通信可能な状態になります。
- SYN(Synchronize)
- クライアントがサーバーに接続要求を送ります。この要求には、接続を開始するためのシーケンス番号(初期シーケンス番号)も含まれています。
- 例:クライアント →
SYN
(シーケンス番号X)
- SYN-ACK(Synchronize-Acknowledge)
- サーバーがクライアントの要求を受け入れ、接続の準備ができたことを示す応答を送ります。応答には、自分のシーケンス番号と、クライアントから受け取ったシーケンス番号+1を確認応答として含めます。
- 例:サーバー →
SYN-ACK
(シーケンス番号Y、確認応答番号X+1)
- ACK(Acknowledge)
- クライアントがサーバーからの応答を確認し、最終的な接続確認を送ります。このメッセージには、サーバーから受け取ったシーケンス番号+1を確認応答として含めます。
- 例:クライアント →
ACK
(確認応答番号Y+1)
この3つのメッセージ交換が完了することで、クライアントとサーバーは通信を開始できる状態になります。
3ハンドシェイクの目的
- 接続の確立: クライアントとサーバーはお互いに通信可能か確認し、シーケンス番号の同期を取ることで、データの送受信の順番を正確に管理します。
- 信頼性の確保: 3ハンドシェイクを通じて、両者が接続に合意したことを確認し、途中でデータが欠落しないようにします。
Bind Requestの通信データ
それでは今回の目的となるBindRequestの通信データを見てみたいと思います。
ただ、いきなり見ても、、、
通信データでは上で説明したBindRequest以外の部分も含まれているので、
わかりやすく順に説明していきます。
0000 45 00 00 54 53 3c 40 00 7f 06 78 e6 0a 0a 0b 6c E..TS<@...x....l
0010 0a 0a 10 02 c9 f9 01 85 bc ab 18 b2 7b c0 3c 09 ............{.<.
0020 50 18 04 00 23 87 00 00 30 2a 02 01 01 60 25 02 P...#...0*...`%.
0030 01 02 04 12 72 65 74 75 72 6e 5c 73 76 63 2d 70 ....return\svc-p
0040 72 69 6e 74 65 72 80 0c 31 65 64 46 67 34 33 30 rinter..1edFg430
0050 31 32 21 21 12!!
TCPヘッダー部分
最初の0x00 – 0x28は TCPヘッダ なので、LDAPメッセージは0x29 から始まります( 30 2a
)。
0000 45 00 00 54 53 3c 40 00 7f 06 78 e6 0a 0a 0b 6c # IP ヘッダ(省略)
0010 0a 0a 10 02 c9 f9 01 85 bc ab 18 b2 7b c0 3c 09 # TCP ヘッダ(省略)
0020 50 18 04 00 23 87 00 00 # TCP フラグメント終了
LDAP Message本体
まずは先頭7byteについて説明します。
上述の通りLDAPにはBindRequest以外にもメッセージの種類がありますが、先頭7byteではどのメッセージ種類かを知ることができます。
0020 50 18 04 00 23 87 00 00 30 2a 02 01 01 60 25
30 # [30] = SEQUENCE (LDAPMessage)
2a # [2a] = LDAPMessageの長さ 42 バイト
02 01 01 # messageID: INTEGER (1)
# [02] = INTEGER型(ASN.1 の識別子)
# [01] = 長さ(1バイト)
# [01] = 値(1)
60 # [60] = BindRequest
25 # [25] = BindRequestの長さ 37 バイト
※MessageIDは値としては1となりますが、ANS.1/BERの書式では上記のようになります
BER(Basic Encoding Rules)とは?
バイナリデータ に変換するルールです。
📌 BER の基本構造
[タグ (Type)] [長さ (Length)] [値 (Value)]
- タグ(Type) → データの型(INTEGER, SEQUENCE, OCTET STRINGなど)
- 長さ(Length) → データのバイト数
- 値(Value) → 実際のデータ
ASN.1(Abstract Syntax Notation One)のタグ番号とは?
ASN.1 のデータ型には 標準のタグ番号 が割り当てられています。
INTEGER のタグ番号は「2(0x02)」 です。
ASN.1 の基本的な型のタグ番号は以下のようになっています:
ASN.1 型 | タグ(16進数) | タグ(10進数) |
---|---|---|
BOOLEAN | 0x01 | 1 |
INTEGER | 0x02 | 2 |
BIT STRING | 0x03 | 3 |
OCTET STRING | 0x04 | 4 |
NULL | 0x05 | 5 |
OBJECT IDENTIFIER | 0x06 | 6 |
SEQUENCE | 0x30 | 48 |
Bind Request本体
ここからがBindRequestです。
冒頭のBind Requestの定義と見比べながら読んでください。
0020 50 18 04 00 23 87 00 00 30 2a 02 01 01 60 25 02 P...#...0*...`%.
0030 01 02 04 12 72 65 74 75 72 6e 5c 73 76 63 2d 70 ....return\svc-p
0040 72 69 6e 74 65 72 80 0c 31 65 64 46 67 34 33 30 rinter..1edFg430
0050 31 32 21 21 12!!
02 01 02 # バージョン: INTEGER (2)
# [02] = INTEGER型(ASN.1 の識別子)
# [01] = 長さ(1バイト)
# [02] = 値(2)
04 # [04] = 名前 (DN)
12 # [12] = 名前の長さ :OCTET STRING (18 バイト)
72 65 74 75 72 6e 5c 73 76 63 2d 70 72 69 6e 74 65 72
# "return\svc-printer"(LDAPのユーザ名)
80 # [80] = 認証パスワード(SIMPLE BIND)
0C # [0C] = 認証パスワードの長さ(12 バイト)
31 65 64 46 67 34 33 30 31 32 21 21 # "1edFg43012!!"(平文パスワード)
さいごに
今回はBind Requestの平文パスワードを取得する例を見ながらLDAPのさわり部分を見てみました。
興味を持った方はReturnというマシンのWriteupも合わせて読みながら是非HackTheBoxで手を動かしながら試してください。