域渗透|Kerberos域认证机制剖析
Kerberos域认证机制剖析
Kerberos概念
Kerberos是一种网络认证协议,其设计目标是通过密钥系统为Client / Server应用程序提供强大的认证服务。该认证过程的实现不依赖于主机操作系统的认证,无需基于主机地址的信任,不要求网络上所有主机的物理安全,并假定网络上传送的数据包可以被任意地读取、修改和插入数据。
在以上情况下, Kerberos作为一种可信任的第三方认证服务,是通过传统的密码技术(如:共享 密钥)执行认证服务的。
域认证所参与的角色
Kerberos的标志是三只狗头,狗头分别代表以下三个角色
- 访问服务的Client
- 提供服务的Server
- KDC(Key Distribution Center)密钥分发中心 kerberos 测试工具介绍
其中KDC服务默认会安装在一个域的域控中,而Client和Server为域内的用户或者是服务,如HTTP服务,SQL服务。在Kerberos中Client是否有权限访问Server端的服务由KDC(Key Distribution Center)发放的票据来决定。
Kerberos认证协议
TGT(Ticket Granting Ticket)
由身份认证服务
AS(Authentication Service)授予的票据,TGT用于身份认证,存储在内存,默认有效期为10小时,通过TGT能够获得票据(Ticket),TGT是一种 临时凭证 的存在,伪造的TGT又被称为 黄金票据。
票据(Server Ticket/Ticket)
是网络对象互相访问的 凭证,
伪造的ST\Ticket又被称为 白银票据。
KDC(Key Distribution Center)
负责管理票据、认证票据、分发票据,但是
KDC不是一个独立的服务,它由以下服务组成:
- AS(Authentication Service): 身份认证服务,为
Client生成TGT(Ticket Granting Ticket)的服务。 - TGS(Ticket Granting Service): 票据授予服务,为
Client生成某个服务的Ticket的服务。
AD(Account Database)
一个类似于本机
SAM的一个数据库,存储所有Client的白名单,只有存在于白名单的Client才能顺利申请到TGT。
※补充:从物理层面看,AD与KDC均为域控制器(Domain Controller)。
域认证粗略流程
过程简述
①-②:Client向kerberos服务请求,希望获取访问Server的权限。 kerberos得到了这个消息,首先得判断Client是否是可信赖的, 也就是白名单黑名单的说法。
这就是AS(Authentication Service)服务完成的工作,通过在AD(Account Database)中存储黑名单和白名单来区分Client。
成功后,AS(Authentication Service)返回TGT(Ticket Granting Ticket)给Client。
③-④:Client得到了TGT(Ticket Granting Ticket)后,继续向kerberos请求,希望获取访问 Server的权限。kerberos又得到了这个消息,这时候通过Client 消息中的TGT,判断出了Client拥有了这个权限,给了Client访问Server的权限Ticket。
⑤-⑥:Client得到Ticket后,终于可以成功访问Server。这个Ticket只是 针对这个Server,其他Server需要向TGS(Ticket Granting Service)申请。

较详简述
AS_REQ:
Client向KDC发起AS_REQ,请求凭据是Client hash加密的时间戳AS_REP:
KDC使用Client hash进行解密,如果结果正确就返回用krbtgt hash加密的TGT票据,TGT里面包含PAC,PAC包含用户Client的sid和用户Client所在的组。TGS_REQ:
Client凭借TGT票据向KDC发起针对特定Server的TGS_REQ请求TGS_REP:
KDC使用krbtgt hash进行解密,如果结果正确,就返回用Server hash加密的TGS票据 [Ticket](这一步不管用户有没有访问Server的权限,只要TGT正确,就返回TGS票据 [Ticket])AP_REQ:
Client拿着TGS票据(Ticket)去请求ServerAP_REP:
Server使用自己的hash解密TGS票据(Ticket)。如果解密正确,就拿着PAC去KDC那边问Client有没有访问权限,域控解密PAC。获取Client的sid,以及所在的组,再根据该服务的ACL,判断Client是否有访问Server的权限。
域认证详细流程
AS_REQ & AS_REP
AS_REQ
1 | 1. pvno |
AS_REP
1 | 1. msg-type |
TGS_REQ & TGS_REP
TGS_REQ
1 | 1. msg-type |
TGS_REP
1 | 1. msg-type |
S4U2SELF
s4u2self的过程如下图所示(前提条件是服务已经有通过KDC验证的TGT)
S4U2self 使得服务可以代表用户获得针对服务自身的kerberos服务票据。这使得服务可以获得用户的授权( 可转发 的用户TGS票据),然后将其用于后期的认证(主要是后期的s4u2proxy),这是为了在用户以不使用 Kerberos 的方式对服务进行身份验证的情况下使用。这里面很重要的一点是服务代表用户获得针对服务自身的kerberos票据这个过程,服务是不需要用户的凭据的

