關於 Relay Attack
說到 relay attack 我相信大家一定都不陌生,透過 EFS 或 printer 等 RPC 可以將高權限的 NTLM 認證打到 attacker 的機器上面,並透過 ntlmrelayx 轉發進而拿到 smb / ldap / http 等服務的 session。
不過這種打法在 kerberos 基本上不會成功,主要是因為 kerberos 的驗證中綁定了特定的 service, kerberos 的 ST 是用目標 service 的 key 加密的。如果 UNC path 指定 attacker 的 hostname,KDC 找不到 attacker 的 SPN(因為 attacker 不在 domain 裡),會 fallback 到 NTLM,根本拿不到 kerberos ticket;如果指定 target 的 hostname,ticket 是正確的但 TCP 也連到 target,attacker 攔不到。兩個條件(正確的票 + 送到 attacker)沒辦法同時滿足。
如何做到 Kerberos Relay
早在 2021 年 James Forshaw 便針對 kerberos relay 的可行性進行相關研究
理論上 kerberos relay 是可行的,不過當時除了中間人攻擊之外找不到合適的漏洞達成。
要完成 kerberos relay,我們需要透過某種方法指定正確的 SPN ,同時將這個服務的 AP_REQ 送到自己手上。
DHCPv6 DNS Spoofing
2022 年 Dirk-jan 發表了一篇 blog 說明如何透過 DHCPv6 達成 kerberos relay。
首先,在大部分的企業環境內根本沒人會用 DHCPv6,所以可以自己架一台 DHCPv6 回應所有 DHCPv6 solicit,並且把自己設定成 IPv6 DNS Resolver,為什麼要用 IPv6 ?因為 IPv6 的 precedence 會比 v4 還高,因此機器會優先詢問 IPv6 的 DNS Server。
等 victim 的 DNS resolver 被劫持後,被動等待 victim 自行發起 DNS dynamic update(Windows 機器定期會做),此時:
victim向假的 DNS server 發起 DNS dynamic update- Attacker 的 DNS server 回應 SOA,把 primary nameserver 指向 target(例如 ADCS)的 hostname
victim準備對 target hostname 做 authenticated DNS update,向KDC請求 targetSPN的 STvictim向 DNS 查詢 target 的 ip- 假的 DNS Resolver 回應 attacker 的 ip
victim將AP-REQ發送到 attacker 手上attacker拿 AP-REQ relay 到 target 的其他 service(例如 ADCS HTTP endpoint),完成 kerberos relay
DNS 和 kerberos 的前後解析不一致
Synacktiv 在 2024 年的時候提出了另一個手法
首先,他們透過 dns 註冊了一組奇怪的 A Record:
fileserver1UWhRCAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAfileserversBAAAA
接著要求 victim 強制認證 fileserver1UWhRCAA..A ,此時:
victim向 DNS 查詢fileserver1UWhRCAA..A,得到 Attacker IPvictim嘗試 parse 出 SPN,偵測到為 marshalled data,將 marshalled data strip 掉- 得到 SPN 為
cifs/fileserver - 向
KDC請求cifs/fileserver的 ST - 向 Attacker 發送 AP-REQ
SPN 的解析問題
為什麼 fileserver1UWhRCA..A 會被解析成 cifs/fileserver?
我們可以來看 SMB client 的正常連線流程,當 SMB client 要連線到 target 時:
- SMB client 呼叫
SecMakeSPNEx2("cifs", "target"),SecMakeSPNEx2會:- 把 service class 和 hostname 組成 SPN:
cifs/target - 嘗試
CredUnmarshalTargetInfo("cifs/target")回傳null - 呼叫
CredMarshalTargetInfo把目標資訊 base64 encode
- 把 service class 和 hostname 組成 SPN:
- 把
SPN和 base64-encoded marshal 接起來丟給SSPI
聽起來很合理,但如果 target 已經是 marshalled data 會發生什麼事?
- SMB client 呼叫
SecMakeSPNEx2("cifs", "targetMarshalledData"),SecMakeSPNEx2會:- 把 service class 和 hostname 組成 SPN:
cifs/targetMarshalledData - 嘗試
CredUnmarshalTargetInfo("cifs/targetMarshalledData")回傳 unmarshalled data - 用 unmarshalled data 重新
CredMarshalTargetInfo把目標資訊 base64 encode
- 把 service class 和 hostname 組成 SPN:
- 把
SPN和 base64-encoded marshal 接起來丟給SSPI
此時 fileserver1UWhRCA..A 被成功解析出 cifs/fileserver 並申請正確的 ST ,但 DNS 卻解析出 fileserver1UWhRCA..A 的 ip,並將 AP-REQ 發送給 attacker,造成前後解析不一致的漏洞。
SecMakeSPNEx2
很明顯就是這個函式在搞,而 SecMakeSPNEx2 本身就是拿來解析 SPN 的,所以理論上可以控制輸入就是會有上面的這些問題
CVE-2025-33073
前面有提到 SMB client 在解析 target name 的時候可以透過 marshalled data 造成前後解析不一致,除了拿來做 kerberos relay 之外,Synacktiv 發現可以利用這個問題繞過 authentication reflection 的檢查
什麼是 Authentication Reflection
前面提到若透過 UNC path 觸發驗證便能拿到該使用者的 NTLM 認證(challenge-response),由於這些有問題的 RPC 通常都是以系統服務運行的,因此我們可以拿到該機器 machine account 的 NTLM 認證,那如果把它 relay 給他自己會發生什麼事?假設我們 relay 給自己的 SMB Service ,就會得到一個 SYSTEM 權限的 SMB session,但這也太蠢了吧?
微軟也是這樣想的,早在 2008 年的 MS08-068 他們就把這個問題給修掉了,修法很簡單就是在 SMB server 端檢查 challenge 是不是自己發的,如果是就拒絕。
但是遇到 SecMakeSPNEx2 一切都不一樣了,我們一樣將 fileserver1UWhRCA..A 指向 attacker IP,同時針對 fileserver1 發起 authentication coercion,此時:
- Coerce
fileserver1的 SYSTEM service 連到fileserver1UWhRCA..A - DNS 解析
fileserver1UWhRCA..A→ attacker IP → TCP 連到 attacker SecMakeSPNEx2→CredUnmarshalTargetInfostrip marshalled data → hostname =fileserver1SspIsTargetLocalhost("fileserver1")→ 是自己 → 走 NTLM local authentication- NTLM 認證透過已建好的 TCP 連線送到 attacker
- Attacker 用 ntlmrelayx relay 回
fileserver1:445 fileserver1的 SMB server 收到認證 → 來自外部 IP(attacker) → MS08-068 的 challenge 檢查不觸發(因為 challenge 不是同一個 SMB instance 發的)→ 認證通過- 拿到 SYSTEM 身份的 SMB session
修補
在 mrxsmb.sys 的 SmbCeCreateSrvCall 中,新增了一段檢查:
if ((unsigned int)CredUnmarshalTargetInfo(
TargetName->Buffer,
TargetName->Length, 0, 0) != STATUS_INVALID_PARAMETER)
{
return STATUS_INVALID_PARAMETER;
}
CredUnmarshalTargetInfo 在 target name 不包含 marshalled data 或格式錯誤時會回傳失敗(STATUS_INVALID_PARAMETER)。所以這段程式碼反過來用 — 如果 CredUnmarshalTargetInfo 成功了(代表 target name 裡有合法的 marshalled data),就拒絕建立 SMB 連線。
在這個修補之後今年又被繞過了CVE-2026-24294 透過 SMB port multiplexing 新功能 connection reuse 時忘記檢查是否為相同 port 繞過CVE-2026-26128 透過 Unicode normalization 不一致繞過
不過這兩個繞過方式並非透過 SPN 前後解析不一致達成,因此就不在這篇討論,有興趣的可以去看 synacktiv 的兩篇文章:
References
- James Forshaw, Using Kerberos for Authentication Relay Attacks, Google Project Zero, 2021
- Dirk-jan Mollema, Relaying Kerberos over DNS using krbrelayx and mitm6, 2022
- James Forshaw, Relaying Kerberos Authentication from DCOM OXID Resolving, 2024
- Andrea Pierini (Decoder), Reflecting Your Authentication: When Windows Ends Up Talking to Itself, 2024
- Synacktiv, Relaying Kerberos over SMB using krbrelayx, 2024
- Synacktiv, NTLM reflection is dead, long live NTLM reflection! — An in-depth analysis of CVE-2025-33073, 2025
- RedTeam Pentesting, Playing with reflective relay to discover new vulnerabilities: CVE-2025-33073, 2025
- Synacktiv, Bypassing Windows authentication reflection mitigations for SYSTEM shells — Part 1, 2026
- Synacktiv, Bypassing Windows authentication reflection mitigations for SYSTEM shells — Part 2, 2026
- Microsoft, CVE-2025-33073 Advisory