Windows 身份验证协议

本文中的图文内容均取自《域渗透攻防指南》,本人仅对感兴趣的内容做了汇总及附注。

导航

  • 0 前言

  • 1 NTLM 协议

    • 1.1 控制台
    • 1.2 工作组环境
    • 1.3 域环境
    • 1.4 NTLM 协议的安全问题
  • 2 Kerberos 协议

    • 2.1 AS-REQ & AS-REP
    • 2.2 TGS-REQ & TGS-REP
    • 2.3 AP-REQ & AP-REP 双向认证
    • 2.4 Kerberos 协议的安全问题

0、前言

在 Windows 工作组及域环境中经常会使用的两个身份验证协议:NTLM 和 Kerberos。

NTLM (New Technology LAN Manager) 协议是微软用于 Windows 身份验证的主要协议之一。它既可用于工作组中的机器身份验证,又可用于域环境身份验证,还可为 SMB、HTTP、LDAP、SMTP 等上层微软应用提供身份验证。

Kerberos 协议是由麻省理工学院提出的一种网络身份验证协议,是一种在开放的非安全网络中认证并识别用户身份信息的方法。它旨在使用密钥加密技术为客户端/服务端应用程序提供强身份验证。

1、NTLM 协议

NTLM 协议是一种基于 Challenge/Response(质询/响应)的验证机制,由三种类型消息组成:

  • Type 1(协商 Negotiate)
  • Type 2(质询 Challenge)
  • Type 3(认证 Authentication)

NTLM 协议有 NTLM v1 和 NTLM v2 两个版本,目前使用最多的是 NTLM v2。 NTLM v1 与 NTLM v2 最显著的区别是 Challenge 值与加密算法不同,共同之处是都使用 NTLM Hash 进行加密。

注:NTLM Hash 和 NTLM 协议不是一个概念。NTLM Hash 是一种类似 MD5 的散列算法,而 NTLM 协议是一种类似 PAP 认证的认证协议。

1.1、控制台

在用户输入密码进行本地认证的过程中,所有操作都是在本地进行的。系统会首先将用户输入的密码转换为 NTLM Hash,然后与 SAM 文件中用户对应的 NTLM Hash 进行比较,如果相同,说明密码正确,反之则错误。

注:Windows 本地用户的密码在经过 NTLM Hash 处理之后均存储在 C:\Windows\ system32\config\SAM 文件中。

当用户注销、重启、锁屏后,操作系统会让 winlogon.exe 显示登录界面,也就是输入框。当 winlogon.exe 接收到输入后,会将密码交给 lsass.exe 进程,而 Isass.exe 进程会保存一份明文密码,然后将明文密码加密成 NTLM Hash 与 SAM 数据库进行比较和认证。

注: 使用 mimikatz 工具获得的用户 明文密码/NTML Hash 密码 就是在 lsass.exe 进程中抓取的。但现在微软已做了安全防护,lsass.exe 进程中已抓取不到明文密码,只能抓到 NTLM Hash 值。

1.2、工作组环境

  • 1)当客户端需要访问服务器的某个服务时,就需要进行身份认证。于是,在客户端输入服务器的用户名和密码进行验证之后,就会缓存服务器密码的 NTLM Hash 值。然后,客户端会向服务端发送一个请求,该请求利用 NTLM SSP 生成 NTLMSSP_NEGOTIATE 消息(被称为 Type 1 协商消息)。

  • 2 )服务端接收到客户端发送过来的 Type 1 消息后,读取其中的内容,并从中选择自己所能接受的服务内容、加密等级、安全服务等,然后传入NTLMSSP,得至(NTLMSSP_CHALLENGE 消息(被称为Type 2 质询消息),并将此 Type 2 消息发回给客户端。在此 Type 2 消息中包含一个由服务端生成的16位随机值,被称为 Challenge 值,服务端会将该 Challenge 值进行缓存。

  • 3)客户端收到服务端返回的 Type 2 消息后,读取服务端所支持的内容,并取出其中的 Challenge 值,用缓存的服务器密码的 NTLM Hash 对其进行加密得到 Response 消息。最后将 Response 和一些其他信息封装到 NTLMSSP_AUTH 消息中(被称为 Type3 认证消息), 发往服务端。

  • 4 )服务端收到认证消息后,从中取出 Net-NTLMHash,然后用自己密码的 NTLM Hash 对 Challenge 值进行一系列加密运算,得到自己计算的 Net-NTLM Hash,并比较自己计算出的 Net-NTLM Hash 和客户端发送的 Net-NTLM Hash 是否相等。如果相等,则证明客户端输入的密码正确,从而认证成功,反之则认证失败。