S4U2PROXY
s4u2proxy的过程如下图所示
s4u2proxy 使得服务1可以使用来自用户的授权( 在S4U2SELF阶段获得),然后用该TGS(放在AddtionTicket里面)向KDC请求访问服务2的TGS,并且代表用户访问服务2,而且只能访问服务2。

委派
在Windows 2000 Server首次发布Active Directory时,Microsoft必须提供一种简单的机制来支持用户通过Kerberos向Web Server进行身份验证并需要代表该用户更新后端数据库服务器上的记录的方案。这通常称为“ Kerberos双跳问题”,并且要求进行委派,以便Web Server在修改数据库记录时模拟用户。
需要注意的一点是接受委派的用户只能是
服务账户或者计算机用户。
非约束委派
例子:
服务(如JACKSON-PC$) 被配置了非约束的委派,那么JACKSON-PC$可以接受任何用户的委派的去请求其他所有服务。在协议层面的实现就是,某个用户委托JACKSON-PC$去访问某个服务,那么这个用户会将 TGT(在TGS里面)发送到JACKSON-PC$并缓存到LSASS中,以方便以后使用。 然后JACKSON-PC$模拟用户去请求某个服务。
配置了非约束委派的用户的userAccountControl 属性有个FLAG位 TrustedForDelegation
关于userAccountControl 每一位对应的意义可以看Converting AD UserAccountControl Attribute Values,(我们在LDAP篇也会详细介绍),其中 TRUSTED_FOR_DELEGATION 对应是 0x80000 ,也就是 524288 。
约束委派
微软很早就意识到非约束委派并不是特别安全,在 Windows 2003上发布了”约束”委派。
其中包括一组 Kerberos 协议扩展,就是本文之前提到的两个扩展 S4U2Self 和 S4U2Proxy。配置它后,约束委派将限制指定服务器可以代表用户执行的服务。这需要SeEnableDelegation特权(该特权很敏感,通常仅授予域管理员)才能为服务配置域帐户,并且将帐户限制为单个域。
例子:
计算机用户(即JACKSON-PC$) 被配置了约束的委派,那么JACKSON-PC$可以接受任何用户的委派的去请求特定的服务。具体过程是收到用户的请求之后,首先代表用户获得针对服务自身的可转发的kerberos服务票据(S4U2SELF),拿着这个票据向KDC请求访问特定服务的可转发的TGS(S4U2PROXY),并且代表用户访问特定服务,而且只能访问该特定服务。
相较于非约束委派,约束委派最大的区别也就是配置的时候选择某个特定的服务,而不是所有服务。
配置了约束委派的用户的userAccountControl 属性有个FLAG位 TrustedToAuthForDelegation 。
关于userAccountControl 每一位对应的意义可以看Converting AD UserAccountControl Attribute Values,其中 TRUSTED_TO_AUTH_FOR_DELEGATION 对应是 0x1000000 ,也就是 16777216 。
基于资源的约束委派
为了配置受约束的委派,必须拥有SeEnableDelegation特权(该特权很敏感,通常仅授予域管理员)。为了使用户/资源更加独立,Windows Server 2012中引入了基于资源的约束委派。基于资源的约束委派允许资源配置受信任的帐户委派给他们。基于资源的约束委派将委派的控制权交给拥有被访问资源的管理员。
基于资源的约束委派只能在运行Windows Server 2012 R2和Windows Server 2012的域控制器上配置,但可以在混合模式林中应用。
这种约束委派的风格与传统约束委派非常相似,但配置相反。
传统约束委派在msDS-AllowedToDelegateTo属性中的帐户A上配置,并定义从A到B的“传出”信任。
基于资源的约束委派在S-AllowedToActOnBehalfOfOtherIdentity属性中的帐户B上配置,并定义从A到B的“传入”信任。

PAC
微软为了访问控制而引进的一个扩展
PAC,PAC在历史上出现过的一个严重的,允许普通用户提升到域管的漏洞MS14068。
引进PAC之后的kerberos流程
- 用户向
KDC发起AS_REQ,请求凭据是用户hash加密的时间戳,KDC使用用户hash进行解密,如果结果正确返回用krbtgt hash加密的TGT票据,TGT里面包含PAC,PAC中包含用户的sid、用户所在的组。

