很早就听说过黄金票据需要 krbtgt 的 NTLM-HASH 和白银票据需要服务器的 NTLM-HASH 才能伪造,但是一直不知道为什么。学习内网渗透怎么能够对 kerberos 通信认证协议不了解呢?
先来介绍一下 NTLM 和一些基础概念吧!
NTLM
NTLM 是 NT LAN Manager 的缩写,NTLM 是基于挑战/应答的身份验证协议,是 Windows NT 早期版本中的标准安全协议。现常用于本地认证(客户端本地进程、服务端本地会话)
基本流程
- 客户端在本地加密当前用户的密码成为密码散列
- 客户端向服务器明文发送账号
- 服务器端产生一个 16 位的随机数字发送给客户端,作为一个 challenge
- 客户端用加密后的密码散列(也就是后面要提到的 NTLM Hash)来加密 challenge,然后返回给服务器,作为 response
- 服务器端将用户名、challenge、response 发送给域控制器
- 域控制器用这个用户名在 SAM 密码管理库中找到这个用户的密码散列,然后使用这个密码散列来加密 chellenge
- 域控制器比较两次加密的 challenge,如果一样那么认证成功,反之认证失败
Hash
LM Hash
LM Hash(LAN Manager Hash) 是 windows 最早用的加密算法,由IBM设计。LM Hash 使用硬编码秘钥的 DES,且存在缺陷。早期的Windows 系统如 XP、Server 2003 等使用LM Hash,而后的系统默认禁用了 LM Hash 并使用 NTLM Hash。
LM Hash的计算方式为:
- 转换用户的密码为大写,14 字节截断
- 不足 14 字节则需要在其后添加 0×00 补足
- 将 14 字节分为两段 7 字节的密码
- 以
KGS!@#$%作为秘钥对这两组数据进行 DES 加密,得到 16 字节的哈希 - 拼接后得到最后的 LM Hash。
NTLM Hash
为了解决 LM Hash 的安全问题,引入了 NTLM 协议
Windows 2000 / XP / 2003 在密码超过 14 位前使用 LM Hash,在密码超过 14 位后使用 NTLM Hash。而之后从 Vista 开始的版本都使用NTLM Hash。
NTLM Hash 的计算方法为:
- 将密码转换为16进制,进行 Unicode 编码
- 基于 MD4 计算哈希值
Kerberos
Kerberos 是一种基于加密 Ticket 的身份认证协议
有一些概念还是要先记住的,不然后面看不懂:
Key Distribution Center: 简称 KDC,密钥分发中心,默认安装在域控。
Authentication Service: 身份验证服务,简称 AS,用于 KDC 对 Client 的认证
Ticket Granting Service: 票据授予服务,简称 TGS 用于 KDC 向 Client 和 Server 分发 Session Key
Session Key【AS|TGS】: 对应服务产生的临时密钥
PAC :PAC(Privilege Attribute Certificate)特权访问证书。包含的是用户的 SID、用户所在的组等一些信息。kerberos 认证协议解决了 “Who am I?” 的问题,但是没有解决 “What can I do?” 的问题。于是就引入了 PAC 来解决 “What can I do?” 的问题
TGT:由 KDC 使用 krbtgt 账户的长期密钥加密生成,内部包含 Session-Key AS、Client-info、PAC、票据生命周期等信息,用于后续向 TGS 申请服务票据。
ST:Service Ticket,服务票据。对于特定的服务有特定的票据。一张服务票据只对一类服务有效。客户机只有拥有服务票据才能够与对应的服务器进行通信
三个阶段
认证过程主要有三个阶段,下面这张图就比较清晰的展示了主要流程

