kerberos协议是由麻省理工学院提出的一种网络身份验证协议,提供了一种在开放的非安全网络中认证识别用户身份信息的方法。它旨在通过使用秘钥加密技术为客户端/服务端应用提供强身份验证,使用kerberos这个名字是因为需要三方的共同参与才能完成一次认证流程。目前主流使用的kerberos版本为2005年RFC4120标准定义的KerberosV5版本,Windows、Linux和Mac OS均支持Kerberos协议
Kerberos基础
在Kerberos协议中,主要有以下三个角色:
- 访问服务的客户端:Kerberos客户端是代表需要访问资源的用户进行操作的应用程序,例如打开文件、查询数据库、打印文档。每个Kerberos客户端在访问资源前都会请求身份验证。
- 提供服务的服务端。域内提供服务的服务端,服务端都有一个独一的SPN。
- 提供认证服务的KDC(Key Distribution Center密钥分发中心):KDC秘钥发行中心是一种网络服务,它向活动目录域内的用户和计算机提供会话票据和临时会话秘钥,其服务账户为krbtgt。KDC作为活动目录域服务ADDS的一部分运行在每个域控制器上。
krbtgt账户,该用户是在创建活动目录时系统自动创建的一个账号,其作用是KDC秘钥发行中心的服务账号,其密码是系统随机生成的,无法正常登录主机。
Kerberos是一种基于票据Ticket的认证方式。客户端想要访问服务端的某个服务,首先需要购买服务端认可的ST服务票据(Service Ticket)。客户端在访问服务之前需要先买好票,等待服务验票之后才能访问,但是这张票并不能直接购买,需要一张TGT认购权证(Ticket Granting Ticket)。也就是说,客户端在买票之前必须要先获得一张TGT认购权证。TGT认购权证和ST服务票据均是由KDC(秘钥分发中心)发放,因为KDC是运行在域控制器上的,所以说TGT认购权证和ST服务票据均是由域控发放。
Kerberos使用TCP/UDP 88端口进行认证,使用TCP/UDP 464端口进行密码重设
Kerberos中一些名词的简称及含义:
简称 | 全拼 |
---|---|
DC | Domain Controller,域控 |
krbtgt | KDC 密钥发行中心服务账户 |
KDC | Key Distribution Center:密钥分发中心,由域控担任 |
AD | Active Directory:活动目录,里面包含域内用户数据库 |
AS | Authentication Service:认证服务 |
TGT | Ticket Granting Ticket:TGT 认购权证,由 KDC 的 AS 认证服务发放 |
TGS | Ticket Granting Service:票据授予服务 |
ST | Service Ticket:ST 服务票据,由 KDC 的 TGS 票据授予服务发放 |
Kerberos协议有两个基础认证模块:AS_REQ & AS_REP 和 TGS_REQ & TGS_REP,以及微软扩展的两个认证模块S4U和PAC。S4U是微软为了实现委派而扩展的模块,分为S4U2Self和S4U2Proxy。在Kerberos最初设计的流程里只说明了如何证明客户端的真实身份,但是并没有说明客户端是否有权限访问该服务,因为域中不同权限的用户能够访问的资源是不同的。因此微软为了解决权限这个问题,引入了PAC(Privilege Attribute Certificate,特权属性证书)的概念。
PAC特权属性证书
PAC(Privilege Attribute Certificate,特权属性证书),其中包含的是各种授权信息、附加凭据信息、配置文件和策略信息等。例如用户所属的用户组,用户所具有的权限等,微软在自己的产品中所实现的额Kerberos流程加入了PAC概念,因为在域中不同权限的用户能够访问的资源是不同的,因此微软设计PAC用来辨别用户身份和权限。
在一个正常的Kerberos认证流程中,KDC返回的TGT认购权证和ST服务票据中都是带有PAC的,这样做的好处就是在以后对资源的访问中,服务端再接收到客户请求的时候不再需要借助KDC的帮助提供完整的授权信息来完成对用户权限的判断,而只需要根据请求中的包含的PAC信息直接与本地的ACL相比较做出裁决。
1、PAC结构
- PAC的顶部结构
typedef unsigned long ULONG;
typedef unsigned short USHORT;
typedef unsigned long64 ULONG64;
typedef unsigned char UCHAR;
typedef struct _PACTYPE {
ULONG cBuffers;
ULONG Version;
PAC_INFO_BUFFER Buffers[1];
} PACTYPE;
- cBuffers:包含数组缓冲区中的条目数
- Version:版本
- Buffers:包含一个PAC_INFO_BUFFER结构的数组
PAC_INFO_BUFFER结构包含了关于PAC的每个部分信息,这部分是最重要的,结构如下:
**typedef struct **_PAC_INFO_BUFFER {
ULONG ulType;
ULONG cbBufferSize;
ULONG64 Offset;
} PAC_INFO_BUFFER;
- ultype:包含此缓冲区中包含的数据的类型,可能是以下之一
- Logon Info (1)
- Client Info Type(10)
- UPN DNS Info (12)
- Sserver Cechksum (6)
- Privsvr Cechksum (7)
- cbBufferSize:缓冲大小
- Offset:缓冲偏移量
2、PAC凭证信息
LOGON INFO类型的PAC_LOGON_INFO包含Kerberos票据客户端的凭据信息。数据本身包含在一个KERB_VALIDATION_INFO结构中,该结构是由NDR编码的。NDR编码的输出被放置在LOGON INFO类型的PAC_INFO_BUFFER结构中。如下:
**typedef struct **_KERB_VALIDATION_INFO {
FILETIME Reserved0;
FILETIME Reserved1;
FILETIME KickOffTime;
FILETIME Reserved2;
FILETIME Reserved3;
FILETIME Reserved4;
UNICODE_STRING Reserved5;
UNICODE_STRING Reserved6;
UNICODE_STRING Reserved7;
UNICODE_STRING Reserved8;
UNICODE_STRING Reserved9;
UNICODE_STRING Reserved10;
USHORT Reserved11;
USHORT Reserved12;
ULONG UserId;
ULONG PrimaryGroupId;
ULONG GroupCount;
[size_is(GroupCount)] PGROUP_MEMBERSHIP GroupIds;
ULONG UserFlags;
ULONG Reserved13[4];
UNICODE_STRING Reserved14;
UNICODE_STRING Reserved15;
PSID LogonDomainId;
ULONG Reserved16[2];
ULONG Reserved17;
ULONG Reserved18[7];
ULONG SidCount;
[size_is(SidCount)] PKERB_SID_AND_ATTRIBUTES ExtraSids;
PSID ResourceGroupDomainSid;
ULONG ResourceGroupCount;
[size_is(ResourceGroupCount)] PGROUP_MEMBERSHIP ResourceGroupIds;
} KERB_VALIDATION_INFO;
重点字段:
- Acct Name:该字段对应的值是用户 sAMAccountName 属性的值
- Full Name:该字段对应的值是用户 displayName 属性的值
- User RID:该字段对应的值是用户的 RID,也就是用户 SID 的最后部分
- Group RID:对于该字段,域用户的 Group RID 恒为 513(也就是 Domain Users 的 RID),机器用户的 Group RID 恒为 515(也就是 Domain Computers 的 RID),域控的 Group RID 恒为 516(也就是 Domain Controllers 的 RID)
- Num RIDS:用户所属组的个数
- GroupIDS:用户所属的所有组的 RID
3、PAC签名
PAC中包含两个数字签名:PAC_SERVER_CHECKSUM 和 PAC_PRIVSVR_CHECKSUM。PAC_SERVER_CHECKSUM是使用服务秘钥进行签名,而PAC_PRIVSVR_CHECKSUM是使用KDC秘钥进行签名。签名有两个原因。首先,存在带有服务秘钥的签名,以验证此PAC由服务进行了签名。其次,带有KDC秘钥的签名是为了防止不受信息的服务用无效的PAC为自己伪造票据。这两个签名分别以PAC_SERVER_CHECKSUM 和 PAC_PRIVSVR_CHECKSUM类型的PAC_INFO_BUFFER发送,在PAC数据用于访问控制之前,必须检查PAC_SERVER_CHECKSUM签名,验证客户端是否知道服务的秘钥。而PAC_PRIVSVR_CHECKSUM签名验证是可选的,默认不开启,它用于验证PAC是否由KDC签发,而不是由KDC以外的具有访问服务密钥的人放入票据
4、KDC验证PAC
PAC中是有两个签名的:PAC_SERVER_CHECKSUM 和 PAC_PRIVSVR_CHECKSUM。一个使用服务秘钥进行签名,另一个使用KDC秘钥进行签名。当服务端收到客户端发来的AP-REQ消息时,只能校验PAC_SERVER_CHECKSUM 签名,并不能校验PAC_PRIVSVR_CHECKSUM签名。因此,正常来说如果需要校验PAC_PRIVSVR_CHECKSUM签名的话,服务端还需要将客户端发来的ST服务票据中的PAC签名发给KDC校验。但是,大部分服务默认并没有开启KDC验证PAC,因此服务端就无需将ST服务票据中的PAC签名发给KDC校验了,这也是白银票据能攻击的前提,因为如果配置了需要验证PAC_PRIVSVR_CHECKSUM签名的话,服务端会将这个PAC数字签名以KRB_VERIFY_PAC的消息通过RPC协议发送给KDC,KDC再将验证这个PAC的数字签名结果以RPC返回码的形式发送给服务端,服务端就可以根据这个返回结果判断PAC的真实性和有效性了。因此如果服务主机配置了要校验PAC_PRIVSVR_CHECKSUM签名的话,就算攻击者拥有服务秘钥,可以制作ST服务票据,也不能伪造KDC的PAC_PRIVSVR_CHECKSUM签名,自然就无法通过KDC的签名校验了。
Kerberos认证流程
1、AS-REQ请求分析
AS-REQ:当域内某个用户想要访问域内某个服务时,于是输入用户名和密码,本机就会向KDC的AS认证服务发送一个AS-REQ认证请求,该请求包中包含如下信息:
- 请求的用户名(cname)。
- 域名(realm)。
- Authenticator:一个抽象的概念,代表一个验证。这里是用户密钥加密的 时间戳。
- 请求的服务名(sname):AS-REQ 这个阶段请求的服务都是 krbtgt。
- 加密类型(etype)。
- 以及一些其他信息:如版本号,消息类型,票据有效时间,是否包含 PAC,协商选项等。
2、AS-REP回复包
AS-REP:当KDC的AS认证服务接收到客户端发来的AS-REQ请求后,从活动目录数据库中取出该用户的秘钥,然后用该秘钥对请求包中的Authenticator预认证部分进行解密,如果解密成功,并且时间戳在有效的范围内,则证明请求者提供的用户秘钥正确。KDC的AS认证服务在成功认证客户端的身份之后,发送AS-REP响应包给客户端。AS-REP响应包中主要包含以下信息:
- 请求的用户名(cname)
- 域名(crealm)
- TGT 认购权证:包含明文的版本号,域名,请求的服务名,以及加密部分 enc-part。加密部分用 krbtgt 密钥加密。加密部分包含 Logon Session Key、用户名、域名、认证时间、认证到期时间和 authorization-data。 authorization-data 中包含最重要的 PAC 特权属性证书(包含用户的 RID, 用户所在组的 RID) 等
- enc_Logon Session Key:使用用户密钥加密 Logon Session Key 后的 值,其作用是用于确保客户端和 KDC 下阶段之间通信安全。也就是 AS- REP 中最外层的 enc-part
- 以及一些其他信息:如版本号,消息类型等
3、TGS-REQ & TGS-REP
客户端在收到KDC的AS-REP回复后,使用用户秘钥解密enc_Logon Session Key(也就是最外层的 enc-part),得到Logon Session Key,并且也拿到了TGT认购权证,之后它会在本地缓存此TGT认购权证和Logon Session Key。现在客户端需要凭借这张TGT认购权证向KDC购买相应的ST服务票据。ST服务票据是KDC另一个服务TGS票据授予服务发放的,在这个阶段,微软引入两个扩展子协议S4u2self 和 S4u2Proxy。
3.1 TGS-REQ请求
TGS-REQ:客户端拿着上一步获得的TGT认购权证发起TGS-REQ请求,向KDC购买指定服务的ST服务票据,请求主要包含如下信息。
- 域名(realm)
- 请求的服务名(sname)
- TGT 认购权证
- Authenticator:一个抽象的概念,代表一个验证。这里使用 Logon Session Key 加密的时间戳
- 加密类型(etype)
- 以及一些其他信息:如版本号,消息类型,协商选项,票据到期时间等
TGS-REP回复包
TGS-REP:KDC的TGS服务接收到TGS-REQ请求之后,首先使用krbtgt秘钥解密TGT认购权证中加密部分得到Logon Session Key和PAC等信息,如果能解密成功则说明该TGT认购权证是KDC颁发的,然后验证PAC的签名,如果签名正确,则证明PAC未经过篡改,然后使用Logon Session Key解密Authenticator得到的时间戳等信息,如果能够解密成功,并且票据时间在范围内,则验证了会话的安全性。在完成上述的检测后,KDC的TGS服务完成了对客户端的认证,TGS服务发送响应包给客户端,响应包主要包含如下信息:
- 请求的用户名(cname)
- 域名(crealm)
- ST 服务票据:包含明文的版本号,域名,请求的服务名,以及加密部分 enc-part,加密部分用服务密钥加密。加密部分包含用户名、域名、认证 时间、认证到期时间、Service Session key 和 authorization-data。 authorization-data 中包含最重要的 PAC 特权属性证书(包含用户的 RID, 用户所在的组的 RDI) 等。
- enc_Service Session key:使用 Logon Session key 加密的 Service Session key,其作用是用于确保客户端和 KDC 下阶段之间通信安全。
- 以及一些其他信息:如版本号、消息类型等。
TGS-REP这步中KDC并不会验证客户端是否有权限访问服务端。因此,这一步不管用户有没有访问服务的权限,只要TGT正确,均会返回ST服务票据,这也就是kerberoasting能利用的原因,任何一个域内用户,都可以请求域内任何一个服务的ST服务票据。
1)ST服务票据
TGS-REP 响应包中的 ticket 便是 ST 服务票据了。ST 服务票据中包含明文显示的信息,如版本号 tkt-vno、域名 realm、请求的服务名 sname。但是 ST 服务票据中最重要的还是加密部分,加密部分是使用服务密钥加密的。加密部分主要包含 的内容有 Server Session Key、请求的用户名 cname、域名 crealm、认证时间 authtime、认证到期时间 endtime、authorization-data 等信息。最重要的还是 authorization-data 部分,这部分中包含客户端的身份权限等信息,这些信息包含在PAC中。
2)Service Session key
TGS-REP 响应包最外层的那部分便是 Service Session Key 了,其作用是用于 确保客户端和 KDC 下阶段之间通信安全,它使用 Logon Session Key 加密。
对其进行解密,它主要包含的内容是认证时间 authtime、认证到期时间 endtime、域名 srealm、请求的服务名 sname、协商标志 flags 等一些信息。 需要说明的是,在 ST 服务票据中也包含 Service Session Key。
双向认证(AP-REQ&AP-REP)
AP-REQ请求
AP-REQ:客户端接收到KDC的TGS回复后,通过缓存的Logon Session Key解密enc_Service Session key 得到Service Session Key,同时也拿到了 ST(Service Ticket)服务票据。Serivce Session Key 和 ST 服务票据会被客户端缓存。客户端访问指定服务时,将发起 AP-REQ 请求,该请求主要包含如下的内容:
- ST 服务票据(ticket)
- Authenticator:一个抽象的概念,代表一个验证。这里指 Serivce Session Key 加密的时间戳
- 以及一些其他信息:如版本号、消息类型,协商选项等
AP-REP回复包
AP-REP:这一步是可选的,当客户端希望验证提供服务的服务端时(也就是 AP- REQ 请求中 mutual-required 协商选项为 True),服务端返回 AP-REP 消息。服 务端收到客户端发来的 AP-REQ 消息后,通过服务密钥解密 ST 服务票据得到 Service Session Key 和 PAC 等信息,然后用 Service Session Key 解密 Authenticator 得到时间戳。如果能解密成功且时间戳在有效范围内,则验证了客户端的身份。验证了客户端身份后,服务端从 ST 服务票据中取出 PAC 中代表用户身份权限信息的数据,然后与请求的服务 ACL 做对比,生成相应的访问令牌。 同时,服务端会检查 AP-REQ 请求中 mutual-required 协商选项是否为 True,如果为 True 的话,说明客户端想验证服务端的身份。此时,服务端会用 Service Session Key 加密时间戳作为 Authenticator,在 AP-REP 响应包中发送给客户端 进行验证。如果 mutual-required 选项为 False 的话,服务端会根据访问令牌的权限决定是否返回相应的服务给客户端。AP-REP 响应包中主要包括如下信息:
- 版本号
- 消息类型
- enc-part:使用 Serivce Session Key 加密的时间戳
Kerberos协议的安全问题
在 AS-REQ 请求阶段,是用用户密码 Hash 或 AES Key 加密的时间戳。因此当只获得了用户密码 Hash 时,也可以发起 AS-REQ 请求,所以也就造成了 PTH 哈希传递攻击;当只获得用户密码的 AES Key 时,也可以发起 AS-REQ 请求,所以也就造成了 PTK 密钥传递攻击。
而 AS-REQ 请求包中 cname 字段的值代表用户名,这个值存在和不存在,返回的包有差异,所以可以用于枚举域内用户名,这种攻击方式被称为 域内用户枚举攻击 (当未获取到有效域用户权限时,可以使用这个方法枚举域内用户)。并且当用户名存在,密码正确和密码错误时,返回的包也不一样,所以可以进行用户名密码爆破。但是在实战中,渗透测试人员通常都会使用一种被称为 密码喷洒 (Password Spraying)的攻击方式来进行测试和攻击。对密码进行喷洒式的攻击,这个叫法很形象,因为它属于自动化密码猜测的一种。这种针对所有用户的自动密码喷洒通常是为了避免帐户被锁定,因为针对同一个用户的连续密码猜测会导 致帐户被锁定。所以只有对所有用户同时执行特定的密码登录尝试,才能增加破解的概率,消除帐户被锁定的概率。普通的爆破就是用户名固定,爆破密码,但是密码喷洒是用固定的密码去跑所有的用户名。
在 AS-REP 阶段,由于返回的 TGT 认购权证是由 krbtgt 用户的密码 Hash 加密的,因此如果我们拥有 krbtgt 的密码 hash 就可以自己制作一个 TGT 认购权证,这种攻击方式被称为黄金票据攻击。同样,在 TGS-REP 阶段,TGS_REP 里面的 ST 服务票据是使用服务的 hash 进行加密的,如果我们拥有服务的 hash,就可以签发任意用户的 ST 服务票据,这个票据也被称为白银票据,这种攻击方式被称为白银票据攻击。相较于黄金票据,白银票据使用要访问服务的 hash,而不是 krbtgt 的 hash。
在 AS-REP 阶段,Login session key 是用用户密码 Hash 加密的。对于域用户,如果设置了“Do not require Kerberos preauthentication”不需要预认证选项,此时攻击者向域控制器的 88 端口发送 AS_REQ 请求,此时域控不会做任何验证就将 TGT 认购权证和该用户 Hash 加密的 Login Session Key 返回。因此,攻击者就可以对获取到的用户 Hash 加密的 Login Session Key 进行离线破解,如果破解成功,就能得到该用户的密码明文,这种攻击方式被称为 AS-REP Roasting 攻击。
在 TGS-REP 阶段,由于 ST 服务票据是用服务 Hash 加密的。因此,如果我们能获取到 ST 服务票据,就可以对该 ST 服务票据进行利息破解,得到服务的 Hash,这种攻击方式被称为 Kerberoasting 攻击。这个问题存在的另外一个因素 是因为用户向 KDC 发起 TGS_REQ 请求,不管用户对服务有没有访问权限,只要 TGT 认购权证正确,那么 KDC 都会返回 ST 服务票据。其实 AS_REQ 里面的服务就是 krbtgt,也就是说这个攻击方式同样可以用于爆破 AS_REP 里面的 TGT 认购 权证,但是之所以没见到这种攻击方式是因为 krbtgt 的密码是随机生成的,爆破不出来