DNS Amplification Basics
Blog post created on 2018-02-04
DNS amplification used to be a very common technique to perform volumetric denial of service (DoS) attacks on a target machine. It relies on the fact that DNS queries are normally sent over UDP. UDP is a protocol that does not require a handshake or similar, like TCP, to initiate a connection. On the other hand, it simply requires the receiving machine to reply to the address specified in the initial request. If this address is spoofed to be the address of your target host, DNS servers would reply to the target, and if enough traffic is generated the target network would be saturated making the target machine unreachable.
Nowadays DNS amplification is still a relatively common vector but substantially harder to achieve due to many additional network security checks that have been implemented around both DNS server management and network traffic filtering.
DNS amplification relies on some simple concepts:
- Find a DNS query that returns a large result (how large the result is will define the amplification factor). For example ANY query to isc.org;
- Find a list of open DNS resolvers that allow incoming queries from arbitrary hosts and ideally do not have rate limiting or other security measures implemented;
- Find a number (ideally large) of machines (usually referred to as a botnet) capable of sending DNS queries with spoofed IP addresses (the spoofed IP address being the address of your target host). Note that many networks nowadays perform egress traffic filtering based on source IP address;
If you have all of the above you are most likely capable of setting up a DNS amplification attack! But how easy is it to perform DNS queries spoofing an IP address? It turns out it is actually extremely simple.
Scapy is a (Python based) powerful interactive packet manipulation program. It can be used directly from the command line or it can be used as a library within your Python programs.
It essentially allows you to create arbitrary protocol packets, stack them in arbitrary orders (even ones that would not make sense), and directly manipulate any relevant headers. You can also build your own protocol support if necessary.
To perform a DNS amplification attack we need to create:
- An IP packet towards a DNS server and a spoofed source IP;
- A UDP packet towards port 53 (standard DNS port);
- A DNS packet;
- And within the DNS packet the actual DNS query;
- And finally send the resulting request on the network.
Converting this to actual code, we essentially get a very clean result:
from scapy.all import * target = "x.x.x.x" # Target host nameserver = "y.y.y.y" # DNS server ip = IP(src=target, dst=nameserver) udp = UDP(dport=53) dns = DNS(rd=1, qdcount=1, qd=DNSQR(qname="isc.org", qtype=255)) request = (ip/udp/dns) send(request)
The script above, once you replace the
nameserver values with valid IP addresses, will send a single DNS query with a spoofed IP address to the relevant DNS server, which, in turn, will respond to the target machine. Of course for this to be sucesfull you would need to be on a network that does not perform agressive egress IP packet filtering.
We can of course achieve the same result by using
dig, the de facto standard Linux DNS querying utility. To perform a DNS amplification request to a target machine with
dig, however, we need to be able to configure one of our machine's network interfaces to be listening for our target IP. This is needed as
dig does not allow us to alter the IP packet directly, but it does allow us to send the DNS query from a specific interface, and if that interface is configured with the target IP address, the operating system will take care of the rest.
The resulting command looks like this:
dig ANY isc.org -b x.x.x.x @y.y.y.y
x.x.x.x being the target IP and
y.y.y.y being the DNS server.
And there you have it, the basics of a DNS amplification request.