├── README.md ├── old_attempts ├── requirements.txt ├── dns_server.py └── dns_server_rebind.py └── index.php /README.md: -------------------------------------------------------------------------------- 1 | # HM-DNS -------------------------------------------------------------------------------- /old_attempts/requirements.txt: -------------------------------------------------------------------------------- 1 | dnslib==0.9.6 -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | DNS Rebinding demo 4 | 5 | 15 | 28 | 29 | 30 |

31 |
32 | 33 | -------------------------------------------------------------------------------- /old_attempts/dns_server.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | LICENSE http://www.apache.org/licenses/LICENSE-2.0 4 | Source: https://gist.github.com/andreif/6069838 5 | """ 6 | import datetime 7 | import sys 8 | import time 9 | import threading 10 | import traceback 11 | import SocketServer 12 | from dnslib import * 13 | 14 | class DomainName(str): 15 | def __getattr__(self, item): 16 | return DomainName(item + '.' + self) 17 | 18 | 19 | D = DomainName('example.com') 20 | IP = '127.0.0.1' 21 | TTL = 60 * 1 #one minute 22 | PORT = 5053 23 | 24 | soa_record = SOA( 25 | mname=D.ns1, # primary name server 26 | rname=D.andrei, # email of the domain administrator 27 | times=( 28 | 201307231, # serial number 29 | 60 * 60 * 1, # refresh 30 | 60 * 60 * 3, # retry 31 | 60 * 60 * 24, # expire 32 | 60 * 60 * 1, # minimum 33 | ) 34 | ) 35 | ns_records = [NS(D.ns1), NS(D.ns2)] 36 | records = { 37 | D: [A(IP), AAAA((0,) * 16), MX(D.mail), soa_record] + ns_records, 38 | D.ns1: [A(IP)], # MX and NS records must never point to a CNAME alias (RFC 2181 section 10.3) 39 | D.ns2: [A(IP)], 40 | D.mail: [A(IP)], 41 | D.andrei: [CNAME(D)], 42 | } 43 | 44 | 45 | def dns_response(data): 46 | request = DNSRecord.parse(data) 47 | 48 | print request 49 | 50 | reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q) 51 | 52 | qname = request.q.qname 53 | qn = str(qname) 54 | qtype = request.q.qtype 55 | qt = QTYPE[qtype] 56 | 57 | if qn == D or qn.endswith('.' + D): 58 | 59 | for name, rrs in records.iteritems(): 60 | if name == qn: 61 | for rdata in rrs: 62 | rqt = rdata.__class__.__name__ 63 | if qt in ['*', rqt]: 64 | reply.add_answer(RR(rname=qname, rtype=QTYPE[rqt], rclass=1, ttl=TTL, rdata=rdata)) 65 | 66 | for rdata in ns_records: 67 | reply.add_ns(RR(rname=D, rtype=QTYPE.NS, rclass=1, ttl=TTL, rdata=rdata)) 68 | 69 | reply.add_ns(RR(rname=D, rtype=QTYPE.SOA, rclass=1, ttl=TTL, rdata=soa_record)) 70 | 71 | print "---- Reply:\n", reply 72 | 73 | return reply.pack() 74 | 75 | 76 | class BaseRequestHandler(SocketServer.BaseRequestHandler): 77 | 78 | def get_data(self): 79 | raise NotImplementedError 80 | 81 | def send_data(self, data): 82 | raise NotImplementedError 83 | 84 | def handle(self): 85 | now = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f') 86 | print "\n\n%s request %s (%s %s):" % (self.__class__.__name__[:3], now, self.client_address[0], 87 | self.client_address[1]) 88 | try: 89 | data = self.get_data() 90 | print len(data), data.encode('hex') # repr(data).replace('\\x', '')[1:-1] 91 | self.send_data(dns_response(data)) 92 | except Exception: 93 | traceback.print_exc(file=sys.stderr) 94 | 95 | 96 | class TCPRequestHandler(BaseRequestHandler): 97 | 98 | def get_data(self): 99 | data = self.request.recv(8192).strip() 100 | sz = int(data[:2].encode('hex'), 16) 101 | if sz < len(data) - 2: 102 | raise Exception("Wrong size of TCP packet") 103 | elif sz > len(data) - 2: 104 | raise Exception("Too big TCP packet") 105 | return data[2:] 106 | 107 | def send_data(self, data): 108 | sz = hex(len(data))[2:].zfill(4).decode('hex') 109 | return self.request.sendall(sz + data) 110 | 111 | 112 | class UDPRequestHandler(BaseRequestHandler): 113 | 114 | def get_data(self): 115 | return self.request[0].strip() 116 | 117 | def send_data(self, data): 118 | return self.request[1].sendto(data, self.client_address) 119 | 120 | 121 | if __name__ == '__main__': 122 | print "Starting nameserver..." 123 | 124 | servers = [ 125 | SocketServer.ThreadingUDPServer(('', PORT), UDPRequestHandler), 126 | SocketServer.ThreadingTCPServer(('', PORT), TCPRequestHandler), 127 | ] 128 | for s in servers: 129 | thread = threading.Thread(target=s.serve_forever) # that thread will start one more thread for each request 130 | thread.daemon = True # exit the server thread when the main thread terminates 131 | thread.start() 132 | print "%s server loop running in thread: %s" % (s.RequestHandlerClass.__name__[:3], thread.name) 133 | 134 | try: 135 | while 1: 136 | time.sleep(1) 137 | sys.stderr.flush() 138 | sys.stdout.flush() 139 | 140 | except KeyboardInterrupt: 141 | pass 142 | finally: 143 | for s in servers: 144 | s.shutdown() -------------------------------------------------------------------------------- /old_attempts/dns_server_rebind.py: -------------------------------------------------------------------------------- 1 | """ 2 | Source: https://github.com/marksteward/rebind 3 | """ 4 | import datetime 5 | import sys 6 | import ConfigParser 7 | import time 8 | import threading 9 | import traceback 10 | import SocketServer 11 | from dnslib import * 12 | import socket 13 | import dns.resolver 14 | 15 | 16 | class DomainName(str): 17 | def __getattr__(self, item): 18 | return DomainName(item + '.' + self) 19 | 20 | 21 | defaults = { 22 | 'root': 'localhost', 23 | 'ttl': '60', 24 | 'ip': '', 25 | 'port': '5053', 26 | 'serialsuffix': '1', 27 | 'resolver': '8.8.8.8', 28 | } 29 | config = ConfigParser.ConfigParser(defaults) 30 | config.read(['rebind.conf']) 31 | 32 | D = DomainName(config.get('rebind', 'root')) 33 | if config.get('rebind', 'ip') == '': 34 | IP = socket.gethostbyname(D) 35 | else: 36 | IP = config.get('rebind', 'ip') 37 | TTL = config.getint('rebind', 'ttl') 38 | PORT = config.getint('rebind', 'port') 39 | SERIALSUFFIX = config.get('rebind', 'serialsuffix') 40 | RESOLVER = config.get('rebind', 'resolver') 41 | 42 | soa_record = SOA( 43 | mname=D.ns1, # primary name server 44 | rname=D.hostmaster, # email of the domain administrator 45 | times=( 46 | int(datetime.datetime.utcnow().strftime('%Y%m%d') + SERIALSUFFIX), # serial number 47 | 60 * 60 * 1, # refresh 48 | 60 * 60 * 3, # retry 49 | 60 * 60 * 24, # expire 50 | 60 * 60 * 1, # minimum 51 | ) 52 | ) 53 | ns_records = [NS(D.ns1), NS(D.ns2)] 54 | records = { 55 | D: [A(IP), AAAA((0,) * 16), MX(D.mail), soa_record] + ns_records, 56 | D.ns1: [A(IP)], # MX and NS records must never point to a CNAME alias (RFC 2181 section 10.3) 57 | D.ns2: [A(IP)], 58 | D.mail: [A(IP)], 59 | D.hostmaster: [CNAME(D)], 60 | } 61 | 62 | clients = {} 63 | 64 | def rchop(string, ending): 65 | if string.endswith(ending): 66 | return string[:-len(ending)] 67 | return string 68 | 69 | def dns_response(data): 70 | request = DNSRecord.parse(data) 71 | 72 | print request 73 | 74 | reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q) 75 | 76 | qname = request.q.qname 77 | qn = rchop(str(qname), '.') 78 | 79 | qtype = request.q.qtype 80 | qt = QTYPE[qtype] 81 | 82 | if qn in records: 83 | for rdata in records[qn]: 84 | rqt = rdata.__class__.__name__ 85 | if qt in ['ANY', rqt]: 86 | reply.add_answer(RR(rname=qname, rtype=getattr(QTYPE, rqt), rclass=1, ttl=TTL, rdata=rdata)) 87 | 88 | if qt in ['ANY']: 89 | for rdata in ns_records: 90 | reply.add_ar(RR(rname=D, rtype=QTYPE.NS, rclass=1, ttl=TTL, rdata=rdata)) 91 | 92 | reply.add_auth(RR(rname=D, rtype=QTYPE.SOA, rclass=1, ttl=TTL, rdata=soa_record)) 93 | 94 | elif not qn.endswith('.' + D): 95 | pass 96 | 97 | else: 98 | data = rchop(qn, '.' + D) 99 | if '.' not in data: 100 | # Main page - not rebound 101 | reply.add_answer(RR(rname=qname, rtype=QTYPE.A, rclass=1, ttl=TTL, rdata=A(IP))) 102 | else: 103 | target, client = data.rsplit('.', 1) 104 | if '-' in client: 105 | op, client = client.split('-', 1) 106 | op = op.upper() 107 | 108 | if op in ['N', 'R']: 109 | clients[client] = op 110 | 111 | if client not in clients: 112 | clients[client] = 'N' # normal 113 | 114 | print 'Client %s is currently %s' % (client, clients[client]) 115 | if clients[client] == 'N': 116 | reply.add_answer(RR(rname=qname, rtype=QTYPE.A, rclass=1, ttl=15, rdata=A(IP))) 117 | else: 118 | try: 119 | print 'Looking up %s' % target 120 | for rdata in dns.resolver.query(target, 'A'): 121 | reply.add_answer(RR(rname=qname, rtype=QTYPE.A, rclass=1, ttl=15, rdata=A(rdata.address))) 122 | except Exception: 123 | pass 124 | 125 | print "---- Reply:\n", reply 126 | 127 | return reply.pack() 128 | 129 | 130 | class BaseRequestHandler(SocketServer.BaseRequestHandler): 131 | 132 | def get_data(self): 133 | raise NotImplementedError 134 | 135 | def send_data(self, data): 136 | raise NotImplementedError 137 | 138 | def handle(self): 139 | now = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f') 140 | print "\n\n%s request %s (%s %s):" % (self.__class__.__name__[:3], now, self.client_address[0], 141 | self.client_address[1]) 142 | try: 143 | data = self.get_data() 144 | print len(data), data.encode('hex') 145 | self.send_data(dns_response(data)) 146 | except Exception: 147 | traceback.print_exc(file=sys.stderr) 148 | 149 | 150 | class TCPRequestHandler(BaseRequestHandler): 151 | 152 | def get_data(self): 153 | data = self.request.recv(8192) 154 | sz = int(data[:2].encode('hex'), 16) 155 | if sz < len(data) - 2: 156 | raise Exception("Wrong size of TCP packet") 157 | elif sz > len(data) - 2: 158 | raise Exception("Too big TCP packet") 159 | return data[2:] 160 | 161 | def send_data(self, data): 162 | sz = ('%04x' % len(data)).decode('hex') 163 | return self.request.sendall(sz + data) 164 | 165 | 166 | class UDPRequestHandler(BaseRequestHandler): 167 | 168 | def get_data(self): 169 | return self.request[0] 170 | 171 | def send_data(self, data): 172 | return self.request[1].sendto(data, self.client_address) 173 | 174 | 175 | if __name__ == '__main__': 176 | print "Starting nameserver..." 177 | 178 | servers = [ 179 | SocketServer.ThreadingUDPServer(('', PORT), UDPRequestHandler), 180 | SocketServer.ThreadingTCPServer(('', PORT), TCPRequestHandler), 181 | ] 182 | for s in servers: 183 | thread = threading.Thread(target=s.serve_forever) # that thread will start one more thread for each request 184 | thread.daemon = True # exit the server thread when the main thread terminates 185 | thread.start() 186 | print "%s server loop running in thread: %s" % (s.RequestHandlerClass.__name__[:3], thread.name) 187 | 188 | try: 189 | while 1: 190 | time.sleep(1) 191 | sys.stderr.flush() 192 | sys.stdout.flush() 193 | 194 | except KeyboardInterrupt: 195 | pass 196 | finally: 197 | for s in servers: 198 | s.shutdown() --------------------------------------------------------------------------------