注:下面是以上身份验证流程通俗化之后的表述。

  1. 客户端向服务端发起一个认证请求,其中包含用户名但无密码相关。
  2. 服务端返回给客户端一个响应,其中包含一个服务端随机生成的 Challenge 值。
  3. 客户端使用用户对应密码的 NTLM Hash 加密该 Challenge 值,得到加密值,然后将加密值发送给服务端。
  4. 服务端接收到加密值之后,也使用用户对应密码的 NTLM Hash 加密该 Challenge 值,然后和收到的加密值进行比对,相等则返回认证成功的响应,否则返回认证失败的响应。

1.3、域环境

  • 1)客户端想要访问服务器的某个服务,需要进行身份认证。于是,在输入服务器的用户名和密码进行验证之后,客户端会缓存服务器密码的 NTLM Hash 值。然后,客户端会向服务端发送一个请求,该请求利用 NTLM SSP 生成 NTLMSSP NEGOTIATE 消息(被称为 Type 1 协商消息)。
  • 2)服务端接收到客户端发送过来的 Type 1 消息,会读取其中的内容,并从中选择自己所能接受的服务内容、加密等级、安全服务等。然后传入 NTLMSSP,得到 NTLMSSP_CHALLENGE 消息(被称为Type 2 质询消息),并将此 Type 2 消息发回给客户端。在此 Type 2 消息中包含一个由服务端生成的 16 位随机值,被称为 Challenge 值,服务端将该 Challenge 值缓存起来。
  • 3)客户端收到服务端返回的 Type 2 消息后,读取服务端所支持的内容,并取出其中的 Challenge 值,用缓存的服务器密码的 NTLM Hash 对其进行加密得到 Response 消息, Response 消息中可以提取出 Net-NTLM Hash。最后将 Response 和一些其他信息封装到
    NTLMSSP_AUTH 消息中(被称为 Type 3 认证消息),发往服务端。
  • 4 )服务端接收到客户端发送来的 NTLMSSP_AUTH 认证消息后,通过 Netlogon 协议与域控制器(Domain Controller,DC 简称域控)建立一个安全通道,将验证消息发给域控。
  • 5)域控收到服务端发来的验证消息后,从中取出 Net-NTLM Hash。然后从数据库中找到该用户的 NTLM Hash,对 Challenge 进行一系列加密运算,得到自己计算的 Net-NTLM Hash,比较自己计算出的Net-NTLM Hash 和服务端发送的 Net-NTLM Hash 是否相等,如
    果相等,则证明客户端输入的密码正确,认证成功,反之认证失败,域控将验证结果发给服务端。
  • 6)服务端根据域控返回的结果,对客户端进行回复。

注:下面是以上身份验证流程通俗化之后的表述。

  1. 客户端向服务端发起一个认证请求,其中包含用户名但无密码相关。
  2. 服务端返回给客户端一个响应,其中包含一个服务端随机生成的 Challenge 值。
  3. 客户端使用用户对应密码的 NTLM Hash 加密该 Challenge 值,得到加密值,然后将加密值发送给服务端。
  4. 服务端将接收到的加密值和挑战值再发送给域控。
  5. 域控接收到加密值之后,也使用用户对应密码的 NTLM Hash 加密接收到的 Challenge 值,然后将结果与收到的加密值进行比对,相等则返回给服务端认证成功的响应,否则返回认证失败的响应。【注意:域控环境下,所有域用户的账户密码均保存在域控的 C:\Windows\NTDS\NTDS.dit 文件中。 】
  6. 服务端再将收到的响应返回给客户端。

1.4、NTLM 协议的安全问题

  1. 从上面 NTLM 认证的流程中可以看到,在 Type 3 NTLMSSP_AUTH 消息中是使用用户密码 Hash 计算的。因此,当没有拿到用户密码的明文而只拿到 Hash 的情况下,可以进行 Pass The Hash(PTH)攻击,也就是常说的哈希传递攻击。
  2. 同样,还是在 Type 3 消息中,存在 Net-NTLM Hash,当获得了 Net-NTLM Hash 后,可以进行中间人攻击,重放 Net-NTLM H ash,这种手法也就是常说的 NTLM Relay( NTLM 中继)攻击。
  3. 由于 NTLM v1 协议加密过程存在天然缺陷,因此可以对 Net-NTLM v1 Hash 进行破解,得到 NTLM Hash 之后即可横向移动。

