Kerberos协议

Kerberos是一种计算机网络授权协议,用来在非安全网络中,对个人通信以安全的手段进行身份认证

Kerberos是一种计算机网络认证协议 ,其设计目标是通过密钥系统为网络中通信的客户机(Client)/服务器(Server)应用程序提供严格的身份验证服务,确保通信双方身份的真实性和安全性。不同于其他网络服务,Kerberos协议中不是所有的客户端向想要访问的网络服务发起请求,他就能建立连接然后进行加密通信,而是在发起服务请求后必须先进行一系列的身份认证,包括客户端和服务端两方的双向认证,只有当通信双方都认证通过对方身份之后,才可以互相建立起连接,进行网络通信。即Kerberos协议的侧重在于认证通信双方的身份,客户端需要确认即将访问的网络服务就是自己所想要访问的服务而不是一个伪造的服务器,而服务端需要确认这个客户端是一个身份真实,安全可靠的客户端,而不是一个想要进行恶意网络攻击的用户。
Kerberos协议中存在三个角色,分别是:
客户端(Client):发送请求的一方
服务端(Server):接收请求的一方
密钥分发中心(Key distribution KDC)
密钥分发中心又分为两个部分,分别是:
AS(Authentication Server):认证服务器,专门用来认证客户端的身份并发放客户用于访问TGS的TGT(票据授予票据)
TGS(Ticket Granting ticket):票据授予服务器,用来发放整个认证过程以及客户端访问服务端时所需的服务授予票据(ticket)

名词解释

Principal:安全个体,具有唯一命名的客户端或服务器,以便于验证和管理。命名规则:主名称(primary)+实例(instance,可选)+领域(realm),如hive/admin@EXAMPLE.COM。主名称可以是任意的字符串或者就是操作系统下的用户名等;实例用于给某个角色的用户或者服务来创建Principal;而域则概念上类似于DNS上的domain域名,可以用来定义一组相似的对象,或者说realm定义了一组principals。

Ticket:票据,一条包含客户端标识信息、会话密钥和时间戳的记录,客户端用它来向服务器认证自己,Kerberos协议中的票据主要有两种类型:TGT(Ticket-Granting Ticket)和服务票据(Service Ticket)。

Krbtgt账户:krbtgt用户,是系统在创建域时自动生成的一个帐号,其作用是密钥分发中心的服务账号,其密码是系统随机生成的,无法登录主机

PAC:这是微软为了访问控制而引进的一个扩展,即特权访问证书。
PAC (Privilege Attribute Certificate,特权属性证书),其中所包含的是各种授权信息、附加凭据信息、配置文件和策略信息等。例如用户所属的用户组, 用户所具有的权限等。在最初的RFC1510中规定的标准Kerberos认证过程中并没有PAC,微软在自己的产品中所实现的Kerberos流程加入了PAC的概念,因为在域中不同权限的用户能够访问的资源是不同的,因此微软设计PAC用来辨别用户身份和权限。
在一个正常的Kerberos认证流程中,KDC返回的TGT和ST中都是带有PAC的。这样做的好处就是在以后对资源的访问中, 服务端再接收到客户请求的时候不再需要借助KDC的帮助提供完整的授权信息来完成对用户权限的判断, 而只需要根据请求中所包含的PAC信息直接与本地资源的ACL相比较做出判断。

PAC的结构:
PAC的顶部结构如下:

typedef unsigned long ULONG;
typedef unsigned short USHORT;
typedef unsigned long64 ULONG64;
typedef unsigned char UCHAR;

// PAC_INFO_BUFFER结构包含了关于PAC的每个部分的信息
typedef struct _PAC_INFO_BUFFER {    
   ULONG ulType;    	// ulType表示包含此缓冲区中包含的数据的类型
   ULONG cbBufferSize;  // cbBufferSize表示缓冲大小  
   ULONG64 Offset;		// Offset表示缓冲偏移量
} PAC_INFO_BUFFER;

// PAC顶部结构
typedef struct _PACTYPE {
   ULONG cBuffers;		// cBuffers表示包含数组缓冲区中的条目数
   ULONG Version;		// Version表示版本
   PAC_INFO_BUFFER Buffers[1];	// Buffers包含一个PAC_INFO_BUFFER结构的数组
} PACTYPE;

