LDAP协议

LDAP(Lightweight Directory Access Protocol),轻量级目录访问协议,LDAP是一个设计来访问目录*数据库* 的协议

而一个目录服务 就是由一个目录服务数据库 加上一套访问协议组成的。对于域渗透来说,这一套组合就是AD+LDAP

一些名词

DC(domain component): 域名组件,表示从属于那个域

CN(Common Name):通用名,可辨别名

OU(Organizational Unit):组织单位,表示用户组

LDAP基础语法

LDAP语法的全称是LDAP查询过滤 语法

顾名思义LDAP是将一个个”条件元”,使用符号(或者关键字)组合起来的语句,形如

1
(uid=sql)这是一个"条件元",意思是寻找uid属性等于sql的条目

LDAP过滤器有:

  • 用与号 (&) 表示的 AND 运算符。(&(uid=sql)(domain=rookie)) 匹配uid属性等于sql且domain属性等于rookie的对象
  • 用竖线 (|) 表示的 OR 运算符。|((uid=sql)(domain=rookie)) 匹配uid属性等于sql或者domain属性等于rookie的对象
  • 用感叹号 (!) 表示的 NOT 运算符。(!(uid=sql)) 匹配uid属性不等于sql的对象
  • 用名称和值表达式的等号 (=) 表示的相等比较。(uid=sql) 匹配uid属性等于sql的对象
  • 用名称和值表达式中值的开头或结尾处的星号 表示的通配符。(uid=sq*) 匹配uid属性以sq开头的对象

注意事项

  • LDAP查询过滤语句最外层一定是一层括号
  • LDAP的逻辑连接词是放在前面的而不是放在中间的

LDAP高级语法

位操作

LDAP中有的字段是位字段,比如userAccountControl字段.

它的属性类在架构分区CN=User-Account-Control,CN=Schema,CN=Configuration,DC=test,DC=local

之所以说这是一个位字段,是由于这个字段的值是由一个个标志位构成的,userAccountControl字段的标志位如下

img

如果说有一个账户他只设置了LOCKOUTNOT_DELEGATED,那么这个账户条目的userAccountControl属性就是0x100000+0x0010,表现形式是一个32位的int类型

那么如果需要查找所有设置了NOT_DELEGATED的账户,该如何查询呢?

显然,之前的简单语法已经不够了。

不过LDAP支持按位搜索,语法如下

1
2
3
<属性名称>:<BitFilterRule-ID> := <十进制比较值>
userAccountControl:1.2.840.113556.1.4.803:=1048576
查询设置了NOT_DELEGATED的账户

BitFilterRule-ID(按位过滤标准id)相当于对于位使用的逻辑连接词

img

当然adfind还提供了一个快捷的选项,可以不用去记忆BitFilterRule-ID

img

ObjectCategory和ObjectClass

ObjectClass

这个属性记录了条目对象来自哪一个类(包括父类)。

1
2
3
例如使用
(ObjectClass=top)
就可以获得ad中的所有对象
ObjectCategory

windows server 2008之前,默认不会对ObjectClass进行索引,理由是对多值属性进行索引会导致性能下降。但是windows2000带有另一个带有索引的单值属性——ObjectCategory

image-20201204164848797

每一个对象类都有一个ObjectCategory属性,这是一个单值属性,属性值是对象的类对象的defaultObjectCategory属性值(就是DN),ObjectClass的值是在创建对象时就赋予对象的,且无法修改

1
2
示例
(objectCategory="CN=Person,CN=Schema,CN=Configuration,DC=rookie,DC=com")

adfind的基础语法

1
2
adfind –b <Search Base> -s <Search Scope> -f <Search Filter>    attributesDesired
adfind -b dc=rookie,dc=com -s subtree -f "(objectclass=group)" -dn

image-20201208194838706

Active Directory 活动目录

目录服务器

目录服务器的特点

  • 树状结构组织数据,类似文件系统
  • 特化查询、浏览、搜索的数据库。读能力强,写能力弱
  • 必须要搭配 一个访问目录数据库的协议

Nameing Context

