cms_scanner 0.0.43.2 → 0.0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c08759ffe67a08d3d1d2a605b909e2005b2236fcb64d2cb5d676a5285b518e47
4
- data.tar.gz: 628124941d9ebde290372e860b36b4f38df9fd860ce54edebe2deb92e6faa3e8
3
+ metadata.gz: 36cf3a147ed137b39e8b2d7f1663bfd454639cce4b8d0f45764af3e3ab0b4b48
4
+ data.tar.gz: a4e4d72d4b8951a04c4f619cc20d1e1293eba77b15533e668738a2e0e62d3306
5
5
  SHA512:
6
- metadata.gz: 39ecc93cb5446fc7d8223c9a397b21e5ff30728c85c5808e47c8a7600c1efe658e4b68dfb8d6f30b916fb7f2103a00af6d752cc0f8e3010c8f3e88ab768e8a46
7
- data.tar.gz: 643282fcf51cab0b08cf09741113fb53ca11f4fdd982bb162d0bd56ad039b4cfe411620ab6a25de2862a9d68d4d4cd23e8681e9416a70820a9dd8f8ab9004b0a
6
+ metadata.gz: cadfdee997e1ef6c7f10ce9f7b8b841acdb1fd5818b5682070f3a07dd5ea34658d55ffd9d86055ac6b7ccf60b5fd965213ba61f22f138873fc6852e137997f0f
7
+ data.tar.gz: 4a37dc5d1eae53a72894f6317cb72132dc07541f76d48ce9067d15fdf4e89d026b074cc4314163883dce3d2006305ff7c607831d8d0cb9c1c4d22e4978b53a91
@@ -7,12 +7,12 @@ module CMSScanner
7
7
  # Core Controller
8
8
  class Core < Base
9
9
  def setup_cache
10
- return unless parsed_options[:cache_dir]
10
+ return unless NS::ParsedCli.cache_dir
11
11
 
12
- storage_path = File.join(parsed_options[:cache_dir], Digest::MD5.hexdigest(target.url))
12
+ storage_path = File.join(NS::ParsedCli.cache_dir, Digest::MD5.hexdigest(target.url))
13
13
 
14
14
  Typhoeus::Config.cache = Cache::Typhoeus.new(storage_path)
15
- Typhoeus::Config.cache.clean if parsed_options[:clear_cache]
15
+ Typhoeus::Config.cache.clean if NS::ParsedCli.clear_cache
16
16
  end
17
17
 
18
18
  def before_scan
@@ -23,12 +23,12 @@ module CMSScanner
23
23
  end
24
24
 
25
25
  def maybe_output_banner_help_and_version
26
- output('banner') if parsed_options[:banner]
27
- output('help', help: option_parser.simple_help, simple: true) if parsed_options[:help]
28
- output('help', help: option_parser.full_help, simple: false) if parsed_options[:hh]
29
- output('version') if parsed_options[:version]
26
+ output('banner') if NS::ParsedCli.banner
27
+ output('help', help: option_parser.simple_help, simple: true) if NS::ParsedCli.help
28
+ output('help', help: option_parser.full_help, simple: false) if NS::ParsedCli.hh
29
+ output('version') if NS::ParsedCli.version
30
30
 
31
- exit(NS::ExitCode::OK) if parsed_options[:help] || parsed_options[:hh] || parsed_options[:version]
31
+ exit(NS::ExitCode::OK) if NS::ParsedCli.help || NS::ParsedCli.hh || NS::ParsedCli.version
32
32
  end
33
33
 
34
34
  # Checks that the target is accessible, raises related errors otherwise
@@ -43,7 +43,7 @@ module CMSScanner
43
43
  when 401
44
44
  raise Error::HTTPAuthRequired
45
45
  when 403
46
- raise Error::AccessForbidden, parsed_options[:random_user_agent]
46
+ raise Error::AccessForbidden, NS::ParsedCli.random_user_agent
47
47
  when 407
48
48
  raise Error::ProxyAuthRequired
49
49
  end