2、Kerberos 协议

Kerberos 是一种基于票据(Ticket)的认证方式。客户端想要访问服务端的某个服务,首先需要购买服务端认可的 ST( Service Ticket,服务票据)。也就是说,客户端在访问服务之前需要先买好票,等待服务验票之后才能访问。但是这张票并不能直接购买,需要一张 TGT(Ticket Granting Ticket,认购权证)。也就是说,客户端在买票之前必须先获得一张 TGT。TGT 和 ST 均是由 KDC 发放的,因为 KDC 运行在域控上,所以说 TGT 和 ST 均是由域控发放的。

注:Kerberos 基于票据的认证方式有点类似于生活中去景区买票逛景点的场景。TGT 票据相当于身份证,ST 票据相当于景区门票。

Kerberos 是西方神话传说地狱守卫三头犬的名字,之所以叫这个名字,是因为它需要三方共同参与才能完成一次认证。而这三颗脑袋映射在服务和生活中分别对应的是:

  • 第一颗脑袋:对应的是域控 KDC 中的 AS 服务(Authentication Service)。类似于生活中的乡镇派出所,我们需要拿着户口本才能办理身份证。
  • 第二颗脑袋:对应的是域控 KDC 中的 TGS 服务(Ticket Granting Service)。类似于生活中的景区售票处,我们需要拿着身份证才能办理景区门票。
  • 第三颗脑袋:对应的是提供服务的服务端。类似于生活中的景区检票口,我们需要拿着景区门票才能成功进入。

在 Kerberos 协议中,主要有以下三个角色。

  • 访问服务的客户端:Kerberos 客户端代表需要访问资源的用户进行操作的应用程序, 例如打开文件、查询数据库或打印文档。每个 Kerberos 客户端在访问资源之前都会请求身份验证。
  • 提供服务的服务端:域内提供服务的服务端,服务端都有唯一的 SPN(服务主体名称)。
  • 提供认证服务的 KDC( Key Distribution Center,密钥分发中心):KDC 是一种网络服务,它向活动目录域内的用户和计算机提供会话票据和临时会话密钥,其服务账户为 krbtgt。KDC 作为活动目录域服务的一部分运行在每个域控制器上。

下图是 Kerberos 协议认证的整个流程,后面各小节会具体分析 Kerberos 认证流程中的每个步骤。

2.1、AS-REQ & AS-REP

AS-REQ 请求 :当域内某个用户想要访问域内某个机器上的服务时,输入用户名和密码,本机就会向 KDC 的 AS 发送 一 个 AS-REQ(认证请求)。该请求包中包含的信息如图 1-68a 所示。

AS-REP 响应 :当 KDC 的 AS 接收到客户端发来的 AS-REQ 后,AS 会从活动目录数据库中取出该用户的密钥,然后用该密钥对请求包中的预认证部分进行解密。如果解密成功,并且时间戳在有效的范围内,则证明请求者提供的用户密钥正确。KDC 的 AS 在成功认证客户端的身份之后,发送 AS-REP 包给客户端。AS-REP 包中主要包括的信息如图 1-68b 所示。

注:下面是以上身份验证流程通俗化之后的表述。

  1. 客户端向域控 KDC AS 发起 AS-REQ 请求,请求中包含:用户名用户密钥 NTLM Hash 加密的时间戳等信息。【注:因域控拥有用户的密钥,因此可以解密出该时间戳进而确认对方的身份。】
  2. 域控 KDC AS 服务向客户端返回 AS-REP 响应,响应中包含:用户密钥 NTLM Hash 加密的 Logon Session KeyTGT 票据 (而该票据中又包含着由 krbtgt 密钥加密的 Logon Session Key)等信息。【注:(1)因客户端拥有用户密钥,因此能够解密得到下一个验证流程的会话加密密钥 Logon Session Key 。(2)TGT 中 krbtgt 加密的内容会被下个流程中的 KDC TGS 服务解密(因为 TGS 也在域控上,同样也拥有 krbtgt 的密钥),从而获得下个验证流程的会话加密密钥 Logon Session Key ,同时也可证明该 TGT 就是 KDC AS 授予的。】

2.2、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( Ticket Granting Service)授予服务发放的。【注:在这个阶段,微软还引入了两个扩展协议 S4u2Self 和 S4u2Proxy,但本文不包含这部分内容。】