AS_REQ & AS_REP
此阶段是 Client 和 AS 的认证获得 TGT
AS_REQ:
当域内的某个客户机试图访问域内的某个服务,需要输入用户名和密码,此时客户端本机的 Kerberos 服务会向 KDC 的 AS 认证服务发送一个 AS_REQ 认证请求。凭证是客户机的哈希值 NTLM HASH 加密时间戳、Client-info(用户名)、Server-info 等信息
AS_REP:
AS 收到后先向 AD 请求,查询是否有这个客户,有的话就取出它的 NTLM-Hash, 并对 AS_REQ 中的加密时间戳进行解密,如果解密成功,则证明客户端的密码是正确的,如果时间戳在 5 分钟内,则预认证成功。然后 AS 会产生一个临时的 Session-Key AS(临时密钥),并使用客户端 Client 的 NTLM-Hash 加密 Session-Key AS 作为响应包的一部分,此 Session-Key 用来保证客户端和 KDS 之间通信的安全,另外一部分内容就是 TGT。
我们来整理一下客户收到的响应包:客户自己 NTLM-HASH 加密的 Session-Key AS、TGT(包含了 Krbtgt NTLM-HASH 加密的 Session-Key AS、时间戳、Client-info、PAC)
TGS_REQ & TGS_REP
此阶段是客户端与 TGS 进行认证,获得 ST
TGS_REQ:
客户端收到 AS_REP 后会用自己的 NTLM-Hash 恢复 Session-Key AS,然后本地缓存此 TGT 和 Session-Key AS。
如果 Client 需要访问某台服务器上的服务,它需要向 TGS 发送 TGS_REQ 请求获得对应的 ST
TGS_REQ 包含这些内容:用 Session-Key AS 加密当前的时间戳、Client-info、Server-info,TGT
TGS_REP:
TGS 收到请求后会用 krbtgt 用户的 NTLM-Hash 解密 TGT 中的内容,得到 Session-key AS、时间戳、Client-info 。然后先比较两次的时间戳,如果时间相隔太久,就需要重新进行 AS 认证。还会将两部分的 Clinet-info 如果两者相等的话,再判断有无访问服务的权限。最后认证成功 TGS 会生成一个 Session-Key TGS,并用 Session-key AS 加密 Session-key TGS 作为相应的一部分。另一部分就是使用 Server 的 NTLM-Hash 加密 Session-key TGS、以及 Client-info 等数据生成 ST。
TGS_REP 包括:Session-Key AS 加密的 Session-key TGS、ST(包含 Server 的 NTLM-Hash 加密的 Session-key TGS、Client-info 等)
SE_REQ & SE_REP
此阶段是 Client 和 Server 的认证
SE_REQ:
客户端 Client 收到 TGS_PEP,用缓存的 Session-Key AS 将 Session-key TGS 解密出来, 然后使用 Session-key TGS 加密 Client-info、时间戳等信息作为一部分内容。然后将 ST 一起发送给 Server
SE_REQ发送内容:Session-Key TGS 加密的 Client-info 和时间戳、ST
SE_REP:
服务端用自身的 NTLM-Hash 将 ST 解密,得到 Session-key TGS, 然后用 Session-key TGS 解密得到 Client-info 、时间戳等信息,比对这些信息。时间戳有效时间一般为 8 小时。服务器使用自身密钥解密 ST,得到 Session-Key TGS 和其中包含的 PAC。PAC 实际上由 KDC 在签发 TGT 时生成,并会被复制到 Service Ticket 中。服务器可以直接验证 PAC 的签名,也可以通过 Netlogon RPC 向域控制器请求 PAC 验证。验证成功后,服务器根据 PAC 中包含的用户 SID、组 SID、SIDHistory 等信息构建访问令牌(Access Token),再与目标资源的 ACL 进行比较,从而决定是否允许访问。
但是在有些服务中并没有验证 PAC 这一步,这也是白银票据能成功的前提,因为就算拥有用户的 Hash,可以伪造 TGS,但是也不能制作 PAC,PAC 当然也验证不成功
黄金票据
学习了上面的 Kerberos 认证,我们仔细思考就会发现,如果我们能够获取 Krbtgt 的 NTLM-Hash,那么我们可以伪造 TGT,要记得 TGT 是用 Krbtgt 的 NTLM-Hash 加密了 Session-Key AS、时间戳、Client-info。虽然我们并不知道 Session-Key AS 是什么,但这并不重要,因为 Session-Key AS 是一个临时生成的密钥,我们也可以给个随机的内容,在后面认证过程中并不需要。而 Client-info 便是我们要伪造的内容。在 Kerberos 认证的第二阶段过程中我们发送的是 Session-Key AS 加密当前的时间戳、Client-info、Server-info,Session Key 并不需要担心,而 TGT 也已经让我们伪造好了。也就达成了够绕过对任意用户的账号策略(还记得第一阶段的认证吗?需要我们输入用户名和密码,返回的是对应用户的 TGT),让用户成为任意组的成员,可用于 Kerberos 认证的任何服务。
黄金票据可以当做一个安装在普通域成员主机上的连接到域控的后门
伪造黄金票据还需要以下信息:
- 需要伪造域管理员用户名
- 完整的域名
- 域 SID
- krbtgt 的 NTLM HASH
可以使用 msf 的 meterpreter 中的 kiwi
首先导入 kiwi
meterpreter > load kiwi
然后输入
golden_ticket_create -d whoamianony.org -k 6be58bfcc0a164af2408d1d3bd313c2a -s S-1-5-21-1315137663-3706837544-1429009142 -u administrator -t /root/krbtgt.ticket
# golden_ticket_create -d 域名 -k krbtgt用户的Hash -s 域sid -u 需要伪造的域管理员用户名 -t /root/krbtgt.ticket
kerberos_ticket_list # 查看本地储存的票据
kerberos_ticket_use /root/krbtgt.ticket # 将票据注入内存
白银票据
我们只需要知道对应的 Server 用户的 NTLM Hash 就可以伪造出 ST。Server 的 NTLM-Hash 加密的 Session-key TGS、Client-info 等,虽然我们并不知道 Session-key TGS,这个临时密钥,但也不重要,我们可以自己创造一个 Session-key TGS,填好 Client-info,就可以伪造出 ST。把 ST 和自己创造的 Session-Key TGS 加密的 Client-info 和时间戳提供给服务器。就可以访问了。
制作白银票据需要以下信息:
- 域名
- 域 SID
- 目标服务器的 FQDN (全限定域名,同时带有计算机名和域名)
- 可利用的服务
- 服务账号的 NTLM 哈希值
- 要伪造的用户名
Mimikatz
kerberos::golden /domain:域名 /sid:域sid /target:全限定域名 /service:服务名 /rc4:服务账号的NTLM-HASH /user:伪造的用户名 /ptt