a few fixes to sunrpc code

this fixes a couple of errors handling error messages
also, some whitespace/indenting adjustments



git-svn-id: file:///home/svn/framework3/trunk@8365 4d416f70-5f16-0410-b530-b9f4589650da
unstable
Joshua Drake 2010-02-03 20:30:09 +00:00
parent 9b79ebd000
commit a052340703
2 changed files with 43 additions and 41 deletions

View File

@ -6,9 +6,9 @@ module Msf
# #
# This mixin provides utility methods for interacting with a SunRPC service on # This mixin provides utility methods for interacting with a SunRPC service on
# a remote machine. These methods may generally be useful in the context of # a remote machine. These methods may generally be useful in the context of
# exploitation. This mixin extends the Tcp exploit mixin. Only one SunRPC # exploitation. This mixin extends the Tcp exploit mixin. Only one SunRPC
# service can be accessed at a time using this class. # service can be accessed at a time using this class.
# #
# http://www.ietf.org/rfc/rfc1057.txt # http://www.ietf.org/rfc/rfc1057.txt
# #
### ###
@ -16,7 +16,7 @@ module Exploit::Remote::SunRPC
include Exploit::Remote::Tcp include Exploit::Remote::Tcp
XDR = Rex::Encoder::XDR XDR = Rex::Encoder::XDR
MSG_ACCEPTED = 0 MSG_ACCEPTED = 0
SUCCESS = 0 # RPC executed successfully SUCCESS = 0 # RPC executed successfully
PROG_UMAVAIL = 1 # Remote hasn't exported program PROG_UMAVAIL = 1 # Remote hasn't exported program
@ -55,8 +55,8 @@ module Exploit::Remote::SunRPC
end end
ret = rpcobj.create ret = rpcobj.create
return print_error("#{rhost} - No response to SunRPC PortMap request") unless ret return print_error("#{rhost} - No response to SunRPC PortMap request") unless ret
arr = XDR.decode!(ret, Integer, Integer, Integer, String, Integer, Integer) arr = XDR.decode!(ret, Integer, Integer, Integer, String, Integer, Integer)
if arr[1] != MSG_ACCEPTED || arr[4] != SUCCESS || arr[5] == 0 if arr[1] != MSG_ACCEPTED || arr[4] != SUCCESS || arr[5] == 0
err = "#{rhost} - SunRPC PortMap request failed: " err = "#{rhost} - SunRPC PortMap request failed: "
@ -65,7 +65,7 @@ module Exploit::Remote::SunRPC
err << 'Program not available' if arr[5] == 0 err << 'Program not available' if arr[5] == 0
print_error(err) print_error(err)
end end
rpcobj.pport = arr[5] rpcobj.pport = arr[5]
end end
@ -75,7 +75,8 @@ module Exploit::Remote::SunRPC
arr = Rex::Encoder::XDR.decode!(ret, Integer, Integer, Integer, String, Integer) arr = Rex::Encoder::XDR.decode!(ret, Integer, Integer, Integer, String, Integer)
if arr[1] != MSG_ACCEPTED || arr[4] != SUCCESS if arr[1] != MSG_ACCEPTED || arr[4] != SUCCESS
err = "SunRPC call for program #{program} [#{progresolv(program)}], procedure #{procedure}, failed: " progname = progresolv(rpcobj.program)
err = "SunRPC call for program #{rpcobj.program} [#{progname}], procedure #{proc}, failed: "
case arr[4] case arr[4]
when PROG_UMAVAIL then err << "Program Unavailable" when PROG_UMAVAIL then err << "Program Unavailable"
when PROG_MISMATCH then err << "Program Version Mismatch" when PROG_MISMATCH then err << "Program Version Mismatch"
@ -100,13 +101,14 @@ module Exploit::Remote::SunRPC
def sunrpc_authunix(*args) def sunrpc_authunix(*args)
rpcobj.authunix_create(*args) rpcobj.authunix_create(*args)
end end
# XXX: Incomplete. Just moved from Rex::Proto::SunRPC::Client # XXX: Incomplete. Just moved from Rex::Proto::SunRPC::Client
def portmap_qry() def portmap_qry()
ret = portmap_req() ret = portmap_req()
arr = Rex::Encoder::XDR.decode!(ret, Integer, Integer, Integer, String, Integer) arr = Rex::Encoder::XDR.decode!(ret, Integer, Integer, Integer, String, Integer)
if arr[1] != MSG_ACCEPTED || arr[4] != SUCCESS || arr[5] == 0 if arr[1] != MSG_ACCEPTED || arr[4] != SUCCESS || arr[5] == 0
err = "SunRPC call for program #{program} [#{progresolv(program)}], procedure #{procedure}, failed: " progname = progresolv(rpcobj.program)
err = "SunRPC query for program #{rpcobj.program} [#{progname}] failed: "
case arr[4] case arr[4]
when PROG_UMAVAIL then err << "Program Unavailable" when PROG_UMAVAIL then err << "Program Unavailable"
when PROG_MISMATCH then err << "Program Version Mismatch" when PROG_MISMATCH then err << "Program Version Mismatch"
@ -116,25 +118,25 @@ module Exploit::Remote::SunRPC
end end
print_error("#{rhost} - #{err}") print_error("#{rhost} - #{err}")
end end
return ret return ret
end end
def progresolv(number) def progresolv(number)
names = File.join(Msf::Config.install_root, "data", "wordlists", "rpc_names.txt") names = File.join(Msf::Config.install_root, "data", "wordlists", "rpc_names.txt")
File.open(names,"r").each_line do |line| File.open(names,"r").each_line do |line|
next if line.empty? || line =~ /^\s*#/ next if line.empty? || line =~ /^\s*#/
if line =~ /^(\S+?)\s+(\d+)/ && number == $2.to_i if line =~ /^(\S+?)\s+(\d+)/ && number == $2.to_i
return $1 return $1
end end
end end
return "UNKNOWN-#{number}" return "UNKNOWN-#{number}"
end end
# Used to track the last SunRPC context # Used to track the last SunRPC context
attr_accessor :rpcobj attr_accessor :rpcobj
end end
end end

