Skip to content

Commit 829cf0f

Browse files
author
jvazquez-r7
committed
name changed to dns_srv_enum
1 parent d1ba860 commit 829cf0f

File tree

1 file changed

+227
-0
lines changed

1 file changed

+227
-0
lines changed
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
##
2+
# ## This file is part of the Metasploit Framework and may be subject to
3+
# redistribution and commercial restrictions. Please see the Metasploit
4+
# web site for more information on licensing and terms of use.
5+
# http://metasploit.com/
6+
##
7+
8+
require 'msf/core'
9+
require "net/dns/resolver"
10+
require 'rex'
11+
12+
class Metasploit3 < Msf::Auxiliary
13+
include Msf::Auxiliary::Report
14+
15+
def initialize(info = {})
16+
super(update_info(info,
17+
'Name' => 'DNS Common Service Record Enumeration',
18+
'Description' => %q{
19+
This module enumerates common DNS service records in a given domain. By setting
20+
the ALL_DNS to true, all the name servers of a given domain are used for
21+
enumeration. Otherwise only the system dns is used for enumration. in order to get
22+
all the available name servers for the given domain the SOA and NS records are
23+
queried. In order to convert from domain names to IP addresses queries for A and
24+
AAAA (IPv6) records are used.
25+
},
26+
'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>' ],
27+
'License' => BSD_LICENSE
28+
))
29+
30+
register_options(
31+
[
32+
OptString.new('DOMAIN', [ true, "The target domain name."]),
33+
OptBool.new( 'ALL_NS', [ false, "Run against all name servers for the given domain.",false])
34+
], self.class)
35+
36+
register_advanced_options(
37+
[
38+
OptInt.new('RETRY', [ false, "Number of times to try to resolve a record if no response is received.", 2]),
39+
OptInt.new('RETRY_INTERVAL', [ false, "Number of seconds to wait before doing a retry.", 2])
40+
], self.class)
41+
end
42+
43+
def run
44+
records = []
45+
@res = Net::DNS::Resolver.new()
46+
if datastore['RETRY']
47+
@res.retry = datastore['RETRY'].to_i
48+
end
49+
50+
if datastore['RETRY_INTERVAL']
51+
@res.retry_interval = datastore['RETRY_INTERVAL'].to_i
52+
end
53+
54+
print_status("Enumerating SRV Records for #{datastore['DOMAIN']}")
55+
records = records + srvqry(datastore['DOMAIN'])
56+
if datastore["ALL_NS"]
57+
get_soa(datastore['DOMAIN']).each do |s|
58+
switchdns(s[:address])
59+
records = records + srvqry(datastore['DOMAIN'])
60+
end
61+
get_ns(datastore['DOMAIN']).each do |ns|
62+
switchdns(ns[:address])
63+
records =records + srvqry(datastore['DOMAIN'])
64+
end
65+
end
66+
records.uniq!
67+
records.each do |r|
68+
print_good("Host: #{r[:host]} IP: #{r[:address].to_s} Service: #{r[:service]} Protocol: #{r[:proto]} Port: #{r[:port]}")
69+
report_host(
70+
:host => r[:address].to_s,
71+
:name => r[:host]
72+
)
73+
report_service(
74+
:host=> r[:address].to_s,
75+
:port => r[:port].to_i,
76+
:proto => r[:proto],
77+
:name => r[:service],
78+
:host_name => r[:host]
79+
)
80+
end
81+
82+
end
83+
84+
def get_soa(target)
85+
results = []
86+
query = @res.query(target, "SOA")
87+
return results if not query
88+
(query.answer.select { |i| i.class == Net::DNS::RR::SOA}).each do |rr|
89+
if Rex::Socket.dotted_ip?(rr.mname)
90+
record = {}
91+
record[:host] = rr.mname
92+
record[:type] = "SOA"
93+
record[:address] = rr.mname
94+
results << record
95+
else
96+
get_ip(rr.mname).each do |ip|
97+
record = {}
98+
record[:host] = rr.mname.gsub(/\.$/,'')
99+
record[:type] = "SOA"
100+
record[:address] = ip[:address].to_s
101+
results << record
102+
end
103+
end
104+
end
105+
return results
106+
end
107+
108+
def srvqry(dom)
109+
results = []
110+
#Most common SRV Records
111+
srvrcd = [
112+
'_gc._tcp.', '_kerberos._tcp.', '_kerberos._udp.', '_ldap._tcp.',
113+
'_test._tcp.', '_sips._tcp.', '_sip._udp.', '_sip._tcp.', '_aix._tcp.',
114+
'_aix._tcp.', '_finger._tcp.', '_ftp._tcp.', '_http._tcp.', '_nntp._tcp.',
115+
'_telnet._tcp.', '_whois._tcp.', '_h323cs._tcp.', '_h323cs._udp.',
116+
'_h323be._tcp.', '_h323be._udp.', '_h323ls._tcp.',
117+
'_h323ls._udp.', '_sipinternal._tcp.', '_sipinternaltls._tcp.',
118+
'_sip._tls.', '_sipfederationtls._tcp.', '_jabber._tcp.',
119+
'_xmpp-server._tcp.', '_xmpp-client._tcp.', '_imap.tcp.',
120+
'_certificates._tcp.', '_crls._tcp.', '_pgpkeys._tcp.',
121+
'_pgprevokations._tcp.', '_cmp._tcp.', '_svcp._tcp.', '_crl._tcp.',
122+
'_ocsp._tcp.', '_PKIXREP._tcp.', '_smtp._tcp.', '_hkp._tcp.',
123+
'_hkps._tcp.', '_jabber._udp.','_xmpp-server._udp.', '_xmpp-client._udp.',
124+
'_jabber-client._tcp.', '_jabber-client._udp.','_kerberos.tcp.dc._msdcs.',
125+
'_ldap._tcp.ForestDNSZones.', '_ldap._tcp.dc._msdcs.', '_ldap._tcp.pdc._msdcs.',
126+
'_ldap._tcp.gc._msdcs.','_kerberos._tcp.dc._msdcs.','_kpasswd._tcp.','_kpasswd._udp.'
127+
]
128+
129+
srvrcd.each do |srvt|
130+
trg = "#{srvt}#{dom}"
131+
begin
132+
133+
query = @res.query(trg , Net::DNS::SRV)
134+
next unless query
135+
query.answer.each do |srv|
136+
if Rex::Socket.dotted_ip?(srv.host)
137+
record = {}
138+
srv_info = srvt.scan(/^_(\S*)\._(tcp|udp)\./)[0]
139+
record[:host] = srv.host.gsub(/\.$/,'')
140+
record[:type] = "SRV"
141+
record[:address] = srv.host
142+
record[:srv] = srvt
143+
record[:service] = srv_info[0]
144+
record[:proto] = srv_info[1]
145+
record[:port] = srv.port
146+
record[:priority] = srv.priority
147+
results << record
148+
vprint_status("SRV Record: #{trg} Host: #{srv.host.gsub(/\.$/,'')} IP: #{srv.host} Port: #{srv.port} Priority: #{srv.priority}")
149+
else
150+
get_ip(srv.host.gsub(/\.$/,'')).each do |ip|
151+
record = {}
152+
srv_info = srvt.scan(/^_(\S*)\._(tcp|udp)\./)[0]
153+
record[:host] = srv.host.gsub(/\.$/,'')
154+
record[:type] = "SRV"
155+
record[:address] = ip[:address]
156+
record[:srv] = srvt
157+
record[:service] = srv_info[0]
158+
record[:proto] = srv_info[1]
159+
record[:port] = srv.port
160+
record[:priority] = srv.priority
161+
results << record
162+
vprint_status("SRV Record: #{trg} Host: #{srv.host} IP: #{ip[:address]} Port: #{srv.port} Priority: #{srv.priority}")
163+
end
164+
end
165+
end
166+
rescue
167+
end
168+
end
169+
return results
170+
end
171+
172+
def get_ip(host)
173+
results = []
174+
query = @res.search(host, "A")
175+
if (query)
176+
query.answer.each do |rr|
177+
if rr.type == "CNAME"
178+
results = results + get_ip(rr.cname)
179+
else
180+
record = {}
181+
record[:host] = host
182+
record[:type] = "AAAA"
183+
record[:address] = rr.address.to_s
184+
results << record
185+
end
186+
end
187+
end
188+
query1 = @res.search(host, "AAAA")
189+
if (query1)
190+
query1.answer.each do |rr|
191+
if rr.type == "CNAME"
192+
results = results + get_ip(rr.cname)
193+
else
194+
record = {}
195+
record[:host] = host
196+
record[:type] = "AAAA"
197+
record[:address] = rr.address.to_s
198+
results << record
199+
end
200+
end
201+
end
202+
return results
203+
end
204+
205+
def switchdns(ns)
206+
vprint_status("Enumerating SRV Records on: #{ns}")
207+
@res.nameserver=(ns)
208+
@nsinuse = ns
209+
end
210+
211+
def get_ns(target)
212+
results = []
213+
query = @res.query(target, "NS")
214+
return results if not query
215+
(query.answer.select { |i| i.class == Net::DNS::RR::NS}).each do |rr|
216+
get_ip(rr.nsdname).each do |r|
217+
record = {}
218+
record[:host] = rr.nsdname.gsub(/\.$/,'')
219+
record[:type] = "NS"
220+
record[:address] = r[:address].to_s
221+
results << record
222+
end
223+
end
224+
return results
225+
end
226+
end
227+

0 commit comments

Comments
 (0)