用户凭借
TGT向KDC发起针对特定服务的TGS_REQ请求,KDC使用krbtgt hash进行解密,如果结果正确,就返回用服务hash加密的ST\Ticket(这一步不管用户有没有访问服务的权限,只要TGT正确,就返回ST\Ticket,这也是kerberoating能利用的原因:任何一个用户,只要hash正确,就可以请求域内任何一个服务的ST\Ticket,具体内容可以参考Windows内网协议学习Kerberos篇之TGSREQ& TGSREP)用户拿着
ST\Ticket去请求服务,服务使用自己的hash解密ST\Ticket。如果解密正确,就拿着PAC去KDC那边询问用户有没有访问权限,域控解密PAC。获取用户的sid、用户所在的组,再判断用户是否有访问服务的权限,有访问权限就允许用户访问(有用户hash,可以制作ST\Ticket,但是不能制作PAC,PAC自然也验证不成功,但是有些服务不去验证PAC,这是白银票据成功的前提)。
特别说明的是,PAC对于用户和服务全程都是不可见的。只有KDC能制作和查看PAC。
相关的安全问题
AS_REQ & AS_REP
PTH\ PTK
连接配置的时候允许使用hash进行认证,不是只有账号密码才能认证。

由于在进行认证的时候,是使用用户hash加密时间戳,所以在使用密码进行登录的情况下,也是先把密码加密成hash后再进行认证。
因此在只有用户hash,没有明文密码的情况下也是可以进行认证的。
不管是rubeus还是impacket里面的相关脚本都是支持直接使用hash进行认证。
1 | 如果 hash 是 ntlm hash ,然后加密方式是 rc4 ,这种就算做是 pass the hash |
在很多地方,不支持rc4加密方式的时候,使用pass the key不失为一种好方法。
用户名枚举
域内没有域账号的情况下进行用户名枚举
有域账号的情况的下可以直接通过LDAP查询(域机器提到System权限后,其机器账号也是域账号)
进行AS_REQ时,用户名存在但密码错误与用户名不存在的相应包有不同,通过这个比较就可以写脚本改变cname的值进行用户名枚举(https://daiker.gitbook.io/windows-protocol/kerberos/1#2.-yong-hu-ming-mei-ju)。
Password Spraying(密码喷洒)
在已有用户名的时候,可以尝试爆破密码。
进行AS_REQ时,用户名存在且密码正确与用户名存在但密码错误的相应包有不同。
实战中,都会使用“密码喷洒(Password Spraying)”的技术来进行测试和攻击。因为针对同一个用户的连续密码猜测会导致帐户被锁定,所以只有对所有用户同时指定唯一的密码去登录尝试,消除帐户被锁定的概率从而增加破解成功率。
AS-REPRoasting(用户明文口令爆破)
对于域用户,设置了选项
Do not require Kerberos preauthentication(不要求Kerberos预身份验证)

此时向域控制器的88端口发送AS_REQ请求,对收到的AS_REP内容重新组合(enc-part底下的ciper,因为这部分是使用用户hash加密session-key,我们通过进行离线爆破就可以获得用户hash),能够拼接成”Kerberos 5 AS-REP etype 23”(18200)的格式,可以使用hashcat对其破解,最终获得该用户的明文口令。
黄金票据
AS确认Client端登录者用户身份,通过伪造的TGT,可以获取任意Kerberos的访问权限,由krbtgt NTLM Hash加密。
伪造条件
1 | 1、域名称 |
在Kerberos认证中,Client通过AS(Authentication Service)认证后,AS会给Client一个Logon Session Key和TGT,而Logon Session Key并不会保存在KDC中,krbtgt的NTLM Hash又是固定的(此账户一般不会改密码),所以只要得到krbtgt的NTLM Hash,就可以伪造TGT和Logon Session Key来进入下一步Client与TGS的交互。
有了金票后,就可以跳过AS验证,直接同KDC交互,不用验证账户和密码,所以也不用担心域管密码被修改。
TGS_REQ & TGS_REP
PTT(pass the ticket)
Kerbreos除了第一步AS_ERQ是使用 时间戳 加密用户hash验证之外,其他的步骤的验证都是通过票据,这个票据可以是TGT(Ticket Granting Ticket)或者TGS票据(Server Ticket/Ticket)。因为票据里面的内容主要是session_key和ticket(使用服务hash加密的,服务包括krbtgt),拿到票据之后,我们就可以用这个票据来作为下阶段的验证了。
kerberosting(服务hash爆破)
因为
TGS_REP里面ticket里的enc_part(是ticket里面的enc_part,不是最外层的enc_part,最外层的enc_part是使用AS_REP里面的session_key加密的,这个session_key我们已经有了,没有意义),是使用要请求的服务的hash加密的,所以我们可以通过爆破获得服务的hash。

这个问题存在的另外一个因素是因为用户向KDC发起TGS_REQ请求,不管用户对服务有没有访问权限,只要TGT正确,那么肯定会返回TGS。
其实AS_REQ里面的服务就是krbtgt,也就是说这个同样用于爆破AS_REP里面的ticket部分的encpart得到krbtgt的hash,但网上没出现这种攻击方式是因为krbtgt的密码是随机生成的,我们也跑不出来.
白银票据
Client向Server发送服务请求,通过伪造的Ticket,只能访问指定的服务,如cifs、http、mssql等,由服务账号NTLM Hash加密。
伪造条件
1 | 1、域名称 |
在Kerberos认证中的第⑤-⑥步,Client带着Ticket和Authenticator3向Server上的某个服务进行请求,Server接收到Client的请求之后,通过自己的Master Key解密Ticket,从而获得Session Key。通过Session Key解密Authenticator3,进而验证对方的身份,验证成功就允许Client访问Server上的指定服务了。
所以我们只需要知道Server用户的Hash就可以伪造出一个Ticket,且不会经过KDC,但是伪造的Ticket只对部分服务起作用(已经在TGT的PAC里,通过SID的值限定了给Client授权的服务)。
非约束委派攻击
如果我们找到配置了 非约束的委派的账户,比如
JACKSON-PC$,并且通过一定手段拿下该账户的权限,然后诱导域管访问该JACKSON-PC$,这个时候域管会将自己TGT发送到JACKSON-PC$并缓存到LSASS中,那我们就可以从LSASS中导出域管的TGT票据,然后通过PTT,从而拥有域管的权限。
约束委派攻击
如果我们找到配置了 约束委派的服务账号,比如
JACKSON-PC$,并且通过一定手段拿下该账号所在的机子。我们就可以利用这个服务账号代表任意用户 (重点:服务代表用户获得针对服务自身的kerberos票据这个过程,服务不需要用户凭据) 进行s4u2self获得一个可转发的票据,然后把获取到的票据用于s4u2proxy(作为AddtionTicket),从而获取一个可转发的TGS,服务就可以代替任意用户访问另外一个服务(既被配置的约束委派的服务:cifs/WIN-JQO4OSMOGK2.JMU.com)。
相较于非约束的委派,约束的委派并不需要用户过来访问就可以代表该用户,但是只能访问特定的服务,不像非约束的委派哪个可以访问任意服务。
1 | 对于 HOST SPN,可以实现完全的远程接管。 |
基于资源的约束委派攻击
基于资源的约束委派具有传统的约束委派的所有安全问题,但是相较于传统的约束委派。基于资源的约束委派的利用又相对较为简单。
主要体现为,普通的约束委派的配置需要SeEnableDelegation权限,而这个权限通常仅授予Domain Admins。因此我们对普通的约束委派的利用,往往在于寻找域内已有的约束委派,再利用。
但是对于基于资源的约束委派,假如我们已经拥有服务账号1,那么只要具备用户2的LDAP权限,这样就可以配置服务1对服务2的约束委派(在服务账户2的用户属性上配置S-AllowedToActOnBehalfOfOtherIdentity为1的sid),服务1就可以控制服务2。
PAC
MS14068
补丁编号是KB3011780,域里面最严重的漏洞之一,它允许任意用户提升到域管权限。
该漏洞最本质的地方在于Microsoft Windows Kerberos KDC无法正确检查Kerberos票证请求随附的特权属性证书(PAC)中的有效签名,这里面的签名就是上面提到的服务检验和和KDC校验和。导致用户可以自己构造一张PAC。 签名原本的设计是要用到HMAC系列的checksum算法,也就是必须要有key的参与,我们没有krbtgt的hash以及服务的hash,就没有办法生成有效的签名,但是问题就出在,实现的时候允许所有的checksum算法都可以,包括MD5。那我们只需要把PAC进行md5,就生成新的校验和。这也就意味着我们可以随意更改PAC的内容,完了之后再用md5给他生成一个服务检验和以及KDC校验和。在MS14-068修补程序之后,Microsoft添加了一个附加的验证步骤,以确保校验和类型为KRB_CHECKSUM_HMAC_MD5。
https://daiker.gitbook.io/windows-protocol/kerberos/3#0x03-xiang-guan-an-quan-wen-ti
参考文章
https://daiker.gitbook.io/windows-protocol/kerberos
https://payloads.online/archivers/2018-11-30/1/