@@ -54,7 +54,7 @@ module CMSScanner
54
54
 
55
55
  return if target.in_scope?(effective_url)
56
56
 
57
- raise Error::HTTPRedirect, effective_url unless parsed_options[:ignore_main_redirect]
57
+ raise Error::HTTPRedirect, effective_url unless NS::ParsedCli.ignore_main_redirect
58
58
 
59
59
  target.homepage_res = res
60
60
  end
@@ -46,7 +46,10 @@ module CMSScanner
46
46
  OptBoolean.new(['--random-user-agent', '--rua',
47
47
  'Use a random user-agent for each scan']),
48
48
  OptFilePath.new(['--user-agents-list FILE-PATH',
49
- 'List of agents to use with --random-user-agent'], exists: true, advanced: true),
49
+ 'List of agents to use with --random-user-agent'],
50
+ exists: true,
51
+ advanced: true,
52
+ default: APP_DIR.join('user_agents.txt')),
50
53
  OptCredentials.new(['--http-auth login:password']),
51
54
  OptPositiveInteger.new(['-t', '--max-threads VALUE', 'The max threads to use'],
52
55
  default: 5),
@@ -15,7 +15,7 @@ module CMSScanner
15
15
  end
16
16
 
17
17
  def run
18
- mode = parsed_options[:interesting_findings_detection] || parsed_options[:detection_mode]
18
+ mode = NS::ParsedCli.interesting_findings_detection || NS::ParsedCli.detection_mode
19
19
  findings = target.interesting_findings(mode: mode)
20
20
 
21
21
  output('findings', findings: findings) unless findings.empty?
@@ -24,6 +24,7 @@ require 'cms_scanner/public_suffix/domain' # Adds a Domain#match method and logi
24
24
  require 'cms_scanner/numeric' # Adds a Numeric#bytes_to_human
25
25
  # Custom Libs
26
26
  require 'cms_scanner/scan'
27
+ require 'cms_scanner/parsed_cli'
27
28
  require 'cms_scanner/helper'
28
29
  require 'cms_scanner/exit_code'
29
30
  require 'cms_scanner/errors'
@@ -14,7 +14,7 @@ module CMSScanner
14
14
  def initialize(parsed_options = {})
15
15
  self.throttle = 0
16
16
 
17
- load_options(parsed_options)
17
+ load_options(parsed_options.dup)
18
18
  end
19
19
 
20
20
  private_class_method :new
@@ -62,6 +62,8 @@ module CMSScanner
62
62
 
63
63
  @user_agents = []
64
64
 
65
+ # The user_agents_list is managed by the CLI options, with the default being
66
+ # APP_DIR/user_agents.txt
65
67
  File.open(user_agents_list).each do |line|
66
68
  next if line == "\n" || line[0, 1] == '#'
67
69
 
@@ -71,11 +73,6 @@ module CMSScanner
71
73
  @user_agents
72
74
  end
73
75
 
74
- # @return [ String ] The path to the user agents list
75
- def user_agents_list
76
- @user_agents_list ||= File.join(APP_DIR, 'user_agents.txt')
77
- end
78
-
79
76
  # @param [ value ] The throttle time in milliseconds
80
77
  #
81
78
  # if value > 0, the max_threads will be set to 1
@@ -22,15 +22,14 @@ module CMSScanner
22
22
  # Reset all the class attibutes
23
23
  # Currently only used in specs
24
24
  def self.reset
25
- @@target = nil
26
- @@parsed_options = nil
27
- @@datastore = nil
28
- @@formatter = nil
25
+ @@target = nil
26
+ @@datastore = nil
27
+ @@formatter = nil
29
28
  end
30
29
 
31
30
  # @return [ Target ]
32
31
  def target
33
- @@target ||= NS::Target.new(parsed_options[:url], parsed_options)
32
+ @@target ||= NS::Target.new(NS::ParsedCli.url, NS::ParsedCli.options)
34
33
  end
35
34
 
36
35
  # @param [ OptParsevalidator::OptParser ] parser
