目录

​查询Active Directory​

​BaseDN​

​过滤规则​

​LDAP高级搜索语法​

​LDAP 查找中的位操作​

​LDAP 查找中的objectCategory和objectClass​


查询Active Directory

通过查询目录,可以直接收集到要求的数据。查询目录需要指定两个要素


  • BaseDN
  • 过滤规则

BaseDN

BaseDN指定了这棵树的根。比如指定BaseDN为​​DC=xie,DC=com​​​就是以​​DC=xie.DC=com​​为根往下搜索

查询Active Directory_sed

BaseDN为​​CN=Users,DC=xie.DC=com​​​就是以CN=Users,​​DC=xie.DC=com​​为根往下搜索

查询Active Directory_搜索_02

过滤规则

LDAP 过滤规则相对简单,很方便入手

LDAP 搜索过滤器语法有以下子集:


  • 用与号 (&) 表示的 AND 运算符。
  • 用竖线 (|) 表示的 OR 运算符。
  • 用感叹号 (!) 表示的 NOT 运算符。
  • 用名称和值表达式的等号 (=) 表示的相等比较。
  • 用名称和值表达式中值的开头或结尾处的星号 (*) 表示的通配符。

下面举几个例子:


  • (uid=testuser):匹配 uid 属性为testuser的所有对象
  • (uid=test*):匹配 uid 属性以test开头的所有对象
  • (!(uid=test*)):匹配 uid 属性不以test开头的所有对象
  • (&(department=1234)(city=Paris)):匹配 department 属性为1234且city属性为Paris的所有对象
  • (|(department=1234)(department=56*)):匹配 department 属性的值为1234或者以56开头的所有对象。

一个需要注意的点就是运算符是放在前面的,跟我们之前常规思维的放在中间不一样。

关于查询目录还有一些高级点的用法,比如 LDAP 控件,位掩码等。

LDAP高级搜索语法

LDAP 查找中的位操作

在LDAP 里面,有些字段是位字段,这里以userAccountControl举例,关于这个字段的详细意义,后面会详细介绍,这里先把他当做一个普通的位字段,不去考虑他的具体含义,这里先看下他的内容。

他的属性类位于架构分区的 ​​CN=User-Account-Control,CN=Schema,CN=Configuration,DC=xie,DC=com​

​attributeSyntax​​​是​​2.5.5.9,​​​​oMSyntax​​​是​​2​​。

查询Active Directory_搜索_03

查表可知是32位的Integer类型。

查询Active Directory_sed_04

之所以我们说他是位字段,是因为他是由一个个位构成。

查询Active Directory_字段_05

比如说一个账户,他只有LOCKOUT和NOT_DELEGATED有值,其他位都没有。那这个用户的属性​​userAccountControl​​的值就为0x0010+0x100000。是个32 位 int 类型。

现在如果我要搜索域内userAccountControl属性的值为NOT_DELEGATED的所有对象。那么用之前简单的LDAP语法就显得力不从心。简单的LDAP搜索语法只能对某个属性进行过滤,还不能对属性里面的某个具体位进行过滤。所以这也是我们这一节要讲的内容。LDAP的语法支持按位搜索。

执行过滤器以搜索位字段,必须遵循以下语法:

<属性名称>:<BitFilterRule-ID>:= <十进制比较值>

其中的​​<BitFilterRule-ID>​​,内容如下。

查询Active Directory_字段_06

我们最常的是LDAP_MATCHING_RULE_BIT_AND ,也就是​​1.2.840.113556.1.4.803​

我们举几个例子。

我们想查询哪些对象设置了 ​​TRUSTED_FOR_DELEGATION ​

查询Active Directory_sed_07

​TRUSTED_FOR_DELEGATION​​对应的十进制比较值为524288

根据语法,我们就可以构造以下过滤规则

(userAccountControl:1.2.840.113556.1.4.803:=524288)

adfind的查询命令如下

adfind.exe -b dc=xie,dc=com -f "(userAccountControl:1.2.840.113556.1.4.803:=524288)" -bit -dn

查询Active Directory_字段_08

但是使用这种语法我们还得去记BitFilterRule,于是adfind提供了一个更为快捷的方式。

查询Active Directory_sed_09

adfind.exe -b dc=xie,dc=com -f "(userAccountControl:AND:=524288)" -bit -dn

查询Active Directory_字段_10

LDAP 查找中的objectCategory和objectClass

(1) objectClass

在前面一节里面说过,在对象的​​objectClass​​​ 属性里面,可以看到这个对象是哪个类的实例,以及这个类的所有父类,比如说​​CN=test,CN=Users,DC=xie,DC=com​​​的​​objectClass​​​是​​top,person,organizationalPerson,user​​​。那我们通过过滤语句​​(objectClass=user)​​​,​​(objectClass=organizationalPerson)​​都能找到这个对象。

查询Active Directory_sed_11

