Aug-05-2018, 12:01 PM
Hi,
I am researching DNS and i am attempting to write/modify a small DNS server application written in python to see if it is possible to send special characters and non-digits in the DNS A response, i will then use dig from my local machine to see if i can map a domain name to a corrupted IP address such as '123%^&*(^'.
I understand this may not be possible as RFC say that the field must be a 32 bit numeric integer, however i would like to build a proof of concept script to test and demonstrate.
I have found a small DNS server script online that sucessfully returns a user supplied IP address for any domain that is requested:
so the script looks like this:
When i make the request from my local machine the script shows that it has sent the payload:
But when i look at my nslookup request and response from my host it shows that the A record has been mapped to a random IP address i have no idea where this has came from:
Additionally when i run it with dig with different payloads instead of an IP address i receive the following:
When i change the size of the IP address field in the script, the MSG sizes changes in proportion with the length of the payload,so it would suggest that the corrupt response is being received, however something strange is happening, maybe the corrupt IP address is being inserted into a different parameter of the dns response other then the A name?
Wireshark also shows that the response has been received however i can not find the corrupted IP address anywhere in the DNS response packet.
So, I am guessing the IP split function has something to do with this, i am new with python and not sure how to remove it or what to replace it with, can anybody shed some light on this?
any idea why when i run nslookup on the modified script i receive a random IP address each time? ( currently receiving an IP from vietnam).
What other modifications do i need to make in the script so it sends any characters in the IP parameter?
Thanks in advance
I am researching DNS and i am attempting to write/modify a small DNS server application written in python to see if it is possible to send special characters and non-digits in the DNS A response, i will then use dig from my local machine to see if i can map a domain name to a corrupted IP address such as '123%^&*(^'.
I understand this may not be possible as RFC say that the field must be a 32 bit numeric integer, however i would like to build a proof of concept script to test and demonstrate.
I have found a small DNS server script online that sucessfully returns a user supplied IP address for any domain that is requested:
import socket class DNSQuery: def __init__(self, data): self.data=data self.dominio='' tipo = (ord(data[2]) >> 3) & 15 # Opcode bits if tipo == 0: # Standard query ini=12 lon=ord(data[ini]) while lon != 0: self.dominio+=data[ini+1:ini+lon+1]+'.' ini+=lon+1 lon=ord(data[ini]) def respuesta(self, ip): packet='' if self.dominio: packet+=self.data[:2] + "\x81\x80" packet+=self.data[4:6] + self.data[4:6] + '\x00\x00\x00\x00' # Questions and Answers Counts packet+=self.data[12:] # Original Domain Name Question packet+='\xc0\x0c' # Pointer to domain name packet+='\x00\x01\x00\x01\x00\x00\x00\x3c\x00\x04' # Response type, ttl and resource data length -> 4 bytes packet+=str.join('',map(lambda x: str(str(x)), ip.split('-'))) # 4bytes of IP return packet if __name__ == '__main__': ip='192.168.1.1' print 'pyminifakeDNS:: dom.query. 60 IN A %s' % ip udps = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udps.bind(('',53)) try: while 1: data, addr = udps.recvfrom(1024) p=DNSQuery(data) udps.sendto(p.respuesta(ip), addr) print 'Respuesta: %s -> %s' % (p.dominio, ip) except KeyboardInterrupt: print 'Finalizando' udps.close()I need to modify the packet section to accept all characters, and remove the IP split function, i havee changed the chr/int to str/str as below
def respuesta(self, ip): packet='' if self.dominio: packet+=self.data[:2] + "\x81\x80" packet+=self.data[4:6] + self.data[4:6] + '\x00\x00\x00\x00' # Questions and Answers Counts packet+=self.data[12:] # Original Domain Name Question packet+='\xc0\x0c' # Pointer to domain name packet+='\x00\x01\x00\x01\x00\x00\x00\x3c\x00\x04' # Response type, ttl and resource data length -> 4 bytes packet+=str.join('',map(lambda x: str(str(x)), ip.split('-'))) # 4bytes of IP return packetI am attempting to send the following DNS response with the A name record as
Quote: test123^&*^
so the script looks like this:
import socket class DNSQuery: def __init__(self, data): self.data=data self.dominio='' tipo = (ord(data[2]) >> 3) & 15 # Opcode bits if tipo == 0: # Standard query ini=12 lon=ord(data[ini]) while lon != 0: self.dominio+=data[ini+1:ini+lon+1]+'.' ini+=lon+1 lon=ord(data[ini]) def respuesta(self, ip): packet='' if self.dominio: packet+=self.data[:2] + "\x81\x80" packet+=self.data[4:6] + self.data[4:6] + '\x00\x00\x00\x00' # Questions and Answers Counts packet+=self.data[12:] # Original Domain Name Question packet+='\xc0\x0c' # Pointer to domain name packet+='\x00\x01\x00\x01\x00\x00\x00\x3c\x00\x04' # Response type, ttl and resource data length -> 4 bytes packet+=str.join('',map(lambda x: str(str(x)), ip.split('-'))) # 4bytes of IP return packet if __name__ == '__main__': ip='test123^&*^' print 'pyminifakeDNS:: dom.query. 60 IN A %s' % ip udps = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udps.bind(('',53)) try: while 1: data, addr = udps.recvfrom(1024) p=DNSQuery(data) udps.sendto(p.respuesta(ip), addr) print 'Respuesta: %s -> %s' % (p.dominio, ip) except KeyboardInterrupt: print 'Finalizando' udps.close()The script executes and waits for the DNS request:
Quote:pyminifakeDNS:: dom.query. 60 IN A test123^&*^
When i make the request from my local machine the script shows that it has sent the payload:
Quote:Respuesta: google.com. -> test123^&*^
But when i look at my nslookup request and response from my host it shows that the A record has been mapped to a random IP address i have no idea where this has came from:
Quote:nslookup google.com myserver
Server: myserver
Address: myserver.49#53
Non-authoritative answer:
Name: google.com
Address: 116.101.115.116
Additionally when i run it with dig with different payloads instead of an IP address i receive the following:
Quote:; <<>> DiG 9.10.3-P4-Ubuntu <<>> @myserver google.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32328
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: Message has 61 extra bytes at end
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;google.com. IN A
;; Query time: 15 msec
;; SERVER: 159.65.87.49#53(159.65.87.49)
;; WHEN: Sun Aug 05 12:51:28 BST 2018
;; MSG SIZE rcvd: 100
When i change the size of the IP address field in the script, the MSG sizes changes in proportion with the length of the payload,so it would suggest that the corrupt response is being received, however something strange is happening, maybe the corrupt IP address is being inserted into a different parameter of the dns response other then the A name?
Wireshark also shows that the response has been received however i can not find the corrupted IP address anywhere in the DNS response packet.
So, I am guessing the IP split function has something to do with this, i am new with python and not sure how to remove it or what to replace it with, can anybody shed some light on this?
any idea why when i run nslookup on the modified script i receive a random IP address each time? ( currently receiving an IP from vietnam).
What other modifications do i need to make in the script so it sends any characters in the IP parameter?
Thanks in advance