@@ -43,21 +42,6 @@ module CMSScanner
43
42
  @@option_parser
44
43
  end
45
44
 
46
- # Set the parsed options and initialize the browser
47
- # with them
48
- #
49
- # @param [ Hash ] options
50
- def self.parsed_options=(options)
51
- @@parsed_options = options
52
-
53
- NS::Browser.instance(options)
54
- end
55
-
56
- # @return [ Hash ]
57
- def parsed_options
58
- @@parsed_options ||= {}
59
- end
60
-
61
45
  # @return [ Hash ]
62
46
  def datastore
63
47
  @@datastore ||= {}
@@ -65,7 +49,7 @@ module CMSScanner
65
49
 
66
50
  # @return [ Formatter::Base ]
67
51
  def formatter
68
- @@formatter ||= NS::Formatter.load(parsed_options[:format], datastore[:views])
52
+ @@formatter ||= NS::Formatter.load(NS::ParsedCli.format, datastore[:views])
69
53
  end
70
54
 
71
55
  # @see Formatter#output
@@ -84,7 +68,7 @@ module CMSScanner
84
68
 
85
69
  # @return [ Boolean ]
86
70
  def user_interaction?
87
- formatter.user_interaction? && !parsed_options[:output]
71
+ formatter.user_interaction? && !NS::ParsedCli.output
88
72
  end
89
73
 
90
74
  # @return [ String ]
@@ -108,7 +92,7 @@ module CMSScanner
108
92
 
109
93
  # @return [ Hash ] All the instance variable keys (and their values) and the verbose value
110
94
  def instance_variable_values
111
- h = { verbose: parsed_options[:verbose] }
95
+ h = { verbose: NS::ParsedCli.verbose }
112
96
  instance_variables.each do |a|
113
97
  s = a.to_s
114
98
  n = s[1..s.size]
@@ -35,13 +35,12 @@ module CMSScanner
35
35
  end
36
36
 
37
37
  def run
38
- parsed_options = option_parser.results
39
- first.class.option_parser = option_parser
40
- first.class.parsed_options = parsed_options
38
+ NS::ParsedCli.options = option_parser.results
39
+ first.class.option_parser = option_parser # To be able to output the help when -h/--hh
41
40
 
42
- redirect_output_to_file(parsed_options[:output]) if parsed_options[:output]
41
+ redirect_output_to_file(NS::ParsedCli.output) if NS::ParsedCli.output
43
42
 
44
- Timeout.timeout(parsed_options[:max_scan_duration], NS::Error::MaxScanDurationReached) do
43
+ Timeout.timeout(NS::ParsedCli.max_scan_duration, NS::Error::MaxScanDurationReached) do
45
44
  each(&:before_scan)
46
45
 
47
46
  @running = true
@@ -49,7 +48,7 @@ module CMSScanner
49
48
  each(&:run)
50
49
  end
51
50
  ensure
52
- Browser.instance.hydra.abort
51
+ NS::Browser.instance.hydra.abort
53
52
 
54
53
  # Reverse is used here as the app/controllers/core#after_scan finishes the output
55
54
  # and must be the last one to be executed. It also guarantee that stats will be output
@@ -103,7 +103,7 @@ module CMSScanner
103
103
  'Request timed out.'
104
104
  elsif response.code.zero?
105
105
  "No response from remote server. WAF/IPS? (#{response.return_message})"
106
- elsif response.code.to_s =~ /^50/
106
+ elsif /^50/.match?(response.code.to_s)
107
107
  'Server error, try reducing the number of threads.'
108
108
  else
