|
|
|
@ -48,8 +48,8 @@ Currently it supports the following modules:
|
|
|
|
|
- pgsql_login : Brute-force PostgreSQL
|
|
|
|
|
- vnc_login : Brute-force VNC
|
|
|
|
|
|
|
|
|
|
- dns_forward : Forward lookup subdomains
|
|
|
|
|
- dns_reverse : Reverse lookup subnets
|
|
|
|
|
- dns_forward : Brute-force DNS
|
|
|
|
|
- dns_reverse : Brute-force DNS (reverse lookup subnets)
|
|
|
|
|
- snmp_login : Brute-force SNMPv1/2 and SNMPv3
|
|
|
|
|
|
|
|
|
|
- unzip_pass : Brute-force the password of encrypted ZIP files
|
|
|
|
@ -128,7 +128,7 @@ psycopg | PostgreSQL | http://initd.org/psycopg/
|
|
|
|
|
--------------------------------------------------------------------------------------------------
|
|
|
|
|
pycrypto | VNC | http://www.dlitz.net/software/pycrypto/ | 2.3 |
|
|
|
|
|
--------------------------------------------------------------------------------------------------
|
|
|
|
|
pydns | DNS | http://pydns.sourceforge.net/ | 2.3.4 |
|
|
|
|
|
dnspython | DNS | http://www.dnspython.org/ | 1.10.0 |
|
|
|
|
|
--------------------------------------------------------------------------------------------------
|
|
|
|
|
pysnmp | SNMP | http://pysnmp.sourceforge.net/ | 4.2.1 |
|
|
|
|
|
--------------------------------------------------------------------------------------------------
|
|
|
|
@ -494,25 +494,29 @@ unzip_pass zipfile=path/to/file.zip password=FILE0 0=passwords.txt -x ignore:cod
|
|
|
|
|
}}}
|
|
|
|
|
{{{ DNS
|
|
|
|
|
|
|
|
|
|
* Forward lookup subdomains.
|
|
|
|
|
* Brute-force subdomains.
|
|
|
|
|
(a) Ignore NXDOMAIN responses (rcode 3).
|
|
|
|
|
-----------
|
|
|
|
|
dns_forward domain=FILE0.google.com 0=names.txt -x ignore:code=3
|
|
|
|
|
(a)
|
|
|
|
|
* Forward lookup domain with all possible TLDs.
|
|
|
|
|
dns_forward name=FILE0.google.com 0=names.txt -x ignore:code=3
|
|
|
|
|
(a)
|
|
|
|
|
* Brute-force domain with every possible TLDs.
|
|
|
|
|
-----------
|
|
|
|
|
dns_forward domain=google.MOD0 0=TLD -x ignore:code=3
|
|
|
|
|
dns_forward name=google.MOD0 0=TLD -x ignore:code=3
|
|
|
|
|
|
|
|
|
|
* Foward lookup SRV records.
|
|
|
|
|
* Brute-force SRV records.
|
|
|
|
|
-----------
|
|
|
|
|
dns_forward domain=MOD0.microsoft.com 0=SRV qtype=SRV -x ignore:code=3
|
|
|
|
|
dns_forward name=MOD0.microsoft.com 0=SRV qtype=SRV -x ignore:code=3
|
|
|
|
|
|
|
|
|
|
* Reverse lookup several subnets.
|
|
|
|
|
* Grab the version of several hosts.
|
|
|
|
|
-----------
|
|
|
|
|
dns_forward server=FILE0 0=hosts.txt name=version.bind qtype=txt qclass=ch
|
|
|
|
|
|
|
|
|
|
* Reverse lookup several networks.
|
|
|
|
|
(a) Ignore names that do not contain 'google.com'.
|
|
|
|
|
(b) Ignore generic PTR records.
|
|
|
|
|
-----------
|
|
|
|
|
dns_reverse host=NET0 0=216.239.32.0-216.239.47.255,8.8.8.0/24 -x ignore:code=3 -x ignore:fgrep!=google.com -x ignore:fgrep=216-239-
|
|
|
|
|
(a) (b)
|
|
|
|
|
(a) (b)
|
|
|
|
|
}}}
|
|
|
|
|
{{{ SNMP
|
|
|
|
|
|
|
|
|
@ -554,7 +558,7 @@ TODO
|
|
|
|
|
----
|
|
|
|
|
* SSL support for SMTP, MySQL, ... (use socat in the meantime)
|
|
|
|
|
* new option -e ns like in Medusa (not likely to be implemented due to design)
|
|
|
|
|
* replace PyDNS|paramiko|IPy with a better module (scapy|libssh2|... ?)
|
|
|
|
|
* replace dnspython|paramiko|IPy with a better module (scapy|libssh2|... ?)
|
|
|
|
|
* rewrite itertools.product that eats too much memory when processing large wordlists
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
@ -585,6 +589,7 @@ from struct import unpack
|
|
|
|
|
import socket
|
|
|
|
|
import subprocess
|
|
|
|
|
import hashlib
|
|
|
|
|
from collections import defaultdict
|
|
|
|
|
try:
|
|
|
|
|
# python3+
|
|
|
|
|
from queue import Queue, Empty, Full
|
|
|
|
@ -2737,6 +2742,72 @@ class VNC_login:
|
|
|
|
|
# }}}
|
|
|
|
|
|
|
|
|
|
# DNS {{{
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
import dns.rdatatype
|
|
|
|
|
import dns.message
|
|
|
|
|
import dns.query
|
|
|
|
|
import dns.reversename
|
|
|
|
|
except ImportError:
|
|
|
|
|
warnings.append('dnspython')
|
|
|
|
|
|
|
|
|
|
def dns_query(server, timeout, protocol, qname, qtype, qclass):
|
|
|
|
|
request = dns.message.make_query(qname, qtype, qclass)
|
|
|
|
|
|
|
|
|
|
if protocol == 'tcp':
|
|
|
|
|
response = dns.query.tcp(request, server, timeout=timeout, one_rr_per_rrset=True)
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
response = dns.query.udp(request, server, timeout=timeout, one_rr_per_rrset=True)
|
|
|
|
|
|
|
|
|
|
if response.flags & dns.flags.TC:
|
|
|
|
|
response = dns.query.tcp(request, server, timeout=timeout, one_rr_per_rrset=True)
|
|
|
|
|
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
|
|
def generate_tld():
|
|
|
|
|
gtld = [
|
|
|
|
|
'aero', 'arpa', 'asia', 'biz', 'cat', 'com', 'coop', 'edu',
|
|
|
|
|
'gov', 'info', 'int', 'jobs', 'mil', 'mobi', 'museum', 'name',
|
|
|
|
|
'net', 'org', 'pro', 'tel', 'travel']
|
|
|
|
|
|
|
|
|
|
cctld = [''.join(i) for i in product(*[ascii_lowercase]*2)]
|
|
|
|
|
tld = gtld + cctld
|
|
|
|
|
return tld, len(tld)
|
|
|
|
|
|
|
|
|
|
def generate_srv():
|
|
|
|
|
common = [
|
|
|
|
|
'_gc._tcp', '_kerberos._tcp', '_kerberos._udp', '_ldap._tcp',
|
|
|
|
|
'_test._tcp', '_sips._tcp', '_sip._udp', '_sip._tcp', '_aix._tcp', '_aix._udp',
|
|
|
|
|
'_finger._tcp', '_ftp._tcp', '_http._tcp', '_nntp._tcp', '_telnet._tcp',
|
|
|
|
|
'_whois._tcp', '_h323cs._tcp', '_h323cs._udp', '_h323be._tcp', '_h323be._udp',
|
|
|
|
|
'_h323ls._tcp', '_h323ls._udp', '_sipinternal._tcp', '_sipinternaltls._tcp',
|
|
|
|
|
'_sip._tls', '_sipfederationtls._tcp', '_jabber._tcp', '_xmpp-server._tcp', '_xmpp-client._tcp',
|
|
|
|
|
'_imap.tcp', '_certificates._tcp', '_crls._tcp', '_pgpkeys._tcp', '_pgprevokations._tcp',
|
|
|
|
|
'_cmp._tcp', '_svcp._tcp', '_crl._tcp', '_ocsp._tcp', '_PKIXREP._tcp',
|
|
|
|
|
'_smtp._tcp', '_hkp._tcp', '_hkps._tcp', '_jabber._udp', '_xmpp-server._udp',
|
|
|
|
|
'_xmpp-client._udp', '_jabber-client._tcp', '_jabber-client._udp',
|
|
|
|
|
'_adsp._domainkey', '_policy._domainkey', '_domainkey', '_ldap._tcp.dc._msdcs', '_ldap._udp.dc._msdcs']
|
|
|
|
|
|
|
|
|
|
def distro():
|
|
|
|
|
import os
|
|
|
|
|
import re
|
|
|
|
|
files = ['/usr/share/nmap/nmap-protocols', '/usr/share/nmap/nmap-services', '/etc/protocols', '/etc/services']
|
|
|
|
|
ret = []
|
|
|
|
|
for f in files:
|
|
|
|
|
if not os.path.isfile(f):
|
|
|
|
|
logger.warn("File '%s' is missing, there will be less records to test" % f)
|
|
|
|
|
continue
|
|
|
|
|
for line in open(f):
|
|
|
|
|
match = re.match(r'([a-zA-Z0-9]+)\s', line)
|
|
|
|
|
if not match: continue
|
|
|
|
|
for w in re.split(r'[^a-z0-9]', match.group(1).strip().lower()):
|
|
|
|
|
ret.extend(['_%s.%s' % (w, i) for i in ('_tcp', '_udp')])
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
srv = set(common + distro())
|
|
|
|
|
return srv, len(srv)
|
|
|
|
|
|
|
|
|
|
class HostInfo:
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.name = set()
|
|
|
|
@ -2757,61 +2828,99 @@ class HostInfo:
|
|
|
|
|
return line
|
|
|
|
|
|
|
|
|
|
class Controller_DNS(Controller):
|
|
|
|
|
hostmap = {}
|
|
|
|
|
records = defaultdict(list)
|
|
|
|
|
hostmap = defaultdict(HostInfo)
|
|
|
|
|
|
|
|
|
|
# show_final {{{
|
|
|
|
|
def show_final(self):
|
|
|
|
|
''' Expected output:
|
|
|
|
|
Records -----
|
|
|
|
|
ftp.example.com. IN A 10.0.1.1
|
|
|
|
|
www.example.com. IN A 10.0.1.1
|
|
|
|
|
prod.example.com. IN CNAME www.example.com.
|
|
|
|
|
ipv6.example.com. IN AAAA dead:beef::
|
|
|
|
|
dev.example.com. IN A 10.0.1.2
|
|
|
|
|
svn.example.com. IN A 10.0.2.1
|
|
|
|
|
websrv1.example.com. IN CNAME prod.example.com.
|
|
|
|
|
blog.example.com. IN CNAME example.wordpress.com.
|
|
|
|
|
'''
|
|
|
|
|
1.2.3.4 ftp.example.com
|
|
|
|
|
. www.example.com
|
|
|
|
|
. www2.example.com
|
|
|
|
|
noip cms.example.com -> www.mistake.com
|
|
|
|
|
print('Records ' + '-'*42)
|
|
|
|
|
for name, infos in sorted(self.records.items()):
|
|
|
|
|
for qclass, qtype, rdata in infos:
|
|
|
|
|
print('%34s %8s %-8s %s' % (name, qclass, qtype, rdata))
|
|
|
|
|
|
|
|
|
|
''' Expected output:
|
|
|
|
|
Hostmap ------
|
|
|
|
|
ipv6.example.com dead:beef::
|
|
|
|
|
ftp.example.com 10.0.1.1
|
|
|
|
|
www.example.com 10.0.1.1
|
|
|
|
|
prod.example.com
|
|
|
|
|
websrv1.example.com
|
|
|
|
|
dev.example.com 10.0.1.2
|
|
|
|
|
svn.example.com 10.0.2.1
|
|
|
|
|
example.wordpress.com ?
|
|
|
|
|
blog.example.com
|
|
|
|
|
Domains ---------------------------
|
|
|
|
|
example.com 8
|
|
|
|
|
Networks --------------------------
|
|
|
|
|
dead:beef::
|
|
|
|
|
10.0.1.x
|
|
|
|
|
10.0.2.1
|
|
|
|
|
'''
|
|
|
|
|
ipmap = {}
|
|
|
|
|
noips = set()
|
|
|
|
|
ipmap = defaultdict(HostInfo)
|
|
|
|
|
noips = defaultdict(list)
|
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
hostmap = {
|
|
|
|
|
'ftp.example.com': {'ip': ['1.2.3.4'], 'alias': []},
|
|
|
|
|
'www.example.com': {'ip': ['1.2.3.4'], 'alias': ['www2.example.com']},
|
|
|
|
|
'www.mistake.com': {'ip': [], 'alias': ['cms.example.com']}, ...}
|
|
|
|
|
ipmap = {'1.2.3.4': {'name': ['www.example.com', 'ftp.example.com'], 'alias': ('www2.example.com')}}
|
|
|
|
|
noips = ['cms.example.com -> www.mistake.com', ...]
|
|
|
|
|
'www.example.com': {'ip': ['10.0.1.1'], 'alias': ['prod.example.com']},
|
|
|
|
|
'ftp.example.com': {'ip': ['10.0.1.1'], 'alias': []},
|
|
|
|
|
'prod.example.com': {'ip': [], 'alias': ['websrv1.example.com']},
|
|
|
|
|
'ipv6.example.com': {'ip': ['dead:beef::'], 'alias': []},
|
|
|
|
|
'dev.example.com': {'ip': ['10.0.1.2'], 'alias': []},
|
|
|
|
|
'example.wordpress.com': {'ip': [], 'alias': ['blog.example.com']},
|
|
|
|
|
|
|
|
|
|
ipmap = {'10.0.1.1': {'name': ['www.example.com', 'ftp.example.com'], 'alias': ['prod.example.com', 'websrv1.example.com']}, ...
|
|
|
|
|
noips = {'example.wordpress.com': ['blog.example.com'],
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
for name, hinfo in self.hostmap.items():
|
|
|
|
|
logger.debug('%s -> %s' % (name, hinfo))
|
|
|
|
|
if not hinfo.ip: # orphan CNAME hostnames (with no IP address) may be still valid virtual hosts
|
|
|
|
|
for alias in hinfo.alias:
|
|
|
|
|
noips.add('%s -> %s' % (alias, name))
|
|
|
|
|
else:
|
|
|
|
|
for ip in hinfo.ip:
|
|
|
|
|
if ip not in ipmap: ipmap[ip] = HostInfo()
|
|
|
|
|
ipmap[ip].name.add(name)
|
|
|
|
|
ipmap[ip].alias.update(hinfo.alias)
|
|
|
|
|
|
|
|
|
|
# pretty print
|
|
|
|
|
def pprint_info(key, infos):
|
|
|
|
|
first = True
|
|
|
|
|
for info in infos:
|
|
|
|
|
if first:
|
|
|
|
|
print('%34s %s' % (info, key))
|
|
|
|
|
first = False
|
|
|
|
|
else:
|
|
|
|
|
print('%34s %s' % (info, key))
|
|
|
|
|
|
|
|
|
|
for ip in hinfo.ip:
|
|
|
|
|
ip = IP(ip)
|
|
|
|
|
ipmap[ip].name.add(name)
|
|
|
|
|
ipmap[ip].alias.update(hinfo.alias)
|
|
|
|
|
|
|
|
|
|
for name, hinfo in self.hostmap.items():
|
|
|
|
|
if not hinfo.ip and hinfo.alias:
|
|
|
|
|
found = False
|
|
|
|
|
for ip, v in ipmap.items():
|
|
|
|
|
if name in v.alias:
|
|
|
|
|
for alias in hinfo.alias:
|
|
|
|
|
ipmap[ip].alias.add(alias)
|
|
|
|
|
found = True
|
|
|
|
|
|
|
|
|
|
if not found: # orphan CNAME hostnames (with no IP address) may be still valid virtual hosts
|
|
|
|
|
noips[name].extend(hinfo.alias)
|
|
|
|
|
|
|
|
|
|
print('Hostmap ' + '-'*42)
|
|
|
|
|
for ip, hinfo in sorted(ipmap.items()):
|
|
|
|
|
pprint_info( ip, hinfo.name)
|
|
|
|
|
pprint_info('.', hinfo.alias)
|
|
|
|
|
|
|
|
|
|
pprint_info('noip', noips)
|
|
|
|
|
for name in hinfo.name:
|
|
|
|
|
print('%34s %s' % (name, ip))
|
|
|
|
|
for alias in hinfo.alias:
|
|
|
|
|
print('%34s' % alias)
|
|
|
|
|
|
|
|
|
|
for k, v in noips.items():
|
|
|
|
|
print('%34s ?' % k)
|
|
|
|
|
for alias in v:
|
|
|
|
|
print('%34s' % alias)
|
|
|
|
|
|
|
|
|
|
print('Domains ' + '-'*42)
|
|
|
|
|
domains = {}
|
|
|
|
|
networks = {}
|
|
|
|
|
for ip, hinfo in ipmap.items():
|
|
|
|
|
for name in hinfo.name:
|
|
|
|
|
i = 1 if name.count('.') > 1 else 0
|
|
|
|
|
for name in hinfo.name.union(hinfo.alias):
|
|
|
|
|
if name.count('.') > 1:
|
|
|
|
|
i = 1
|
|
|
|
|
else:
|
|
|
|
|
i = 0
|
|
|
|
|
d = '.'.join(name.split('.')[i:])
|
|
|
|
|
if d not in domains: domains[d] = 0
|
|
|
|
|
domains[d] += 1
|
|
|
|
@ -2831,67 +2940,37 @@ class Controller_DNS(Controller):
|
|
|
|
|
|
|
|
|
|
for net, ips in sorted(nets.items()):
|
|
|
|
|
if len(ips) == 1:
|
|
|
|
|
print(' '*10 + '%39s' % ips[0])
|
|
|
|
|
print(' '*34 + ' %s' % ips[0])
|
|
|
|
|
else:
|
|
|
|
|
print(' '*10 + '%37s.x' % '.'.join(str(net).split('.')[:-1]))
|
|
|
|
|
print(' '*34 + ' %s.x' % '.'.join(str(net).split('.')[:-1]))
|
|
|
|
|
|
|
|
|
|
# }}}
|
|
|
|
|
|
|
|
|
|
def push_final(self, resp):
|
|
|
|
|
for name, hinfo in resp.hostmap.items():
|
|
|
|
|
if name not in self.hostmap:
|
|
|
|
|
self.hostmap[name] = hinfo
|
|
|
|
|
else:
|
|
|
|
|
self.hostmap[name].ip.update(hinfo.ip)
|
|
|
|
|
self.hostmap[name].alias.update(hinfo.alias)
|
|
|
|
|
if hasattr(resp, 'rrs'):
|
|
|
|
|
for rr in resp.rrs:
|
|
|
|
|
name, qclass, qtype, data = rr
|
|
|
|
|
|
|
|
|
|
def generate_tld():
|
|
|
|
|
gtld = [
|
|
|
|
|
'aero', 'arpa', 'asia', 'biz', 'cat', 'com', 'coop', 'edu',
|
|
|
|
|
'gov', 'info', 'int', 'jobs', 'mil', 'mobi', 'museum', 'name',
|
|
|
|
|
'net', 'org', 'pro', 'tel', 'travel']
|
|
|
|
|
info = (qclass, qtype, data)
|
|
|
|
|
if info not in self.records[name]:
|
|
|
|
|
self.records[name].append(info)
|
|
|
|
|
|
|
|
|
|
cctld = [''.join(i) for i in product(*[ascii_lowercase]*2)]
|
|
|
|
|
tld = gtld + cctld
|
|
|
|
|
return tld, len(tld)
|
|
|
|
|
if not qclass == 'IN':
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
def generate_srv():
|
|
|
|
|
common = [
|
|
|
|
|
'_gc._tcp', '_kerberos._tcp', '_kerberos._udp', '_ldap._tcp',
|
|
|
|
|
'_test._tcp', '_sips._tcp', '_sip._udp', '_sip._tcp', '_aix._tcp', '_aix._udp',
|
|
|
|
|
'_finger._tcp', '_ftp._tcp', '_http._tcp', '_nntp._tcp', '_telnet._tcp',
|
|
|
|
|
'_whois._tcp', '_h323cs._tcp', '_h323cs._udp', '_h323be._tcp', '_h323be._udp',
|
|
|
|
|
'_h323ls._tcp', '_h323ls._udp', '_sipinternal._tcp', '_sipinternaltls._tcp',
|
|
|
|
|
'_sip._tls', '_sipfederationtls._tcp', '_jabber._tcp', '_xmpp-server._tcp', '_xmpp-client._tcp',
|
|
|
|
|
'_imap.tcp', '_certificates._tcp', '_crls._tcp', '_pgpkeys._tcp', '_pgprevokations._tcp',
|
|
|
|
|
'_cmp._tcp', '_svcp._tcp', '_crl._tcp', '_ocsp._tcp', '_PKIXREP._tcp',
|
|
|
|
|
'_smtp._tcp', '_hkp._tcp', '_hkps._tcp', '_jabber._udp', '_xmpp-server._udp',
|
|
|
|
|
'_xmpp-client._udp', '_jabber-client._tcp', '_jabber-client._udp',
|
|
|
|
|
'_adsp._domainkey', '_policy._domainkey', '_domainkey', '_ldap._tcp.dc._msdcs', '_ldap._udp.dc._msdcs']
|
|
|
|
|
if qtype == 'PTR':
|
|
|
|
|
data = data[:-1]
|
|
|
|
|
self.hostmap[data].ip.add(name)
|
|
|
|
|
|
|
|
|
|
def distro():
|
|
|
|
|
import os
|
|
|
|
|
import re
|
|
|
|
|
files = ['/usr/share/nmap/nmap-protocols', '/usr/share/nmap/nmap-services', '/etc/protocols', '/etc/services']
|
|
|
|
|
ret = []
|
|
|
|
|
for f in files:
|
|
|
|
|
if not os.path.isfile(f):
|
|
|
|
|
logger.warn("File '%s' is missing, there will be less records to test" % f)
|
|
|
|
|
continue
|
|
|
|
|
for line in open(f):
|
|
|
|
|
match = re.match(r'([a-zA-Z0-9]+)\s', line)
|
|
|
|
|
if not match: continue
|
|
|
|
|
for w in re.split(r'[^a-z0-9]', match.group(1).strip().lower()):
|
|
|
|
|
ret.extend(['_%s.%s' % (w, i) for i in ('_tcp', '_udp')])
|
|
|
|
|
return ret
|
|
|
|
|
else:
|
|
|
|
|
if qtype in ('A', 'AAAA'):
|
|
|
|
|
name = name[:-1]
|
|
|
|
|
self.hostmap[name].ip.add(data)
|
|
|
|
|
|
|
|
|
|
srv = set(common + distro())
|
|
|
|
|
return srv, len(srv)
|
|
|
|
|
elif qtype == 'CNAME':
|
|
|
|
|
name, data = name[:-1], data[:-1]
|
|
|
|
|
self.hostmap[data].alias.add(name)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from DNS import DnsRequest, DNSError
|
|
|
|
|
except ImportError:
|
|
|
|
|
warnings.append('pydns')
|
|
|
|
|
|
|
|
|
|
class DNS_reverse:
|
|
|
|
|
'''Reverse lookup subnets'''
|
|
|
|
@ -2902,50 +2981,46 @@ class DNS_reverse:
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
available_options = (
|
|
|
|
|
('host', 'IP addresses to reverse'),
|
|
|
|
|
('host', 'IP addresses to reverse lookup'),
|
|
|
|
|
('server', 'name server to query (directly asking a zone authoritative NS may return more results) [8.8.8.8]'),
|
|
|
|
|
('timeout', 'seconds to wait for a DNS response [10]'),
|
|
|
|
|
('timeout', 'seconds to wait for a DNS response [5]'),
|
|
|
|
|
('protocol', 'send queries over udp or tcp [udp]'),
|
|
|
|
|
)
|
|
|
|
|
available_actions = ()
|
|
|
|
|
|
|
|
|
|
Response = Response_Base
|
|
|
|
|
|
|
|
|
|
def execute(self, host, server='8.8.8.8', timeout='10'):
|
|
|
|
|
resolver = DnsRequest(qtype='PTR', server=server, timeout=int(timeout))
|
|
|
|
|
|
|
|
|
|
ip = IP(host)
|
|
|
|
|
ptr = ip.reverseName()
|
|
|
|
|
result = resolver.req(ptr.rstrip('.'))
|
|
|
|
|
hostnames = [ans['data'] for ans in result.answers]
|
|
|
|
|
def execute(self, host, server='8.8.8.8', timeout='5', protocol='udp'):
|
|
|
|
|
|
|
|
|
|
hostmap = {}
|
|
|
|
|
for n in hostnames:
|
|
|
|
|
if n not in hostmap: hostmap[n] = HostInfo()
|
|
|
|
|
hostmap[n].ip.add(ip)
|
|
|
|
|
response = dns_query(server, int(timeout), protocol, dns.reversename.from_address(host), qtype='PTR', qclass='IN')
|
|
|
|
|
|
|
|
|
|
code = result.header['rcode']
|
|
|
|
|
status = result.header['status']
|
|
|
|
|
mesg = '%s %s' % (status, ', '.join(hostnames))
|
|
|
|
|
code = response.rcode()
|
|
|
|
|
status = dns.rcode.to_text(code)
|
|
|
|
|
rrs = [[host, c, t, d] for _, _, c, t, d in [rr.to_text().split(' ', 4) for rr in response.answer]]
|
|
|
|
|
|
|
|
|
|
mesg = '%s %s' % (status, ''.join('[%s]' % ' '.join(rr) for rr in rrs))
|
|
|
|
|
resp = self.Response(code, mesg)
|
|
|
|
|
resp.hostmap = hostmap
|
|
|
|
|
|
|
|
|
|
resp.rrs = rrs
|
|
|
|
|
|
|
|
|
|
return resp
|
|
|
|
|
|
|
|
|
|
class DNS_forward:
|
|
|
|
|
'''Forward lookup subdomains'''
|
|
|
|
|
'''Forward lookup names'''
|
|
|
|
|
|
|
|
|
|
usage_hints = [
|
|
|
|
|
"""%prog domain=FILE0.google.com 0=names.txt -x ignore:code=3""",
|
|
|
|
|
"""%prog domain=google.MOD0 0=TLD -x ignore:code=3""",
|
|
|
|
|
"""%prog domain=MOD0.microsoft.com 0=SRV qtype=SRV -x ignore:code=3""",
|
|
|
|
|
"""%prog name=FILE0.google.com 0=names.txt -x ignore:code=3""",
|
|
|
|
|
"""%prog name=google.MOD0 0=TLD -x ignore:code=3""",
|
|
|
|
|
"""%prog name=MOD0.microsoft.com 0=SRV qtype=SRV -x ignore:code=3""",
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
available_options = (
|
|
|
|
|
('domain', 'domains to lookup'),
|
|
|
|
|
('name', 'domain names to lookup'),
|
|
|
|
|
('server', 'name server to query (directly asking the zone authoritative NS may return more results) [8.8.8.8]'),
|
|
|
|
|
('timeout', 'seconds to wait for a DNS response [10]'),
|
|
|
|
|
('qtype', 'comma-separated list of types to query [ANY,A,AAAA]'),
|
|
|
|
|
('timeout', 'seconds to wait for a DNS response [5]'),
|
|
|
|
|
('protocol', 'send queries over udp or tcp [udp]'),
|
|
|
|
|
('qtype', 'type to query [ANY]'),
|
|
|
|
|
('qclass', 'class to query [IN]'),
|
|
|
|
|
)
|
|
|
|
|
available_actions = ()
|
|
|
|
|
|
|
|
|
@ -2956,48 +3031,18 @@ class DNS_forward:
|
|
|
|
|
|
|
|
|
|
Response = Response_Base
|
|
|
|
|
|
|
|
|
|
def execute(self, domain, server='8.8.8.8', timeout='10', qtype='ANY,A,AAAA'):
|
|
|
|
|
resolver = DnsRequest(server=server, timeout=int(timeout))
|
|
|
|
|
|
|
|
|
|
hostmap = {}
|
|
|
|
|
for qt in qtype.split(','):
|
|
|
|
|
result = resolver.req(domain, qtype=qt.strip())
|
|
|
|
|
def execute(self, name, server='8.8.8.8', timeout='5', protocol='udp', qtype='ANY', qclass='IN'):
|
|
|
|
|
|
|
|
|
|
for r in result.answers + result.additional + result.authority:
|
|
|
|
|
t = r['typename']
|
|
|
|
|
n = r['name']
|
|
|
|
|
d = r['data']
|
|
|
|
|
|
|
|
|
|
if t not in ('A', 'AAAA', 'CNAME', 'DNAME', 'SRV'):
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if t == 'SRV':
|
|
|
|
|
_, _, _, d = d
|
|
|
|
|
|
|
|
|
|
if t in ('CNAME', 'DNAME', 'SRV'):
|
|
|
|
|
n, d = d, n
|
|
|
|
|
|
|
|
|
|
if n not in hostmap:
|
|
|
|
|
hostmap[n] = HostInfo()
|
|
|
|
|
response = dns_query(server, int(timeout), protocol, name, qtype=qtype, qclass=qclass)
|
|
|
|
|
|
|
|
|
|
if t == 'A':
|
|
|
|
|
hostmap[n].ip.add(IP(d))
|
|
|
|
|
|
|
|
|
|
elif t == 'AAAA':
|
|
|
|
|
hostmap[n].ip.add(IP(hexlify(d)))
|
|
|
|
|
|
|
|
|
|
elif t in ('CNAME', 'DNAME'):
|
|
|
|
|
hostmap[n].alias.add(d)
|
|
|
|
|
|
|
|
|
|
elif t == 'SRV':
|
|
|
|
|
hostmap[n].alias.add(d)
|
|
|
|
|
|
|
|
|
|
code = result.header['rcode']
|
|
|
|
|
status = result.header['status']
|
|
|
|
|
mesg = '%s %s' % (status, ' | '.join('%s / %s' % (k, v) for k, v in hostmap.items()))
|
|
|
|
|
code = response.rcode()
|
|
|
|
|
status = dns.rcode.to_text(code)
|
|
|
|
|
rrs = [[n, c, t, d] for n, _, c, t, d in [rr.to_text().split(' ', 4) for rr in response.answer + response.additional + response.authority]]
|
|
|
|
|
|
|
|
|
|
mesg = '%s %s' % (status, ''.join('[%s]' % ' '.join(rr) for rr in rrs))
|
|
|
|
|
resp = self.Response(code, mesg)
|
|
|
|
|
resp.hostmap = hostmap
|
|
|
|
|
|
|
|
|
|
resp.rrs = rrs
|
|
|
|
|
|
|
|
|
|
return resp
|
|
|
|
|
|
|
|
|
@ -3156,8 +3201,8 @@ modules = [
|
|
|
|
|
('pgsql_login', (Controller, Pgsql_login)),
|
|
|
|
|
('vnc_login', (Controller, VNC_login)),
|
|
|
|
|
|
|
|
|
|
('dns_reverse', (Controller_DNS, DNS_reverse)),
|
|
|
|
|
('dns_forward', (Controller_DNS, DNS_forward)),
|
|
|
|
|
('dns_reverse', (Controller_DNS, DNS_reverse)),
|
|
|
|
|
('snmp_login', (Controller, SNMP_login)),
|
|
|
|
|
|
|
|
|
|
('unzip_pass', (Controller, Unzip_pass)),
|
|
|
|
@ -3173,7 +3218,7 @@ dependencies = {
|
|
|
|
|
'mysql-python': [('mysql_login',), 'http://sourceforge.net/projects/mysql-python/'],
|
|
|
|
|
'psycopg': [('pgsql_login',), 'http://initd.org/psycopg/'],
|
|
|
|
|
'pycrypto': [('vnc_login',), 'http://www.dlitz.net/software/pycrypto/'],
|
|
|
|
|
'pydns': [('dns_reverse', 'dns_forward'), 'http://pydns.sourceforge.net/'],
|
|
|
|
|
'dnspython': [('dns_reverse', 'dns_forward'), 'http://www.dnspython.org/'],
|
|
|
|
|
'IPy': [('dns_reverse', 'dns_forward'), 'https://github.com/haypo/python-ipy'],
|
|
|
|
|
'pysnmp': [('snmp_login',), 'http://pysnmp.sf.net/'],
|
|
|
|
|
'unzip': [('unzip_pass',), 'http://www.info-zip.org/'],
|
|
|
|
|