PAC_INFO_BUFFER结构包含了关于PAC的每个部分的信息,其中 ulType表示包含此缓冲区中包含的数据的类型。它可能数据类型是以下之一:

Logon Info (1)
Client Info Type (10)
UPN DNS Info (12)
Server Cechksum (6)
Privsvr Cechksum (7)

PAC凭证信息:
LOGON INFO类型的PAC_LOGON_INFO包含Kerberos票据客户端的凭据信息。数据本身包含在一个KERB_VALIDATION_INFO结构中,该结构是由NDR编码的。NDR编码的输出被放置在LOGON INFO类型的PAC_INFO_BUFFER结构中。如图所示,是WireShark抓包的PAC_LOGON_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

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以外的具有访问服务密钥的人放入票据中。
签名包含在以下结构中:

typedef struct _PAC_SIGNATURE_DATA {
    ULONG SignatureType;			// 此字段包含用于创建签名的校验和的类型,校验和必须是一个键控的校验和。
    UCHAR Signature[1];     		// 此字段由一个包含校验和数据的字节数组组成。字节的长度可以由包装PAC_INFO_BUFFER结构来决定。
} PAC_SIGNATURE_DATA, *PPAC_SIGNATURE_DATA;

KDC验证PAC:
我们注意到,PAC中是有两个签名的:PAC_SERVER_CHECKSUM和 PAC_PRIVSVR_CHECKSUM。一个是使用服务密钥(PAC_SERVER_CHECKSUM)进行签名,另一个使用KDC密钥(PAC_PRIVSVR_CHECKSUM)进行签名。当服务端收到客户端发来的AP-REQ消息时,只能校验PAC_SERVER_CHECKSUM签名,而并不能校验PAC_PRIVSVR_CHECKSUM签名。因此,正常来说如果需要校验PAC_PRIVSVR_CHECKSUM签名的话,服务端还需要将客户端发来的ST服务票据中的PAC签名发给
但是,由于大部分服务默认并没有KDC验证PAC这一步(需要将目标服务主机配置为验证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协议工作的基本步骤:

认证阶段:客户端向AS发送身份请求,并提供用户名和口令。AS验证客户端的身份,如果验证通过,AS会生成一个加密的票据(Ticket-Granting Ticket,TGT)和会话密钥。这个TGT包含了客户端访问TGS所需的身份认证信息,会话密钥则是用于客户端和TGS之间的安全通信。
获取服务票据:客户端使用之前从AS获取的会话密钥对TGT进行解密,然后携带解密后的TGT向TGS发送请求,请求访问特定服务的票据。TGS验证客户端的TGT的有效性,如果验证通过,TGS会生成一个用于访问特定服务的票据(Service Ticket)和另一个会话密钥。这个服务票据包含了客户端访问特定服务所需的身份认证信息。

客户端访问服务:

客户端使用从TGS获取的服务票据和会话密钥,向目标服务发送请求。
服务验证客户端的服务票据的有效性,如果验证通过,服务会与客户端使用共享的会话密钥进行通信。

Kerberos认证的前提条件:

Kerberos协议他是一个“限权”的认证协议,Kerberos中会自带一个数据库,这个数据库会由创建Kerberos的运维人员提前在库中添加好整个系统中拥有使用Kerberos认证权限的用户和网络服务。在后续的认证中也是根据数据库中是否存在该用户和服务来判断该对象是否能够通过认证服务的; 所有使用Kerberos协议的用户和网络服务,在他们添加进Kerberos系统中时,都会根据自己当前的密码(用户密码,人为对网络服务随机生成的密码)生成一把密钥存储在Kerberos数据库中,且Kerberos数据库也会同时保存用户的基本信息(例如: 用户名,用户IP地址等)和网络服务的基本信息(IP,Server Name);
Kerberos中存在的三个角色,只要是发生了两两之间的通信,那么都需要先进行身份认证;
认证步骤分为三个阶段

AS_REQ & AS_REP
TGS_REQ & TGS_REP
AP-REQ & AP-REP

AS_REQ & AS_REP
为了获得能够用来访问服务端服务的票据,客户端首先需要来到KDC获得服务授予票据(Ticket)。由于客户端是第一次访问KDC,此时KDC也不确定该客户端的身份,所以第一次通信的目的为KDC认证客户端身份,确认客户端是一个可靠且拥有访问KDC权限的客户端,过程如下:
1、 客户端用户向KDC以明文的方式发起请求,该次请求中携带了自己的用户名、主机IP、和当前时间戳;
2、 KDC当中的AS(Authentication Server)接收请求(AS是KDC中专门用来认证客户端身份的认证服务器)后去Kerberos认证数据库中根据用户名查找是否存在该用户,此时只会查找是否有相同用户名的用户,并不会判断身份的可靠性;
3、 如果没有该用户名,认证失败,服务结束;如果存在该用户名,则AS认证中心便认为用户存在,此时便会返回给客户端,其中包含两部分内容:
第一部分内容称为TGT,它叫做票据授予票据,客户端需要使用TGT去KDC中的TGS(票据授予中心)获取访问网络服务所需的Ticket(服务授予票据),TGT中包含的内容有Kerberos数据库中存在的该客户端的Name、IP、当前时间戳、客户端即将访问的TGS的Name、TGT的有效时间以及一把用于客户端和TGS间进行通信的Session_key(CT_SK)。整个TGT使用TGS密钥加密,客户端是解密不了的,由于密钥从没有在网络中传输过,所以也不存在密钥被劫持破解的情况。
第二部分内容是使用客户端密钥加密的一段内容,其中包括用于客户端和TGS间通信的Session_key(CT_SK),客户端即将访问的TGS的Name以及TGT的有效时间,和一个当前时间戳。该部分内容使用客户端密钥加密,所以客户端在拿到该部分内容时可以通过自己的密钥解密。如果是一个假的客户端,那么他是不会拥有真正客户端的密钥的,因为该密钥也从没在网络中进行传输过。这也同时认证了客户端的身份,如果是假客户端会由于解密失败从而中断认证流程。

TGS_REQ & TGS_REP
此时的客户端收到了来自KDC(其实是AS)的响应,并获取到了其中的两部分内容。客户端会用自己的密钥将第二部分内容进行解密,分别获得时间戳,自己将要访问的TGS的信息,和用于与TGS通信时的密钥CT_SK。
首先它会根据时间戳判断该时间戳与自己发送请求时的时间的差值是否大于5分钟,如果大于5分钟则认为该AS是伪造的,认证至此失败。如果时间戳合理,客户端便准备向TGS发起请求,其次请求的目的是为了获取能够访问目标网络服务的服务授予票据(Ticket)。
在第二次通信请求中,客户端将携带三部分内容交给KDC中的TGS,第二次通信过程具体如下所述:
客户端行为:
1、 客户端使用CT_SK加密将自己的客户端信息发送给KDC,其中包括客户端名、IP、时间戳;
2、 客户端将自己想要访问的Server服务以明文的方式发送给KDC;
3、 客户端将使用TGS密钥加密的TGT也原封不动的也携带给KDC;
TGS行为:
1、 此时KDC中的TGS(票据授予服务器)收到了来自客户端的请求。它首先根据客户端明文传输过来的Server服务IP查看当前Kerberos系统中是否存在可以被用户访问的该服务。如果不存在,认证失败结束。如果存在,则继续接下来的认证。
2、 TGS使用自己的密钥将TGT中的内容进行解密,此时它看到了经过AS认证过后并记录的用户信息,一把Session_Key即CT_SK,还有时间戳信息,他会根据时间戳判断此次通信是否真是可靠有无超出时延。
3、 如果时延正常,则TGS会使用CK_SK对客户端的第一部分内容进行解密(使用CT_SK加密的客户端信息),取出其中的用户信息和TGT中的用户信息进行比对,如果全部相同则认为客户端身份正确,方可继续进行下一步。
4、 此时KDC将返回响应给客户端,响应内容包括:
(1) 第一部分:用于客户端访问网络服务使用Server密码加密的ST(Server Ticket),其中包括客户端的Name,IP,需要访问的网络服务的地址Server IP,ST的有效时间,时间戳以及用于客户端和服务端之间通信的CS_SK(Session Key)。
(2) 第二部分:使用CT_SK加密的内容,其中包括CS_SK和时间戳,还有ST的有效时间。由于在第一次通信的过程中,AS已将CT_SK通过客户端密码加密交给了客户端,且客户端解密并缓存了CT_SK,所以该部分内容在客户端接收到时是可以自己解密的。

AP-REQ & AP-REP
此时的客户端收到了来自KDC(TGS)的响应,并使用缓存在本地的CT_SK解密了第二部分内容(第一部分内容中的ST是由Server密码加密的,客户端无法解密),检查时间戳无误后取出其中的CS_SK准备向服务端发起最后的请求。
客户端:
客户端使用CK_SK将自己的主机信息和时间戳进行加密作为交给服务端的第一部分内容,然后将ST(服务授予票据)作为第二部分内容都发送给服务端。
服务端:
服务器此时收到了来自客户端的请求,它会使用自己的密钥,即Server密钥将客户端第二部分内容进行解密,核对时间戳之后将其中的CS_SK取出,使用CS_SK将客户端发来的第一部分内容进行解密,从而获得经过TGS认证过后的客户端信息,此时它将这部分信息和客户端第二部分内容带来的自己的信息进行比对,最终确认该客户端就是经过KDC认证的具有真实身份的客户端,是它可以提供服务的客户端。此时服务端返回一段使用CT_SK加密的表示接收请求的响应给客户端,在客户端收到请求之后,使用缓存在本地的CS_ST解密之后也确定了服务端的身份(其实服务端在通信的过程中还会使用数字证书证明自己身份)。
至此,第三次通信完成。此时也代表着整个Kerberos认证的完成,通信的双方都确认了对方的身份,此时便可以进行整个网络的通信了。

Kerberos攻击方式

Kerberos 认证并不是天衣无缝的,这其中也会有各种漏洞能够被我们利用

黄金票据(Golden ticket)

针对黄金票据的攻击发生在这一阶段。因为TGT黄金票据是由krbtgt用户的Hash加密的,所以如果我们获取了这个Hash,就可以用Mimikatz伪造任意TGT(可自己制作一个TGT认购权证)。总共需要以下信息:
要伪造的域用户(名称、Hash),一般是域管理员;
域名;
域的SID;
krbtgt用户的Hash;
黄金、白银票据主要为了维持权限,尤其是黄金票据,是后门的万能钥匙

白银票据(Silver ticket)

白银票据不同于黄金票据,白银票据的利用过程是伪造 TGS,通过已知的授权服务密码生成一张可以访问该服务的 TGT。因为在票据生成过程中不需要使用KDC,所以可以绕过域控制器,很少留下日志。而黄金票据在利用过程中由 KDC 颁发 TGT,并且在生成伪造的 TGT 得 20 分钟内,TGS不会对该TGT 的真伪进行效验。白银票据依赖于服务账号的密码散列值,这不同于黄金票据利用需要使用 Krbtgt 账号的密码哈希值,因此更加隐蔽。
在TGS_REP阶段,TGS_REP里面的ticket的enc-part是使用服务的Hash进行加密的,如果我们拥有服务的Hash,就可以给我们自己签发任意用户的TGS票据,这个票据也称为白银票据。相较于黄金票据,白银票据使用要访问服务的Hash,而不是krbtgt的Hash,由于生成的是TGS票据,不需要跟域控打交道,但是白银票据只能访问特定服务。但是要注意一点的是,伪造的白银票据没有带有有效KDC签名的PAC。如果将目标主机配置为验证KDC PAC签名,则银票将不起作用。

AS_REP Roasting攻击

AS-REP Roasting攻击前提条件:域用户设置了“不要求kerberos预身份验证,需要一台可与KDC进行通信的主机/用户。针对AS-REP Roasting攻击主要分为两步:1、获取AS-REP响应包中用户Hash加密的Login Session Key。
2、对上一步获得的Login Session Key进行解密。
AS_REP阶段,最外层的enc-part是用用户密码Hash加密的。对于域用户,如果设置了选项 “Do not require Kerberos preauthentication” ,此时向域控器的88端口发送AS_REQ请求,对收到的AS_REP内容(enc-part底下的ciper,因为这部分是使用用户的Hash加密的Login Session Key,我们通过进行离线爆破就可以获得用户Hash)重新组合,能够拼接成 “Kerberos 5 AS_REP etype 23”(18200) 的格式,接下来可以使用hashcat对其破解。
获取Hash:Rubeus,ASREPRoast.ps1脚本。对于非域内机器,想要获取域内设置了“不需要kerberos预身份验证”的域内账号,可以使用ADFind执行如下命令来进行过滤查询,这个前提也得拥有一个有效的域用户账号和密码。查询出设置了“不需要kerberos预身份验证”的域内账号之后,再使用ASREPRoast.ps1脚本或impacket 下的 GetNPUsers.py 脚本获取针对指定用户的用户 Hash 加密的 Login Session Key 也就是 Hash。然后运行命令调用 ASREPRoast.ps1 脚本获取针对指定用户 test 的用户 Hash 加密的 Login Session Key 也就是 Hash,该格式可以被 John 直接爆破。也可以使用 impacket 下的 GetNPUsers.py 脚本,只需要把上一步过滤出的设置了 “不需要 kerberos 预身份验证” 的域内账号写在 users.txt 文件中即可运行如下命令获取针对指定用户 test 的用户 Hash 加密的 Login Session Key 也就是 Hash,该格式可以被 John 直接爆破。
或者可以直接进行盲爆,这就不需要有效的域用户账号密码。适用于攻击者在域外且没有一个有效的域账号密码。通过将大量用户写在 users.txt 文件中,运行如下命令自动获取指定 users.txt 文件中的用户是否设置了 “不需要 kerberos 预身份验证” 属性,并获取设置了 “不需要 kerberos 预身份验证” 账号的用户 Hash 加密的 Login Session Key

关于爆破hash,可以执行如下命令使用 John 对第一步获取到的 Hash 进行爆破,但是爆破 的成功与否也与我们的字典强度有关。

john --wordlist=/opt/pass.txt hash.txt

如果想用 hashcat 进行爆破的话,由于第一步获取的 hash 格式并不能直接被 hashcat 所爆破,所以我们得手动添加 $23 到如图所示位置。

Kerberoast攻击

Kerberoasting 是一种允许攻击者窃取使用 RC4 加密的 KRB_TGS 票证的技术,以暴力破解应用程序服务 HASH 来获取其密码。Kerberos 使用所请求服务的 NTLM 哈希来加密给定服务主体名称 (SPN) 的 KRB_TGS 票证。当域用户向域控制器 KDC 发送针对已注册 SPN 的任何服务的 TGS 票证请求时,KDC 会生成 KRB_TGS
在TGS_REP阶段,由于enc-part是用服务密码Hash加密的,所以我们可以通过爆破获得服务的Hash。
域上的任何经过身份验证的用户,只要TGT没问题,就能够从TGS处根据SPN请求ST,然后进行暴力破解。SPN格式:SERVICE/host.name。可以用Windows自带的SetSPN.exe查询SPN, 命令为setspn -Q /。之后,可以用mimikatz指定服务目标、导出ST,用tgsrepcrack破解,相关工具有很多。
Kerberoasting攻击主要步骤如下:
1.发现SPN服务
2.使用工具向 SPN 请求 TGS 票据
3.转储 .kirbi 或 ccache 或服务 HASH 的 TGS 票据
4.将 .kirbi 或 ccache 文件转换为可破解格式
5.使用hashcat等工具配合字典进行暴力破解
并且随着技术的不断更新,kerberoasting 攻击的工具与手段也越来越多,因此我们把多个步骤的攻击叫做旧 kerberoasting 攻击,单个步骤的攻击叫做新 kerberoasting 攻击

MS14-068

这里便用到了我们之前所讲到的 PAC 这个东西,PAC 是用来验证 Client 的访问权限的,它会被放在 TGT 里发送给 Client,然后由Client 发送给 TGS。但也恰恰是这个 PAC 造成了MS14-068这个漏洞。该漏洞是位于 kdcsvc.dll 域控制器的密钥分发中心(KDC)服务中的 Windows 漏洞,它允许经过身份验证的用户在其获得的票证 TGT中插入任意的 PAC 。普通用户可以通过呈现具有改变了 PAC 的 TGT 来伪造票据获得管理员权限。

参考
https://blog.csdn.net/weixin_46944519/article/details/126828074
https://blog.csdn.net/qq_36540900/article/details/127014448
https://blog.csdn.net/weixin_45954730/article/details/135481514
本文仅供学习参考

posted on 2024-07-22 12:36  m0userathxy  阅读(4)  评论(0编辑  收藏  举报