由于域林结构的复杂性,AD被设计得具有分布式特点。一个域林之中有多个域,一个域有多个域控,而每一台域控都有一个独立的AD,那么就有必要将数据隔离到多个分区中,如果不隔离的话,每个域控都要复制整个林环境的数据。分区之后域控就可以有选择的复制数据,而windows的就将AD划分成若干个分区,这些分区就是Nameing Context(命名上下文,简称NC),每个NC都有自己的安全边界。

AD预定义了三个Nameing Context

  • Configuration NC(配置NC)
  • Domian NC(域NC)
  • Schema NC(模式NC)

Configuration NC

配置NC,域林的配置信息的主要储存数据库,包含有关站点,服务,分区和Active DirectorySchema 的信息,这个NC会被复制到每个域控的AD里。如rookie.com域林的配置NC就是CN=Configuration,DC=rookie,DC=com

image-20201117220602429

Domian NC

每一个域都有一个域NC,不同的域有不同的域NC,用于存储一些特定的与域相关的数据,其中包括该域内的所有计算机,所有用户的具体信息。有如下条目

image-20201117224643073

具体含义

image-20201117224737656

Schema NC

包含Schema信息,这个信息定义了AD中使用的类,对象和属性。

LDAP中的类

域内所有条目都是一个类的实例。

image-20201118202310400

这就是AD之中的一个条目,这个条目是类Computer的实例,其中有什么属性就是有类Computer决定的。

可以在ObjectClass属性查看实例所有的相关类,包括这个条目对应的类和它的父类。

image-20201118204140436

类的继承关系是从上至下的

类有三种类型

  • 结构类(Structural)

    结构类规定了对象实例的基本属性,每个条目属于且仅属于一个结构型对象类。前面说过域内每个条目都是类的实例,这个类必须是结构类。只有结构类才有实例。比如说前面说过的Computer类。

  • 抽象类(Abstract)

    抽象类型是结构类或其他抽象类的父类,它将对象属性中公共的部分组织在一起。跟面对对象里面的抽象方法一样,他没有实例,只能充当结构类或者抽象类的父类。比如说top 类。注意抽象类只能从另一个抽象类继承。

  • 辅助类(Auxiliary)

    辅助类型规定了对象实体的扩展属性。虽然每个条目只属于一个结构型对象类,但可以同时属于多个辅助型对象类。注意辅助类不能从结构类继承

Schema NC里面的条目是所有类的实例。那么既然是实例,那么这些类条目也是拥有对应的类的,主要有classSchema、attributeSchema等

image-20201118222649251

组和OU

组介绍

在域内,我们无时无刻不在跟组打交道,比如我们熟悉的域管,就是一个组。按照用途来分,组分为通讯组安全组。对于通讯组,我们接触的比较多的就是邮件组将若干个人划分到一个通讯组,给这个通讯组发件,那组内用户都能收到。但是通讯组不能控制对资源的访问,域渗透并不关心这个。

安全组是权限的集合。举个例子,运维需要对公司的网络进行管理,需要一些特殊的管理权限,我们就可以设置个组,对组配置权限。然后将运维拉近组里面,组里面的运维就拥有了该权限。安全组可以根据作用范围划分为。

  • 全局组 (Global group):可以包括本域内所有账户,作用范围包括本林内所有域。来自本域影响全林
  • 通用组(Universal group):可以包括本林内的所有账户,作用范围包括本林内所有域。来自全林影响全林
  • 域本地组(Domain Local group):可以包括本林的所有账户,作用范围本域来自全林影响本域

LDAP查询组

所有的组都是group类的实例化

所以所有组的条目的objectClassobjectCategory性的属性值都是group。可以通过这个特性达到过滤组的效果 。

而组的类型信息存储在groupType属性之中,这个属性是一个位字段

这个位字段的标志位

img

1
(&(ojectCategory=group)(grouptype:AND:=2))     查找所有全局组

常见组介绍

  • Administraors

域本地组,具备管理员权限,拥有对域最大的管理权限。

  • Domain Admins

全局组。也就是常说的域管组,域内所有机器都会将Domain Admins添加到本地管理组之中

  • Enterprise Admins

通用组。域林中根域才会有的这个组,其他域没有这个组,但是其他与都会将其添加到Administrators里面。

AGDLP

在微软的建议之中,不推荐单独给用户添加权限,给是将权限赋予一个组,然后将用户拉近组中。这种设置权限的策略就是AGDLP

  • A表示用户账号,Account
  • G表示全局组,Global group
  • U表示通用组,Universal Group
  • L表示本地组, local group
  • DL表示域本地组,Domain local group
  • P表示资源权限,Resource Permissions