View File

@ -16,16 +16,16 @@ class RPCTimeout < ::Interrupt
end end
# XXX: CPORT! # XXX: CPORT!
class Client class Client
AUTH_NULL = 0 AUTH_NULL = 0
AUTH_UNIX = 1 AUTH_UNIX = 1
PMAP_PROG = 100000 PMAP_PROG = 100000
PMAP_VERS = 2 PMAP_VERS = 2
PMAP_GETPORT = 3 PMAP_GETPORT = 3
CALL = 0 CALL = 0
attr_reader :rhost, :rport, :proto, :program, :version attr_reader :rhost, :rport, :proto, :program, :version
attr_accessor :pport attr_accessor :pport
@ -40,13 +40,13 @@ class Client
rhost, rport, program, version, proto.downcase rhost, rport, program, version, proto.downcase
@pport = nil @pport = nil
@auth_type = AUTH_NULL @auth_type = AUTH_NULL
@auth_data = '' @auth_data = ''
@call_sock = nil @call_sock = nil
end end
# XXX: Add optional parameter to have proto be something else # XXX: Add optional parameter to have proto be something else
def create() def create()
proto_num = 0 proto_num = 0
@ -60,7 +60,7 @@ class Client
Rex::Encoder::XDR.encode(CALL, 2, PMAP_PROG, PMAP_VERS, PMAP_GETPORT, Rex::Encoder::XDR.encode(CALL, 2, PMAP_PROG, PMAP_VERS, PMAP_GETPORT,
@auth_type, [@auth_data, 400], AUTH_NULL, '', @auth_type, [@auth_data, 400], AUTH_NULL, '',
@program, @version, proto_num, 0) @program, @version, proto_num, 0)
sock = make_rpc(@proto, @rhost, @rport) sock = make_rpc(@proto, @rhost, @rport)
send_rpc(sock, buf) send_rpc(sock, buf)
ret = recv_rpc(sock) ret = recv_rpc(sock)
@ -73,46 +73,46 @@ class Client
buf = buf =
Rex::Encoder::XDR.encode(CALL, 2, @program, @version, procedure, Rex::Encoder::XDR.encode(CALL, 2, @program, @version, procedure,
@auth_type, [@auth_data, 400], AUTH_NULL, '')+ @auth_type, [@auth_data, 400], AUTH_NULL, '')+
buffer buffer
if !@call_sock if !@call_sock
@call_sock = make_rpc(@proto, @rhost, @pport) @call_sock = make_rpc(@proto, @rhost, @pport)
end end
send_rpc(@call_sock, buf) send_rpc(@call_sock, buf)
recv_rpc(@call_sock, timeout) recv_rpc(@call_sock, timeout)
end end
def destroy def destroy
close_rpc(@call_sock) if @call_sock close_rpc(@call_sock) if @call_sock
@call_sock = nil @call_sock = nil
end end
def authnull_create def authnull_create
@auth_type = AUTH_NULL @auth_type = AUTH_NULL
@auth_data = '' @auth_data = ''
end end
def authunix_create(host, uid, gid, groupz) def authunix_create(host, uid, gid, groupz)
raise ::Rex::ArgumentError, 'Hostname length is too long' if host.length > 255 raise ::Rex::ArgumentError, 'Hostname length is too long' if host.length > 255
# 10? # 10?
raise ::Rex::ArgumentError, 'Too many groups' if groupz.length > 10 raise ::Rex::ArgumentError, 'Too many groups' if groupz.length > 10
@auth_type = AUTH_UNIX @auth_type = AUTH_UNIX
@auth_data = @auth_data =
Rex::Encoder::XDR.encode(0, host, uid, gid, groupz) # XXX: TIME! GROUPZ?! Rex::Encoder::XDR.encode(0, host, uid, gid, groupz) # XXX: TIME! GROUPZ?!
end end
# XXX: Dirty, integrate some sort of request system into create/call? # XXX: Dirty, integrate some sort of request system into create/call?
def portmap_req(host, port, rpc_vers, procedure, buffer) def portmap_req(host, port, rpc_vers, procedure, buffer)
buf = Rex::Encoder::XDR.encode(CALL, 2, PMAP_PROG, rpc_vers, procedure, buf = Rex::Encoder::XDR.encode(CALL, 2, PMAP_PROG, rpc_vers, procedure,
AUTH_NULL, '', AUTH_NULL, '') + buffer AUTH_NULL, '', AUTH_NULL, '') + buffer
sock = make_rpc('tcp', host, port) sock = make_rpc('tcp', host, port)
send_rpc(sock, buf) send_rpc(sock, buf)
ret = recv_rpc(sock) ret = recv_rpc(sock)
close_rpc(sock) close_rpc(sock)
return ret return ret
end end
@ -128,11 +128,11 @@ class Client
if !self.should_fragment if !self.should_fragment
return Rex::Encoder::XDR.encode(0x80000000 | buf.length) + buf return Rex::Encoder::XDR.encode(0x80000000 | buf.length) + buf
end end
str = buf.dup str = buf.dup
fragmented = '' fragmented = ''
while (str.size > 0) while (str.size > 0)
frag = str.slice!(0, rand(3) + 1) frag = str.slice!(0, rand(3) + 1)
len = frag.size len = frag.size
@ -153,7 +153,7 @@ class Client
end end
sock.write(buf) sock.write(buf)
end end
def recv_rpc(sock, timeout=60) def recv_rpc(sock, timeout=60)
buf = sock.get(timeout) buf = sock.get(timeout)
buf.slice!(0..3) buf.slice!(0..3)
@ -163,11 +163,11 @@ class Client
return buf if buf.length > 1 return buf if buf.length > 1
return nil return nil
end end
def close_rpc(sock) def close_rpc(sock)
sock.close sock.close
end end
def gen_xid def gen_xid
return Rex::Encoder::XDR.encode(rand(0xffffffff) + 1) return Rex::Encoder::XDR.encode(rand(0xffffffff) + 1)
end end
@ -175,4 +175,4 @@ end
end end
end end
end end