109
109
  "Unknown response received Code: #{response.code}\nBody: #{response.body}"
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CMSScanner
4
+ # Class to hold the parsed CLI options and have them available via
5
+ # methods, such as #verbose?, rather than from the hash.
6
+ # This is similar to an OpenStruct, but class wise (rather than instance), and with
7
+ # the logic to update the Browser options accordinly
8
+ class ParsedCli
9
+ @options = {}
10
+
11
+ class << self
12
+ attr_reader :options
13
+ end
14
+
15
+ # Sets the CLI options, and put them into the Browser as well
16
+ # @param [ Hash ] options
17
+ def self.options=(options)
18
+ @options = options.dup
19
+
20
+ NS::Browser.reset
21
+ NS::Browser.instance(@options)
22
+ end
23
+
24
+ # @return [ Boolean ]
25
+ def self.verbose?
26
+ options[:verbose] ? true : false
27
+ end
28
+
29
+ # Unknown methods will return nil, this is the expected behaviour
30
+ # rubocop:disable Style/MissingRespondToMissing
31
+ def self.method_missing(method_name, *_args, &_block)
32
+ super if method_name == :new
33
+
34
+ options[method_name.to_sym]
35
+ end
36
+ # rubocop:enable Style/MissingRespondToMissing
37
+ end
38
+ end
@@ -32,7 +32,7 @@ module CMSScanner
32
32
  formatter.output('@scan_aborted',
33
33
  reason: e.is_a?(Interrupt) ? 'Canceled by User' : e.message,
34
34
  trace: e.backtrace,
35
- verbose: controllers.first.parsed_options[:verbose] ||
35
+ verbose: NS::ParsedCli.verbose ||
36
36
  run_error_exit_code == NS::ExitCode::EXCEPTION)
37
37
  ensure
38
38
  formatter.beautify
@@ -61,10 +61,8 @@ module CMSScanner
61
61
  at_exit do
62
62
  exit(run_error_exit_code) if run_error
63
63
 
64
- controller = controllers.first
65
-
66
64
  # The parsed_option[:url] must be checked to avoid raising erros when only -h/-v are given
67
- exit(NS::ExitCode::VULNERABLE) if controller.parsed_options[:url] && controller.target.vulnerable?
65
+ exit(NS::ExitCode::VULNERABLE) if NS::ParsedCli.url && controllers.first.target.vulnerable?
68
66
  exit(NS::ExitCode::OK)
69
67
  end
70
68
  end
@@ -20,7 +20,7 @@ module CMSScanner
20
20
  # which can be huge (~ 2Go)
21
21
  res = head_and_get(path, [200], get: params.merge(headers: { 'Range' => 'bytes=0-700' }))
22
22
 
23
- res.body =~ pattern ? true : false
23
+ res.body&.match?(pattern) ? true : false
24
24
  end
25
25
 
26
26
  # @param [ String ] path
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Version
4
4
  module CMSScanner
5
- VERSION = '0.0.43.2'
5
+ VERSION = '0.0.44.0'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cms_scanner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.43.2
4
+ version: 0.0.44.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - WPScanTeam
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-03 00:00:00.000000000 Z
11
+ date: 2019-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -184,14 +184,14 @@ dependencies:
184
184
  requirements:
185
185
  - - "~>"
186
186
  - !ruby/object:Gem::Version
187
- version: 0.66.0
187
+ version: 0.67.1
188
188
  type: :development
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
192
  - - "~>"
193
193
  - !ruby/object:Gem::Version
194
- version: 0.66.0
194
+ version: 0.67.1
195
195
  - !ruby/object:Gem::Dependency
196
196
  name: simplecov
197
197
  requirement: !ruby/object:Gem::Requirement
@@ -299,6 +299,7 @@ files:
299
299
  - lib/cms_scanner/formatter/buffer.rb
300
300
  - lib/cms_scanner/helper.rb
301
301
  - lib/cms_scanner/numeric.rb
302
+ - lib/cms_scanner/parsed_cli.rb
302
303
  - lib/cms_scanner/progressbar_null_output.rb
303
304
  - lib/cms_scanner/public_suffix/domain.rb
304
305
  - lib/cms_scanner/references.rb
@@ -330,7 +331,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
330
331
  requirements:
331
332
  - - ">="
332
333
  - !ruby/object:Gem::Version
333
- version: '2.3'
334
+ version: '2.4'
334
335
  required_rubygems_version: !ruby/object:Gem::Requirement
335
336
  requirements:
336
337
  - - ">="