常见组权限策略

img

OU(组织单位)介绍

组织单位(Organization Unit),是一个容器对象,可以将域中的对象组织成逻辑组。组织单位中可以包含的对象: 用户,计算机,工作组,打印机,安全策略,其他组织单位

OU示例

img

OU与普通容器的区别

OU是一个专用容器,与普通容器的区别是,OU可以被设置组策略,然后延续影响到OU之下的所有计算机。而普通容器就不可以被设置组策略

OU与组的区别

最简单说法就是,组是管理者的集合OU是被管理者的集合

组的建立是为了方便权限的赋予,OU的建立是为了方便管理。

OU委派

假如我们有一个这样的需求:要使一个账户拥有将管理一个特定OU的权限,但是又不能赋予他域管权限。这需要怎么办?

OU委派就是为了解决这个需求诞生的,组织单位的委派就是赋予某一个账户管理一个OU的权限,这些权限主要包含在ACL之中。

查询OU

所有OU是OrganizationalUnit类的实例

所以查询OU对象的语句就是(objectclass=orgaizationalUnit)

域用户与计算机用户

查询域用户

使用LADP查询域用户
1
(&(objectCategory=person)(objectClass=user))

image-20201208211816030

使用SAMR协议查询

在impacket 里面有一个脚本:samrdump.py。这个脚本就是使用samr来查询域用户的

1
python3 samrdump.py domain/username:passwd@ip

image-20201208224111170

域用户的一些属性

  • sn对应姓

    image-20201208224730763

  • giveName对应名

    image-20201208225008545

  • displayName对应展示名

    image-20201208225055454

  • UserPrincipaName(UPN)格式是用户名@域名

    image-20201208225302926

  • sAMAccountName

    image-20201208225422086

  • 时间相关:账号创建时间,设置密码时间,上次登录时间,这些属性任意域用户都可以看的到。

    • whenCreated
    • pwdLastSet
    • Lastlogon
  • userAccountControl:这个属性至关重要,这个字段记录了账户的一些”特性“,可以通过这个字段筛选出我们需要的账户对象。比如说查询密码永不过期的账户可以使用这个标志位

    img

    这是一个位字段,这个字段的标志位如下

    img

    机器用户

    默认情况下,加入了域内的机器用户存放在computer这个容器之中,域控则在Domain controllers这个之中OU里面。

    机器用户对域渗透的作用

    先看一下Domian computer里对象的objectclass属性

    image-20201209105301447

    可以看到这些实例是computer类的实例,而computer类是user类的子类,所以computer类继承了user类的所有属性。而user类是所有域用户的类,那么也就意味着域用户拥有的所有属性,机器用户都拥有。甚至可以说机器用户就是域用户

    假设拿到了一个域内机器,但是这个机器上没有域用户。这个时候机器用户就有了用途。

    每一个机器对应的机器用户就是本地system用户,域内的用户名就是机器名+$,这个可以通过查看sAMAccountName获得

    image-20201209110551256

    Windows用户账户拥有三种常见等级(权限从左到右,依次提升):Users用户组,Administrator用户组,SYSTEM

    所以我们可以将当前用户提升到system,就可以当作域用户使用。这里涉及Windows提权知识之后会再学习记录。

    域用户相关信息收集

    默认情况下,一个域用户是可以再域内任何一个普通机器上登陆的,这是为什么呢?

    可以来看一下域内机器的本地安全策略

    image-20201209200210726

    在默认情况下本地用户组允许本地登陆,其中就包括Users这个组,而Users这组又包含着Domain Users这个组,所有域用户就这样被包含到了域内机器的本地用户组了。

    对此,域管理员一般有两个做法:

    • 在用户账户处做限制,设置其只能登陆某一台机器
    • 在机器方面做限制,将Users组删除,把需要登陆这台机器的账户添加到Administrator之中
    查看域用户可以登录的主机

    如果域管理员使用了第一种方法设置某一个账户只能登陆某些机器,那么这个设置就会被userWorkStation这个字段记录,而这个字段是对所有用户都可读的,然后就可以根据查询到的数据去登陆相应主机。

参考文章