TGS-REQ 请求 :客户端用上一步获得的 TGT 发起 TGS-REQ,向 KDC 购买针对指定服务的 ST,该请求主要包含的信息,如图 1-76a 所示。

TGS-REP 响应:KDC 的 TGS 服务接收到 TGS-REQ 之后会进行如下操作。首先,使用 krbtgt 密钥解密 TGT 中的加密部分,得到 Logon Session Key 和 PAC 等信息,解密成功则说明该 TGT 是 KDC 颁发的;然后,验证 PAC 的签名,签名正确证明 PAC 未经过篡改;最后,使用 Logon Session Key 解密 authenticator 得到时间戳等信息,如果能够解密成功,并且票据时间在有效范围内,则验证了会话的安全性。

在完成上述的检测后,KDC 的 TGS 就完成了对客户端的认证,TGS 发送回复包给客户端。该回复包中主要包括的信息,如图 1-76b 所示。

注意:TGS-REP 中 KDC 并不会验证客户端是否有权限访问服务端。因此,不管用户有没有访问服务的权限,只要 TGT 正确,均会返回 ST。
注:下面是以上身份验证流程通俗化之后的表述。

  1. 客户端向域控 KDC TGS 发起 TGS-REQ 请求,请求中包含:TGT 票据Logon Session Key 加密的时间戳等信息。【注:因域控 TGS 服务拥有 krbtgt 用户的密钥,因此可以解密 TGT 票据得到其中的 Logon Session Key ,进而通过该密钥解密出该时间戳从而确认对方的身份。】
  2. 域控 KDC TGS 服务向客户端返回 TGS-REP 响应,响应中包含:Logon Session Key 加密的 Service Session KeyST 票据 (而该票据中又包含着由 服务密钥加密的 Service Session Key )等信息。【注:(1)因客户端已拥有 Logon Session Key,因此其能够解密得到下一个验证流程的会话加密密钥 Service Session Key 。(2)ST 中通过服务密钥 加密的内容会被下个验证流程中的服务端解密(因为服务密钥就是服务启动账户,服务端自然是知道的),从而获得下个验证流程的会话加密密钥 Service Session Key ,同时也可证明该 ST 就是 KDC TGS 授予的。】

2.3、AP-REQ & AP-REP 双向认证

客户端收到 KDC 返回的 TGS-REP 消息后,从中取出 ST,准备开始申请访问服务。由于我们是通过 SMB 协议远程连接的,因此 AP-REQ & AP-REP 消息是放在 SMB 协议中的。

AP-REQ 请求 :客户端接收到 KDC 的 TGS 回复后,通过缓存的 Logon Session Key 解密 enc_Service Session key 得到 Service Session Key,同时它也拿到了 ST。Serivce Session Key 和 ST 会被客户端缓存。客户端访问指定服务时,将发起 AP-REQ,该请求主要包含的信息如图 1-84a 所示。

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 包中发送给客户端进行验证,该请求主要包含的信息如图 1-84b 所示。如果 mutual-required 选项为 False,服务端会根据访问令牌的权限决定是否返回相应的服务给客户端。

注:下面是以上身份验证流程通俗化之后的表述。

  1. 客户端向服务端发起 AP-REQ 请求,请求中包含:ST 票据Service Session Key 加密的时间戳等信息。【注:因服务端拥有服务启动账户的密钥,因此可以解密 ST 票据得到其中的 Service Session Key ,进而通过该密钥解密出该时间戳从而确认对方的身份。】
  2. 服务端如果向客户端返回 AP-REP 响应,那么响应中会包含:**Service Session Key 加密的时间戳 **等信息。【注:因客户端已拥有 Service Session Key,因此其可以通过该密钥解密出该时间戳从而确认对方的身份。】