所有的类都是​​top​​​类的子类。因此当我们过滤​​(objectClass=top)​​可以找到域内的所有对象。

adfind.exe -b dc=xie,dc=com -s subtree -bit -f "(objectclass=*)" -c 
adfind.exe -b dc=xie,dc=com -s subtree -bit -f "(objectclass=top)" -c

查询Active Directory_字段_12

(2) objectCategory

在Windows Server 2008之前默认不对objectClass属性进行索引。最初认为对多值属性(如objectClass)进行索引会导致性能下降。如此一来,Windows 2000 附带了未索引的objectClass 属性和另一个已建立索引的单值属性,称为objectCategory。

接下来介绍下​​objectCategory​​这个属性。对象类的每个实例还具有一个objectCategory属性,该属性是一个单值属性。并且建立了索引。其中包含对象是其实例的类或其父类之一的专有名称。

比如说​​CN=hack,CN=Users,DC=xie,DC=com ​​​他的​​objectCategory​​​是 ​​CN=Person,CN=Schema,CN=Configuration,DC=xie,DC=com​

查询Active Directory_sed_13

创建对象时,系统会将其objectCategory属性设置为由其对象类的​​defaultObjectCategory​​属性指定的值,无法更改对象的objectCategory属性。

查询Active Directory_字段_14

如果我们想过滤所有objectCategory的属性为​​CN=Person,CN=Schema,CN=Configuration,DC=xie,DC=com​​的对象,这个很简单。

(objectCategory="CN=Person,CN=Schema,CN=Configuration,DC=test,DC=local")

adfind查询语法如下

adfind.exe -b dc=xie,dc=com -s subtree -bit -f "(objectCategory="CN=Person,CN=Schema,CN=Configuration,DC=xie,DC=com")" -dn

查询Active Directory_sed_15

但是这样,又有点不方便,需要记住记住类的DN,所以LDAP在实现上实现了个小技巧。对象类有个属性​​lDAPDisplayName​​​,指定他的显示名。事实上,我们看​​objectClass​​​属性里面的类以及父类(比如top.person),他的名字都是这个类的​​lDAPDisplayName。​

​CN=Person,CN=Schema,CN=Configuration,DC=xie,DC=com​​​的​​lDAPDisplayName ​​​是 ​​person。​

查询Active Directory_字段_16

所以LDAP在实现上,支持用类的​​lDAPDisplayName​​​作为搜索条件。所以如果我们想找所有​​CN=Person,CN=Schema,CN=Configuration,DC=xie,DC=com​​的实例,可以简化为以下过滤规则。

(objectCategory=person)

adfind搜索语法为

adfind.exe -b dc=xie,dc=com -s subtree -bit -f "(objectCategory=person)" -dn

查询Active Directory_字段_17

(3) objectClass 与objectCategory的结合使用

如果想确保查询在所有版本的Active Directory上都能正常运行,建议使用 objectClass 和 objectCategory 结合。如果在目录中已经索引了ObjectClass ,或者所有域控制器都在运行Windows Server 2008或更高版本,则可以随意使用 objectClass,而不必担心会对性能产生影响。

这里我们介绍下objectClass 和 objectCategory 的结合使用。前面我们分别介绍了objectClass 以及objectCategory,但是没讲怎么把他们结合在一起使用。

我们这里再来理一理思路。

​CN=hack,CN=Users,DC=xie,DC=com​​​这个对象。他的​​objectClass​​​是​​top,person,organizationalPerson,user​​​。他的​​objectCategory​​​是​​person​​。


  • 一个对象的​​objectClass​​ 是一个类的对象类,以及这个对象类的所有父类。
  • 一个对象的​​objectCategory​​ 是一个类的对象类或者这个对象类的所有父类。

所以说一个对象的​​objectCategory​​​ 必定是​​objectClass​​ 中的其中一个。

user,person,organizationalPerson类将其defaultObjectCategory设置为person。这允许像(objectCategory= person)这样的搜索过滤器通过单个查询定位所有这些类的实例。

比如说,我们要定位所有的user 类的实例。(​​CN=test,CN=Users,DC=xie,DC=com​​就是user类的一个对象)

user 类的继承关系如下。

top => person => organizationalPerson => user

那​​person​​​,​​organizationalPerson​​​,​​user​​都将其defaultObjectCategory设置为person。因此我们可以先过滤。

(objectCategory=person)

但是这样的结果并不精准。我们使用objectClass进一步在过滤后的结果进行过滤

(&(objectCategory=person)(objectClass=user))

这样就能精准匹配到了。其实说通俗点就是,objectCategory建立索引,所以查询时间比较快。我们通过objectCategory划分一个大的范围,然后通过objectClass进行精准匹配。

当然如果在目录中已经索引了ObjectClass ,或者所有域控制器都在运行Windows Server 2008或更高版本,我们直接使用 objectClass(​​(objectClass=user)​​) 也能很精准地匹配并且不用考虑效率问题。