Skip to content

Add native DHCPv6 DNS-takeover coercion (CVE-2026-20929) - #21724

Draft
Pushpenderrathore wants to merge 4 commits into
rapid7:masterfrom
Pushpenderrathore:feature/dhcpv6-dns-takeover
Draft

Add native DHCPv6 DNS-takeover coercion (CVE-2026-20929)#21724
Pushpenderrathore wants to merge 4 commits into
rapid7:masterfrom
Pushpenderrathore:feature/dhcpv6-dns-takeover

Conversation

@Pushpenderrathore

Copy link
Copy Markdown
Contributor

Part of #21693.

Second of a stacked series adding native Kerberos authentication relay to Metasploit. #21709 contributes the relay stack and the ESC8 target. This PR contributes the DHCPv6 half of the coercion side, and the rogue Router Advertisement half follows in a separate PR stacked on this one.

Description

Metasploit has no native IPv6 DNS coercion primitive today, so the documented workflow for this class of attack depends on external tooling (mitm6). This adds it natively.

auxiliary/spoof/dhcp/dhcpv6_dns_takeover runs a rogue DHCPv6 server that hands the attacker to IPv6 clients as their DNS server, paired with a DNS server that poisons names under a target domain and transparently forwards everything else so the victim stays functional. Windows prefers IPv6 over IPv4, so becoming the client's IPv6 DNS server is enough to intercept name resolution even on an IPv4 network.

Once a client resolves a target service through the attacker it can be coerced into authenticating to the attacker. Paired with a Kerberos relay target such as ESC8 AD CS web enrollment, this is the coercion half of the Kerberos relay via DNS technique (CVE-2026-20929).

New supporting code:

  • Rex::Proto::DHCPv6 (constants.rb, packet.rb, server.rb), a native DHCPv6 message parser and rogue server. Metasploit had no DHCPv6 support at all.
  • Msf::Exploit::Remote::DNS::NamePoisoner, a shared mixin holding the poison-under-a-domain plus forward-everything-else DNS behaviour, so the Router Advertisement module in the follow-up PR reuses it rather than duplicating it.

Related Issue: #21693

Breaking Changes

None. New module and new Rex::Proto tree, nothing existing is modified apart from the msf_autoload.rb inflection needed for the DHCPv6 constant.

Reviewer Notes

The msf_autoload.rb change is a Zeitwerk inflection so dhcpv6 resolves to DHCPv6 rather than Dhcpv6. Without it the constant does not load.

Opened as a draft. Unit coverage is green and the DNS half has been exercised, but the full coerce to relay to certificate chain is not yet validated end to end. That validation needs a two host lab with the CA separate from the KDC, since a single host collapses the KDC into the relay target. Flagging that up front rather than after review.

The DNS poisoning is deliberately scoped to a configured domain with pass-through for everything else. A blanket poisoner breaks the victim immediately and gets noticed.

Verification Steps

    • bundle exec rspec spec/lib/rex/proto/dhcpv6 spec/modules/auxiliary/spoof and confirm no failures.
    • use auxiliary/spoof/dhcp/dhcpv6_dns_takeover, set DOMAIN to a domain you control in a lab, run. Confirm the DNS server reports it is poisoning names under that domain.
    • From an IPv6 capable client on the same segment, confirm the client picks up the attacker as its DNS server after a DHCPv6 exchange.
    • Confirm a lookup for a name under the target domain returns the attacker address, and that a lookup outside it is forwarded unchanged so the client keeps working.

Test Evidence

$ bundle exec rspec spec/lib/rex/proto/dhcpv6 spec/modules/auxiliary/spoof
35 examples, 0 failures

$ ruby tools/dev/msftidy.rb modules/auxiliary/spoof/dhcp/dhcpv6_dns_takeover.rb
1 file inspected, no offenses detected

DNS half coming up against a lab domain:

[*] DNS server started, poisoning names under kerberos.issue

Environment

Field Details
Operating System macOS 15 (Darwin 25.5.0), Ruby 3.3.8
Target Software/Hardware IPv6 capable Windows client on the same segment

Pre-Submission Checklist

  • Included a corresponding documentation markdown file in documentation/modules (new modules only)
  • No sensitive information (IP addresses, credentials, API keys, hashes) in code or documentation
  • Tested on the target environment specified in the Environment section above (unit coverage green, full lab chain still pending, see Reviewer Notes)
  • Included RSpec tests for library changes (encouraged for lib/ changes)
  • Read the CONTRIBUTING.md and module acceptance guidelines

Provide the native coercion half of the Kerberos relay via DNS
(CVE-2026-20929), removing the dependency on external tooling like mitm6:

- Add Rex::Proto::DHCPv6, a native DHCPv6 packet library (RFC 8415 plus
  the RFC 3646 DNS options): message/option encoding and helpers to build
  the rogue server responses that hand a client the attacker as its DNS
  server.
- Add Rex::Proto::DHCPv6::Server, a reusable rogue DHCPv6 server that
  answers Solicit/Request/Renew/Rebind/Confirm/Information-Request.
- Add auxiliary/spoof/dhcp/dhcpv6_dns_takeover, which runs the rogue
  DHCPv6 server and a paired DNS server that poisons names under a target
  domain (A/AAAA or a CNAME for the DNS-CNAME relay trick) while
  forwarding all other lookups so the victim stays functional.
Two defects found while validating the rogue DHCPv6 server against a live
client on the lab network:

- The multicast group join packed the interface index in network byte
  order, so on little-endian hosts the kernel joined on interface 0 and
  the server never received the multicast Solicit. Pack it in native
  byte order to match struct ipv6_mreq.
- The client address was read assuming recvfrom always returns an address
  array, but older rex-socket versions return the host string directly,
  so the reply went to a malformed destination. Handle both shapes.

With these fixes a cross-host Solicit is answered with an Advertise
addressed correctly to the client on udp/546, handing out the attacker as
the DNS server.
Move the selective DNS poisoning behaviour out of the DHCPv6 DNS takeover
module into a reusable DNS::NamePoisoner mixin (TARGET_DOMAIN, TARGET_HOSTS,
SPOOF_IP6, RELAY_CNAME plus the on_dispatch_request poison/forward logic and
the IPv6 validation helper), so the upcoming Router Advertisement takeover
module can share the exact same coercion behaviour instead of duplicating it.

The DHCPv6 module now just includes the mixin and keeps its DHCPv6-specific
options and server wiring. No behaviour change; its spec is unchanged and green.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

1 participant