Kerberos协议
Kerberos是一种在开放的非安全网络中认证并识别用户身份信息的方法,
它旨使用密钥加密技术为客户端/服务端应用程序提供强身份认证。
目前主流的Kerberos版本是2005年的RFC4120标准的Kerberos v5,
Windows、Linux和MacOs均支持Kerberos协议。
Kerberos基础
Kerberos协议中主要有以下3种角色
1.访问服务的客户端:
Kerberos客户端代表需要访问资源的用户进行操作的应用程序,比如打开文件,查询数据库或打印文档,
每个Kerberos客户端在访问资源之前都会请求身份验证。
2.提供服务的服务端
域内提供服务的服务端,服务端都有唯一的SPN(服务主体名称)。
3.提供认证的KDC(密钥分发中心)
KDC主要是提供活动目录域内用户和计算机的会话票据和临时会话密钥,其服务账号为krbtgt
KDC作为活动目录域服务的一部分运行在每个域控制器上。
需要注意的是krbtgt账号是活动目录系统自动创建的一个账号,其作用是KDC(密钥分发中心)的服务账号,
密码是系统随机生成的,无法正常登陆主机。
Kerberos简述认证方式:
服务票据:
Kerberos认证方式被称为票据(Ticket)客户端要想访问服务端的某个服务,
需要使用服务端认可的服务票据简称ST(Service Ticket 服务票据),
客户端在访问服务端之前就需要先具备服务票据。
TGT:
客户端在申请服务端票据之前需要先拿到TGT,TGT和ST都是由KDC发放的,
KDC都运行在域控上可以看成TGT和ST都是域控发放的。
88端口和464端口:
Kerberos使用TCP/UDP 88端口进行认证,使用TCP/UDP 464端口进行密码重设。
Kerberos协议两大基础认证模块
AS_REQ & AS_REP 模块
TGS_REQ & TGS_REP模块
微软扩展的两个认证模块:
S4U(委派拓展模块):
微软实现委派而扩展的模块分为S4u2Self、S4u2Proxy。
PAC(特权属性证书):
在Kerberos最初的设计的流程里直说嘛了如何证明客户端的真实身份,
并没有说明客户端是否有权限访问该服务,因为在域中不同的权限的用户
能够访问的资源是不同的,因此微软为了解决这个权限为题引入了PAC。
PAC(特权属性证书)简述
PAC是为了解决微软在域中不同权限访问的资源是不同的问题,
因此PAC中包含了各种授权信息、附加凭据信息、配置文件、
和策略信息等,比如用户所属于的用户组,用户所拥有的权限等,
在原本的Kerberos协议是中没有PAC存在的是微软后加的,
微软设计特权属性证书是用来识别用户身份和权限。
在正常的Kerberos认证流程中,KDC(密钥分发中心)TGT(票据)和ST(服务票据)都是带有PAC
的,这样做的好处是服务端接收客户请求的时候不需要借助KDC提供完整的授权信息来完成对用户
权限的判断,只需要根据请求中所包含的PAC(特权属性证书)直接与本地资源的ACP相比较来作出裁决。
PAC结构
typedef unsigned long ULONG;
typedef unsigned long USHORT;
typedef unsigned long long64 ULONG64;
typedef unsigned char UCHAR;
typdef struct _PACTYPE{
ULONG cBuffers;
ULONG Version;
PAC_INFO_BUFFER Buffers[1]
}PACTYPE;
cBuffers:包含数据缓冲区中的条目数
Version:版本
Buffers:包括一个PAC_INFO_BUFFER结构的数组。
PAC签名
PAC主要包括两个数字签名:
1.PAC_SERVER_CHECKSUM
PAC_SERVER_CHECKSUM是使用服务密钥进行签名
2.PAC_PRIVSVR_CHECKSUM
PAC_PRIVSVR_CHECKSUM是使用KDC密钥进行签名
为什么需要PAC签名:
1.PAC_SERVER_CHECKSUM服务密钥签名,以验证此PAC已由服务签名。
2.PAC_PRIVSVR_CHECKSUM是KDC密钥签名的是为了防止不受信任的服务用无效的PAC为自己伪造票据,
需要注意:
PAC数据用于访问控制之前,必须检查PAC_SERVER_CHECKSUM签名,验证客户端是否知道服务密钥,
PAC_PRIVSVR_CHECKSUM签名的验证时可选的,默认不开启它用于验证PAC是否由KDC签发,而不是由
KDC以外的具有访问服务密钥的第三方放入票据中。
KDC验证PAC
服务端接收客户端发来的AP-REQ消息时,只能校验PAC_SERVER_CHECKSUM签名,并不能校验
PAC_PRIVSVR_CHECKSUM签名,如果要校验PAC_PRIVSVR_CHECKSUM签名服务端还需要将客户端发来的
ST中的PAC签名发给KDC进行校验,大部分服务默认没有KDC验证PAC默认未开启,如果要开启需要将目标
服务主机配置为验证KDC PAC签名,开启后ST中的PAC就发给KDC校验了。
PAC_PRIVSVR_CHECKSUM开启的情况下白银票据攻击能否成功
如果开启了KDC验证PAC,那么白银票据攻击不会成功,白银票据攻击的前提是
关闭了PAC_PRIVSVR_CHECKSUM签名认证,因为服务端会将这个PAC签名以KRB_VERIFY_PAC的消息
通过RPC协议发给KDC,KDC验证这个PAC数字签名后结果以RPC返回码形式发给服务端,服务端根据
返回结果判断PAC的真实性和有效性,就算攻击者拥有服务密钥,能够制作ST也不能伪造KDC的PAC_PRIVSVR_CHECKSUM签名,
无法通过KDC校验。
PAC在Kerberos中的优缺点
优点:
关闭KDC校验PAC
客户端在访问网络资源的时候,服务端不再需要向KDC查询授权信息,
而是直接在本地进行PAC信息域ACL比较,从而节约了网络资源。
缺点:
开启KDC校验PAC
PAC在用户认证阶段引入会导致认证耗时过长,Windows Kerberos客户端会通过RPC调用KDC
上的函数来验证PAC信息,这时候服务单域KDC之间的RPC包流量增加,PAC是微软特有的内容,
开启PAC的域中不支持装有其他操作系统的服务器,限制了域配置的灵活性。
问答小环节
1.S4U和PAC是否是Kerberos协议原本支持的模块
S4U和PAC是微软的拓展两大模块,原本的Kerberos并没太这俩模块。
2.Linux和MacOs是否支持Kerberos协议
支持,原生Kerberos协议支持Linux和MacoOs,但是缺少微软的两大拓展模块S4U和PAC。
3.S4U、PAC、ST、TGT、KDC、SPN上述名词全称是什么
S4U:(委派拓展模块)
PAC:(特权证书拓展模块)
ST:(服务票据)
TGT:(准予票据)
KDC:(密钥分发中心)
SPN:(服务主体名称)
4.域控的88端口和464端口的作用是什么
88端口:Kerberos认证端口
464端口:密码重设端口
5.KDC返回的TGT和ST是否带有PAC
在微软的Kerberos认证流程中,KDC返回的PAC都是带有PAC的,
这样可以在以后对资源的访问中,服务端接收到客户请求的时候不需要借助KDC
提供完整的授权来完成对用户权限的判断,只需要根据包含PAC语言本地资源ACL
相比较作出裁决。
6.PAC主要包括那两个数字签名
PAC_SERVER_CHECKSUM签名
PAC_PRIVSVR_CHECKSUM签名
7.KDC验证PAC默认是否开启
默认不开启因为会造成很大的网络资源使用
8.KDC验证PAC的情况下白银票据攻击能否成功
不能成功,因为就算拥有服务密钥也没有PAC_PRIVSVR_CHECKSUM签名,
无法通过KDC的PAC校验
数据包分析环境如下
用户: 10.211.55.2
域内主机: 10.211.55.16
域控: 10.211.54.4
使用getST.py请求域内主机的cifs服务ST
Kerberos认证流程
1.AS-REQ:客户端向KDC的AS(认证服务)请求TGT
2.AS-REP:身份认证通过后KDC发放TGT
3.TGS-REQ:客户端拿这TGT向KDC的TGS请求ST(服务票据)
4.TGS-REP:身份认证通过后KDC发放ST(服务票据)
5.AP-REQ:客户端拿着ST向服务端请求服务
下面为可选:
PAC_PRIVSVR_CHECKSUM签名开启校验发送PAC给KDC校验
6.AP-REP:客户端希望认证提供服务的服务端时,服务端返回该该数据
的双向认证,双向认证后的服务端返回服务资源给客户端。
AS-REP&AS-REQ
这是的AS-REQ&AS-REP请求过程,下面将简述下请求过程所包含的内容
AS-REQ:
1.请求的用户名cname
2.域名realm
3.Authenticator用户加密的时间戳
4.请求的服务名sname
5.加密类型etype
6.其他信息、如版本号、消息类型、票据有效时间、是否包含PAC、协商项目等。
AS-REP:
1.版本号、域名、用户等
2.版本号、域名、请求的服务名
3.enc-part加密部分
Logon Session Key
用户名、域名、认证时间、认证到期时间戳
PAC
PAC_SERVER_CHECKSUM签名
PAC_PRIVSVR_CHECKSUM签名
krbtgt密钥进行的加密
AS-REQ的Kerberos数据内容分析
PA-DATA pA-ENC-TIMESTAMP:
预认证,就是用户密码Hash加密时间戳作为value发送给KDC的AS,
然后KDC从活动目录中查询用户的Hash,使用用户Hash进行解密,
获得时间戳如果能解密且时间戳在一定范围内,则证明认证通过,
由于使用了用户密码Hash加密的时间戳,因此也就造成了哈希传递攻击,
需要注意的是在AS-REQ中只有PA-DATA pA-ENC-TIMESTAMP部分是加密的,
这一部分成为预认证,称为Authenticator,使用用户密码Hash或用户密码AES Key
来加密时间戳的。
PA-DATA pA-PAC-REQUEST:
启用PAC支持的扩展,这里的value对应值为True或False,
KDC根据include的值来确定返回的票据中是否需要挈带PAC。
include-pac:是否包含PAC,这里是True,说明包含PAC。
kdc-options:用于KDC协商一些设置
cname:请求的用户名,这个用户是否存在返回的包是有差异的,因此可以通过差异来进行枚举域内用户名,
当用户存在时,密码正确与否会影响返回包,因此也可以进行密码喷洒。
realm:域名
sname:请求的服务包含type和value,在AS-REQ中sname始终为krbtgt。
AS-REP数据包分析
KDC的AS接收到客户端发来的AS-REQ后,AS从活动目录库中取出该用户密码,然后用该用户密钥
对请求包中预认证部分进行解密,如果解密成功,并且时间戳在有效时间之内,则说明请求者提供的
用户密钥正确。
AS-REP中的重要字段
1.ticket:认证权证票据其中ticket中enc-part是加密部分,这部分是使用krbtgt的密码Hash加密的,
因此如果我们拥有krbtgt的Hash就可以自己制作一个ticket,这就是黄金票据攻击的原理。
TGT包含的内容:
1.tkt-vno:版本号
2.realm:域名
3.sname:服务名
4.en-part最重要的加密部分使用krbtgt账户的密钥加密,
主要包括Logon Session Key、请求的用户名cname、域名crealm、认证时间authtime、
认证到期时间endtime、authorization-data部分信息包含客户单身份等信息,这些信息包含在PAC中,
PAC凭证信息部分PAC_LOGON_INFO主要是通过User RID和Group RID来辨别用户权限的。
KDC生成PAC过程:
KDC在收到客户端发过来的AS-REQ后,从请求中取出cname字段,然后查询活动目录数据库,
找到sAMAccountName属性为cname字段的值的用户,用该用户的身份生成一个对应的PAC。
2.外层enc-part:其中Logon Session Key,这部分是用请求的用户密码Hash加密的,
作为下一阶段的认证密钥。
Logon Session Key:
AS-REP包最外层的那部分便是加密的Logon Session Key,用户确保客户端和KDC下一个阶段的通信安全,
使用请求用户的密钥加密。
解密后包含如下内容:
认证时间authtime、认证到期时间endtime、域名srealm、请求服务名sname、
协商标志flags等信息,可以看到在AS-REP中存在了两个Logon Session Key,其中一个位于TGT中由
krbtgt hash加密、另一个存在于外层enc-part中由AS-REQ中cname的用户名密钥Hash加密。
简述:TGT和加密的Logon Session Key,TGT部分是使用krbtgt密钥加密的,Long Session Key是使用用户密钥加密的。
TGS-REQ数据包分析
客户端收到KDC的AS-REP后使用用户密钥解密enc_Logon Session Key,
也就是最外层的enc-part,得到Logon Session Key,并且也获得了TGT和Logon Session
Key,之后会将这俩本地缓存现在客户端需要凭借这张TGT向KDC购买相应的ST,
ST是KDC的另一个服务TGS授权服务发放的,在这阶段微软引入了两个扩展自协议,
S4u2Self、S4u2Proxy跟委派相关。
TGS-REQ主要包含的内容如下:
域名realm
请求服务名sname
TGT
Authenticator(Longn Session key加密的时间戳)
加密类型etype
其他信息、版本号、消息类型、协商类型、到期时间等。
padata:
可以从下面的图片中看到padata中包含了ap-req,这是TGS-REQ必须携带的部分,这部分包含了AS_REP中
获取到的TGT票据和使用原始的Logon Session Key加密的时间戳。
ap-req:
TGS_REQ必须携带的部分。
ticket:AS-REQ回复包中返回的TGT。
authenticator:原始Logon Session Key加密的时间戳,用于保证会话安全,该字段主要用于下一阶段的会话安全
认证,确保下一阶段的会话安全,TGS-REQ的ap-req中的authenticator字段的值使用的是上一步AS-REP中返回
Logon Session Key加密的时间戳。
TGS-REP数据包分析
KDC的TGS服务接收到TGS-REQ之后会进行如下操作,首先使用krbtgt密钥解密
TGT中的加密部分,得到Logon Session Key和PAC等信息,解密成功则说明该TGT是
KDC颁发的,然后验证PAC的签名,签名正确证明PAC未经过篡改,最后使用Logon Session
Key解密authenticator得到时间戳等信息,Logon Session Key解密authenticator得到时间戳
信息,如果能够解密成功,并且票据时间在有效范围,则验证了会话安全性,在完成上述检测后
KDC的TGS完成了对客户端的认证,TGS会发送回复包给客户端。
需要注意:
TGS-REP中KDC并不会验证客户端是否有权限访问服务端,因此不管用户有没有访问
服务的权限,只要TGT正确,均会返回ST。
ticket:即ST。
enc-part(ticket中的):这部分是服务的密钥加密的。
enc-part(最外层的):
这部分是用原始的Logon Session Key加密的,里面最重要的字段是Service Session Key,
作为下一阶段的认证密钥。
TGS-REP包中最重要的就是ST和Service Session Key,ST中加密部分是使用服务密钥加密的,而
Service Session Key是使用Logon Session Key加密的。
ST:
TGS-REP包中的ticket便是ST,ST中包含明文显示的信息,如版本号、tkt-vno、域名
realm、请求的服务名sname、但是最终的还是加密部分,加密部分是使用服务密钥加密的,
主要包含Server Session Key,请求的用户名cname、域名crealm、认证时间authtime、
认证到期时间endtime、authorization-data等信息,其中authorization-data部分包含客户端的
身份权限等信息,如果对authorization-data进行解密查看PAC的凭据信息部分PAC_LOGON_INFO,
主要是通过User RID和Group RID来辨别用户权限的。
Service Session Key:
即是最外层的enc-part部分使用原始的Logon Session Key加密,用于确保客户端和KDC下一阶段
的通信安全,主要包含认证时间authtime、认证到期时间endtime、域名srealm、请求的服务名sname、
协商标志flage等信息,在ST中也包含Service Session Key。
AP-REQ&&AP-REP双向认证
AP-REQ:
客户端接收到KDC的TGS回复后,通过缓存的Logon Session Key解密enc_Service Session Key得到
Service Session Key,同时它也拿到了ST,Service Session Key和ST会被客户端缓存,客户端访问指定服务
时,将发起AP-REQ。
AS-REQ Kerberos内容:
ap-req
ticket 票据
sname 加密的时间戳
enc-part
authenticator
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,如果是则说明客户端想验证服务端的身份,此时服务端会用Service Session Key加密时间戳
作为Authenticator在AP-REP包中发送给客户端进行验证,如果mutual-required选项为False,服务端会根据访问
令牌的权限决定是否返回相应的服务给客户端。
双向认证:
这里的认证过程是双向认证:
1、服务端验证客户端:防止非法用户操作
当需要访问服务时,客户端将Ticket和使用Server Session Key加密的客户端信息和时间戳发送给服务端。
服务端收到客户端的请求,使用该服务的NTML hash解密Ticket,得到Server Session Key,再使用Server Session Key解密其他数据,然后将解密出来的数据和Ticket解密出来的数据进行比较,验证通过后,因为启用了PAC,服务端会将PAC发送给DC询问此用户是否有访问权限。DC收到PAC后会解密PAC,然后通过PAC中的SID判断用户信息、用户权限等,最后将结果返回到服务端。这里如果设置了ACL,服务端还会判断ACL有没有限制用户请求的服务,全部通过后服务端成功验证客户端。
2、客户端验证服务端:防止误入恶意服务
服务端将使用Server Session Key加密的客户端信息和时间戳(这里的时间戳是第三阶段客服端发送给服务端的时间戳)发送给客户端,客户端使用Server Session Key解密数据,解密成功之后客户端将时间戳和原来发送的时间戳进行对比,如果一致则客户端成功认证服务端。
Kerberos认证的第三阶段完成,Kerberos认证完成,客户端和服务端建立通信。
简单来说:服务端验证客户端需要开启PAC_PRIVSVR_CHECKSUM签名校验将PAC转交给DC询问可以防止白银票据攻击,客户端AP-REQ请求中mutual-required选项为True服务端使用Server Session Key加密的客户端信息和时间戳,Server Session Key是由原始Logon Session Key加密的以此验证服务端
S4u2Self&S4u2Proxy
微软对Kerberos协议扩展了两个自协议:S4u2Self(Service for User to Self)和S4u2Proxy(Service for User to Proxy)。
S4u2Self:
S4u2Self可以代表仁医用户请求针对自身的服务票据,S4u2Proxy可以用上一步获取的ST以用户名义请求针对其他
指定服务的ST。
跟正常的TGS-REQ相比,S4u2Self协议的TGS-REQ包会多一个PA-DATA pa-FOR-USER,
name为要模拟的用户,并且sname也是请求的服务自身。
S4u2Proxy:
和正常的TGS-REQ包相比,S4u2Proxy协议的TGS-REQ包会增加一个additional-tickets字段,
该字段的内容就是上一步利用S4u2Self请求的ST。