关注公众号回复20231110获取最新网络安全以及内网渗透等资料。
文章目录
Ldap篇
LDAP全称是Lightweight Directory Access Protocol,轻量目录访问协议。顾名思义,LDAP是设计用来访问目录数据库的一个协议。
在这之前我们先介绍一下目录服务。目录数据库是由目录服务数据库和一套访问协议组成。
目录服务数据库也是一种数据库,这种数据库相对于我们熟知的关系型数据库(比如MySQL,Oracle),主要有以下几个方面的特点。
它成树状结构组织数据,类似文件目录一样。
它是为查询、浏览和搜索而优化的数据库,也就是说LDAP的读性能特别强,但是写性能差,而且还不支持事务处理、回滚等复杂功能。
为了能够访问目录数据库,必须设计一台能够访问目录服务数据库的协议,LDAP是其中一种实现协议。
其实如上说的简单点就是AD是目录数据库,而Ldap就是为了目录数据库而产生的一种协议。
如图:
目录树:如上图所示,在一个目录服务系统中,整个目录信息集可以表示为一个目录信息树,树中的每个节点是一个条目。
条目:每个条目就是一条记录,每个条目有自己的唯一可区别的名称(DN)比如图中的每个圆圈都是一条记录。
DN,RDN:比如说第一个叶子条目,他有一个唯一可区分的名称DN:uid=bob,ou=people,dc=acme,dc=org。类似于文件目录的相对路径绝对路径,他除了有个DN之外,还有个RDN,他与目录结构无关,比如之前咱们提过的uid=bob,ou=people,dc=acme,dc=org,他的RDN就是uid=bob
属性:描述条目具体信息。比如`uid=bill,ou=people,dc=acme,dc=org,他有属性name 为bill,属性age为11,属性school 为xx。
如果我们想访问域内的Active Directory,有两种办法
域内的每一台域控都有一份完整的本域的Active Directory,可以通过连接域控的389/636端口(636端口是LDAPS)来进行连接查看修改。
389对应的是Ldap协议,636则对应的是Ldaps协议。
如果用户知道访问的对象处于那个域的话,那么可以直接通过以上方式来搜索对象非常容易,但是考虑到这种情况,不知道对象所在的域,我们不得不去域林中的每个域搜索。为了解决这个问题,微软提出全局编录服务器(GC,Global Catalog), 全局编录服务器中除了保存本域中所有对象的所有属性外,还保存林中其它域所有对象的部分属性,这样就允许用户通过全局编录信息搜索林中所有域中对象的信息。也就是说如果需要在整个林中进行搜索,而不单单是在具体的某个域进行搜索的时候,可以连接域控的3268/3269端口。
Naming Context
首先有一点得明确,Active Directory具有分布式特性,一个林中有若干个域,每个域内有若干台域控,每台域控有一个独立的Active Directory。这个时候就有必要将数据隔离到多个分区中,如果不隔离的话,则每个域控制器都必须复制林中的所有数据。若隔离为若干个分区之后,就可以有选择性的复制某几个分区。微软将Active Directory划分为若干个分区(这个分区我们称为Naming Context,简称NC),每个Naming Context都有其自己的安全边界。
我们使用ADExplorer连接进来就可以看到这五个,后两个Naming Context后面再说。主要介绍一下前三个。
Domain NC
第一个Domain NC,域内的所有计算机,所有用户的具体信息都存在于这个Domain NC中,这个NC中有很多的容器。
如下代表这些容器的意思:
RDN | 说明 |
---|---|
CN=Builtin | 内置本地安全组的容器,包括管理员,域用户和账号操作员等等 |
CN=Computers | 机器用户的容器,包括加入域的所有机器 |
OU=Domain Controllers | 域控制器的容器,包括域内所有域控 |
CN=ForeignSecurityPrincipals | 代表域中来自森林外部域的组中的成员 |
CN=Keys | Server 2016之后才有,关键凭证对象的默认容器 |
CN=Managed Service Accounts | 托管服务帐户的容器。 |
CN=System | 各种预配置对象的容器。包括信任对象,DNS对象和组策略对象 |
CN=TPM Devices | 可信平台模块(TPM)密钥的恢复信息的容器。 |
CN=Users | 用户和组对象的默认容器 |
并且在每一个容器中,都有很多的条目,也就是记录,而记录也有很多的属性。
Configuration NC
Configuration NC简称配置NC,里面主要存储着林配置的相关信息,里面包含站点,服务,分区和Active DirectorySchema 的信息,并且被复制到林中每一个域控制器,配置NC根位于配置容器中,该容器是林根域的子容器,例如test.local林将为CN=Configuration,DC=test,DC=local.
Configuration NC简称配置NC,里面主要存储着林配置的相关信息,里面包含站点,服务,分区和Active DirectorySchema 的信息,并且被复制到林中每一个域控制器,配置NC根位于配置容器中,该容器是林根域的子容器,例如test.local林将为CN=Configuration,DC=test,DC=local.
RDN | 说明 |
---|---|
CN=DisplaySpecifiers | 定义了Active Directory管理单元的各种显示格式 |
CN=Extended-Rights | 扩展权限对象的容器,我们将在域内ACL那篇文章里面详解 |
CN=ForestUpdates | 包含用于表示森林状态和与域功能级别更改的对象 |
CN=Partitions | 包含每个Naming Context,Application Partitions以及外部LDAP目录引用的对象 |
CN=Physical Locations | 包含位置对象,可以将其与其他对象关联 以表示该对象的位置。 |
CN=Services | 存储有关服务的配置信息,比如文件复制服务 |
CN=Sites | 包含所有站点拓扑和复制对象 |
CN=WellKnown Security Principals | 包含常用的外部安全性主题的对象,比如Anonymous,Authenticated Users,Everyone等等 |
Schema NC
Schema NC中包含Schema 信息,在Schema 信息中定义了Active Directory中使用的类,对象和属性。与域NC和配置 NC 不同,模式NC不维护容器或组织单位的层次结构,相反,它是具有classSchema,attributeSchema 和 subSchema 对象的单个容器。
LDAP 中的类和继承
域内每个条目都是类的实例。而类是一组属性的集合。
例如:
CN=USER-WIN7,CN=Computers,DC=relaysec,DC=com表示一个条目,里面有众多属性描述条目具体的信息。
而这个条目有那些属性是由他的类来决定的,比如说CN=USER-WIN7,CN=Computers,DC=relaysec,DC=com这个条目他的类就是computer。这个是在ObjectClass中的。
类是可以继承的,子类可以继承父类所有的属性,TOP是所有类的父类,可以看到top这个字段,在这里除了computer之外还有user top person等字段,均表示的是user是computer的父类,top是person的父类。
类的分类
结构类
结构类规定了对象实例的基本属性,每个条目属于且仅属于一个结构型对象类。前面说过域内每个条目都是类的实例,这个类必须是结构类。只有结构类才有实例。比如说前面说过的Computer类。其实这个类跟我们在Java对象中的普通类是差不多的。
抽象类
抽象类型是结构类或其他抽象类的父类,它将对象属性中公共的部分组织在一起。跟面对对象里面的抽象方法一样,他没有实例,只能充当结构类或者抽象类的父类。比如说top 类。注意抽象类只能从另一个抽象类继承。
这个就和Java对象中的抽象类是差不多的,这里所说的只能充当结构类或者抽象类的父类,就相当于说结构类去继承了抽象类。
辅助类
辅助类型规定了对象实体的扩展属性。虽然每个条目只属于一个结构型对象类,但可以同时属于多个辅助型对象类。注意辅助类不能从结构类继承。
Schema NC中的类
域内每个条目都是类的实例。所有的类都存储在Schema NC里面,是Schema NC的一个条目。也就是说一个条目是类的实例,类是Schema NC的一个条目。
就比如说前面说过的CN=USER-WIN7,CN=Computers,DC=relaysec,DC=com是Computer类的实例,那么Computer就存储在Schema NC里面,是Schema NC的一个条目。
下面我们就
- 前面说过每个条目都是类的实例,而类是是Schema NC的一个条目。因此类条目也是一个类的实例,这个类是ClassSchema(CN=Computer,CN=Schema,CN=Configuration,DC=relaysec,DC=com),所有的类条目都是classSchema类的实例。
可以在ObjectClass属性中看到:
-
通过adminDescription,adminDisplayName,cn,name属性得到名称是Conputer。
-
defaultSecurityDescriptor属性表示如果在创建Computer这个类的实例的时候,如果没指定ACL,就用这个属性的值作为实例的ACL。在实例的nTSecurityDescriptor里面。
属性rDNAttID表明通过LDAP连接到类的实例的时候,使用的两个字母的前缀用过是cn。所以他的实例CN=USER-WIN7,CN=Computers,DC=relaysec,DC=com使用的前缀是cn。
-
属性objectClassCategory为1说明他是一个结构类,那么1代表结构类,2代表是一个抽象类,3代表是辅助类。
属性subClassOf表明它的父类是user类。
systemPossSuperior约束了他的实例只能创建在这三个类container,organizationalUnit,domainDNS的实例底下。
比如computer类的一个实例,CN=WIN7,CN=Computers,DC=test,DC=local,它位于容器CN=Computers,DC=test,DC=local底下,而CN=Computers,DC=test,DC=local是container的实例,container在systemPossSuperior底下,这不违反这个约束。
Schema NC中的属性
Schema NC除了定义了Active Directory中使用的类,还定义了Active Directory中使用的属性。
每个属性都是一个条目,是类attributeSchema的实例。
在域内的所有属性必须在这里定义,而这里的条目,最主要的是限定了属性的语法定义。其实就是数据类型,比如 Boolean类型,Integer类型等。
以CN=Object-Sid,CN=Schema,CN=Configuration,DC=relaysec,DC=com为例。
他的attributeSyntax是2.5.5.17
搜索Active Directory
通过查询目录,可以直接收集到要求的数据。查询目录需要指定两个要素。
- BaseDN
- 过滤规则
BaseDN
BaseDN指定了这棵树的根。比如指定BaseDN为DC=relaysec.DC=com就是以DC=relaysec.DC=com为根往下搜索
过滤规则
LDAP 过滤规则相对简单,很方便入手
LDAP 搜索过滤器语法有以下子集:
- 用与号 (&) 表示的 AND 运算符。
- 用竖线 (|) 表示的 OR 运算符。
- 用感叹号 (!) 表示的 NOT 运算符。
- 用名称和值表达式的等号 (=) 表示的相等比较。
- 用名称和值表达式中值的开头或结尾处的星号 (*) 表示的通配符。
相关访问Active Directory的工具
ADSI 编辑器
微软自带,输入adsiedit.msc即可访问
ldapsearch
ldapsearch -x -h 10.211.1.210 -D "win7@relaysec.com" -b "CN=Users,DC=relaysec,DC=com" -w Admin123.. dn
导出的格式为LDIF格式,有人写了个工具支持导出为sqlite文件,然后阅读sqlite文件
ldapsearch -x -h 10.211.1.210 -D "win7@relaysec.com" -b "CN=Users,DC=relaysec,DC=com" -w Admin123.. -o ldif-wrap=no >client.laif
下载地址:https://github.com/stufus/ADOffline
python2 adoffline.py client.laif
然后将这个文件拿出来导入到Navicat中或者也可以直接打开。
Navicat:
组
组介绍
域中的组我们分为两类,第一类是通讯组,就是类似于邮件组之类的,第二类是安全组,就比如说运维需要对公司网络进行管理,需要给一些特殊的管理权限,再比如说就跟VPN一样,我们用深信服VPN的时候有些网段的权限我们是无法访问,需要管理员进行开启。
查询组
所有的组都是Group的实例,可以查看ObjectClass属性得知。所以我们可以通过这个属性进行查询。
这里使用的是AdFind查询,使用Ldap相关的正则进行查询。
AdFind.exe -s dc=relaysec,dc=com -f "(objectClass=group)" -s suntree -c
也可以使用(objectCategory=group)来过滤组。
查询域内所有组。
AdFind.exe -s dc=relaysec,dc=com -f "(objectClass=group)" -dn
查询域内全局组:
这是根据GroupType属性进行查询的。
语法: <属性名称>: := <十进制比较值>
AdFind.exe -b dc=relaysec,dc=com -s subtree -bit -f "(&(objectcategory=group)(grouptype:ADN:=2))" -dn
查询域内的所有通用组
AdFind.exe -b dc=relaysec,dc=com -s subtree -bit -f "(&(objectcategory=group)(grouptype:ADN:=8))" -dn
域内的所有域本地组
AdFind.exe -b dc=relaysec,dc=com -s subtree -bit -f "(&(objectcategory=group)(grouptype:ADN:=4))" -dn
查询域内的所有安全组,包括全局组,通用组,域本地组
AdFind.exe -b dc=relaysec,dc=com -s subtree -bit -f "(&(objectcategory=group)(grouptype:ADN:=2147483646))" -dn
组范围
组范围可以划分为全局组,通用组,域本地组。
组类型 | 可授予权限 | 可包含 | 成员是否在全局编录复制 | |
---|---|---|---|---|
全局组 | 在同一林中或信任域或林中的任何域上 | 来自同一域的账户以及全局组 | 无 | |
通用组 | 在同一林中或信任林中的任何域上 | 来自同一林中任何域的账户以及全局组 | 是 | |
域本地组 | 在同一域中 | 无 |
域本地组(Domain Local group)
顾名思义,就是本域内的本地组。不适用于林,适用于本域。可包含林内的账户,通用组,全局组。其他域内的通用组要在本域拥有权限,一般都是加入这个域的域本地组。比如说一个林里面,只有林根域有Enterprise Admins这个组,这是个通用组。然后其他子域 的域本地组Administrators会把林根域的Enterprise Admins加进里面,所以林根域的Enterprise Admins组用户才在整个林内具备管理员权限。如果想要一个只允许访问同一个域中的资源的组,那么使用域本地组即可。
通用组(Universal group)
上面已经简单提过了通用组,典型例子是Enterprise Admins这个组。在林的场景下比较有用。组内成员会在GC(全局编录器)内复制。如果你想要一个可以访问林中任何东西的组,并且可以在林中包含任何账户,请使用通用组。
全局组 (Global group)
全局组比较复杂,前面说了。在单域内用域本地组,在林中使用通用组。全局组应该说是一种比较折中的方案,他可以在林中使用,但是只能包含本域内的账户。全局组的使用范围是本域以及受信任关系的其他域。最为常见的全局组是Domain Admin,也就是我们常说的域管。因为全局组只能包含本域内账户,因此来自一个域的账户不能嵌套在另一个域中的全局组中,这就是为什么来自同一个域的用户不符合在外部域中的域管的成员资格(由于其全局范围的影响)。
常见组介绍
Administrators
域本地组。具备系统管理员的权限,拥有对整个域最大的控制权,可以执行整个域的管理任务。Administrators包括Domain Admins和Enterprise Admins。
Domain Admins
全局组。我们常说的域管组。默认情况下,域内所有机器会把Domain Admins加入到本地管理员组里面。
Enterprise Admins
通用组。在林中,只有林根域才有这个组,林中其他域没有这个组,但是其他域默认会把这个组加入到本域的Administrators里面去。
Domain Users
全局组。包括域中所有用户帐户,在域中创建用户帐户后,该帐户将自动添加到该组中。默认情况下,域内所有机器会把Domain Users加入到本地用户组里面,也就是为什么默认情况底下,啥都不配置。域用户可以登录域内任何一台普通成员机器。
AGDLP
安全组是权限的集合,所以在微软的建议中,并不建议给赋予单个用户权限,而是赋予一个组权限,然后将成员拉近组。下面介绍下AGDLP策略。这里直接用网上的图。
- A表示用户账号,Account
- G表示全局组,Global group
- U表示通用组,Universal Group
- L表示本地组, local group
- DL表示域本地组,Domain local group
- P表示资源权限,Resource Permissions
有常见的几种权限划分方式
-
AGP,将用户账户添加到全局组,然后赋予全局组权限
AGLP,将用户账户添加到全局组,将全局组添加到本地组, 然后赋予本地组权限
ADLP 将用户账户添加到域本地组,然后赋予域本地组权限
AGDLP,将用户账户添加到全局组,将全局组添加到域本地组, 然后赋予域本地组权限
AGUDLP,将用户账户添加到全局组,将全局组添加到通用组,将通用组添加到域本地组, 然后赋予域本地组权限 -
AGUDLP,将用户账户添加到全局组,将全局组添加到通用组,将通用组添加到域本地组, 然后赋予域本地组权限
-
查询组内用户以及用户所属的组
现在目前有两个组,一个是group1,一个是group2,这里将group2 加入到group1中。也就是说group2作为了group1的成员。
可以在group2的memberOf属性中可以看到它隶属于group1这个组。
而在group1中,有一个member属性标识group2是他的成员。
根据这两个属性,我们就可以开始过滤了。
group1 => group2
group2 => group4
group2 => user1
group3 => user1
如上是一个例子,我们来说明一下,group1组里面的成员是group2,group2的成员是group4以及user1这个账户,group3里面的成员是user1。
查询group2中有那些成员:
这里是根据member属性进行查询的。
AdFind.exe -b CN=group2,CN=Users,DC=relaysec,DC=com member
查看user1用户属于那个组。
这里是查看这个用户的memberOf属性。
AdFind.exe -s substree -b CN=user1,CN=Users,DC=relaysec,DC=com memberOF
或者过滤member为user1的所有对象
AdFind.exe -s substree -b DC=relaysec,DC=com -f "(member="CN=user1,CN=Users,DC=relaysec,DC=com")" -dn
查询group1的所有成员,以及成员的成员。
AdFind.exe -s substree -b DC=relaysec,DC=com -f (memberOF:INCHAIN:="CN=group1,CN=Users,DC=relaysec,DC=com")" -bit -dn
查看user1属于哪些组,这些组又属于哪些组,如此往上递归查询,直到这个组不属于其他组。
AdFind.exe -s substree -b DC=relaysec,DC=com -f "(member:INCHAIN:="CN=user1,CN=Users,DC=relaysec,DC=com")" -bit -dn
OU
OU其实就是组织单位,是一个容器对象,将域内的对象组织成逻辑组,其实说白了就是分组,比如说网络部门为一组,开发部门为一组,组织单位包含用户,计算机,工作组,打印机,安全策略,其他组织单位等等,那么既然有组织单位那么肯定就有组策略,可以给这个组设置相关的策略。
如下图可以右击relaysec.com->新建->组织单位
组织单位OU和容器的区别
组织单位(OU)是专用容器,与常规容器的区别在于管理员可以将组策略应用于OU,然后系统将其下推到OU中的所有计算机。您不能将组策略应用于容器。需要注意的是Domain Computers是一个普通容器,而Domain Controllers是一个OU,因此可以可以将组策略应该于Domain Controllers,不可以将组策略应用于Domain Computers。
OU和组的区别
组织单位跟组是两个完全不同的概念。很多人经常会把这两个弄混。组是权限的集合。OU是管理对象的集合。举个前面举过的例子,运维需要对公司的网络进行管理,需要一些特殊的管理权限,我们就可以设置个组,对组配置权限。然后将运维拉近组里面,组里面的运维就拥有了该权限。比如我们需要对财务部里面的用户进行统一管理,那我们可以设置个OU,然后把财务部的用户拉近这个OU,这样就可以进行集中管理,比如说下发组策略。说通俗点,组是管理的集合,OU是被管理的集合。
OU委派
考虑这样一种需求,如果我们想允许某个用户把其他用户拉近OU,而不赋予这个用户域管权限,我们可以在这个OU给这个用户委派 添加成员的权限。组织单位的委派其实就是赋予某个域内用户对OU的某些管理权限。这些权限体现在ACL里面。
查询OU
所有的OU都是organizationalUnit类的实例,
我们可以用(objectClass=organizationalUnit)或者(objectCategory=organizationalUnit)来过滤OU。
AdFind.exe -s substree -b DC=relaysec,DC=com -f "(objectClass=organizationalUnit)" -dn
查询OU里面的账户,可以指定BaseDN为OU就行
AdFind.exe -s substree -b "OU=开发一组,DC=relaysec,DC=com" -dn
域用户和机器用户
当我们拥有一个域用户的时候,想要枚举域内的所有用户,主要有两个方法。
通过SAMR协议查询
samr 也不算是一种专门的协议,就是一个RPC接口。
我们平时使用的net user /domain就是使用samr 进行查询的。
在impacket 里面有一个脚本samrdump.py就是专门调用samr 去查询域用户的。
python3 samrdump.py relaysec.com/win7:Admin123..@10.211.1.210
通过Ldap 语法查询
域用户存储于活动目录数据库里面,对其他用户可见。可以通过Ldap 去查询。
过滤语法如下
(&(objectCategory=person)(objectClass=user))
AdFind.exe -s substree -b "DC=relaysec,DC=com" -f "(&(objectCategory=person)(objectClass=user))" -dn
域用户部分属性介绍
这些属性在LDAP 里面都可以查看
姓对应的属性就是sn
AdFind.exe -s substree -b "CN=user1,CN=Users,DC=relaysec,DC=com" sn
名对应的属性是giveName
AdFind.exe -s substree -b "CN=user1,CN=Users,DC=relaysec,DC=com" giveName
展示名,对应的属性是displayName
AdFind.exe -s substree -b "CN=user1,CN=Users,DC=relaysec,DC=com" disName CN
值得注意的是,displayName不能用于登陆,虽然跟域用户名往往一样。但是这个不是直接用于登陆的我们登陆用的账号,在一些公司里面,displayName往往是中文,登陆的用户名是拼音。登陆的格式有以下两种格式。
第一种格式是UserPrincipalName,我们简称为UPN,一般的格式是用户名@域名这样的格式。
AdFind.exe -s substree -b "CN=user1,CN=Users,DC=relaysec,DC=com" disName UserPrincipalName
第二种格式是域名\sAMAccountName这种格式
AdFind.exe -s substree -b "CN=user1,CN=Users,DC=relaysec,DC=com" sAMAccountName
用户相关的一些时间
whenCreated 账号创建时间
pwdLastSet 设置密码时间
Lastlogon 上次登录时间
AdFind.exe -s substree -b "CN=域用户-WIN7,CN=Users,DC=relaysec,DC=com" whenCreated pwdLastSet Lastlogon
这样看的话不是很只管,Adfind做了一些转换:
AdFind.exe -s substree -b "CN=域用户-WIN7,CN=Users,DC=relaysec,DC=com" whenCreated pwdLastSet Lastlogon -tdcs
值得注意的是Lastlogon这个属性值在不同的域控制器上是不会同步的。所以要查询一个用户的最后登录时间,得指定不同的域控制器来查询。
Ldap位字段
Ldap位字段是由一个一个位来组成的,比如说userAccountControl这个字段他就是由一个一个位组成的。
位字段查询是极其重要的。它可以查询那些机器设置了约束性委派,那些机器设置了非约束性委派。
他的属性类位于架构分区的CN=User-Account-Control,CN=Schema,CN=Configuration,DC=test,DC=local
attributeSyntax是2.5.5.9,oMSyntax是2。
查表可知是32位的Integer类型。
之所以我们说他是位字段,是因为他是由一个个位构成。
每一个位都表达不同的意思。
那么我们现在来解释一下这些标志位的意思:
首先在基于 Windows Server 2003 的域中,LOCK_OUT 和 PASSWORD_EXPIRED 已替换为名为 ms-DS-User-Account-Control-Computed 的新属性。这一点需要注意。
属性标志 | 所代表的意思 |
---|---|
SCRIPT | 运行登录脚本 |
ACCOUNTDISABLE | 已禁用用户帐户 |
HOMEDIR_REQUIRED | 需要主文件夹 |
PASSWD_NOTREQD | 无需密码 |
PASSWD_CANT_CHANGE | 用户无法更改密码。 它是用户对象的权限 |
ENCRYPTED_TEXT_PASSWORD_ALLOWED | 用户可以发送加密的密码 |
TEMP_DUPLICATE_ACCOUNT | 它是用户的主帐户位于另一个域中的帐户。 此帐户提供用户对此域的访问权限,但不提供对信任此域的任何域的访问权限。 它有时是指本地用户帐户。 |
NORMAL_ACCOUNT | 表示典型用户的默认帐户类型 |
INTERDOMAIN_TRUST_ACCOUNT | 信任其他域的系统域信任的帐户 |
WORKSTATION_TRUST_ACCOUNT | 它是运行 Microsoft Windows NT 4.0 Workstation、Microsoft Windows NT 4.0 Server、Microsoft Windows 2000 Professional 或 Windows 2000 Server 的计算机的计算机帐户,是此域的成员。 |
SERVER_TRUST_ACCOUNT | 它是域控制器的计算机帐户,该域控制器是此域的成员 |
DONT_EXPIRE_PASSWD | 表示不应在帐户上过期的密码。 |
MNS_LOGON_ACCOUNT | 这是一个 MNS 登录帐户。 |
SMARTCARD_REQUIRED | 设置此标志时,它会强制用户使用智能卡登录。 |
TRUSTED_FOR_DELEGATION | 设置此标志时,Kerberos 委派信任的运行服务的服务帐户(用户或计算机帐户)。 任何此类服务都可以模拟请求该服务的客户端。 若要为 Kerberos 委派启用服务,必须在服务帐户的 userAccountControl 属性上设置此标志。 |
NOT_DELEGATED | 设置此标志时,即使服务帐户设置为受信任的 Kerberos 委派,也不会将用户的安全上下文委派给服务。 |
USE_DES_KEY_ONLY | 限制此主体仅使用数据加密标准 (DES) 密钥加密类型。 |
DONT_REQUIRE_PREAUTH | 此帐户不需要对登录进行 Kerberos 预身份验证。 |
PASSWORD_EXPIRED | 用户的密码已过期。 |
TRUSTED_TO_AUTH_FOR_DELEGATION | 该帐户已启用委派。 这是一个安全敏感设置。 应严格控制启用此选项的帐户。 此设置允许在帐户下运行的服务假定客户端的身份,并以该用户的身份向网络上的其他远程服务器进行身份验证。 |
PARTIAL_SECRETS_ACCOUNT | 该帐户为只读域控制器 (RODC)。 这是一个安全敏感设置。 从 RODC 中删除此设置会损害该服务器上的安全性。 |
那么既然有了这些标志位之后,那么我们就可以通过标志位来查询相关的信息。
微软提供了位的过滤,所以我们可以通过标志位进行过滤。
语法: <属性名称>: := <十进制比较值>
这里的表示的是AND OR等等
如下对照表:
adfind为了不让这个太麻烦了,所以我们可以直接不需要输入OID,直接输入AND 或者 OR等等即可。
这里举三个例子。
查询 此帐户不需要对登录进行 Kerberos 预身份验证,那么对应的也就是DONT_REQUIRE_PREAUTH,他的十进制为4194304。
那么它的语法就是(useraccountControl:AND:=4194304)。
可以看到这里查询出来了hack用户不需要进行kerberos预身份验证。
这里需要加上 -bit这个参数,表示指定按位进行过滤。
AdFind.exe -s substree -b "dc=relaysec,dc=com" -f "(userAccountControl:AND:=4194304)" -bit -dn
如下图:
查询用户的密码永不过期的账户,那么它对应的标志位就是DONT_EXPIRE_PASSWD,并且10进制就是65536。
AdFind.exe -s substree -b "dc=relaysec,dc=com" -f "(userAccountControl:AND:=65536)" -bit -dn
查询设置了约束性委派的账户,那么它对应的标志位就是TRUSTED_FOR_DELEGATION,对应的十进制就是524288。、
AdFind.exe -s substree -b "dc=relaysec,dc=com" -f "(userAccountControl:AND:=524288)" -bit -dn
如上就是Ldap的位字段查找。这是一重点。
机器用户
默认情况底下,加入域的机器默认在CN=Computer这个容器里面,域控默认在Domain Controllers这个OU里面。有些域内会通过redircmp进行修改
机器用户跟system 用户的关系
如果拿到一台域内机器,然后发现没有域内用户。 这个时候有很多人用mimikatz 抓一下,没抓到域用户,就束手无策了。
我们随便点开一台Domain Computer,这里以WIN7这台机子做为测试。
我们查看他的ObjectClass属性。
发现他是computer 类的实例。
而computer 类的user 类的子类域用户是user类的实例。之前我们说过类是属性的集合。子类继承了父类的所有属性,因此域用户该有的属性,计算用户都有,甚至我们可以说,机器用户就是一种域用户。
那回到之前的那个问题,如果拿到一台域内机器,然后发现没有域内用户的情况。我们上面说了,机器用户其实就是一个域用户,那我们怎么使用这个机器用户呢。其实本地用户SYSTEM就对应于域内的机器用户,在域内的用户名就是机器名+
,
比如
w
i
n
7
,他的机器名是
W
I
N
7
,那他在域内的登录名就是
w
i
n
7
,比如win7,他的机器名是WIN7,那他在域内的登录名就是win7
,比如win7,他的机器名是WIN7,那他在域内的登录名就是win7。
所以我们可以将当前用户提到system(非管理员需要配合提权漏洞,管理员组的非administrators需要bypassuac,administrator提到system。这个网上有很多方法,psexec,mimikatz等等)。就可以在域内充当机器用户了。
查找域内的所有机器
可以通过objectclass=Computer或者objectcategory=Computer查找域内的所有机器
AdFind.exe -s substree -b "dc=relaysec,dc=com" -f "objectClass=computer" -bit -dn
adfind 对查询计算机,提供了一些快捷方式。
AdFind.exe -sc computers_active -dn
域内的域控都在Domain Controller这个OU底下,可以通过查看这个OU里面的机器来找到域内的所有域控。
AdFind.exe -b "OU=domain Controllers,DC=relaysec,DC=com" -f "objectclass=computer" -dn
adfind 对查询域控,也提供了一些快捷方式。
AdFind.exe -sc dcdmp -dn
域用户账户与机器用户的对应关系
域用户默认能登录域内的任何一台普通机器
如果我们是自己搭建过域环境的话,应该会知道,默认情况底下,域用户是能够登录域内的任何一台机器用户的。我们在这里面探究一下原因。
在域成员机器的本地安全策略里面,默认情况底下,本地用户组允许本地登录。其中包括Users组。
那么Users组中包含了Domain Users 也就是域成员组。
而域内用户默认都在Domain Users组里面。
因为域用户默认都在Domain Users组里面,而Domain Users在Users组里面。默认情况底下Users组内的成员允许本地登录。所以域内成员默认都能登录域内任何一台机器。
对于这种情况,很多域内都没有解决这个问题。而有些域内运维意识到这个问题。一般会有这两种修改方案。
在域用户这边做限制,设置域用户只允许登录到某台机器。
在机器这边做限制,设置域用户只允许登录到某台机器。
这个可以通过下发组策略实现。因为一般都会把常登陆这台机器的域用户加入到Administrators组里面。不允许User组里面用户本地登录。把下图的Users删除掉。这样登陆这台机器的域用户,因为在Administrators组里面,也可以登录。而其他域用户也不能登录。
查看域用户能够登录的主机
域用户默认能本地登录域内的任何一台主机。为了缓解这个问题。上一小节我们提出了两种解决方案。也会带来新的问题。我们可以根据这个找到域用户能够登录的主机。限制了域用户只能登录到某台主机之后,在LDAP里面,会设置一个字段,userWorkStation。这个字段保存了这个域用户只能登录到某台机器。而这个字段对于域内任何用户都是可读的,我们可以通过读域用户的userWorkStation来查看域用户限制登录到那一台机子。那个用户也就能够登录那台机子。
AdFind.exe -h 10.211.1.210 -sc u:win7 userWorkstations
这里就代表win7这个用户是可以登录域用户-WIN7这个机器的。
查看域用户正在登陆的主机
当我们想寻找一个域用户正在登陆的主机的情况下,主要有以下几种方式
这个我们可以通过远程机器的注册表来实现,注册表中有一个key是用户的sid。
这个S-1-5-21-… 代表的就是win7这个正在登录的用户。
具体原理可以访问:https://www.anquanke.com/post/id/196510#h3-10
这里有几个现成的工具可以使用:
psloggedon.exe
netsess.exe
PVEFindADUser.exe
hunter.exe
查看域用户登录过的主机
这里可以导出DC的日志,但是需要有域控的权限,比如说我们拿到了域控之后想找到域内某个用户的主机。
域内用户A在机器B正常登录的时候,由于本地没有域用户A的hash。机器B会去域控那边做验证,登录成功的话,在域控那边,会有个4624的日志,登录类型为3。
找到事件查看器->windows日志->安全。
值得注意的是,在域内可能存在多台域控,日志并不同步,请将每一台域控的日志都导出来。导出日志和查看日志有很多方式,这里提供一个实现。
导出日志,wevtutil是自带的
wevtutil epl Security C:\Users\Administrator\Desktop\1.evtx /q:“*[System[(EventID=4624)] and EventData[Data[@Name=‘LogonType’]=‘3’]]” //导出日志
将日志拷贝到我们的电脑.使用LogParser开始提取日志
LogParser.exe -i:EVT -o:CSV "SELECT TO_UPPERCASE(EXTRACT_TOKEN(Strings,5,'|')) as USERNAME,TO_UPPERCASE(EXTRACT_TOKEN(Strings,18,'|')) as SOURCE_IP FROM 1.evtx" >log.csv // 提取日志
如下图:
Windows访问控制模型
在域内中设置权限,其实和文件中设置权限的方式几乎是一样的,权限控制都是使用windows访问控制模型。
windows访问控制模型是由两部分组成的。
1.访问令牌 (Access Token) 包含用户的标识(User SID,Group SIDS) 以及特权列表。
2.安全描述符,被访问的安全对象的相关安全信息。
这里的安全对象包括但不限于
NTFS卷上的文件和目录
注册表项
网络共享
服务
Active Directory对象
进程等等
这里我们主要注重介绍Active Directory对象的相关权限,也就是AD树上的每一个条目。
在域内用户的身份上用SID来表示的而不是使用用户名来查看的,我们可以通过查看用户属性Objectsid来查看一个用户的SID。
大体的流程就是,当对象A来访问的时候,A会出示自己的Access Token,然后包含自己的用户Sid,自己所在的组的Sid,以及特权列表,B这个安全对象有自己的ACL。
B首先判断是不是需要特权才能访问,如果需要特权,则查看A的Access Token看有没有那个特权。
B通过A的Access Token,来判断A的用户 sid以及组sids,跟自己的ACL做比对,来判断是否让A进行访问。
ACL介绍
ACL主要有两个作用
权限访问控制:一个用户能不能访问安全对象。
日志记录功能:访问成功与否。
根据ACL的两个作用,ACL包含DACL和SACL,也就是说DACL对应的是安全访问控制,SACL对应的是日志记录功能。
DAL起到的作用是权限访问控制,也就是判断一个用户能不能访问安全对,DACL由多条ACE构成。
如下红框的都是每一条的ACE。
那DACL 是怎么判断用户能否访问呢。
DACL
在这之前首先介绍一下SRM。
SRM是一个监视器,SRM提供安全对象的访问,读取等权限。
对象的安全是由访问控制ACE来描述的,所有的ACE组成就变成了ACL。
没有ACL的对象主体意味着任何主体都是可以访问的。
有ACL的主体则由SRM检查其中每一项的ACE,从而决定主体的访问是否被允许。
SRM对ACL的解析是:
明确定义的DENYACE。
明确定义的ALLOWACE
继承的DENYACE。
继承的ALLOWACE。
如下图:
1.那么当用户A去访问对象D的时候,首先会从第二条ACE机型判断(因为DENY优先于第一条的allow),也就是ACE拒绝SID为13的对象访问,那么在用户A中,用户的sid以及组的sid都没有13,所以就到第一条ACE也就是允许sid为50的对象对象访问,这里用户A的用户SID是13,所以于允许访问对象D。
2.当用户B去访问对象D的时候,首先还是看第二条ACE进行判断,匹配到用户B有一个组的sid等于13,所以直接拒绝访问。
3.用户C 去访问对象D的时候,首先查看第二条ACE进行判断,没有匹配到,那么看第一条ACE,也没有匹配到,所以直接拒绝访问。
当每条ACE都没匹配上的时候,是拒绝访问的。因此值得注意的是,这里有两种情况
1.ACE 条目的数量为0 的情况这种情况底下,有DACL,但是ACE条目的数量为0,是不允许任何用户访问的
2.没有DACL的情况这种情况,是允许任何用户访问的。
SACL
SACL的作用是记录访问成功与否,SACL也是由一条一条的ACE构成,每条ACE的内容是某个用户访问成功/失败 某个权限。当访问跟满足这条ACE的时候就会被记录下来。
ACE
DACL 是由一条条的ACE构成。SACL也是由一条条的ACE构成,在这里我们只关心DACL的ACE。
在上面我们的举例里面,一条DACL的可能是这样。允许sid 为50 的用户访问。
这个是为了简单得描述。其实一条ACE的内容量远不止于此。可以把一条ACE归纳为四个方面。
1.谁对你有权限
2.是允许还是拒绝
3.有什么权限
4.这个权限能不能被继承
允许sid 为50 的用户访问。这个表述其实就解决了前面两个。谁对你有权限,是允许还是拒绝。
接下来我们主要来讲下后面两个
有什么权限:
前面说能访问吗,其实是很笼统的说法。关于权限,大致可以划分为三个大的权限。
1.通用权限就是对这个条目的通用权限,通用读,通用写等。
2.对某个属性的权限一个条目包含若干个属性,通用属性是对整个条目的权限。域内的ACL同时也支持某个属性的权限。
3.扩展权限全面说的都是读写执行权限,但是域内的安全对象相对较为复杂,读写执行权限是不够用的,域内的ACL也支持扩展权限,比如强制更改密码。
SDDL
安全描述符定义语言(SDDL)定义了ConvertSecurityDescriptorToStringSecurityDescriptor
和ConvertStringSecurityDescriptorToSecurityDescriptor
函数用来将安全描述符描述为文本字符串的字符串格式。该语言还定义了字符串元素,用于描述安全描述符的组成部分中的信息。
它存储的位置在nTSecurityDescriptor属性。
可以使用Adfind进行查询。
AdFind.exe -b "CN=USER-WIN7,CN=Computers,DC=relaysec,DC=com" nTSecurityDescriptor -rawsddl
可以看到它分为了很多个ACE,在括号中的都是ACE。
SDDL 可以大致划分为一下四个部分。
O:DA: ---> ower
G:DU -->Primary Group
D:
(A;CIID;GW;;;S-1-5-21-1812960810-2335050734-3517558805-1103)
(OA;;WP;bf967950-0de6-11d0-a285-00aa003049e2;bf967a86-0de6-11d0-a285-00aa003049e2;S-1-5-21-1812960810-
S:
(OU;CIIOIDSA;WP;f30e3bbe-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)(OU;CIIOID
其中O代表这条ACL的所有者
G表示primary group,Windows 通常忽略此参数(这是为了 POSIX 兼容性,但它现在已经退化了)
然后剩下的两个部分就是DACL和SACL,都是由一条一条的ACE构成(在SDDL里面一个括号代表一条ACE),这里侧重点说的是DACL的ACE。
我们前面说过,DACL的ACE的作用主要可以分为
我们将ACE拆开,
A; ACE类型(允许/拒绝/审核)
CI; ACE标志(继承和审核设置)
RP; 权限(读取所有属性)
;对象类型(GUID)
;继承的对象类型(GUID)
S-1-5-21-1812960810-2335050734-3517558805-1103 受托人SID
这些部分使用分号连接,例如
(A;OICIIO;FA;;;CO)
A; = 允许
OICIIO:继承标志(对象继承、容器继承、仅继承)
FA = 完全访问
;; = 通常,对象类型和继承类型未设置,并且在 SDDL ACE 中缺失,如本例所示。
CO = 创建者所有者的简写。许多知名 SID 都有简写符号
接下来我们解释一下如上的ACE是什么意思。
在这之前我们需要添加一条ACE,将win7这个用户添加到这台机器的访问权限中。
然后我们定位到这个sid,如下:
(A;CIID;GW;;;S-1-5-21-1812960810-2335050734-3517558805-1103)
接下来来解释一下:
可以看到:
谁对你有权限sid 为 S-1-5-21-1812960810-2335050734-3517558805-1103的用户
是允许还是拒绝根据ACE类型可以看到是允许
有什么权限GW 表示是通用权限
个权限能不能被继承CI 表示权限可以被继承
关于这些值的解释可以看https://clan8blog.wordpress.com/2016/08/08/sddl-explained/
扩展权限
上面代表的是通用权限的情况,但是还有对某个属性的权限,以及扩展权限两种。看下面一个例子。
(
OA; ACE类型(允许/拒绝/审核)
; ACE标志(继承和审核设置)
CR; 权限(增量权限列表)
00299570-246d-11d0-a768-00aa006e0529; 对象类型(GUID)
; 继承的对象类型(GUID)
S-1-5-21-1812960810-2335050734-3517558805-1178 受托人SID
)
这个是扩展权限的,相较于通用权限,对某个属性的权限,以及扩展权限这两种权限的话,
我们可以看到主要是多了个GUID(00299570-246d-11d0-a768-00aa006e0529),我们查下这个GUID(00299570-246d-11d0-a768-00aa006e0529)是强制更改密码,因此这个权限是扩展权限,强制更改密码。
对于某个具体属性的权限或者扩展权限,是哪个属性或者是哪个扩展权限,体现在对象类型里面,类型是GUID。
对于扩展权限,都存储在CN=Extended-Rights,CN=Configuration,DC=relaysec,DC=com里面,具体在rightsGuid这个属性里面,是字符串属性
如果我们已经知道了GUID,然后去查询扩展权限的名字,我们可以这样查询。
Adfind.exe -b "CN=Extended-Rights,CN=Configuration,DC=relaysec,DC=com" -f "rightsGuid=00299570-246d-11d0-a768-00aa006e0529" name
对某个属性的权限
对哪个属性的权限,也是用GUID 体现出来的,之前我们说过,所有属性的都存储在结构分区里面,可以以此作为查询
Adfind.exe -schema -f "schemaIDGUID={{GUID:BF9679C0-0DE6-11D0-A285-00AA003049E2}}" -binenc name
但是SDDL的可阅读性实在太差了,Adfind 可以更方便阅读一点。
AdFind.exe -b "CN=USER-WIN7,CN=Computers,DC=relaysec,DC=com" nTSecurityDescriptor -sddl
AdFind.exe -b “CN=USER-WIN7,CN=Computers,DC=relaysec,DC=com” nTSecurityDescriptor -sddl+++
利用Adfind 过滤 ACL
如果想用adfind 过滤ACL的话,我们可以使用-sddlfilter,语法如下
-sddlfilter ;;;;;
后面跟的参数对应的是ace条目相应的参数,值得注意的是,过滤的格式跟输出的格式要保持一致。s
如果-rawsddl ,最后一个参数是sid,这个时候用-sddlfilter进行过滤,最后一个参数就要用sid的形式。
如果是-sddl+++,最后一个参数已经解析后账号名,这个时候用-sddlfilter进行过滤,最后一个参数就要用账号名的形式。
查找某个对象在域内的ACL权限
AdFind.exe -s subtree -b "DC=relaysec,DC=local" nTSecurityDescriptor -sddl+++ -sddlfilter ;;;;;"RELAYSEC\DC$" -recmute
查找更改一个对象的S-AllowedToActOnBehalfOfOtherIdentity的权限
AdFind.exe -s subtree -b "DC=relaysec,DC=com" nTSecurityDescriptor -sddl++ -sddlfilter ;;;"msDS-AllowedToActOnBehalfOfOtherIdentity";; -recmute
查找域内具备dcync 权限的用户
对域对象只需要具备一下这两个权限,就有dcsync的权限。
'DS-Replication-Get-Changes' = 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 对应的意思是:复制目录更改
'DS-Replication-Get-Changes-All' = 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2 对饮的意思是:复制目录更改所有项
这里我给win7这个域用户这两个权限,我们进行查询。
那么也就是说只要拥有了这两个权限,也就是拥有了DCSYNC的权限。
可以看到如下这些账号都是具有dcsync的权限的。
AdFind.exe -s subtree -b "DC=relaysec,DC=com" nTsecurityDescriptor -sddl+++ -sddlfilter ;;;"Replicating Directory Changes";; -recmute
可以看到win7用户具有dscync的权限了。
特权
如果我们需要赋予域用户特权一般都是通过组策略下发。比如说默认情况底下的Default Domain Controllers Policy(GUID={6AC1786C-016F-11D2-945F-00C04FB984F9})这条组策略会把SeEnableDelegationPrivilege这个特权赋予Administrators组中。
而查询一个用户具备的特权,可以用whoami /priv来查看
然后这里着重介绍一个特权SeEnableDelegationPrivilege,其实特权这个东西不止是域,在整个windows安全体系里面都很重要,有兴趣可以深入研究下。
SeEnableDelegationPrivilege
利用思路一般都是找到域内的非约束委派用户或者约束委派用户,然后加以利用,因为,默认情况底下,在域内只有SeEnableDelegationPrivilege权限的用户才能设置委派。而这个权限默认域内的Administrators组的用户才能拥有,所以我们一般都是使用SeEnableDelegationPrivilege这个权限来留后门。
我们赋予win7SeEnableDelegationPrivilege特权
可以通过图形化的组策略管理编辑器进行编辑,也可以在C:\Windows\SYSVOL\sysvol\relaysec.com\Policies{6AC1786C-016F-11D2-945F-00C04fB984F9}\MACHINE\Microsoft\Windows NT\SecEdit的GptTmpl.inf里面进行直接编辑。
所以这里我们也可以直接编辑GptTmpl.inf,将win7的sid (这里上面已经说过了如何拿到这个sid)添加进去。
win7这个用户就拥有SeEnableDelegationPrivilege特权了(这一步有个地方要注意,由于是通过组策略的方法,不会立刻更新,可以通过gpupdate /force 手动更新)。
这里组策略编辑器可以通过组策略然后点击编辑即可进入。
并且win7对自己有GenericAll / GenericWrite权限(这个默认是没有的)
然后后面就是委派的相关利用了,这里就不操作,后面专门有一篇对委派攻击的文章。
ACL
一些比较有攻击价值的ACL权限介绍
下面介绍一些比较有实战价值的权限,可以用以在域渗透的时候寻找攻击路径或者用于充当后门。
对某些属性的WriteProperty ,有以下属性
● member(bf9679c0-0de6-11d0-a285-00aa003049e2)
● servicePrincipalName(28630EBB-41D5-11D1-A9C1-0000F80367C1)
● GPC-File-Sys-Path(f30e3bc1-9ff0-11d1-b603-0000f80367c1)
(2) 扩展权限有
● User-Force-Change-Password(0299570-246d-11d0-a768-00aa006e0529)
可以在不知道当前目标用户的密码的情况下更改目标用户的密码
● DS-Replication-Get-Changes(1131f6aa-9c07-11d1-f79f-00c04fc2dcd2) 和 DS-Replication-Get-Changes-All(1131f6ad-9c07-11d1-f79f-00c04fc2dcd2)
对域对象具有这两个扩展权限的用户具备dcsync 权限
(3) 通用权限有
● WriteDacl
● AllExtendedRights
● WriteOwner
● GenericWrite
● GenericAll
● Full Control
下面逐个演示利用方式
AddMembers
可以将任意用户,组或计算机添加到目标组。
如果一个用户对一个组有AddMembers权限,那么这个用户可以将任何用户加入这个组,从而具备这个组的权限。
比如说win7这个用户具备对Domain Admins这个组的AddMembers权限,其实也就是对member(bf9679c0-0de6-11d0-a285-00aa003049e2) 这个属性的写权限。
通过AdFind将任意用户(这里是win7)加进Domain Admins。
AdFind.exe -users -rb CN=hack -dsq|admod -users -rb CN="Domain Admins" -stdinadd member
GenericAll
GenericAll在安全描述符中的Access Mask中进行标识,是包含了所有其他权限的权限。授予对目标对象的完全控制权,包括WriteDacl 和 WriteOwner 特权。可以使用PowerView中的Add-DomainObjectAcl进行利用。
这里使用两个用户进行演示,第一个用户是win7,第二个用户是hack。
win7的sid:
hack的sid:
然后我们尝试使用win7这个账户来对hack这个账户进行更改密码。
可以看到这里是无法更改的。
此时我们设置hack的dacl,设置为win7 完全控制权限。
此时我们再去修改的时候。
可以发现已经修改完成了。
那么我们可以使用powerview来进行枚举。
看一下hack用户的:可以看到红框的这个ACL表示win7账户对hack账户具有完全管理(GenericAll)权限。
Get-ObjectAcl -SamAccountName hack -ResolveGUIDs | ? {$_.ActiveDirectoryRights -eq "GenericAll"}
此时再使用已经修改的密码结合runas命令就可以直接创建一个hack权限的cmd窗口:
runas /noprofile /user:relaysec\hack cmd
GenericAll on Group
环境和上文相同,GenericAll on Group说的是对一个组有GenericAll权限,查看用户组domain admins:
Get-NetGroup "domain admins"
此时hack和win7均为域内普通权限用户,然后在域管理员组domain admins的DACL中加入win7的GenericAll权限:
Add-DomainObjectAcl -TargetIdentity "domain admins" -PrincipalIdentity win7 -Rights all -Verbose
然后再win2012上使用命令查看domain admins的权限
Get-ObjectAcl -ResolveGUIDs| ? {$_.objectdn -eq "CN=Domain Admins,CN=Users,DC=relaysec,DC=com"}
可以看到在结果中有一条SID为win7的SID,权限为GenericAll
那么现在我们就可以将任意的用户添加到Domain Admins组中了。
net group "domain admins" hack /add /domain
可以看到已经成功将hack加入管理员组,然后再将hack移除出domain admins了,并将DACL中的内容删除之后再尝试加入,发现已经被拒绝。
在win7具有这个权限的时候使用Powerviewer能够达到相同的添加用户到某个组的目的,不过使用net命令更方便一点
Add-DomainGroupMember -Identity 'Domain Admins' -Members 'test'
WriteDacl
WriteDacl允许委托人修改受影响对象的DACL。这意味着攻击者可以添加或删除特定的访问控制项,从而使他们可以授予自己对对象的完全访问权限。因此,WriteDacl是在链中启用其他权利的权利。
Self (Self-Membership) on Group
这条权限指的是某个账户能够把自身添加到某个组的权限(需要在某个组的高级权限中添加ACE,也就是说针对的是组对象)
那么现在win7这个用户就可以将自己添加进Domain Admins这个组中了。
在这里插入图片描述
WriteProperty
WriteProperty直译为写所有权。这个权限利用针对的对象为组对象,能够赋予账户对于某个组的可写权限,在Domain Admins组里设置win7账户的WriteProperty权限:
Get-ObjectAcl -ResolveGUIDs| ? {$_.objectdn -eq "CN=Domain Admins,CN=Users,DC=relaysec,DC=com"}
WriteProperty on Group
WriteProperty on Group说的是对一个组具有WriteProperty权限的情况下,“写入全部属性”除了WriteProperty还包括了其他的权限:
CreateChild, DeleteChild, Self, WriteProperty, ExtendedRight, GenericRead, WriteDacl, WriteOwner
在Domain Admins组的列表中添加写入全部属性,会生成一条新的ACE
访问被标记为特殊,没有实际显示具体权限,测试添加此条ACE前后:
查询Domain Admins的ACL。
Get-ObjectAcl -ResolveGUIDs| ? {$_.objectdn -eq "CN=Domain Admins,CN=Users,DC=relaysec,DC=com"}
WriteOwner
WriteOwner权限允许委托人修改对象的安全描述符的所有者部分。也就是说,假如用户A对administrator用户有这个权限,那么A能利用这个权限给自己附加其他的权限。
win7称为所有者之后,其实也就具备了WriteDacl的权限了。
AdminSDHolder
AdminSDHolder是位于Active Directory中的系统分区(CN=AdminSDHolder,CN=System,DC=relaysec,DC=com)中的一个对象。
这个的作用就是,他会作为域内某些特权组的安全模版。所谓安全模版,就是说有一个进程(SDProp),每隔60分钟运行一次,将这个对象的ACL复制到某些特权组成员的对象的ACL里面去。
这些特权组和用户默认有 · Account Operators · Administrator · Administrators · Backup Operators · Domain Admins · Domain Controllers · Enterprise Admins · Krbtgt · Print Operators · Read-only Domain Controllers · Replicator · Schema Admins · Server Operators
属性adminCount在Active Directory中标记特权组和用户,对于特权组和用户,该属性将设置为1。通过查看adminCount设置为1的所有对象,可以找到所有的特权组和用户。 但值得注意的是。一旦用户从特权组中删除,他们仍将adminCount值保持为1,但Active Directory不再将其视为受保护的对象。因此通过admincount=1匹配到的所有对象,不一定都是特权组
AdFind.exe -f “admincount=1” -dn
因为AdminSDHolder对象的这个作用,因此我们常常用AdminSDHolder来做后门。
我们给AdminSDHolder对象新增一条ACE。win7的完全控制。
由于这个ACL过个60分钟会同步到特权组和用户,这个特权组和用户包括域管,所以其实win7对域管已经有完全控制的权限了,达到了后门的目的。
最后还有一点,默认这个时间是60分钟是可以更改的,通过更改注册表项
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters\AdminSDProtectFrequency
至此Ldap暂时结束