Tuesday, December 21, 2021

Responder and IPv6 attacks

 Responder comes with full IPv6 support by default, which allows you to perform more attacks on IPv4 and IPv6 networks. As pointed by several people over the years, Responder has always been lacking of IPv6 support and missed several attack paths, especially when it comes to IPv6 only networks or even mixed IPv4/IPv6 since IPv6 is always the preferred stack on Windows.

Responder also comes with a basic DNS server answering to A, SRV and now AAAA records. Tools like mitm6 can be used to get IPv6 traffic (via DHCPv6) and Responder will take care of answering the resulting IPv6 and IPv4 DNS requests.

While working on Responder IPv6 implementation i started to wonder how could it be possible to inject some network settings on IPv4 hosts with a static IP, such as a Windows domain controller. One of the great thing about IPv6 implementation, from a pentester standpoint,  is that you don't need to be on an IPv6 enabled network to successfully conduct these attacks.

IPv6 Router Advertisement:

Since DHCPv6 had already been pretty well covered by @_dirkjan with mitm6, and since we are primarily targeting hosts with a static address, ICMPv6 Router Advertisement seemed like a good option. In this case, we don't need to inject a route, or even an IP, the ideal goal would be a DNS server, which is possible on any Windows workstation/servers even when their IPv4 DNS settings are static, but not on a domain controller.


Since I was not able to either inject an IPv6 IP or DNS server on the domain controller, the only option left was DNSSL (RFC 6106).
DNSSL allows you to provide a DNS suffix or also commonly known as DNS Search List. For example, if you're part of the domain name "test.local" and your workstation name is desktop-123, the FQND would be "desktop-123.test.local" and the DNS suffix would be "test.local".

Scapy to the rescue:

Scapy is a great tool/library to quickly test this kind of payload on your network.
The following Python proof of concept will add a DNS suffix on a domain controller (server 2019, with latest updates):
>>> from scapy import all

>>> ra = IPv6 (dst = 'FF02::1')/ICMPv6ND_RA (routerlifetime = 0, reachabletime = 0, prf = 0)/ICMPv6NDOptDNSSL (lifetime = 120, searchlist = ['data.rogueserver.live'])

>>> send(ra)

These lines means send a multicast ICMPv6 Router advertisement to 'FF02::1', router lifetime and reachabletime is set to 0 and we inject a DNSSL called 'data.rogueserver.live' with a lifetime of 2 minutes; We don't want to mess for too long, since every hosts listening for ICMPv6 RA advertisement multicast, will get poisoned with that DNSSL.

Effect on The Domain Controller:

Basically, every DNS requests that were not resolved by the DNS server (domain controller) will be sent to 'data.rogueserver.live'. So for example, if your workstation is joined to the "corp.local" domain, and it's looking for "wpad.corp.local" and that entry does not exist then the PDC will issue a DNS lookup (before NBT-NS/LLMNR -if enabled-) for "wpad.data.rogueserver.live".

This should not cause much disruption on the network since normal DNS queries will be first resolved by the domain controller, actually most home modem/router usually has a '.lan' '.local' DNS suffix and those DNS requests goes unanswered all the time.

Responder Attack:

 Now that we have successfully injected a DNS suffix on the domain controller, we need to exploit it.
Steps are similar to SSRF, SQLI, XXE exfiltration, first you need a cheap domain name, like 'rogueserver.live' and a server on the internet.

Next step is to configure DNS settings on your domain name:
  • Set an A record like 'rogueserver.live' for your domain name pointing to your server IP.
  • Set another A record like 'ns.rogueserver.live' for your domain name pointing to you server IP
  • set a NS record for 'data.rogueserver.live' pointing to 'ns.rogueserver.live'
  • set 2-3 NS records for 'rogueserver.live' pointing to your DNS provider. Usually ns1.provider.com, ns2.provider.com, etc.
DNS has been setup, now comes the Responder part. First, i had to update Responder's DNS server to take care of the pseudo-record OPT for EDNS since every requests coming from the PDC will have an OPT additional record (RFC 7873).
You need two instances of Responder. One on the target local network, let's say hosted on and one instance on the internet.
The instance on the internet will be used as a rogue DNS server, answering to the domain controller with the local IP of the other Responder instance hosted on the local network.
The attack looks like that on the VPS Responder instance:
Here, we are using Responder with the -e option, which poison the request with an IP of our choice, in this case a local IP (, poisoned from the internet.

And on the other Responder instance (, which is located on the local network where the target PDC is located:

Additional Remarks:

With that DNS suffix injected, any sysadmin on the network who mistype a name like 'pdc02' instead of 'pdc-02' will get poisoned, since the name wont be resolved by active directory DNS server, and our rogue server will resolve it. Basically, it will act as what LLMNR/NBT-NS use to do before it was disabled; Resolving queries that were not resolved by the domain controller, but with the priority of a DNS lookup.


Disable IPv6 on the domain controller if it's not necessary.
If IPv6 is necessary on your network, look for switch security option such as RAguard on cisco.


Post a Comment