コンテンツにスキップ

LDAP と AD セキュリティ記述子

技術目次へ戻る

LDAP は AD オブジェクトの検索や属性変更に使われます。Impacket では用途に よって 2 つのクライアント を使い分けます。コードを追うときは、まず 対象コマンドがどちらを呼ぶか確認してください。属性変更の意味や LDIF の例は LDAP の変更操作にまとめています。

実装使うコマンド向いている操作
impacket.ldap.LDAPConnectionGetADUsers、GetUserSPNs、GetNPUsers、GetLAPSPassword、findDelegation などbind、search、簡単な modify
ldap3 (init_ldap_session)dacledit、owneredit、rbcd、badsuccessor、addcomputer の LDAPS 経路SD control 付きの変更、複雑な modify

ASN.1 は ldapasn1.py (RFC 4511)。 AD の security descriptor は ldaptypes.py。 拡張権限 GUID は msada_guids.py。

impacket/acl.py は AD ではありません。 SMB ファイルの FileSecInformation と LSARPC による SID 解決です。 nTSecurityDescriptor を触るときは ldaptypes を使います。

LDAPConnection(url, baseDN='', dstIp=None, signing=True, timeout=None):

schemeポートsigning 既定TLS
ldap://389オン無し
ldaps://636オフ (チャネル自体が TLS)pyOpenSSL TLS_METHOD
gc://3268オフ無し (Global Catalog)

dstIp は接続先だけを上書きし、Kerberos SPN ldap/<url のホスト> は 名前側を使います。

LDAPS の channel binding は RFC 5929 tls-server-end-point: + ピア証明書の SHA-256 を構造体に載せ、その MD5 を channel_binding_value にします。 NTLM Type3 の AV_CHANNEL_BINDINGS と、Kerberos AP-REQ の CheckSumField.Bnd がこれを消費します。CBT 必須の DC では、これを付けないと bind が失敗します。 検査コマンドは CheckLDAPStatus。

login(..., authenticationChoice='sasl'):

choice中身
simpleuser@domain または DOMAIN\user + password
sicilyNegotiateSicily NTLM (Type1 in negotiate、Type3 in response)
sasl (既定)GSS-SPNEGO + NTLMv2。Type3 に MIC を付ける。signing 時は SPNEGOCipher

kerberosLogin():

  1. CCache.parseFile で ldap/<host> を探す
  2. 無ければ getKerberosTGT → getKerberosTGS
  3. SPNEGO + AP-REQ。checksum 0x8003。signing なら CONF|INTEG、 LDAPS なら Bnd に CBT
  4. BindRequest SASL GSS-SPNEGO

signing 有効後の send() は 4 byte 長 + wrap です。Kerberos は GSS_Wrap_LDAP、NTLM は SPNEGOCipher.encrypt。recv_raw() が復号します。

ldap3 経路 (impacket.examples.utils.init_ldap_session) は NTLM/Kerberos を ldap3 の SASL に渡し、modify 時の security_descriptor_control を使います。dacledit 系はこちらです。

LDAPConnection.search の既定は wholeSubtree、neverDerefAliases。 フィルタは RFC 4515 (& | !、=、>=、<=、:=、*、\XX)。

ページングは control OID 1.2.840.113556.1.4.319 (SimplePagedResultsControl、既定 size 1000)。サーバ cookie を空になるまで 回します。大きいドメインで -stealth のようにフィルタを外すと、 ページング無しでは切り詰められます。

modify 操作定数: ADD=0、DELETE=1、REPLACE=2、INCREMENT=3。 SD を触るときは control OID 1.2.840.113556.1.4.801 (SDFlagsControl)。 flag: OWNER=1、GROUP=2、DACL=4、SACL=8。dacledit の read は DACL のみ (0x04) が多いです。

[MS-DTYP] 2.4.6 の self-relative SD です。

SR_SECURITY_DESCRIPTOR
Revision, Control
OffsetOwner / OffsetGroup / OffsetSacl / OffsetDacl
OwnerSid, GroupSid, Sacl, Dacl
ACL
AceCount + ACE[]
ACE
AceType, AceFlags, AceSize + body

よく使う ACE:

AceTypeクラス用途
0x00ACCESS_ALLOWED_ACE通常許可。RBCD の SID 列挙もこれ
0x01ACCESS_DENIED_ACE拒否
0x05ACCESS_ALLOWED_OBJECT_ACEobject GUID 付き。DCSync / ResetPassword
0x06ACCESS_DENIED_OBJECT_ACEobject 拒否

object ACE は ACE_OBJECT_TYPE_PRESENT / INHERITED_OBJECT_TYPE_PRESENT と GUID の組み合わせが意味を持ちます。SID が同じだから消してよい、ではありません。

代表的な mask:

名前値意味
WRITE_DACL0x40000DACL 変更
WRITE_OWNER0x80000owner 変更
READ_CONTROL0x20000SD 読み取り
ADS_RIGHT_DS_CONTROL_ACCESS0x100拡張権限
WRITE_PROP0x20属性書き込み
CREATE_CHILD / DELETE_CHILD0x1 / 0x2子オブジェクト

msada_guids.EXTENDED_RIGHTS の例:

  • 00299570-246d-11d0-a768-00aa006e0529 — User-Force-Change-Password
  • 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 — DS-Replication-Get-Changes
  • 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2 — Get-Changes-All (DCSync の片側)
  • ab721a53-1e2f-11d0-9819-00aa0040529b — User-Change-Password

RECALC_ACE_SIZE (既定 True) は再シリアライズ時に ACE サイズを計算し直します。 AD が持っていたパディングとずれることがあるので、backup/restore は 元の binary blob を保持します (dacledit の JSON backup)。

操作属性 / 対象コマンド
DACL 編集nTSecurityDescriptordacledit
owner 変更SD Ownerowneredit
RBCDmsDS-AllowedToActOnBehalfOfOtherIdentity (中身は SD)rbcd
委任列挙UAC、msDS-AllowedToDelegateTo などfindDelegation
LAPSms-Mcs-AdmPwd / Windows LAPS + GKDIGetLAPSPassword
dMSAdelegated MSA 属性badsuccessor

RBCD の値は SID 配列ではなく self-relative SD です。create_allow_ace の mask は 983551 (フルコントロール相当)。flush は属性全体を空にし、 remove は指定 SID の ACE だけを除きます。

  • LDAPConnection と ldap3 のどちらを直すかを先に決める
  • SD control 無しで nTSecurityDescriptor を読むと欠ける
  • ACE 順序、未知 ACE、inheritance flag を round-trip で失わない
  • 関連テスト: tests/SMB_RPC/test_ldap.py