2.4、Kerberos 协议的安全问题

  1. 在 AS-REQ 阶段,使用的是用户密码 Hash 或 AES Key 加密的时间戳。当只获得了用户密码 Hash 时,发起 AS-REQ 会造成 PTH 攻击;当只获得用户密码的 AES Key 时,发起 AS-REQ 会造成 PTK 攻击。
  2. AS-REQ 包中 cname 字段的值代表用户名,这个值存在和不存在,返回的包不一样, 所以可以用于枚举域内用户名,这种攻击方式被称为域内用户枚举攻击(当未获取到有效域用户权限时,可以使用这个方法枚举域内用户)。当用户名存在,密码正确和错误时,返回的包也不一样,所以可以进行用户名密码爆破。
  3. 在实战中,渗透测试人员通常会使用一种被称为密码喷洒(Password Spraying)的攻击方式来进行测试和攻击。对密码进行喷洒式的攻击,这个叫法很形象,因为它属于自动化密码猜测的一种。这种针对所有用户的自动密码喷洒通常是为了避免账户被锁定,因为针对同一个用户的连续密码猜测会导致账户被锁定,所以只有对所有用户同时执行特定的密码登录尝试,才能增加破解的概率,从而避免账户被锁定。普通的爆破就是用户名固定,爆破密码,但是密码喷洒是用固定的密码去爆破所有的用户名。
  4. 在 AS-REP 阶段,由于返回的 TGT 是由 krbtgt 用户的密码 Hash 加密的,因此如果我们拥有 krbtgt 的密码 Hash 就可以自己制作一个 TGT,这个票据也被称为黄金票据,这种攻击方式被称为黄金票据传递攻击。
  5. 同样,在 TGS-REP 阶段,TGS-REP 中的 ST 是使用服务的 Hash 进行加密的,如果我们拥有服务的 Hash 就可以签发任意用户的 ST,这个票据也被称为白银票据,这种攻击方式被称为白银票据传递攻击。相较于黄金票据传递攻击,白银票据传递攻击使用的是要访问服务的 H ashy,而不是 krbtgt 的 Hash。
  6. 在 AS-REP 阶段,Logon Session Key 是用用户密码 Hash 加密的。对于域用户,如果设置了"Do not require Kerberos preauthentication"(不需要预认证)选项,攻击者会向域控的 88 端口发送 AS-REQ,此时域控不会做任何验证就将 TGT 和该用户 Hash 加密的 Logon Session Key 返回。这样,攻击者就可以对获取到的用户 Hash 加密的 Logon Session Key 进行离线破解,如果破解成功,就能得到该用户的密码明文,这种攻击方式被称为 AS-REP Roasting 攻击。
  7. 在 TGS-REP 阶段,由于 ST 是用服务 Hash 加密的,因此,如果我们能获取到 ST,就可以对该 ST 进行破解,得到服务的 Hash,造成 Kerberoasting 攻击。这种攻击方式存在的另外一个原因是用户向 KDC 发起 TGS-REQ请求时,不管用户对服务有没有访问权限,只要 TGT 正确,KDC 都会返回 ST。其实在 AS-REP 阶段,TGT 是用 krbtgt 用户的 Hash 加密的,也就是说这种攻击方式同样可以用于爆破 AS-REP 中的 TGT,但之所以没见到过这种攻击方式,是因为 krbtgt 的密码是系统随机生成的,通常是爆破不出来的。

注:以上安全问题被攻击的前提条件分别如下。

哈希传递攻击:需获得用户的 NTLM Hash。

域用户名枚举攻击:拥有用户名字典即可。

密码喷洒攻击:拥有用户名和密码字典即可。

黄金票据攻击:需获得 krbtgt 用户的 NTLM Hash。

白银票据攻击:需获得服务启动账户的 NTLM Hash。

AS-REP Roasting 攻击:首先需要有域用户已关闭预身份验证功能,然后才能获得由域用户的 NTLM Hash 加密的 Logon Session Key,最后才能爆破该加密内容,从而获得用户的明文密码。

Kerberoasting 攻击:需先获得一域用户的凭证,然后才能获得域中已注册服务的 ST 票据,然后才能爆破获得服务启动账户的明文密码。

相关推荐
sky.fly2 小时前
多路由器通过RIP动态路由实现通讯(单臂路由)
网络·windows·智能路由器
sevevty-seven6 小时前
解决 Arduino IDE 2.3.6 在 Windows 上无法启动:缺少 Documents 文件夹与注册表路径错误
ide·windows·stm32
虾球xz8 小时前
游戏引擎学习第235天:在 Windows 上初始化 OpenGL
windows·学习·游戏引擎
JANYI20189 小时前
C语言中的双链表和单链表详细解释与实现
c语言·开发语言·windows
桃花岛主709 小时前
WINDOWS下使用命令行读取本地摄像头FFMPEG+DirectShow,ffplay直接播放摄像头数据
windows·ffmpeg
sky.fly9 小时前
RIP动态路由(三层交换机+单臂路由)
服务器·网络·windows
郝亚军14 小时前
后向动态链表增删查改
linux·windows·链表
小王C语言21 小时前
【C++初阶】--- list容器功能模拟实现
c++·windows·list
johnrui1 天前
JAVA设计模式:注解+模板+接口
java·windows·设计模式